/******************************************************************************* * 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.descriptor.xml; import java.util.Iterator; import java.util.List; import org.eclipse.persistence.tools.workbench.mappingsmodel.MWDataField; import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWClassIndicatorFieldPolicy; import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWClassIndicatorPolicy; import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWClassIndicatorValue; import org.eclipse.persistence.tools.workbench.mappingsmodel.schema.MWSchemaContextComponent; import org.eclipse.persistence.tools.workbench.mappingsmodel.xml.MWXmlField; import org.eclipse.persistence.tools.workbench.mappingsmodel.xml.MWXmlNode; import org.eclipse.persistence.tools.workbench.mappingsmodel.xml.MWXpathContext; import org.eclipse.persistence.tools.workbench.mappingsmodel.xml.MWXpathSpec; import org.eclipse.persistence.tools.workbench.mappingsmodel.xml.SchemaChange; import org.eclipse.persistence.tools.workbench.utility.iterators.NullIterator; import org.eclipse.persistence.tools.workbench.utility.node.Node; import org.eclipse.persistence.descriptors.InheritancePolicy; import org.eclipse.persistence.oxm.XMLDescriptor; import org.eclipse.persistence.oxm.XMLField; import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping; import org.eclipse.persistence.oxm.mappings.XMLDirectMapping; /** * Class indicator policy that holds an xml field */ public final class MWXmlClassIndicatorFieldPolicy extends MWClassIndicatorFieldPolicy implements MWXpathContext { private MWXmlField xmlField; private volatile boolean useXSIType; public static String USE_XSITYPE_PROPERTY = "useXSIType"; // **************** Constructors ****************************************** /** Toplink use only */ private MWXmlClassIndicatorFieldPolicy() { super(); } protected MWXmlClassIndicatorFieldPolicy(MWClassIndicatorPolicy.Parent parent) { this(parent, NullIterator.instance()); } protected MWXmlClassIndicatorFieldPolicy(MWClassIndicatorPolicy.Parent parent, Iterator descriptorsAvailableForIndication) { super(parent); setDescriptorsAvailableForIndicatorDictionary(descriptorsAvailableForIndication); } // **************** Initialization **************************************** protected void initialize(Node parent) { super.initialize(parent); this.xmlField = new MWXmlField(this); this.useXSIType = false; } protected void addChildrenTo(List children) { super.addChildrenTo(children); children.add(this.xmlField); } // **************** Xml field ********************************************* public MWXmlField getXmlField() { return this.xmlField; } public MWDataField getField() { return this.getXmlField(); } // **************** Use xsi type ****************************************** public boolean isUseXSIType() { return this.useXSIType; } public void setUseXSIType(boolean newValue) { boolean oldValue = this.useXSIType; this.useXSIType = newValue; this.firePropertyChanged(USE_XSITYPE_PROPERTY, oldValue, newValue); if (newValue) { this.setClassNameIsIndicator(false); this.generateIndicatorValueValues(); } } private void generateIndicatorValueValues() { Iterator indicatorValues = classIndicatorValues(); while(indicatorValues.hasNext()) { MWClassIndicatorValue value = (MWClassIndicatorValue)indicatorValues.next(); MWXmlDescriptor descriptor = (MWXmlDescriptor)value.getDescriptorValue(); if (descriptor.getSchemaContext() != null) { String name = descriptor.getSchemaContext().contextTypeQname(); value.setIndicatorValue(name); } } } private void clearIndicatorValuesValues() { Iterator indicatorValues = classIndicatorValues(); while(indicatorValues.hasNext()) { MWClassIndicatorValue value = (MWClassIndicatorValue)indicatorValues.next(); value.setIndicatorValue(null); } } // **************** MWXpathContext implementation ************************* public MWSchemaContextComponent schemaContext(MWXmlField xmlField) { return this.xmlDescriptor().getSchemaContext(); } public MWXpathSpec xpathSpec(MWXmlField xmlField) { return this.buildXpathSpec(); } protected MWXpathSpec buildXpathSpec() { return new MWXpathSpec() { public boolean mayUseCollectionData() { return false; } public boolean mayUseComplexData() { return false; } public boolean mayUseSimpleData() { return true; } }; } // **************** Convenience ******************************************* private MWClassIndicatorFieldPolicy.Parent classIndicatorFieldPolicyParent() { return (MWClassIndicatorFieldPolicy.Parent) this.getParent(); } /** Return the xml descriptor that contains this class indicator field policy */ private MWXmlDescriptor xmlDescriptor() { return (MWXmlDescriptor) this.classIndicatorFieldPolicyParent().getContainingDescriptor(); } // **************** Problem support *************************************** protected void addProblemsTo(List newProblems) { super.addProblemsTo(newProblems); this.checkClassIndicatorField(newProblems); } protected boolean fieldSpecified() { if (!isUseXSIType()) { return getXmlField().isResolved(); } return true; } // **************** Model synchronization ********************************* /** @see MWXmlNode#resolveXpaths() */ public void resolveXpaths() { this.xmlField.resolveXpaths(); } /** @see MWXmlNode.schemaChanged(SchemaChange) */ public void schemaChanged(SchemaChange change) { this.xmlField.schemaChanged(change); } // **************** Runtime conversion ************************************ public void adjustRuntimeInheritancePolicy(InheritancePolicy runtimeInheritancePolicy) { super.adjustRuntimeInheritancePolicy(runtimeInheritancePolicy); if (this.useXSIType) { runtimeInheritancePolicy.setClassIndicatorField(new XMLField("@xsi:type")); } else { runtimeInheritancePolicy.setClassIndicatorFieldName(this.getXmlField().getXpath()); } } // **************** TopLink methods *************************************** public static XMLDescriptor buildDescriptor() { XMLDescriptor descriptor = new XMLDescriptor(); descriptor.setJavaClass(MWXmlClassIndicatorFieldPolicy.class); descriptor.getInheritancePolicy().setParentClass(MWClassIndicatorFieldPolicy.class); XMLDirectMapping useXSITypeMapping = (XMLDirectMapping)descriptor.addDirectMapping("useXSIType", "@use-xsitype"); useXSITypeMapping.setNullValue(Boolean.FALSE); XMLCompositeObjectMapping xmlFieldMapping = new XMLCompositeObjectMapping(); xmlFieldMapping.setReferenceClass(MWXmlField.class); xmlFieldMapping.setAttributeName("xmlField"); xmlFieldMapping.setGetMethodName("getXmlFieldForTopLink"); xmlFieldMapping.setSetMethodName("setXmlFieldForTopLink"); xmlFieldMapping.setXPath("xml-field"); descriptor.addMapping(xmlFieldMapping); return descriptor; } private MWXmlField getXmlFieldForTopLink() { return (this.xmlField.isSpecified()) ? this.xmlField : null; } private void setXmlFieldForTopLink(MWXmlField xmlField) { this.xmlField = ((xmlField == null) ? new MWXmlField(this) : xmlField); } }