/* * citygml4j - The Open Source Java API for CityGML * https://github.com/citygml4j * * Copyright 2013-2017 Claus Nagel <claus.nagel@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.citygml4j.util.xlink; import org.citygml4j.model.citygml.ade.ADEComponent; import org.citygml4j.model.citygml.appearance.AppearanceModuleComponent; import org.citygml4j.model.common.base.ModelObject; import org.citygml4j.model.gml.base.AbstractGML; import org.citygml4j.model.gml.feature.AbstractFeature; import org.citygml4j.model.gml.feature.FeatureProperty; import org.citygml4j.model.gml.geometry.AbstractGeometry; import org.citygml4j.model.module.gml.GMLCoreModule; import org.citygml4j.util.walker.GMLFunctionWalker; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class XLinkResolver { private ModelObject resolveXlink(String target, AbstractGML root, GMLIdWalker walker) { if (target == null || target.length() == 0) return null; if (root == null) return null; return root.accept(walker); } public ModelObject getObject(String target, AbstractGML root) { return resolveXlink(target, root, new GMLWalker(clipGMLId(target))); } public AbstractGeometry getGeometry(String target, AbstractGML root) { ModelObject object = resolveXlink(target, root, new GeometryWalker(clipGMLId(target))); return object instanceof AbstractGeometry ? (AbstractGeometry)object : null; } public AbstractFeature getFeature(String target, AbstractGML root) { ModelObject object = resolveXlink(target, root, new FeatureWalker(clipGMLId(target))); return object instanceof AbstractFeature ? (AbstractFeature)object : null; } @SuppressWarnings("unchecked") public <T extends AbstractGML> T getAbstractGML(String target, AbstractGML root, Class<T> type) { if (type == null) return null; ModelObject object = getObject(target, root); return (type.isInstance(object)) ? (T)object : null; } private String clipGMLId(String target) { return target.replaceAll("^.*?#+?", ""); } private static final class GMLWalker extends GMLIdWalker { GMLWalker(String gmlId) { super(gmlId); } @Override public ModelObject apply(AbstractGML abstractGML) { return (abstractGML.isSetId() && super.gmlId.equals(abstractGML.getId())) ? abstractGML : null; } } private static final class FeatureWalker extends GMLIdWalker { FeatureWalker(String gmlId) { super(gmlId); } @Override public ModelObject apply(AbstractFeature abstractFeature) { return (abstractFeature.isSetId() && super.gmlId.equals(abstractFeature.getId())) ? abstractFeature : null; } } private static final class GeometryWalker extends GMLIdWalker { GeometryWalker(String gmlId) { super(gmlId); } @Override public ModelObject apply(AbstractGeometry abstractGeometry) { return (abstractGeometry.isSetId() && super.gmlId.equals(abstractGeometry.getId())) ? abstractGeometry : null; } @Override public <E extends AbstractFeature> ModelObject apply(FeatureProperty<E> featureProperty) { if (featureProperty.isSetObject() && featureProperty.getObject() instanceof AppearanceModuleComponent) return null; return super.apply(featureProperty); } @Override public ModelObject apply(AbstractFeature abstractFeature) { if (abstractFeature instanceof AppearanceModuleComponent) return null; return super.apply(abstractFeature); } } private static abstract class GMLIdWalker extends GMLFunctionWalker<ModelObject> { private final String gmlId; GMLIdWalker(String gmlId) { this.gmlId = gmlId; } @Override public ModelObject apply(ADEComponent adeComponent) { if (adeComponent.isSetContent() && addToVisited(adeComponent.getContent())) { ADEComponent result = adeComponent(adeComponent.getContent(), (Element)null); if (result != null) return (result.getContent() == adeComponent.getContent()) ? adeComponent : result; } return null; } protected ADEComponent adeComponent(Element element, Element parent) { String elementId = element.getAttribute("id"); if (elementId.length() == 0) { for (GMLCoreModule gml : GMLCoreModule.getInstances()) { switch (gml.getVersion()) { case v3_1_1: elementId = element.getAttributeNS(gml.getNamespaceURI(), "id"); break; } if (elementId.length() > 0) break; } } if (elementId.length() > 0 && gmlId.equals(elementId)) return new ADEComponent(element); NodeList childs = element.getChildNodes(); for (int i = 0; i < childs.getLength(); ++i) { Node node = childs.item(i); if (node.getNodeType() == Node.ELEMENT_NODE && addToVisited(node)) { ADEComponent ade = adeComponent((Element)node, element); if (ade != null) return ade; } } return null; } } }