/*
* 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.builder.jaxb.xml.io.writer;
import java.util.HashSet;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.sax.SAXResult;
import org.citygml4j.model.citygml.CityGML;
import org.citygml4j.model.citygml.ade.ADEComponent;
import org.citygml4j.model.citygml.appearance.Appearance;
import org.citygml4j.model.citygml.appearance.AppearanceMember;
import org.citygml4j.model.citygml.core.AbstractCityObject;
import org.citygml4j.model.citygml.core.CityModel;
import org.citygml4j.model.citygml.core.CityObjectMember;
import org.citygml4j.model.gml.feature.AbstractFeature;
import org.citygml4j.model.gml.feature.FeatureMember;
import org.citygml4j.model.module.ModuleContext;
import org.citygml4j.model.module.gml.GMLCoreModule;
import org.citygml4j.util.internal.xml.TransformerChain;
import org.citygml4j.util.xml.SAXWriter;
import org.citygml4j.xml.io.writer.CityGMLWriteException;
import org.citygml4j.xml.io.writer.CityGMLWriter;
import org.citygml4j.xml.io.writer.CityModelInfo;
import org.citygml4j.xml.io.writer.FeatureWriteMode;
import org.xml.sax.SAXException;
public class JAXBSimpleWriter extends AbstractJAXBWriter implements CityGMLWriter {
public JAXBSimpleWriter(SAXWriter writer, JAXBOutputFactory factory, ModuleContext moduleContext) throws CityGMLWriteException {
super(writer, factory, moduleContext);
}
public void write(AbstractFeature abstractFeature) throws CityGMLWriteException {
if (featureWriteMode == FeatureWriteMode.SPLIT_PER_COLLECTION_MEMBER && featureSplitter != null)
abstractFeature = split(abstractFeature);
try {
JAXBElement<?> jaxbElement = jaxbMarshaller.marshalJAXBElement(abstractFeature);
if (jaxbElement != null) {
Marshaller marshaller = jaxbContext.createMarshaller();
// validate output
if (useValidation) {
marshaller.setSchema(validationSchemaHandler.getSchema());
if (validationEventHandler != null)
marshaller.setEventHandler(validationEventHandler);
}
// marshal output
if (transformerChainFactory == null)
marshaller.marshal(jaxbElement, writer);
else {
// apply transformation before marshalling
TransformerChain chain = transformerChainFactory.buildChain();
chain.tail().setResult(new SAXResult(writer));
marshaller.marshal(jaxbElement, chain.head());
}
writer.flush();
}
} catch (JAXBException | SAXException | TransformerConfigurationException e) {
throw new CityGMLWriteException("Caused by: ", e);
}
}
private AbstractFeature split(AbstractFeature input) {
List<CityGML> results = featureSplitter.split(input);
CityModel cityModel = null;
CityModel origModel = null;
HashSet<String> gmlIds = null;
if (input instanceof CityModel) {
cityModel = new CityModelInfo((CityModel)input).toCityModel();
origModel = (CityModel)results.get(0);
gmlIds = new HashSet<String>();
} else
cityModel = new CityModel();
for (CityGML result : results) {
if (result instanceof AbstractFeature) {
if (result == origModel)
continue;
AbstractFeature feature = (AbstractFeature)result;
if (gmlIds != null && feature.isSetId())
gmlIds.add('#' + feature.getId());
if (feature instanceof AbstractCityObject) {
CityObjectMember member = new CityObjectMember();
member.setCityObject((AbstractCityObject)feature);
cityModel.addCityObjectMember(member);
}
else if (feature instanceof Appearance) {
AppearanceMember member = new AppearanceMember();
member.setAppearance((Appearance)feature);
cityModel.addAppearanceMember(member);
}
else {
FeatureMember member = new FeatureMember();
member.setFeature(feature);
cityModel.addFeatureMember(member);
}
}
// handle ADE feature
else if (result instanceof ADEComponent){
ADEComponent ade = (ADEComponent)result;
if (gmlIds != null) {
String gmlId = ade.getContent().getAttribute("id");
if (gmlId.length() == 0)
gmlId = ade.getContent().getAttributeNS(GMLCoreModule.v3_1_1.getNamespaceURI(), "id");
gmlIds.add('#' + gmlId);
}
// add ADE feature to new CityModel
if (isCityObject(ade)) {
CityObjectMember member = new CityObjectMember();
member.setGenericADEComponent(ade);
cityModel.addCityObjectMember(member);
}
else {
FeatureMember member = new FeatureMember();
member.setGenericADEComponent(ade);
cityModel.addFeatureMember(member);
}
}
}
if (origModel != null) {
if (origModel.isSetCityObjectMember())
for (CityObjectMember member : origModel.getCityObjectMember())
if (!(member.isSetHref() && gmlIds.contains(member.getHref())))
cityModel.addCityObjectMember(member);
else
gmlIds.remove(member.getHref());
if (origModel.isSetAppearanceMember())
for (AppearanceMember member : origModel.getAppearanceMember())
if (!(member.isSetHref() && gmlIds.contains(member.getHref())))
cityModel.addAppearanceMember(member);
else
gmlIds.remove(member.getHref());
if (origModel.isSetFeatureMember())
for (FeatureMember member : origModel.getFeatureMember())
if (!(member.isSetHref() && gmlIds.contains(member.getHref())))
cityModel.addFeatureMember(member);
else
gmlIds.remove(member.getHref());
}
return cityModel;
}
}