docs: @SuppressWarnings({"unchecked", "checkstyle:cyclomaticcomplexity", "checkstyle:npathcomplexity"})
  	public static <T extends MapElement> T readMapElement(Element element, String elementNodeName,
  			Class<T> type, PathBuilder pathBuilder, XMLResources resources) throws IOException {
  		final UUID id = XMLUtil.getAttributeUUIDWithDefault(element, null, XMLUtil.ATTR_ID);
  
  		String nn = elementNodeName;
  
  		if (nn == null || nn.length() == 0) {
  			nn = element.getNodeName();
  		}
  
  		if (NODE_POINT.equals(nn)) {
  			final double x = XMLUtil.getAttributeDouble(element, ATTR_X);
  			final double y = XMLUtil.getAttributeDouble(element, ATTR_Y);
  			final boolean doubleFrame = XMLUtil.getAttributeBooleanWithDefault(element, false, ATTR_DOUBLEFRAME);
  			final double size = XMLUtil.getAttributeDoubleWithDefault(element, GeoLocationUtil.GIS_POINT_SIZE, ATTR_SIZE);
  			final MapPoint point;
  			if (type != null && MapPoint.class.isAssignableFrom(type)) {
  				try {
  					if (id != null) {
  						final Constructor<T> cons = type.getConstructor(UUID.class, double.class, double.class);
  						point = (MapPoint) cons.newInstance(id, x, y);
  					} else {
  						final Constructor<T> cons = type.getConstructor(double.class, double.class);
  						point = (MapPoint) cons.newInstance(x, y);
  					}
  				} catch (AssertionError e) {
  					throw e;
  				} catch (Throwable e) {
  					throw new IOException(e);
  				}
  			} else if (id == null) {
  				point = new MapPoint(x, y);
  			} else {
  				point = new MapPoint(id, x, y);
  			}
  			point.setDoubleFramed(doubleFrame);
  			point.setPointSize(size);
  
  			readGISElementAttributes(element, point, pathBuilder, resources);
  			final Integer color = XMLUtil.getAttributeColorWithDefault(element, null, XMLUtil.ATTR_COLOR);
  			if (color != null) {
  				point.setColor(color);
  			}
  
  			return (T) point;
  		}
  
  		if (NODE_CIRCLE.equals(nn)) {
  			final double x = XMLUtil.getAttributeDouble(element, ATTR_X);
  			final double y = XMLUtil.getAttributeDouble(element, ATTR_Y);
  			final double radius = XMLUtil.getAttributeDoubleWithDefault(element,
  					MapElementConstants.getPreferredRadius(), ATTR_RADIUS);
  			final MapCircle circle;
  			if (type != null && MapCircle.class.isAssignableFrom(type)) {
  				try {
  					if (id != null) {
  						final Constructor<T> cons = type.getConstructor(UUID.class, double.class, double.class);
  						circle = (MapCircle) cons.newInstance(id, x, y);
  					} else {
  						final Constructor<T> cons = type.getConstructor(double.class, double.class);
  						circle = (MapCircle) cons.newInstance(x, y);
  					}
  				} catch (AssertionError e) {
  					throw e;
  				} catch (Throwable e) {
  					throw new IOException(e);
  				}
  			} else if (id == null) {
  				circle = new MapCircle(x, y);
  			} else {
  				circle = new MapCircle(id, x, y);
  			}
  			circle.setRadius(radius);
  
  			readGISElementAttributes(element, circle, pathBuilder, resources);
  			final Integer color = XMLUtil.getAttributeColorWithDefault(element, null, XMLUtil.ATTR_COLOR);
  			if (color != null) {
  				circle.setColor(color);
  			}
  
  			return (T) circle;
  		}
  		if (NODE_POLYLINE.equals(nn)) {
  			final boolean isWide = XMLUtil.getAttributeBooleanWithDefault(element, false, ATTR_WIDE);
  			final MapPolyline polyline;
  			if (type != null && MapPolyline.class.isAssignableFrom(type)) {
  				try {
  					if (id != null) {
  						final Constructor<T> cons = type.getConstructor(UUID.class);
  						polyline = (MapPolyline) cons.newInstance(id);
  					} else {
  						polyline = (MapPolyline) type.newInstance();
  					}
  				} catch (AssertionError e) {
  					throw e;
  				} catch (Throwable e) {
  					throw new IOException(e);
  				}
  			} else if (id == null) {
  				polyline = new MapPolyline();
  			} else {
  				polyline = new MapPolyline(id);
  			}
  			polyline.setWidePolyline(isWide);
  			readMapComposedElementPoints(element, polyline);
  
  			readGISElementAttributes(element, polyline, pathBuilder, resources);
  			final Integer color = XMLUtil.getAttributeColorWithDefault(element, null, XMLUtil.ATTR_COLOR);
  			if (color != null) {
  				polyline.setColor(color);
  			}
  
  			return (T) polyline;
  		}
  		if (NODE_POLYGON.equals(nn)) {
  			final MapPolygon polygon;
  			if (type != null && MapPolygon.class.isAssignableFrom(type)) {
  				try {
  					if (id != null) {
  						final Constructor<T> cons = type.getConstructor(UUID.class);
  						polygon = (MapPolygon) cons.newInstance(id);
  					} else {
  						polygon = (MapPolygon) type.newInstance();
  					}
  				} catch (AssertionError e) {
  					throw e;
  				} catch (Throwable e) {
  					throw new IOException(e);
  				}
  			} else if (id == null) {
  				polygon = new MapPolygon();
  			} else {
  				polygon = new MapPolygon(id);
  			}
  			readMapComposedElementPoints(element, polygon);
  
  			readGISElementAttributes(element, polygon, pathBuilder, resources);
  			final Integer color = XMLUtil.getAttributeColorWithDefault(element, null, XMLUtil.ATTR_COLOR);
  			if (color != null) {
  				polygon.setColor(color);
  			}
  
  			return (T) polygon;
  		}
  		if (NODE_MULTIPOINT.equals(nn)) {
  			final boolean doubleFrame = XMLUtil.getAttributeBooleanWithDefault(element, false, ATTR_DOUBLEFRAME);
  			final double size = XMLUtil.getAttributeDoubleWithDefault(element, GeoLocationUtil.GIS_POINT_SIZE, ATTR_SIZE);
  			final MapMultiPoint multipoint;
  			if (type != null && MapMultiPoint.class.isAssignableFrom(type)) {
  				try {
  					if (id != null) {
  						final Constructor<T> cons = type.getConstructor(UUID.class);
  						multipoint = (MapMultiPoint) cons.newInstance(id);
  					} else {
  						multipoint = (MapMultiPoint) type.newInstance();
  					}
  				} catch (AssertionError e) {
  					throw e;
  				} catch (Throwable e) {
  					throw new IOException(e);
  				}
  			} else if (id == null) {
  				multipoint = new MapMultiPoint();
  			} else {
  				multipoint = new MapMultiPoint(id);
  			}
  			multipoint.setDoubleFramed(doubleFrame);
  			multipoint.setPointSize(size);
  			readMapComposedElementPoints(element, multipoint);
  
  			readGISElementAttributes(element, multipoint, pathBuilder, resources);
  			final Integer color = XMLUtil.getAttributeColorWithDefault(element, null, XMLUtil.ATTR_COLOR);
  			if (color != null) {
  				multipoint.setColor(color);
  			}
  
  			return (T) multipoint;
  		}
  		throw new IOException("unable to parse the XML node to retrieve a map element"); //$NON-NLS-1$
  	}