/******************************************************************************* * 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.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Vector; import org.apache.xerces.impl.xs.XSModelGroupImpl; import org.apache.xerces.impl.xs.XSParticleDecl; import org.apache.xerces.xs.XSModelGroup; import org.apache.xerces.xs.XSObject; import org.eclipse.persistence.oxm.XMLDescriptor; import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping; import org.eclipse.persistence.tools.workbench.utility.iterators.CompositeIterator; 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.iterators.TransformationListIterator; import org.eclipse.persistence.tools.workbench.utility.node.Node; import org.eclipse.persistence.tools.workbench.utility.string.StringTools; public final class ExplicitModelGroup extends AbstractParticle implements MWModelGroup { private volatile String compositor; private List particles; // **************** Static methods **************************************** public static XMLDescriptor buildDescriptor() { XMLDescriptor descriptor = new XMLDescriptor(); descriptor.setJavaClass(ExplicitModelGroup.class); descriptor.getInheritancePolicy().setParentClass(AbstractParticle.class); descriptor.addDirectMapping("compositor", "@compositor"); XMLCompositeCollectionMapping particlesMapping = new XMLCompositeCollectionMapping(); particlesMapping.setAttributeName("particles"); particlesMapping.setReferenceClass(AbstractSchemaComponent.class); particlesMapping.setXPath("particles/particle"); descriptor.addMapping(particlesMapping); return descriptor; } // **************** Constructors ****************************************** /** Toplink use only */ private ExplicitModelGroup() { super(); } ExplicitModelGroup(AbstractSchemaModel parent) { super(parent); } // **************** Initialization **************************************** protected void initialize() { super.initialize(); this.particles = new Vector(); } protected /* private-protected */ void initialize(Node parent) { super.initialize(parent); this.compositor = MWModelGroup.SEQUENCE; } protected void addChildrenTo(List children) { super.addChildrenTo(children); synchronized (this.particles) { children.addAll(this.particles); } } // **************** Internal ************************************************ ListIterator particles() { return this.particles.listIterator(); } // **************** MWModelGroup contract *********************************** public String getCompositor() { return this.compositor; } public boolean containsWildcard() { boolean containsWildcard = false; for (Iterator stream = this.particles(); stream.hasNext() && containsWildcard == false; ) { MWParticle particle = (MWParticle) stream.next(); if (particle instanceof Wildcard) { containsWildcard = true; } else if (particle instanceof MWModelGroup) { containsWildcard |= ((MWModelGroup) particle).containsWildcard(); } } return containsWildcard; } // **************** MWParticle contract *********************************** public void addDirectlyOwnedComponentsTo(Collection directlyOwnedComponents) { for (Iterator stream = this.particles(); stream.hasNext(); ) { MWParticle particle = (MWParticle) stream.next(); if (particle instanceof MWElementDeclaration) { directlyOwnedComponents.add(particle); } else { particle.addDirectlyOwnedComponentsTo(directlyOwnedComponents); } } } public int compareSchemaOrder(MWElementDeclaration element1, MWElementDeclaration element2) { MWParticle particle1 = null, particle2 = null; for (Iterator stream = this.particles(); stream.hasNext(); ) { MWParticle particle = (MWParticle) stream.next(); if (element1.isDescendantOf(particle)) { particle1 = particle; } if (element2.isDescendantOf(particle)) { particle2 = particle; } } if (particle1 == null || particle2 == null) { return 0; } else if (particle1 == particle2) { return particle1.compareSchemaOrder(element1, element2); } else if (this.particles.indexOf(particle1) < this.particles.indexOf(particle2)) { return -1; } else if (this.particles.indexOf(particle1) > this.particles.indexOf(particle2)) { return +1; } else { return 0; } } public boolean isEquivalentTo(XSParticleDecl xsParticle) { return xsParticle.getTerm() instanceof XSModelGroup; } // **************** MWSchemaModel contract ******************************** public Iterator structuralComponents() { return this.particles(); } public Iterator descriptorContextComponents() { return new CompositeIterator(this.descriptorContextComponentIterators()); } private Iterator descriptorContextComponentIterators() { return new TransformationIterator(this.particles()) { protected Object transform(Object next) { MWParticle particle = (MWParticle) next; if (particle.isDescriptorContextComponent()) { return new SingleElementIterator(particle); } else { return particle.descriptorContextComponents(); } } }; } public Iterator xpathComponents() { return new CompositeIterator(this.xpathComponentIterators()); } // NOTE: If anyone is upset by use of "instanceof" here, please give me suggestions - pwf private ListIterator xpathComponentIterators() { return new TransformationListIterator(this.particles()) { protected Object transform(Object next) { MWParticle particle = (MWParticle) next; if (particle instanceof MWElementDeclaration) { return new SingleElementIterator(particle); } else { return ((MWParticle) next).xpathComponents(); } } }; } public MWAttributeDeclaration nestedAttribute(String namespaceUrl, String attributeName) { for (Iterator stream = this.particles(); stream.hasNext(); ) { MWAttributeDeclaration attribute = ((MWParticle) stream.next()).nestedAttribute(namespaceUrl, attributeName); if (attribute != null) { return attribute; } } return null; } // NOTE: If anyone is upset by use of "instanceof" here, please give me suggestions - pwf public MWElementDeclaration nestedElement(String namespaceUrl, String elementName) { for (Iterator stream = this.particles(); stream.hasNext(); ) { MWParticle particle = (MWParticle) stream.next(); MWElementDeclaration element; if (particle instanceof MWElementDeclaration) { element = (MWElementDeclaration) particle; if (elementName.equals(element.getName())) { return element; } } else { element = particle.nestedElement(namespaceUrl, elementName); if (element != null) { return element; } } } return null; } // NOTE: If anyone is upset by use of "instanceof" here, please give me suggestions - pwf public int totalElementCount() { int totalElementCount = 0; for (Iterator stream = this.particles(); stream.hasNext(); ) { MWParticle particle = (MWParticle) stream.next(); if (particle instanceof MWElementDeclaration) { totalElementCount ++; } else { totalElementCount += particle.totalElementCount(); } } return totalElementCount; } // **************** SchemaModel contract ********************************** protected void reloadInternal(XSObject xsObject) { XSModelGroupImpl groupNode = null; if (xsObject instanceof XSParticleDecl) { super.reloadInternal(xsObject); groupNode = (XSModelGroupImpl) ((XSParticleDecl)xsObject).getTerm(); } else { groupNode = (XSModelGroupImpl) xsObject; } this.reloadCompositor(groupNode); this.reloadParticles(groupNode); } private void reloadCompositor(XSModelGroup xsGroup) { if (xsGroup.getCompositor() == XSModelGroup.COMPOSITOR_CHOICE) { this.compositor = MWModelGroup.CHOICE; } else if (xsGroup.getCompositor() == XSModelGroup.COMPOSITOR_SEQUENCE) { this.compositor = MWModelGroup.SEQUENCE; } else /** xsGroup.getCompositor() == XSModelGroup.COMPOSITOR_ALL) */ { this.compositor = MWModelGroup.ALL; } } private void reloadParticles(XSModelGroup xsGroup) { List newParticles = new Vector(); ListIterator oldParticles = this.particles(); while (oldParticles.hasNext()) { MWParticle oldParticle =(MWParticle)oldParticles.next(); if (!containsEquivalentNode(oldParticle, XercesTools.listIteratorFromXSObjectList(xsGroup.getParticles()))) { oldParticles.remove(); this.getProject().nodeRemoved(oldParticle); } } ListIterator particleNodes = XercesTools.listIteratorFromXSObjectList(xsGroup.getParticles()); while (particleNodes.hasNext()) { XSParticleDecl particleNode = (XSParticleDecl)particleNodes.next(); MWParticle oldParticle = containsEquivalentParticle(particleNode, this.particles()); if (oldParticle != null) { oldParticle.reload(particleNode); newParticles.add(oldParticle); } else { MWParticle newParticle = MWParticle.ParticleFactory.newParticle(this, particleNode); newParticles.add(newParticle); } } this.particles = newParticles; } private MWParticle containsEquivalentParticle(XSParticleDecl particleNode, ListIterator particles) { while (particles.hasNext()) { MWParticle particle = (MWParticle)particles.next(); if (particle.isEquivalentTo((XSParticleDecl)particleNode)) { return particle; } } return null; } private boolean containsEquivalentNode(MWParticle particle, Iterator particleNodes) { while (particleNodes.hasNext()) { XSParticleDecl particleNode = (XSParticleDecl)particleNodes.next(); if (particle.isEquivalentTo(particleNode)) { return true; } } return false; } public void resolveReferences() { super.resolveReferences(); for (Iterator stream = this.particles.iterator(); stream.hasNext(); ) { ((MWParticle) stream.next()).resolveReferences(); } } }