/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.tools.workbench.mappingsmodel.schema; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Vector; import javax.xml.XMLConstants; import org.apache.xerces.impl.dv.xs.XSSimpleTypeDecl; import org.apache.xerces.xs.XSObject; import org.apache.xerces.xs.XSSimpleTypeDefinition; import org.apache.xerces.xs.XSTypeDefinition; import org.eclipse.persistence.mappings.converters.ObjectTypeConverter; import org.eclipse.persistence.oxm.XMLDescriptor; import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping; import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping; import org.eclipse.persistence.oxm.mappings.XMLDirectMapping; import org.eclipse.persistence.tools.workbench.mappingsmodel.MWModel; import org.eclipse.persistence.tools.workbench.utility.iterators.CompositeIterator; import org.eclipse.persistence.tools.workbench.utility.iterators.NullIterator; import org.eclipse.persistence.tools.workbench.utility.iterators.SingleElementIterator; import org.eclipse.persistence.tools.workbench.utility.iterators.TransformationIterator; import org.eclipse.persistence.tools.workbench.utility.node.Node; public final class ExplicitSimpleTypeDefinition extends ExplicitSchemaTypeDefinition implements MWSimpleTypeDefinition { // **************** Variables ********************************************* /** The variety of this simple type: one of ATOMIC, LIST, or UNION */ private volatile String variety; /** If this simple type is a restriction of another type, this is that type */ private volatile ReferencedSimpleTypeDefinition baseType; /** If this simple type is a list of items of another type, this is that type */ private volatile MWSimpleTypeDefinition itemType; /** If this simple type is a union of types, these are those types */ private volatile List<MWSimpleTypeDefinition> memberTypes; // **************** Constructors ****************************************** /** Toplink use only */ protected ExplicitSimpleTypeDefinition() { super(); } ExplicitSimpleTypeDefinition(MWModel parent, String name) { super(parent, name); } ExplicitSimpleTypeDefinition(MWModel parent, String name, String namespace) { super(parent, name, namespace); } ExplicitSimpleTypeDefinition(MWModel parent, String name, String namespace, boolean builtIn) { super(parent, name, namespace, builtIn); } // **************** Initialization **************************************** protected void initialize(Node parent) { super.initialize(parent); this.variety = ATOMIC; this.baseType = ReferencedSimpleTypeDefinition.simpleUrType(this); this.memberTypes = new Vector(); } protected void addChildrenTo(List children) { super.addChildrenTo(children); children.add(this.baseType); if (this.itemType != null) { children.add(this.itemType); } children.addAll(this.memberTypes); } // **************** MWSimpleTypeDefinition contract *********************** public String getVariety() { return this.variety; } public boolean isAtomic() { return this.variety == ATOMIC; } public boolean isList() { return this.variety == LIST; } public boolean isUnion() { return this.variety == UNION; } public MWSimpleTypeDefinition getItemType() { return this.itemType; } public ListIterator memberTypes() { return this.memberTypes.listIterator(); } // **************** MWSchemaTypeDefinition contract *********************** public MWSchemaTypeDefinition getBaseType() { return this.baseType; } public boolean isComplex() { return false; } public Iterator baseBuiltInTypes() { if (this.builtIn) { return new SingleElementIterator(this); } else if (this.isList()) { return this.itemType.baseBuiltInTypes(); } else if (this.isUnion()) { return new CompositeIterator(this.memberTypeBaseBuiltInTypes()); } else /* this.isAtomic() */ { return this.baseType.baseBuiltInTypes(); } } private Iterator memberTypeBaseBuiltInTypes() { return new TransformationIterator(this.memberTypes.iterator()) { protected Object transform(Object next) { return ((MWSimpleTypeDefinition) next).baseBuiltInTypes(); } }; } // **************** MWSchemaContextComponent contract ********************* public boolean containsText() { return true; } public boolean containsWildcard() { return false; } public int compareSchemaOrder(MWElementDeclaration element1, MWElementDeclaration element2) { // no elements in a simple type return 0; } // **************** MWNamedSchemaComponent contract *********************** public String componentTypeName() { return "simpleType"; } // **************** MWSchemaComponent contract **************************** /** * Simple types have no structural subcomponents. */ public Iterator structuralComponents() { return NullIterator.instance(); } // **************** SchemaModel contract ********************************** protected void reloadInternal(XSObject xsObject) { super.reloadInternal(xsObject); XSSimpleTypeDecl simpleTypeNode = (XSSimpleTypeDecl) xsObject; this.reloadVariety(simpleTypeNode); if (getNamespaceUrl() != null) { this.builtIn = (getNamespaceUrl().equals(XMLConstants.W3C_XML_SCHEMA_NS_URI) || getNamespaceUrl().equals(XMLConstants.W3C_XPATH_DATATYPE_NS_URI)); } } private void reloadVariety(XSSimpleTypeDecl xsSimpleTypeDecl) { if (xsSimpleTypeDecl.getVariety() == XSSimpleTypeDefinition.VARIETY_LIST) { this.variety = LIST; } else if (xsSimpleTypeDecl.getVariety() == XSSimpleTypeDefinition.VARIETY_UNION) { this.variety = UNION; } else if (xsSimpleTypeDecl.getVariety() == XSSimpleTypeDefinition.VARIETY_ATOMIC) { this.variety = ATOMIC; } else if (xsSimpleTypeDecl.getVariety() == XSSimpleTypeDefinition.VARIETY_ABSENT){ this.variety = ABSENT; } else { throw new IllegalArgumentException(); } this.reloadBaseType(xsSimpleTypeDecl); this.reloadItemType(xsSimpleTypeDecl); this.reloadMemberTypes(xsSimpleTypeDecl); } private void reloadBaseType(XSSimpleTypeDecl xsSimpleTypeDecl) { XSTypeDefinition baseTypeNode = xsSimpleTypeDecl.getBaseType(); if (baseTypeNode != null) { if (this.baseType == null) { this.baseType = new ReferencedSimpleTypeDefinition(this, baseTypeNode.getName(), baseTypeNode.getNamespace()); } this.baseType.reload(baseTypeNode); } else { this.baseType = ReferencedSimpleTypeDefinition.simpleUrType(this); } } private void reloadItemType(XSSimpleTypeDecl xsSimpleTypeDecl) { MWSimpleTypeDefinition oldItemType = this.itemType; XSSimpleTypeDefinition itemTypeNode = xsSimpleTypeDecl.getItemType(); if (this.isList()) { // itemTypeNode will not be null if this is a list this.itemType = MWSimpleTypeDefinition.Reloader.reloadedSimpleType(this, oldItemType, itemTypeNode); } else { this.itemType = null; } if (oldItemType != null && oldItemType != this.itemType) { this.getProject().nodeRemoved(oldItemType); } } private void reloadMemberTypes(XSSimpleTypeDecl xsSimpleTypeDecl) { if (this.isUnion()) { // vector will not be empty if this is a union ListIterator<MWSimpleTypeDefinition> memberTypes = this.memberTypes.listIterator(); ListIterator<XSObject> memberTypeNodes = XercesTools.listIteratorFromXSObjectList(xsSimpleTypeDecl.getMemberTypes()); // refresh member types that have corresponding nodes while (memberTypes.hasNext() && memberTypeNodes.hasNext() ) { MWSimpleTypeDefinition oldMemberType = (MWSimpleTypeDefinition) memberTypes.next(); XSSimpleTypeDefinition memberTypeNode = (XSSimpleTypeDefinition) memberTypeNodes.next(); MWSimpleTypeDefinition newMemberType = MWSimpleTypeDefinition.Reloader.reloadedSimpleType(this, oldMemberType, memberTypeNode); if (oldMemberType != newMemberType) { memberTypes.set(newMemberType); this.getProject().nodeRemoved(oldMemberType); } } // add member types for new nodes while (memberTypeNodes.hasNext()) { XSSimpleTypeDefinition memberTypeNode = (XSSimpleTypeDefinition) memberTypeNodes.next(); MWSimpleTypeDefinition newMemberType = MWSimpleTypeDefinition.Reloader.reloadedSimpleType(this, null, memberTypeNode); memberTypes.add(newMemberType); } // remove member types for those with no corresponding nodes while (memberTypes.hasNext()) { MWSimpleTypeDefinition oldMemberType = (MWSimpleTypeDefinition) memberTypes.next(); memberTypes.remove(); this.getProject().nodeRemoved(oldMemberType); } } else { for (Iterator stream = this.memberTypes.iterator(); stream.hasNext(); ) { MWSimpleTypeDefinition oldMemberType = (MWSimpleTypeDefinition) stream.next(); stream.remove(); this.getProject().nodeRemoved(oldMemberType); } } } public void resolveReferences() { super.resolveReferences(); this.baseType.resolveReferences(); if (this.itemType != null) { this.itemType.resolveReferences(); } for (Iterator stream = this.memberTypes.iterator(); stream.hasNext(); ) { ((MWSimpleTypeDefinition) stream.next()).resolveReferences(); } } // **************** TopLink methods *************************************** public static XMLDescriptor buildDescriptor() { XMLDescriptor descriptor = new XMLDescriptor(); descriptor.setJavaClass(ExplicitSimpleTypeDefinition.class); descriptor.getInheritancePolicy().setParentClass(ExplicitSchemaTypeDefinition.class); XMLDirectMapping varietyMapping = (XMLDirectMapping) descriptor.addDirectMapping("variety", "variety/text()"); ObjectTypeConverter varietyConverter = new ObjectTypeConverter(); // the first one here is to ensure that if the xml value is null, that the object value is ATOMIC // we don't want a "null value", as that will write null out to the XML if the object value is ATOMIC varietyConverter.addConversionValue(null, ATOMIC); varietyConverter.addConversionValue(ATOMIC, ATOMIC); varietyConverter.addConversionValue(LIST, LIST); varietyConverter.addConversionValue(UNION, UNION); varietyMapping.setConverter(varietyConverter); XMLCompositeObjectMapping baseTypeMapping = new XMLCompositeObjectMapping(); baseTypeMapping.setAttributeName("baseType"); baseTypeMapping.setReferenceClass(ReferencedSimpleTypeDefinition.class); baseTypeMapping.setXPath("base-type"); descriptor.addMapping(baseTypeMapping); XMLCompositeObjectMapping itemTypeMapping = new XMLCompositeObjectMapping(); itemTypeMapping.setAttributeName("itemType"); itemTypeMapping.setReferenceClass(ReferencedSimpleTypeDefinition.class); itemTypeMapping.setXPath("item-type"); descriptor.addMapping(itemTypeMapping); XMLCompositeCollectionMapping memberTypesMapping = new XMLCompositeCollectionMapping(); memberTypesMapping.setAttributeName("memberTypes"); memberTypesMapping.setReferenceClass(ReferencedSimpleTypeDefinition.class); memberTypesMapping.setXPath("member-types"); descriptor.addMapping(memberTypesMapping); return descriptor; } }