package com.revolsys.record.io.format.esri.rest.map; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.TreeMap; import com.revolsys.collection.Parent; import com.revolsys.collection.map.MapEx; import com.revolsys.collection.map.Maps; import com.revolsys.io.PathName; import com.revolsys.logging.Logs; import com.revolsys.record.io.format.esri.rest.ArcGisResponse; import com.revolsys.record.io.format.esri.rest.ArcGisRestService; import com.revolsys.record.io.format.esri.rest.ArcGisRestServiceContainer; import com.revolsys.record.io.format.esri.rest.CatalogElement; import com.revolsys.record.io.format.json.Json; import com.revolsys.spring.resource.Resource; import com.revolsys.util.Property; import com.revolsys.util.function.Function3; import com.revolsys.webservice.WebServiceResource; public abstract class ArcGisRestAbstractLayerService extends ArcGisRestService implements Parent<CatalogElement> { public static final Map<String, Function3<ArcGisRestAbstractLayerService, CatalogElement, MapEx, LayerDescription>> LAYER_FACTORY_BY_TYPE = Maps .<String, Function3<ArcGisRestAbstractLayerService, CatalogElement, MapEx, LayerDescription>> buildHash() // .add("Group Layer", GroupLayer::new) .add("Feature Layer", FeatureLayer::new) .add("Table", FeatureLayer::new) .add("Annotation Layer", AnnotationLayer::new) .getMap(); private List<CatalogElement> children = Collections.emptyList(); private Map<String, LayerDescription> rootLayersByName = Collections.emptyMap(); public ArcGisRestAbstractLayerService(final ArcGisRestServiceContainer parent, final String type) { super(parent, type); } protected ArcGisRestAbstractLayerService(final String type) { super(type); } public LayerDescription addLayer(final CatalogElement parent, final Map<String, LayerDescription> layersByName, MapEx layerProperties) { final int id = layerProperties.getInteger("id"); final Resource resource = getResource(Integer.toString(id), ArcGisResponse.FORMAT_PARAMETER); try { layerProperties = Json.toMap(resource); final String layerType = layerProperties.getString("type"); final Function3<ArcGisRestAbstractLayerService, CatalogElement, MapEx, LayerDescription> factory = LAYER_FACTORY_BY_TYPE .get(layerType); LayerDescription layer; if (factory == null) { layer = new LayerDescription(this, parent, layerProperties); } else { layer = factory.apply(this, parent, layerProperties); } final String name = layer.getName(); if (Property.hasValue(name)) { layersByName.put(name.toLowerCase(), layer); return layer; } else { return null; } } catch (final Throwable e) { e.printStackTrace(); Logs.debug(this, "Unable to initialize layer: " + resource, e); return null; } } @Override @SuppressWarnings("unchecked") public <C extends WebServiceResource> C getChild(final String name) { if (name == null) { return null; } else { refreshIfNeeded(); return (C)this.rootLayersByName.get(name.toLowerCase()); } } @Override public List<CatalogElement> getChildren() { refreshIfNeeded(); return this.children; } @SuppressWarnings("unchecked") public <L extends LayerDescription> L getLayer(final PathName pathName) { refreshIfNeeded(); final List<String> elements = pathName.getElements(); if (!elements.isEmpty()) { LayerDescription layer = this.rootLayersByName.get(elements.get(0)); for (int i = 1; layer != null && i < elements.size(); i++) { if (layer instanceof GroupLayer) { final GroupLayer layerGroup = (GroupLayer)layer; final String childLayerName = elements.get(i); layer = layerGroup.getLayer(childLayerName); } else { return null; } } return (L)layer; } return null; } protected void initChildren(final MapEx properties, final List<CatalogElement> children, final Map<String, LayerDescription> rootLayersByName) { final Map<String, GroupLayer> groups = new TreeMap<>(); final Map<String, LayerDescription> layers = new TreeMap<>(); final List<MapEx> layerDefinitions = properties.getValue("layers", Collections.emptyList()); for (final MapEx layerProperties : layerDefinitions) { final Integer parentLayerId = layerProperties.getInteger("parentLayerId"); if (parentLayerId == null || parentLayerId == -1) { final LayerDescription layer = addLayer(this, rootLayersByName, layerProperties); if (layer != null) { final String layerName = layer.getName(); if (layer instanceof GroupLayer) { final GroupLayer group = (GroupLayer)layer; groups.put(layerName, group); } else { layers.put(layerName, layer); } } } } final List<MapEx> tableDefinitions = properties.getValue("tables", Collections.emptyList()); for (final MapEx layerProperties : tableDefinitions) { final LayerDescription layer = addLayer(this, rootLayersByName, layerProperties); if (layer != null) { final String layerName = layer.getName(); layers.put(layerName, layer); } } children.addAll(groups.values()); children.addAll(layers.values()); } @Override protected void initialize(final MapEx properties) { super.initialize(properties); final List<CatalogElement> children = new ArrayList<>(); final Map<String, LayerDescription> rootLayersByName = new TreeMap<>(); initChildren(properties, children, rootLayersByName); this.children = Collections.unmodifiableList(children); this.rootLayersByName = Collections.unmodifiableMap(rootLayersByName); } }