/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.xml.factory;
import static org.teiid.designer.xml.PluginConstants.PLUGIN_ID;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xsd.XSDComponent;
import org.teiid.core.designer.ModelerCoreException;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.types.DatatypeConstants;
import org.teiid.designer.mapping.factory.DefaultMappableTree;
import org.teiid.designer.mapping.factory.FragmentMappingAdapter;
import org.teiid.designer.metamodels.xml.ProcessingInstruction;
import org.teiid.designer.metamodels.xml.XmlAttribute;
import org.teiid.designer.metamodels.xml.XmlComment;
import org.teiid.designer.metamodels.xml.XmlContainerNode;
import org.teiid.designer.metamodels.xml.XmlDocumentNode;
import org.teiid.designer.metamodels.xml.XmlElement;
import org.teiid.designer.metamodels.xml.XmlFragment;
import org.teiid.designer.metamodels.xml.XmlFragmentUse;
import org.teiid.designer.metamodels.xml.XmlNamespace;
import org.teiid.designer.metamodels.xsd.XsdUtil;
import org.teiid.designer.xml.PluginConstants;
/**
* XmlMappableTree
*
* @since 8.0
*/
public class XmlMappableTree extends DefaultMappableTree implements PluginConstants.PreferenceKeys {
private static EObject stringDatatype;
private FragmentMappingAdapter fragmentAdapter;
/**
* Construct an instance of XmlMappableTree.
*
* @param treeRoot
*/
public XmlMappableTree( EObject treeRoot ) {
super(treeRoot);
fragmentAdapter = new FragmentMappingAdapter(treeRoot);
}
/* (non-Javadoc)
* @See org.teiid.designer.mapping.factory.IMappableTree#getChildren(org.eclipse.emf.ecore.EObject)
*/
@Override
public Collection getChildren( EObject node ) {
Collection children = super.getChildren(node);
ArrayList result = new ArrayList(children.size());
int attributeIndex = 0;
for (Iterator iter = children.iterator(); iter.hasNext();) {
Object child = iter.next();
if (child instanceof XmlFragmentUse) {
EObject childToAdd = (EObject)child;
XmlFragment fragment = (XmlFragment)fragmentAdapter.getFragment(childToAdd);
if (fragment != null) {
EObject root = fragment.getRoot();
if (root != null) {
childToAdd = root;
}
}
result.add(child);
} else if (child instanceof XmlNamespace || child instanceof XmlComment || child instanceof ProcessingInstruction) {
// skip it
} else {
if (child instanceof XmlAttribute) {
// add attributes to the beginning of the list
result.add(attributeIndex++, child);
} else {
result.add(child);
}
}
}
return result;
}
/* (non-Javadoc)
* @See org.teiid.designer.mapping.factory.IMappableTree#getExternalRoots(boolean)
*/
@Override
public List getExternalRoots( boolean recurseFragments ) {
return super.getExternalRoots(recurseFragments);
}
/* (non-Javadoc)
* @See org.teiid.designer.mapping.factory.IMappableTree#getParent(org.eclipse.emf.ecore.EObject)
*/
@Override
public EObject getParent( EObject node ) {
// even if we are inside a fragment, the
return super.getParent(node);
}
/* (non-Javadoc)
* @See org.teiid.designer.mapping.factory.IMappableTree#isExternal(org.eclipse.emf.ecore.EObject)
*/
@Override
public boolean isExternal( EObject node ) {
// if this node's XmlFragment is not the same as super.getTreeRoot, then the node is external.
return !getTreeRoot().equals(getFragmentRoot(node));
}
/**
* Obtain the real XmlFragmentRoot for the specified node
*
* @param node
* @return
*/
public EObject getFragmentRoot( EObject node ) {
XmlFragment result = null;
while (node != null) {
if (node instanceof XmlFragment) {
result = (XmlFragment)node;
break;
}
node = node.eContainer();
}
return result;
}
/* (non-Javadoc)
* @See org.teiid.designer.mapping.factory.IMappableTree#getDatatype(org.eclipse.emf.ecore.EObject)
*/
@Override
public EObject getDatatype( EObject node ) {
boolean useXsdType = true;
IEclipsePreferences prefs = new InstanceScope().getNode(PLUGIN_ID);
if (prefs.get(MAPPING_TYPE_FROM_XSD, null) == null) {
// then use default value if available
IEclipsePreferences defaultPrefs = new DefaultScope().getNode(PLUGIN_ID);
useXsdType = defaultPrefs.getBoolean(MAPPING_TYPE_FROM_XSD, useXsdType);
} else {
useXsdType = prefs.getBoolean(MAPPING_TYPE_FROM_XSD, useXsdType);
}
if (!useXsdType) {
return getStringDatatype();
}
EObject result = null;
// get the schema node
XSDComponent schemaNode = null;
if (node instanceof XmlElement) {
schemaNode = ((XmlElement)node).getXsdComponent();
} else if (node instanceof XmlAttribute) {
schemaNode = ((XmlAttribute)node).getXsdComponent();
}
if (schemaNode != null) {
// get the schema node's type definition
result = XsdUtil.getSimpleType(schemaNode);
}
if (result == null) {
// default type is String
result = getStringDatatype();
}
return result;
}
/**
* Static method to find the String datatype - only need to look it up once.
*
* @return
*/
private static EObject getStringDatatype() {
if (stringDatatype == null) {
try {
stringDatatype = ModelerCore.getWorkspaceDatatypeManager().getBuiltInDatatype(DatatypeConstants.BuiltInNames.STRING);
} catch (ModelerCoreException e) {
PluginConstants.Util.log(e);
}
}
return stringDatatype;
}
/* (non-Javadoc)
* @See org.teiid.designer.mapping.factory.IMappableTree#areEquivalent(org.eclipse.emf.ecore.EObject, org.eclipse.emf.ecore.EObject)
*/
@Override
public boolean areEquivalent( EObject objA,
EObject objB ) {
// if ( objA instanceof XmlDocumentNode && objB instanceof XmlDocumentNode ) {
// return ((XmlDocumentNode) objA).getXsdComponent().equals(((XmlDocumentNode) objB).getXsdComponent());
// }
// return super.areEquivalent(objA, objB);
// per defect 12301, all mappings will be unique
return false;
}
/* (non-Javadoc)
* @See org.teiid.designer.mapping.factory.IMappableTree#getUniqueName(org.eclipse.emf.ecore.EObject)
*/
@Override
public String getUniqueName( EObject node ) {
if (node instanceof XmlDocumentNode) {
String name = ((XmlDocumentNode)node).getName();
EObject parent = node.eContainer();
while (parent != null && parent instanceof XmlContainerNode) {
parent = parent.eContainer();
}
if (parent != null && parent instanceof XmlDocumentNode) {
return name + '_' + ((XmlDocumentNode)parent).getName();
}
}
return super.getUniqueName(node);
}
/**
* @see org.teiid.designer.mapping.factory.IMappableTree#isVisibleNode(org.eclipse.emf.ecore.EObject)
* @since 4.2
*/
public boolean isVisibleNode( EObject node ) { // NO_UCD
// hide all XmlNamespace objects
return !(node instanceof XmlNamespace);
}
}