use of org.eclipse.persistence.internal.oxm.schema.model.Element in project eclipselink by eclipse-ee4j.
the class SchemaGenerator method buildSchemaComponentsForXPath.
/**
* This method will build element/complexType/typedefparticle components for a given xml-path,
* and return an XmlPathResult instance containg the sequence that the target should be added
* to, as well as the current schema - which could be different than the working schema used
* before calling this method in the case of a prefixed path element from a different namespace.
* Regarding the path 'target', if the xml-path was "contact-info/address/street", "street"
* would be the target. In this case the sequence containing the "address" element would be
* set in the XmlPathResult to be returned.
*
* The exception case is an 'any', where we want to process the last path element before
* returning - this is necessary due to the fact that an Any will be added to the sequence
* in place of the last path element by the calling method.
*/
private AddToSchemaResult buildSchemaComponentsForXPath(XPathFragment frag, AddToSchemaResult xpr, boolean isChoice, Property next) {
boolean isAny = next.isAny() || next.isAnyAttribute();
TypeDefParticle currentParticle = xpr.particle;
Schema workingSchema = xpr.schema;
// each nested choice on a collection will be unbounded
boolean isUnbounded = false;
if (currentParticle != null) {
isUnbounded = (currentParticle.getMaxOccurs() != null && currentParticle.getMaxOccurs() == Occurs.UNBOUNDED);
}
// don't process the last frag; that will be handled by the calling method if necessary
// note that we may need to process the last frag if it has a namespace or is an 'any'
boolean lastFrag = (frag.getNextFragment() == null || frag.getNextFragment().nameIsText());
// if the element is already in the sequence we don't want the calling method to add a second one
if (lastFrag && (elementExistsInParticle(frag.getLocalName(), frag.getShortName(), currentParticle) != null)) {
xpr.particle = null;
return xpr;
}
// if the current element exists, use it; otherwise create a new one
Element currentElement = elementExistsInParticle(frag.getLocalName(), frag.getShortName(), currentParticle);
boolean currentElementExists = (currentElement != null);
if (!currentElementExists) {
currentElement = new Element();
// don't set the element name yet, as it may end up being a ref
ComplexType cType = new ComplexType();
TypeDefParticle particle = null;
if (isChoice) {
particle = new Choice();
if (isUnbounded) {
particle.setMaxOccurs(Occurs.UNBOUNDED);
}
} else {
XPathFragment nextFragment = frag.getNextFragment();
if (frag.containsIndex() || frag.getPredicate() != null || (!next.isXmlList() && null != nextFragment && nextFragment.isAttribute() && helper.isCollectionType(next.getType()))) {
currentElement.setMaxOccurs(Occurs.UNBOUNDED);
}
particle = new Sequence();
}
cType.setTypeDefParticle(particle);
currentElement.setComplexType(cType);
} else {
// if the current element already exists, we may need to change it's type
XPathFragment nextFrag = frag.getNextFragment();
if (nextFrag != null && nextFrag.isAttribute()) {
if (currentElement.getType() != null && currentElement.getComplexType() == null) {
// there's already a text mapping to this element, so
// attributes can be added by making it complex with
// simple content.
SimpleType type = currentElement.getSimpleType();
if (type != null) {
ComplexType cType = new ComplexType();
cType.setSimpleContent(new SimpleContent());
Extension extension = new Extension();
extension.setBaseType(type.getRestriction().getBaseType());
cType.getSimpleContent().setExtension(extension);
currentElement.setSimpleType(null);
currentElement.setComplexType(cType);
} else {
String eType = currentElement.getType();
ComplexType cType = new ComplexType();
SimpleContent sContent = new SimpleContent();
Extension extension = new Extension();
extension.setBaseType(eType);
sContent.setExtension(extension);
cType.setSimpleContent(sContent);
currentElement.setType(null);
currentElement.setComplexType(cType);
}
}
}
}
// may need to create a ref, depending on the namespace
Element globalElement = null;
String fragUri = frag.getNamespaceURI();
if (fragUri != null) {
Schema fragSchema = getSchemaForNamespace(fragUri);
String targetNS = workingSchema.getTargetNamespace();
// handle Attribute case
if (frag.isAttribute()) {
if (fragSchema == null || (fragSchema.isAttributeFormDefault() && !fragUri.equals(targetNS)) || (!fragSchema.isAttributeFormDefault() && fragUri.length() > 0)) {
// if fragSchema is null, just generate the ref
if (fragSchema != null) {
Attribute globalAttribute = null;
globalAttribute = fragSchema.getTopLevelAttributes().get(frag.getLocalName());
if (globalAttribute == null) {
globalAttribute = createGlobalAttribute(frag, workingSchema, fragSchema, next);
}
} else {
// may need to add an import
addImportIfRequired(workingSchema, null, fragUri);
}
// add the attribute ref to the current element
String attributeRefName;
if (fragUri.equals(targetNS)) {
String prefix = fragSchema.getNamespaceResolver().resolveNamespaceURI(fragUri);
attributeRefName = prefix + COLON + frag.getLocalName();
} else {
attributeRefName = frag.getShortName();
}
TypeDefParticleOwner type;
if (currentParticle != null) {
type = currentParticle.getOwner();
} else {
type = xpr.simpleContentType;
}
if (type instanceof ComplexType) {
createRefAttribute(attributeRefName, (ComplexType) type);
}
// set the frag's schema as it may be different than the current schema
xpr.schema = fragSchema;
// ref case - indicate to the calling method that there's nothing to do
xpr.particle = null;
}
// since we are dealing with an attribute, we are on the last fragment; return
return xpr;
}
// here we are dealing with an Element
if ((fragSchema.isElementFormDefault() && !fragUri.equals(targetNS)) || (!fragSchema.isElementFormDefault() && fragUri.length() > 0)) {
// must generate a global element and create a reference to it
// if the global element exists, use it; otherwise create a new one
globalElement = fragSchema.getTopLevelElements().get(frag.getLocalName());
if (globalElement == null) {
globalElement = createGlobalElement(frag, workingSchema, fragSchema, isChoice, isUnbounded, next, (lastFrag && !isAny));
}
// if the current element doesn't exist set a ref and add it to the sequence
if (!currentElementExists) {
// use prefix from the working schema's resolver - add prefix/uri pair if necessary
String fragPrefix = workingSchema.getNamespaceResolver().resolveNamespaceURI(fragUri);
if (fragPrefix == null) {
fragPrefix = workingSchema.getNamespaceResolver().generatePrefix(frag.getPrefix());
workingSchema.getNamespaceResolver().put(fragPrefix, fragUri);
}
currentElement = createRefElement(fragPrefix + COLON + frag.getLocalName(), currentParticle);
if (frag.containsIndex() || frag.getPredicate() != null || helper.isCollectionType(next.getType())) {
currentElement.setMaxOccurs(Occurs.UNBOUNDED);
}
currentElementExists = true;
}
// set the frag's schema as it may be different than the current schema
xpr.schema = fragSchema;
// at this point, if we are dealing with the last fragment we will need to return
if (lastFrag) {
// add a second one...unless we're dealing with an 'any'
if (isAny) {
// set the particle that the 'any' will be added to by the calling method
xpr.particle = globalElement.getComplexType().getTypeDefParticle();
return xpr;
}
// ref case - indicate to the calling method that there's nothing to do
xpr.particle = null;
return xpr;
}
// make the global element current
currentElement = globalElement;
}
}
if (!lastFrag || (lastFrag && isAny)) {
// if we didn't process a global element, and the current element isn't already in the sequence, add it
if (!currentElementExists && globalElement == null) {
currentElement.setName(frag.getLocalName());
Integer minOccurs = next.getMinOccurs();
if (minOccurs != null)
currentElement.setMinOccurs(String.valueOf(minOccurs));
else
currentElement.setMinOccurs(Occurs.ZERO);
currentParticle.addElement(currentElement);
}
// set the correct particle to use/return
if (currentElement.getComplexType() != null) {
if (currentElement.getComplexType().getTypeDefParticle() == null) {
// complexType with simple-content
xpr.simpleContentType = currentElement.getComplexType();
xpr.particle = null;
} else {
xpr.particle = currentElement.getComplexType().getTypeDefParticle();
}
} else {
// If there's no complex type, we're building the path through an element with
// a simple type. In order to build the path through this
// element, switch to a complex type with simple content.
SimpleType type = currentElement.getSimpleType();
if (type != null) {
ComplexType cType = new ComplexType();
cType.setSimpleContent(new SimpleContent());
Extension extension = new Extension();
extension.setBaseType(type.getRestriction().getBaseType());
cType.getSimpleContent().setExtension(extension);
currentElement.setSimpleType(null);
currentElement.setComplexType(cType);
xpr.particle = null;
xpr.simpleContentType = cType;
} else {
String eType = currentElement.getType();
ComplexType cType = new ComplexType();
SimpleContent sContent = new SimpleContent();
Extension extension = new Extension();
extension.setBaseType(eType);
sContent.setExtension(extension);
cType.setSimpleContent(sContent);
currentElement.setType(null);
currentElement.setComplexType(cType);
xpr.particle = null;
xpr.simpleContentType = cType;
}
}
}
// if we're on the last fragment, we're done
if (lastFrag) {
return xpr;
}
// call back into this method to process the next path element
return buildSchemaComponentsForXPath(frag.getNextFragment(), xpr, isChoice, next);
}
use of org.eclipse.persistence.internal.oxm.schema.model.Element in project eclipselink by eclipse-ee4j.
the class SchemaGenerator method addElementRefToSchema.
/**
* Convenience method that adds an element ref to a given schema.
*
* @param schema the schema being built
* @param compositor the sequence/choice/all the new reference will be added to
* @param referencedElement the element being referenced
* @param referencedElementURI the URI of the element being referenced
*/
private void addElementRefToSchema(Schema schema, TypeDefParticle compositor, Element referencedElement, String referencedElementURI) {
Element reference = new Element();
reference.setMinOccurs(referencedElement.getMinOccurs());
reference.setMaxOccurs(referencedElement.getMaxOccurs());
Schema attributeSchema = this.getSchemaForNamespace(referencedElementURI);
if (attributeSchema != null && attributeSchema.getTopLevelElements().get(referencedElement.getName()) == null) {
// reset min/max occurs as they aren't applicable for global elements
referencedElement.setMinOccurs(null);
referencedElement.setMaxOccurs(null);
// don't overwrite global elements; may have been defined by a type
attributeSchema.getTopLevelElements().put(referencedElement.getName(), referencedElement);
}
String prefix = getPrefixForNamespace(schema, referencedElementURI);
if (prefix == null) {
reference.setRef(referencedElement.getName());
} else {
reference.setRef(prefix + COLON + referencedElement.getName());
}
// make sure a ref doesn't already exist before adding this one
if (elementExistsInParticle(reference.getName(), reference.getRef(), compositor) == null) {
compositor.addElement(reference);
}
}
use of org.eclipse.persistence.internal.oxm.schema.model.Element in project eclipselink by eclipse-ee4j.
the class SchemaGenerator method createRefElement.
/**
* Create an element reference and add it to a given particle. This
* method will typically be called when processing an XPath and a
* prefixed path element is encountered that requires an element ref.
*/
public Element createRefElement(String elementRefName, TypeDefParticle particle) {
Element refElement = new Element();
// ref won't have a complex type
refElement.setComplexType(null);
refElement.setMinOccurs(Occurs.ZERO);
refElement.setMaxOccurs(Occurs.ONE);
refElement.setRef(elementRefName);
particle.addElement(refElement);
return refElement;
}
use of org.eclipse.persistence.internal.oxm.schema.model.Element in project eclipselink by eclipse-ee4j.
the class SchemaGenerator method addToSchemaType.
public void addToSchemaType(TypeInfo ownerTypeInfo, java.util.List<Property> properties, TypeDefParticle compositor, ComplexType type, Schema workingSchema) {
// If there are no properties we don't want a sequence/choice or all tag written out
if (properties.size() == 0) {
type.setAll(null);
type.setSequence(null);
type.setChoice(null);
ownerTypeInfo.setCompositor(null);
return;
}
boolean extAnyAdded = false;
// generate schema components for each property
for (Property next : properties) {
if (next == null) {
continue;
}
Schema currentSchema = workingSchema;
TypeDefParticle parentCompositor = compositor;
boolean isChoice = (parentCompositor instanceof Choice);
ComplexType parentType = type;
// ignore transient and inverse reference/non-writeable properties
if (!next.isTransient() && !(next.isInverseReference() && !next.isWriteableInverseReference())) {
// handle xml extensions
if (next.isVirtual()) {
boolean extSchemaAny = false;
if (ownerTypeInfo.getXmlVirtualAccessMethods().getSchema() != null) {
extSchemaAny = ownerTypeInfo.getXmlVirtualAccessMethods().getSchema().equals(XmlVirtualAccessMethodsSchema.ANY);
}
if (extSchemaAny && !next.isAttribute()) {
if (!extAnyAdded) {
addAnyToSchema(next, compositor, true, Constants.ANY_NAMESPACE_ANY);
extAnyAdded = true;
continue;
} else {
// any already added
continue;
}
} else {
// proceed, adding the schema element as usual
}
}
// handle transformers
if (next.isSetXmlTransformation() && next.getXmlTransformation().isSetXmlWriteTransformers()) {
addTransformerToSchema(next, ownerTypeInfo, compositor, type, workingSchema);
continue;
}
// handle XmlJoinNodes
if (next.isSetXmlJoinNodes()) {
addXmlJoinNodesToSchema(next, parentCompositor, currentSchema, parentType);
continue;
}
// deal with xml-path case
if (next.getXmlPath() != null) {
// create schema components based on the XmlPath
AddToSchemaResult xpr = addXPathToSchema(next, parentCompositor, currentSchema, isChoice, type);
// if the returned object or schema component is null there is nothing to do
if (xpr == null || ((parentCompositor = xpr.particle) == null && xpr.simpleContentType == null)) {
continue;
}
// now process the property as per usual, adding to the created schema component
if (xpr.schema == null) {
// no need to generate the attribute in the target schema
continue;
}
currentSchema = xpr.schema;
if (parentCompositor == null) {
parentType = xpr.simpleContentType;
} else if (parentCompositor.getOwner() instanceof ComplexType) {
parentType = ((ComplexType) parentCompositor.getOwner());
}
// deal with the XmlElementWrapper case
} else if (!isChoice && !next.isMap() && next.isSetXmlElementWrapper()) {
AddToSchemaResult asr = addXmlElementWrapperToSchema(next, currentSchema, compositor);
// if returned object is null there is nothing to do
if (asr == null) {
continue;
}
// the returned object contains ComplexType and TypeDefParticles to use
parentType = asr.type;
parentCompositor = asr.particle;
}
// handle mixed content
if (next.isMixedContent()) {
parentType.setMixed(true);
}
// handle attribute
if (next.isAttribute() && !next.isAnyAttribute()) {
addAttributeToSchema(buildAttribute(next, currentSchema), next.getSchemaName(), currentSchema, parentType);
// handle any attribute
} else if (next.isAnyAttribute()) {
addAnyAttributeToSchema(parentType);
// handle choice
} else if (next.isChoice()) {
addChoiceToSchema(next, ownerTypeInfo, parentType, parentCompositor, currentSchema);
// handle reference
} else if (next.isReference()) {
addReferenceToSchema(next, currentSchema, parentCompositor);
// handle any
} else if (next.isAny() || next.getVariableAttributeName() != null) {
addAnyToSchema(next, parentCompositor);
// add an element
} else if (!(ownerTypeInfo.getXmlValueProperty() != null && ownerTypeInfo.getXmlValueProperty() == next)) {
Element element = buildElement(next, parentCompositor instanceof All, currentSchema, ownerTypeInfo);
addElementToSchema(element, next.getSchemaName().getNamespaceURI(), next.isPositional(), parentCompositor, currentSchema, ownerTypeInfo.getJavaClass().getPackageName());
}
}
}
}
use of org.eclipse.persistence.internal.oxm.schema.model.Element in project eclipselink by eclipse-ee4j.
the class SchemaGenerator method addXmlElementWrapperToSchema.
/**
* Convenience method for processing an XmlElementWrapper for a given property. Required schema
* components will be generated and set accordingly.
*
* @param property the property containing an XmlElementWrapper
* @param schema the schema currently being generated
* @param compositor sequence/choice/all that the generated wrapper Element will be added to
* @return AddToSchemaResult containing current ComplexType and TypeDefParticle
*/
private AddToSchemaResult addXmlElementWrapperToSchema(Property property, Schema schema, TypeDefParticle compositor) {
XmlElementWrapper wrapper = property.getXmlElementWrapper();
Element wrapperElement = new Element();
String name = wrapper.getName();
// handle nillable
wrapperElement.setNillable(wrapper.isNillable());
// namespace in not the target or ##default, create a ref with min/max = 1
String wrapperNS = wrapper.getNamespace();
if (!wrapperNS.equals(XMLProcessor.DEFAULT) && !wrapperNS.equals(schema.getTargetNamespace())) {
wrapperElement.setMinOccurs(Occurs.ONE);
wrapperElement.setMaxOccurs(Occurs.ONE);
String prefix = getOrGeneratePrefixForNamespace(wrapperNS, schema);
wrapperElement.setRef(prefix + COLON + name);
compositor.addElement(wrapperElement);
// assume that the element exists and does not need to be created
return null;
}
wrapperElement.setName(name);
if (wrapper.isRequired()) {
wrapperElement.setMinOccurs(Occurs.ONE);
} else {
wrapperElement.setMinOccurs(Occurs.ZERO);
}
if (!wrapperNS.equals(XMLProcessor.DEFAULT)) {
String lookupNamespace = schema.getTargetNamespace();
if (lookupNamespace == null) {
lookupNamespace = EMPTY_STRING;
}
NamespaceInfo namespaceInfo = getNamespaceInfoForNamespace(lookupNamespace);
boolean isElementFormQualified = false;
if (namespaceInfo != null) {
isElementFormQualified = namespaceInfo.isElementFormQualified();
}
shouldAddRefAndSetForm(wrapperElement, wrapperNS, lookupNamespace, isElementFormQualified, true);
}
compositor.addElement(wrapperElement);
ComplexType wrapperType = new ComplexType();
Sequence wrapperSequence = new Sequence();
wrapperType.setSequence(wrapperSequence);
wrapperElement.setComplexType(wrapperType);
return new AddToSchemaResult(wrapperSequence, wrapperType);
}
Aggregations