/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.xsd.builders.utils;
import static org.whole.lang.xsd.util.NamespaceUtils.calculateInternalNamespace;
import static org.whole.lang.xsd.util.NamespaceUtils.getDefaultNamespace;
import static org.whole.lang.xsd.util.NamespaceUtils.isXsiNamespace;
import static org.whole.lang.xsd.util.NamespaceUtils.redefineDefaultNamespace;
import static org.whole.lang.xsd.util.NamespaceUtils.redefineNamespace;
import java.io.File;
import java.io.IOException;
import org.whole.lang.bindings.BindingManagerFactory;
import org.whole.lang.bindings.IBindingManager;
import org.whole.lang.iterators.IEntityIterator;
import org.whole.lang.iterators.IteratorFactory;
import org.whole.lang.reflect.EntityDescriptor;
import org.whole.lang.xml.model.Attribute;
import org.whole.lang.xml.model.Attributes;
import org.whole.lang.xml.util.QName;
import org.whole.lang.xml.util.ResourceResolver;
import org.whole.lang.xsd.codebase.XsdDeployStrategies;
import org.whole.lang.xsd.factories.XsdEntityFactory;
import org.whole.lang.xsd.model.NamespaceDecl;
import org.whole.lang.xsd.model.Schema;
import org.whole.lang.xsd.util.SchemaUtils;
/**
* @author Enrico Persiani
*/
public class AttributesPreprocessor {
private IBindingManager bindings;
private IBindingManager namespaces;
public AttributesPreprocessor(IBindingManager bindings, IBindingManager namespaces) {
this.namespaces = namespaces;
this.bindings = bindings;
}
private String getCurrentFolderLocation() {
try {
return new File(".").getCanonicalPath();
} catch (IOException e) {
throw new IllegalStateException("cannot find current folder location", e);
}
}
protected String getFolderLocation() {
return bindings.wIsSet("folderLocation") ? bindings.wStringValue("folderLocation") : getCurrentFolderLocation();
}
/* was LSResourceResolver, workaround for Android compatibility */
protected ResourceResolver getLSResourceResolver() {
return bindings.wIsSet("lsResourceResolver") ? (ResourceResolver) bindings.wGetValue("lsResourceResolver") :
(bindings.wIsSet("packageName") ? new ResourceResolver(bindings.wStringValue("packageName")) : null);
}
public void preprocess(Attributes attributes) {
IEntityIterator<Attribute> iterator = IteratorFactory.<Attribute>childIterator();
iterator.reset(attributes);
while(iterator.hasNext()) {
Attribute attribute = iterator.next();
if (updateNamespaceDeclarations(attribute) || processXsiDirectives(attribute))
iterator.remove();
}
}
private IBindingManager results = BindingManagerFactory.instance.createBindingManager();
protected boolean updateNamespaceDeclarations(Attribute attribute) {
results.wClear();
if (!AttributesMatcherFactory.matchNamespaceDeclaration(attribute, results))
return false;
String uri = results.wStringValue("uri");
if (results.wIsSet("xmlns")) {
String prefix = results.wStringValue("xmlns");
redefineNamespace(namespaces, prefix, uri);
} else
redefineDefaultNamespace(namespaces, uri);
return true;
}
public boolean hasExplicitType() {
return bindings.wLocalNames().contains("xsiType");
}
public EntityDescriptor<?> getExplicitType() {
String[] typeRef = bindings.wStringValue("xsiType").split(":");
if (typeRef.length == 1) {
} else {
}
String targetNamespace = typeRef.length == 1 ?
getDefaultNamespace(namespaces) : namespaces.wStringValue(typeRef[0]);
// QName qname = QName.create(namespaces, attribute.getName(), getDefaultNamespace(namespaces));
// QName.create(namespaces, , getDefaultNamespace(namespaces));
return null;//CommonsDataTypePersistenceParser.getEntityDescriptor(edUri);
}
protected boolean processXsiDirectives(Attribute attribute) {
QName qname = QName.create(namespaces, getDefaultNamespace(namespaces), attribute.getName());
if (!isXsiNamespace(qname.getNamespaceURI()))
return false;
if ("schemaLocation".equals(qname.getLocalPart()))
processSchemaLocation(attribute.getValue().wStringValue());
else if ("noNamespaceSchemaLocation".equals(qname.getLocalPart()))
processNoNamespaceSchemaLocation(attribute.getValue().wStringValue());
else if ("type".equals(qname.getLocalPart()))
bindings.wDefValue("xsiType", attribute.getValue().getValue());
else if ("nil".equals(qname.getLocalPart()))
bindings.wDefValue("nil", true);
else
throw new IllegalStateException("unknown xml schema instance directive");
return true;
}
protected void processNoNamespaceSchemaLocation(String schemaLocationUrl) {
String targetNamespace = calculateInternalNamespace(true);
Schema schema = SchemaUtils.load(targetNamespace, schemaLocationUrl, getFolderLocation(), getLSResourceResolver());
// add the generated default namespace to the schema
final XsdEntityFactory xef = XsdEntityFactory.instance;
NamespaceDecl namespaceDecl = xef.createNamespaceDecl();
namespaceDecl.setUri(xef.createAnyURI(targetNamespace));
schema.getNamespaces().add(namespaceDecl);
schema.setTargetNamespace(xef.createAnyURI(targetNamespace));
if (XsdDeployStrategies.shouldDeploy(bindings, targetNamespace))
SchemaUtils.deploy(schema, BindingManagerFactory.instance.createArguments());
redefineDefaultNamespace(namespaces, targetNamespace);
}
protected void processSchemaLocation(String schemaLocations) {
String[] locations = schemaLocations.split("\\s+");
if (locations.length % 2 != 0)
throw new IllegalArgumentException("bad schemaLocation directive "+schemaLocations);
for (int i=0; i<locations.length; i+=2) {
String targetNamespace = locations[i];
String schemaLocation = locations[i+1];
if (XsdDeployStrategies.shouldDeploy(bindings, targetNamespace))
SchemaUtils.deploy(targetNamespace, schemaLocation, getFolderLocation(), getLSResourceResolver());
//FIXME XsdRegistry.instance().getURIResolverRegistry().addLocator(targetNamespace, schemaLocation);
}
}
}