/**
* 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;
import static org.whole.lang.xsd.builders.utils.AttributesMatcherFactory.containsReferenceAttribute;
import static org.whole.lang.xsd.reflect.XsdEntityDescriptorEnum.*;
import static org.whole.lang.xsd.reflect.XsdFeatureDescriptorEnum.*;
import org.whole.lang.bindings.IBindingManager;
import org.whole.lang.builders.IBuilderOperation;
import org.whole.lang.commons.factories.CommonsEntityAdapterFactory;
import org.whole.lang.commons.reflect.CommonsEntityDescriptorEnum;
import org.whole.lang.matchers.Matcher;
import org.whole.lang.reflect.EntityDescriptor;
import org.whole.lang.reflect.FeatureDescriptor;
import org.whole.lang.util.EntityUtils;
import org.whole.lang.xml.factories.XmlEntityFactory;
import org.whole.lang.xml.model.Attributes;
import org.whole.lang.xml.model.QualifiedName;
import org.whole.lang.xml.reflect.XmlEntityDescriptorEnum;
import org.whole.lang.xml.util.QName;
import org.whole.lang.xml.util.XmlUtils;
import org.whole.lang.xsd.builders.utils.MappingContext;
import org.whole.lang.xsd.util.NamespaceUtils;
/**
* @author Enrico Persiani
*/
public class XmlSpecific2XsdBuilderAdapter extends XmlSpecific2XsiBuilderAdapter {
public XmlSpecific2XsdBuilderAdapter(IBuilderOperation op, IBindingManager bm) {
super(op, bm);
}
@Override
public MappingContext elementEntity_(EntityDescriptor<?> context, QName name, Attributes attributes) {
if (containsReferenceAttribute(attributes)) {
EntityDescriptor<?> ed = null;
if (Particles.equals(context) && matches("element", name))
ed = ElementRef;
else if (matches("attribute", name))
ed = AttributeUseRef;
else if (matches("attributeGroup", name))
ed = AttributeGroupRef;
else if (matches("group", name))
ed = ModelGroupRef;
FeatureDescriptor fd = calculateFeatureDescriptor(context, name);
if (!EntityUtils.isComposite(context))
builder.wFeature(fd);
builder.wEntity_(ed);
attributeEntities(ed, attributes);
return MappingContext.create(ed, fd, false);
} else
return super.elementEntity_(context, name, attributes);
}
private final boolean matches(String name, QName tag) {
return name.equals(tag.getLocalPart()) &&
NamespaceUtils.isXsdNamespace(tag.getNamespaceURI());
}
@Override
protected void anyAttributeEntities(EntityDescriptor<?> context, Attributes anyAttributes) {
builder.wFeature(attributes);
builder.wEntity_(Attributes, 0);
for (int i=0, size=anyAttributes.wSize(); i<size; i++)
anyAttributeEntity(context, (org.whole.lang.xml.model.Attribute) anyAttributes.wGet(i));
builder._wEntity(Attributes);
}
@Override
protected void attributeEntity(FeatureDescriptor fd, EntityDescriptor<?> ed, String value) {
switch (ed.getOrdinal()) {
case Bounded_ord:
case Unbounded_ord:
if ("unbounded".equals(value)) {
builder.wFeature(fd);
builder.wEntity(Unbounded);
} else
super.attributeEntity(fd, Bounded, value);
break;
case NamespaceSpecs_ord:
builder.wFeature(fd);
if ("##any".equals(value))
builder.wEntity(AnyNamespaceSpecs);
else if ("##other".equals(value))
builder.wEntity(OtherNamespaceSpecs);
else {
builder.wEntity_(NamespaceSpecsList);
for (String namespaceSpec : value.split("\\s+")) {
if ("##targetNamespace".equals(namespaceSpec))
builder.wEntity(TargetNamespaceSpec);
else if ("##local".equals(namespaceSpec))
builder.wEntity(LocalNamespaceSpec);
else
builder.wEntity(AnyURI, namespaceSpec);
}
builder._wEntity(NamespaceSpecsList);
}
break;
case MemberTypes_ord:
builder.wFeature(fd);
builder.wEntity_(MemberTypes);
for (String memeberType : value.split("\\s+"))
builder.wEntity(QName, memeberType);
builder._wEntity(MemberTypes);
break;
case DerivationSet_ord:
builder.wFeature(fd);
if ("#all".equals(value))
builder.wEntity(DerivationAll);
else {
builder.wEntity_(DerivationList);
if (!XmlUtils.isIgnorableWhitespace(value))
for (String derivationControl : value.split("\\s+"))
builder.wEntity(DerivationControl, derivationControl);
builder._wEntity(DerivationList);
}
break;
default:
super.attributeEntity(fd, ed, value);
}
}
protected void buildEntityNamespaceDecls(EntityDescriptor<?> context) {
if (context.has(namespaces)) {
builder.wEntity_(NamespaceDecls);
for (String prefix : ns.wLocalNames()) {
builder.wEntity_(NamespaceDecl);
if (NamespaceUtils.isDefaultNamespacePrefix(prefix))
builder.wEntity(CommonsEntityDescriptorEnum.Resolver);
else
builder.wEntity(Name, prefix);
builder.wEntity(AnyURI, ns.wStringValue(prefix));
builder._wEntity(NamespaceDecl);
}
builder._wEntity(NamespaceDecls);
}
}
@Override
protected void attributeEntities(EntityDescriptor<?> context, Attributes attributes) {
// adds namespace declarations
buildEntityNamespaceDecls(context);
//FIXME workaround, must implement mapping of xml:lang attribute
if (Schema.equals(context) || Documentation.equals(context)) {
QualifiedName name = Matcher.find(
XmlEntityFactory.instance.createQualifiedName(
CommonsEntityAdapterFactory.createVariable(XmlEntityDescriptorEnum.NameSpace, "prefix"),
XmlEntityFactory.instance.createName("lang")), attributes, false);
if (name != null)
attributes.wRemove(name.wGetParent());
}
super.attributeEntities(context, attributes);
}
protected org.whole.lang.xml.model.Element normalizeXmlFragment(org.whole.lang.xml.model.Element xmlFragment) {
xmlFragment.accept(new XmlFragmentNormalizer());
return xmlFragment;
}
}