/**
* <copyright>
* </copyright>
*
* $Id$
*/
package com.openMap1.mapper.impl;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Iterator;
import java.util.Vector;
import com.openMap1.mapper.util.ClassModelMaker;
import com.openMap1.mapper.util.EclipseFileUtil;
import com.openMap1.mapper.util.FileUtil;
import com.openMap1.mapper.util.ModelUtil;
import com.openMap1.mapper.util.XMLUtil;
import com.openMap1.mapper.util.messageChannel;
import com.openMap1.mapper.converters.AbstractMapperWrapper;
import com.openMap1.mapper.converters.CSV_Wrapper;
import com.openMap1.mapper.core.NamespaceSet;
import com.openMap1.mapper.core.namespace;
import com.openMap1.mapper.util.MapperValidator;
import com.openMap1.mapper.writer.MappedXMLWriter;
import com.openMap1.mapper.writer.XMLWriter;
import com.openMap1.mapper.writer.objectGetter;
import java.util.Collection;
import java.util.Map;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.DiagnosticChain;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.impl.EObjectImpl;
import org.eclipse.emf.ecore.util.EObjectContainmentEList;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.xsd.XSDSchema;
import org.osgi.framework.Bundle;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Attr;
import com.openMap1.mapper.core.ClassSet;
import com.openMap1.mapper.core.MapperException;
import com.openMap1.mapper.core.StructureMismatch;
import com.openMap1.mapper.core.SchemaMismatch;
import com.openMap1.mapper.userConverters.DBConnect;
import com.openMap1.mapper.reader.MDLXOReader;
import com.openMap1.mapper.reader.XOReader;
import com.openMap1.mapper.structures.MapperWrapper;
import com.openMap1.mapper.structures.StructureDefinition;
import com.openMap1.mapper.structures.DBStructure;
import com.openMap1.mapper.structures.V2StructureDef;
import com.openMap1.mapper.structures.XSDStructure;
import com.openMap1.mapper.AttributeDef;
import com.openMap1.mapper.ElementDef;
import com.openMap1.mapper.GlobalMappingParameters;
import com.openMap1.mapper.ImportMappingSet;
import com.openMap1.mapper.MappedStructure;
import com.openMap1.mapper.MapperPackage;
import com.openMap1.mapper.MaxMult;
import com.openMap1.mapper.MinMult;
import com.openMap1.mapper.Namespace;
import com.openMap1.mapper.NodeDef;
import com.openMap1.mapper.ParameterClass;
import com.openMap1.mapper.ParameterClassValue;
import com.openMap1.mapper.StructureType;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>Mapped Structure</b></em>'.
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* <ul>
* <li>{@link com.openMap1.mapper.impl.MappedStructureImpl#getName <em>Name</em>}</li>
* <li>{@link com.openMap1.mapper.impl.MappedStructureImpl#getRootElement <em>Root Element</em>}</li>
* <li>{@link com.openMap1.mapper.impl.MappedStructureImpl#getUMLModelURL <em>UML Model URL</em>}</li>
* <li>{@link com.openMap1.mapper.impl.MappedStructureImpl#getStructureType <em>Structure Type</em>}</li>
* <li>{@link com.openMap1.mapper.impl.MappedStructureImpl#getStructureURL <em>Structure URL</em>}</li>
* <li>{@link com.openMap1.mapper.impl.MappedStructureImpl#getTopElementType <em>Top Element Type</em>}</li>
* <li>{@link com.openMap1.mapper.impl.MappedStructureImpl#getTopElementName <em>Top Element Name</em>}</li>
* <li>{@link com.openMap1.mapper.impl.MappedStructureImpl#getMappingParameters <em>Mapping Parameters</em>}</li>
* <li>{@link com.openMap1.mapper.impl.MappedStructureImpl#getParameterClasses <em>Parameter Classes</em>}</li>
* </ul>
* </p>
*
* @generated
*/
public class MappedStructureImpl extends EObjectImpl implements MappedStructure {
private StructureDefinition structureDefinition = null;
private EPackage classModelRoot = null;
private MapperWrapper wrapper = null;
/**
* The default value of the '{@link #getName() <em>Name</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getName()
* @ordered
*/
protected static final String NAME_EDEFAULT = "";
/**
* The cached value of the '{@link #getName() <em>Name</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getName()
* @generated
* @ordered
*/
protected String name = NAME_EDEFAULT;
/**
* The cached value of the '{@link #getRootElement() <em>Root Element</em>}' containment reference.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getRootElement()
* @generated
* @ordered
*/
protected ElementDef rootElement;
/**
* The default value of the '{@link #getUMLModelURL() <em>UML Model URL</em>}' attribute.
* <!-- begin-user-doc -->
* default UML model URI is not null
* <!-- end-user-doc -->
* @see #getUMLModelURL()
* @ordered
*/
protected static final String UML_MODEL_URL_EDEFAULT = "";
/**
* The cached value of the '{@link #getUMLModelURL() <em>UML Model URL</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getUMLModelURL()
* @generated
* @ordered
*/
protected String uMLModelURL = UML_MODEL_URL_EDEFAULT;
/**
* The default value of the '{@link #getStructureType() <em>Structure Type</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getStructureType()
* @generated
* @ordered
*/
protected static final StructureType STRUCTURE_TYPE_EDEFAULT = StructureType.XSD;
/**
* The cached value of the '{@link #getStructureType() <em>Structure Type</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getStructureType()
* @generated
* @ordered
*/
protected StructureType structureType = STRUCTURE_TYPE_EDEFAULT;
/**
* The default value of the '{@link #getStructureURL() <em>Structure URL</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getStructureURL()
* @generated
* @ordered
*/
protected static final String STRUCTURE_URL_EDEFAULT = null;
/**
* The cached value of the '{@link #getStructureURL() <em>Structure URL</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getStructureURL()
* @generated
* @ordered
*/
protected String structureURL = STRUCTURE_URL_EDEFAULT;
/**
* The default value of the '{@link #getTopElementType() <em>Top Element Type</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getTopElementType()
* @generated
* @ordered
*/
protected static final String TOP_ELEMENT_TYPE_EDEFAULT = null;
/**
* The cached value of the '{@link #getTopElementType() <em>Top Element Type</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getTopElementType()
* @generated
* @ordered
*/
protected String topElementType = TOP_ELEMENT_TYPE_EDEFAULT;
/**
* The default value of the '{@link #getTopElementName() <em>Top Element Name</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getTopElementName()
* @generated
* @ordered
*/
protected static final String TOP_ELEMENT_NAME_EDEFAULT = null;
/**
* The cached value of the '{@link #getTopElementName() <em>Top Element Name</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getTopElementName()
* @generated
* @ordered
*/
protected String topElementName = TOP_ELEMENT_NAME_EDEFAULT;
/**
* The cached value of the '{@link #getMappingParameters() <em>Mapping Parameters</em>}' containment reference.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getMappingParameters()
* @generated
* @ordered
*/
protected GlobalMappingParameters mappingParameters;
/**
* The cached value of the '{@link #getParameterClasses() <em>Parameter Classes</em>}' containment reference list.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getParameterClasses()
* @generated
* @ordered
*/
protected EList<ParameterClass> parameterClasses;
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected MappedStructureImpl() {
super();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass() {
return MapperPackage.Literals.MAPPED_STRUCTURE;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public String getName() {
return name;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setName(String newName) {
String oldName = name;
name = newName;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MapperPackage.MAPPED_STRUCTURE__NAME, oldName, name));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public ElementDef getRootElement() {
return rootElement;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public NotificationChain basicSetRootElement(ElementDef newRootElement, NotificationChain msgs) {
ElementDef oldRootElement = rootElement;
rootElement = newRootElement;
if (eNotificationRequired()) {
ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, MapperPackage.MAPPED_STRUCTURE__ROOT_ELEMENT, oldRootElement, newRootElement);
if (msgs == null) msgs = notification; else msgs.add(notification);
}
return msgs;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setRootElement(ElementDef newRootElement) {
if (newRootElement != rootElement) {
NotificationChain msgs = null;
if (rootElement != null)
msgs = ((InternalEObject)rootElement).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - MapperPackage.MAPPED_STRUCTURE__ROOT_ELEMENT, null, msgs);
if (newRootElement != null)
msgs = ((InternalEObject)newRootElement).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - MapperPackage.MAPPED_STRUCTURE__ROOT_ELEMENT, null, msgs);
msgs = basicSetRootElement(newRootElement, msgs);
if (msgs != null) msgs.dispatch();
}
else if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MapperPackage.MAPPED_STRUCTURE__ROOT_ELEMENT, newRootElement, newRootElement));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public String getUMLModelURL() {
return uMLModelURL;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setUMLModelURL(String newUMLModelURL) {
String oldUMLModelURL = uMLModelURL;
uMLModelURL = newUMLModelURL;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MapperPackage.MAPPED_STRUCTURE__UML_MODEL_URL, oldUMLModelURL, uMLModelURL));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public StructureType getStructureType() {
return structureType;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setStructureType(StructureType newStructureType) {
StructureType oldStructureType = structureType;
structureType = newStructureType == null ? STRUCTURE_TYPE_EDEFAULT : newStructureType;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MapperPackage.MAPPED_STRUCTURE__STRUCTURE_TYPE, oldStructureType, structureType));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public String getStructureURL() {
return structureURL;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setStructureURL(String newStructureURL) {
String oldStructureURL = structureURL;
structureURL = newStructureURL;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MapperPackage.MAPPED_STRUCTURE__STRUCTURE_URL, oldStructureURL, structureURL));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public String getTopElementType() {
return topElementType;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setTopElementType(String newTopElementType) {
String oldTopElementType = topElementType;
topElementType = newTopElementType;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MapperPackage.MAPPED_STRUCTURE__TOP_ELEMENT_TYPE, oldTopElementType, topElementType));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public String getTopElementName() {
return topElementName;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setTopElementName(String newTopElementName) {
String oldTopElementName = topElementName;
topElementName = newTopElementName;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MapperPackage.MAPPED_STRUCTURE__TOP_ELEMENT_NAME, oldTopElementName, topElementName));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public GlobalMappingParameters getMappingParameters() {
return mappingParameters;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public NotificationChain basicSetMappingParameters(GlobalMappingParameters newMappingParameters, NotificationChain msgs) {
GlobalMappingParameters oldMappingParameters = mappingParameters;
mappingParameters = newMappingParameters;
if (eNotificationRequired()) {
ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, MapperPackage.MAPPED_STRUCTURE__MAPPING_PARAMETERS, oldMappingParameters, newMappingParameters);
if (msgs == null) msgs = notification; else msgs.add(notification);
}
return msgs;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setMappingParameters(GlobalMappingParameters newMappingParameters) {
if (newMappingParameters != mappingParameters) {
NotificationChain msgs = null;
if (mappingParameters != null)
msgs = ((InternalEObject)mappingParameters).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - MapperPackage.MAPPED_STRUCTURE__MAPPING_PARAMETERS, null, msgs);
if (newMappingParameters != null)
msgs = ((InternalEObject)newMappingParameters).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - MapperPackage.MAPPED_STRUCTURE__MAPPING_PARAMETERS, null, msgs);
msgs = basicSetMappingParameters(newMappingParameters, msgs);
if (msgs != null) msgs.dispatch();
}
else if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MapperPackage.MAPPED_STRUCTURE__MAPPING_PARAMETERS, newMappingParameters, newMappingParameters));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public EList<ParameterClass> getParameterClasses() {
if (parameterClasses == null) {
parameterClasses = new EObjectContainmentEList<ParameterClass>(ParameterClass.class, this, MapperPackage.MAPPED_STRUCTURE__PARAMETER_CLASSES);
}
return parameterClasses;
}
/**
* <!-- begin-user-doc -->
* check that the class mode lcan be found
* <!-- end-user-doc -->
*/
public boolean canFindClassModel(DiagnosticChain diagnostics, Map<?,?> context) {
classModelRoot = null; // in case it has been cached, and the file location changed.
boolean canfindModel = false;
try {canfindModel = (getClassModelRoot() != null);}
catch (MapperException ex) {}
if (!canfindModel) {
if (diagnostics != null) {
diagnostics.add
(new BasicDiagnostic
(Diagnostic.ERROR,
MapperValidator.DIAGNOSTIC_SOURCE,
MapperValidator.MAPPED_STRUCTURE__CAN_FIND_CLASS_MODEL,
("Cannot find class model at " + getUMLModelURL()),
new Object [] { this }));
}
return false;
}
return true;
}
/**
* <!-- begin-user-doc -->
* If the mapped structure is an XSD,
* check that the structure definition can be found
* <!-- end-user-doc -->
*/
public boolean canFindStructureDefinition(DiagnosticChain diagnostics, Map<?,?> context) {
structureDefinition = null; // in case it has been cached, and the file location changed
boolean canFindStructure = true;
// EMF may throw a ResourceException if it can't find the resource
try {canFindStructure = (getStructureDefinition() != null);}
catch (Exception ex) {canFindStructure = false;}
if (!canFindStructure) {
if (diagnostics != null) {
diagnostics.add
(new BasicDiagnostic
(Diagnostic.ERROR,
MapperValidator.DIAGNOSTIC_SOURCE,
MapperValidator.MAPPED_STRUCTURE__CAN_FIND_STRUCTURE_DEFINITION,
("Cannot find structure definition at " + getStructureURL()),
new Object [] { this }));
}
return false;
}
return true;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
switch (featureID) {
case MapperPackage.MAPPED_STRUCTURE__ROOT_ELEMENT:
return basicSetRootElement(null, msgs);
case MapperPackage.MAPPED_STRUCTURE__MAPPING_PARAMETERS:
return basicSetMappingParameters(null, msgs);
case MapperPackage.MAPPED_STRUCTURE__PARAMETER_CLASSES:
return ((InternalEList<?>)getParameterClasses()).basicRemove(otherEnd, msgs);
}
return super.eInverseRemove(otherEnd, featureID, msgs);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case MapperPackage.MAPPED_STRUCTURE__NAME:
return getName();
case MapperPackage.MAPPED_STRUCTURE__ROOT_ELEMENT:
return getRootElement();
case MapperPackage.MAPPED_STRUCTURE__UML_MODEL_URL:
return getUMLModelURL();
case MapperPackage.MAPPED_STRUCTURE__STRUCTURE_TYPE:
return getStructureType();
case MapperPackage.MAPPED_STRUCTURE__STRUCTURE_URL:
return getStructureURL();
case MapperPackage.MAPPED_STRUCTURE__TOP_ELEMENT_TYPE:
return getTopElementType();
case MapperPackage.MAPPED_STRUCTURE__TOP_ELEMENT_NAME:
return getTopElementName();
case MapperPackage.MAPPED_STRUCTURE__MAPPING_PARAMETERS:
return getMappingParameters();
case MapperPackage.MAPPED_STRUCTURE__PARAMETER_CLASSES:
return getParameterClasses();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@SuppressWarnings("unchecked")
@Override
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case MapperPackage.MAPPED_STRUCTURE__NAME:
setName((String)newValue);
return;
case MapperPackage.MAPPED_STRUCTURE__ROOT_ELEMENT:
setRootElement((ElementDef)newValue);
return;
case MapperPackage.MAPPED_STRUCTURE__UML_MODEL_URL:
setUMLModelURL((String)newValue);
return;
case MapperPackage.MAPPED_STRUCTURE__STRUCTURE_TYPE:
setStructureType((StructureType)newValue);
return;
case MapperPackage.MAPPED_STRUCTURE__STRUCTURE_URL:
setStructureURL((String)newValue);
return;
case MapperPackage.MAPPED_STRUCTURE__TOP_ELEMENT_TYPE:
setTopElementType((String)newValue);
return;
case MapperPackage.MAPPED_STRUCTURE__TOP_ELEMENT_NAME:
setTopElementName((String)newValue);
return;
case MapperPackage.MAPPED_STRUCTURE__MAPPING_PARAMETERS:
setMappingParameters((GlobalMappingParameters)newValue);
return;
case MapperPackage.MAPPED_STRUCTURE__PARAMETER_CLASSES:
getParameterClasses().clear();
getParameterClasses().addAll((Collection<? extends ParameterClass>)newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eUnset(int featureID) {
switch (featureID) {
case MapperPackage.MAPPED_STRUCTURE__NAME:
setName(NAME_EDEFAULT);
return;
case MapperPackage.MAPPED_STRUCTURE__ROOT_ELEMENT:
setRootElement((ElementDef)null);
return;
case MapperPackage.MAPPED_STRUCTURE__UML_MODEL_URL:
setUMLModelURL(UML_MODEL_URL_EDEFAULT);
return;
case MapperPackage.MAPPED_STRUCTURE__STRUCTURE_TYPE:
setStructureType(STRUCTURE_TYPE_EDEFAULT);
return;
case MapperPackage.MAPPED_STRUCTURE__STRUCTURE_URL:
setStructureURL(STRUCTURE_URL_EDEFAULT);
return;
case MapperPackage.MAPPED_STRUCTURE__TOP_ELEMENT_TYPE:
setTopElementType(TOP_ELEMENT_TYPE_EDEFAULT);
return;
case MapperPackage.MAPPED_STRUCTURE__TOP_ELEMENT_NAME:
setTopElementName(TOP_ELEMENT_NAME_EDEFAULT);
return;
case MapperPackage.MAPPED_STRUCTURE__MAPPING_PARAMETERS:
setMappingParameters((GlobalMappingParameters)null);
return;
case MapperPackage.MAPPED_STRUCTURE__PARAMETER_CLASSES:
getParameterClasses().clear();
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public boolean eIsSet(int featureID) {
switch (featureID) {
case MapperPackage.MAPPED_STRUCTURE__NAME:
return NAME_EDEFAULT == null ? name != null : !NAME_EDEFAULT.equals(name);
case MapperPackage.MAPPED_STRUCTURE__ROOT_ELEMENT:
return rootElement != null;
case MapperPackage.MAPPED_STRUCTURE__UML_MODEL_URL:
return UML_MODEL_URL_EDEFAULT == null ? uMLModelURL != null : !UML_MODEL_URL_EDEFAULT.equals(uMLModelURL);
case MapperPackage.MAPPED_STRUCTURE__STRUCTURE_TYPE:
return structureType != STRUCTURE_TYPE_EDEFAULT;
case MapperPackage.MAPPED_STRUCTURE__STRUCTURE_URL:
return STRUCTURE_URL_EDEFAULT == null ? structureURL != null : !STRUCTURE_URL_EDEFAULT.equals(structureURL);
case MapperPackage.MAPPED_STRUCTURE__TOP_ELEMENT_TYPE:
return TOP_ELEMENT_TYPE_EDEFAULT == null ? topElementType != null : !TOP_ELEMENT_TYPE_EDEFAULT.equals(topElementType);
case MapperPackage.MAPPED_STRUCTURE__TOP_ELEMENT_NAME:
return TOP_ELEMENT_NAME_EDEFAULT == null ? topElementName != null : !TOP_ELEMENT_NAME_EDEFAULT.equals(topElementName);
case MapperPackage.MAPPED_STRUCTURE__MAPPING_PARAMETERS:
return mappingParameters != null;
case MapperPackage.MAPPED_STRUCTURE__PARAMETER_CLASSES:
return parameterClasses != null && !parameterClasses.isEmpty();
}
return super.eIsSet(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public String toString() {
if (eIsProxy()) return super.toString();
StringBuffer result = new StringBuffer(super.toString());
result.append(" (name: ");
result.append(name);
result.append(", uMLModelURL: ");
result.append(uMLModelURL);
result.append(", structureType: ");
result.append(structureType);
result.append(", structureURL: ");
result.append(structureURL);
result.append(", topElementType: ");
result.append(topElementType);
result.append(", topElementName: ");
result.append(topElementName);
result.append(')');
return result.toString();
}
/**
* Set a structure definition, and add its namespaces to the mapping parameters
*/
public void setStructureDefinition(StructureDefinition structureDefinition)
{
this.structureDefinition = structureDefinition;
getMappingParameters().addNamespaces(structureDefinition);
}
/**
* Get a Structure Definition, cache it and return it - or return null if none can be found
*/
public StructureDefinition getStructureDefinition() throws MapperException
{
if (structureDefinition == null) try
{
// XML schema or csv structure definition
if (getStructureType()== StructureType.XSD)
{
String uriString = getStructureURL();
if ((uriString != null) && !(uriString.equals("")))
{
if (uriString.endsWith("xsd"))
{
URI uri = URI.createURI(uriString);
XSDSchema theSchema = XSDStructure.getXSDRoot(uri);
if (theSchema != null)
{
structureDefinition = new XSDStructure(theSchema);
}
}
else if (uriString.endsWith("csv"))
{
Object input = null;
try
{
input = new FileInputStream(new File(uriString));
}
catch (Exception ex)
{throw new MapperException("Cannot open csv file at '" + uriString + "'");}
CSV_Wrapper csvStructure = new CSV_Wrapper(this,null);
csvStructure.getStructure(input);
structureDefinition = csvStructure;
}
}
}
// V2 structure definition
if (getStructureType()== StructureType.V2)
{
String uriString = getStructureURL();
if ((uriString != null) && !(uriString.equals("")))
{
URI uri = URI.createURI(uriString);
Element mwbRoot = XMLUtil.getRootElement(uri);
structureDefinition = new V2StructureDef(mwbRoot);
}
}
// RDBMS structure definition; cannot get structure definition, as there is no user name and password
else if (getStructureType() == StructureType.RDBMS)
{
}
}
catch (Exception ex)
{
System.out.println(ex.getMessage());
structureDefinition = null;
throw new MapperException("Cannot find structure definition: " + ex.getMessage());
}
return structureDefinition;
}
/**
* connect to a relational database and return its structure definition
* @param userName
* @param password
* @return
* @throws MapperException
*/
public StructureDefinition connectToRDB(String userName, String password) throws MapperException
{
if (getStructureType() == StructureType.RDBMS) try
{
String jdbcConnectString = getStructureURL();
if ((jdbcConnectString != null) && !(jdbcConnectString.equals("")))
{
DBConnect dbConnect = new DBConnect(jdbcConnectString,userName,password,null);
dbConnect.connect();
structureDefinition = new DBStructure(dbConnect.con());
}
}
catch (Exception ex)
{
ex.printStackTrace();
throw new MapperException("Cannot connect to Relational database: " + ex.getMessage());
}
return structureDefinition;
}
/**
* Set the class model root
*/
public void setClassModelRoot(EPackage classModelRoot)
{this.classModelRoot = classModelRoot;}
/**
* Get the class model root - from the resource if necessary
*/
public EPackage getClassModelRoot() throws MapperException
{
// if the root has not yet been got (e.g. when the editor was opened) get it
if (classModelRoot == null)
{
if ((getUMLModelURL() != null) && !(getUMLModelURL().equals("")))
{
try {
URI classModelURI = URI.createURI(getUMLModelURL());
/* if not running in Eclipse, assume that the Eclipse project folder
* structure defines the relative location of the class model and the mapped structure */
if (!FileUtil.isInEclipse())
{
String mappingLocation = eResource().getURI().toString();
String classModelLocation = FileUtil.ecoreFileLocation(mappingLocation, getUMLModelURL());
classModelURI = URI.createURI("file:/" + classModelLocation);
}
EObject umlRoot = ClassModelMaker.makeClassModelFromFile(classModelURI);
if (umlRoot instanceof EPackage) setClassModelRoot((EPackage)umlRoot);
}
catch (Exception ex)
{
ex.printStackTrace();
throw new MapperException("Exception getting class model root: " + ex.getMessage());
} // class model root remains null, so caught below
}
}
return classModelRoot;
}
/**
* @return name of the file containing the class model
*/
public String getClassModelFileName()
{
String res = "'undefined'";
if (getUMLModelURL() != null)
{
StringTokenizer st = new StringTokenizer(getUMLModelURL(),"/\\");
while (st.hasMoreTokens()) res = st.nextToken();
}
return res;
}
/**
* @return name of the file containing the structure to be mapped
*/
public String getStructureFileName()
{
String res = "'undefined'";
if (getStructureURL() != null)
{
StringTokenizer st = new StringTokenizer(getStructureURL(),"/\\");
while (st.hasMoreTokens()) res = st.nextToken();
}
return res;
}
/**
* @param path String form of a descending path, starting with "/"
* @return the Element or Attribute reached by that path; or null if there is none.
*/
public NodeDef getNodeDefByPath(String path)
{
if (path == null) return null;
if (!path.startsWith("/")) return null;
StringTokenizer st = new StringTokenizer(path,"/");
String first = st.nextToken();
ElementDef root = getRootElement();
if (root.getName().equals(first))
{
if (path.length() == first.length() + 1) return root;
else return root.getDescendantByPath(path.substring(first.length() + 1));
}
else return null;
}
//---------------------------------------------------------------------------------------------
// validating XML Instances against the mapped structure
//---------------------------------------------------------------------------------------------
/**
* check that the XML instance with this root conforms to the
* mapped structure; return a list of mismatches
* @param rootEl root element of the document being checked
* @return Vector of all structure mismatches detected (duplicates not removed)
* @throws MapperException eg if the document associates a namespace URI with more than one prefix,
* (XML allows this but I don't yet; I could do) or mentions a namespace URI not known in the mapping set
*/
public Vector<StructureMismatch> checkInstance(Element rootEl) throws MapperException
{
Vector<StructureMismatch> mismatches = new Vector<StructureMismatch>();
/* If there is a java mapping class, then that should make some checks (not yet implemented)
* but meanwhile, normal checks of the instance, such as two namespaces with the same prefix, are not appropriate */
if ((mappingParameters != null)
&& (mappingParameters.getMappingClass() != null)
&& (!mappingParameters.getMappingClass().equals("")))
{
/* FIXME - make the java mapping class interface support some checks. */
}
else
{
NamespaceSet instanceNSSet = XMLUtil.getNameSpaceSet(rootEl);
checkInstance(rootEl,true,"",instanceNSSet,mismatches);
}
return mismatches;
}
/**
* check that the XML instance with this root conforms to the
* mapped structure; build a list of mismatches where it does not
* @param rootEl
* @param isRoot true if this mapping set applies from the root of the document
* @param path if isRoot is true, ignored. If isRoot is false, the path from the root
* of the document, with no final '/'
* @param mismatches Vector of StructureMismatch objects, to be built up.
* @throws MapperException eg if the document associates a namespace URI with more than one prefix,
* (XML allows this but I don't yet; I could do) or mentions a namespace URI not known in the mapping set
*/
public void checkInstance(Element rootEl, boolean isRoot, String path, NamespaceSet instanceNSSet,
Vector<StructureMismatch> mismatches)
throws MapperException
{
// if the mapping set uses a Java class, do not try to match the structure
if ((getMappingParameters() != null) &&
!(getMappingParameters().getMappingClass().equals(""))) return;
// only check the element name at the top of the mapping set if it is not an imported mapping set
String prefixConvertedName = convertToMappedStructurePrefix(rootEl.getNodeName(),instanceNSSet,false);
if ((isRoot) && (!(prefixConvertedName.equals(getRootElement().getName()))))
mismatches.add(new StructureMismatch(path,StructureMismatch.STRUCTURE_UNEXPECTED_NAME,
getRootElement().getName(),rootEl.getNodeName()));
String thePath = path;
if (isRoot) thePath = "/" + getRootElement().getName();
checkElementMatch(rootEl,getRootElement(),thePath,instanceNSSet, mismatches);
}
/**
* recursive descent of elements in an XML instance, checking that they match the mapped
* structure
* @param el Element in the instance
* @param edd corresponding ElementDef in the mapped structure; its name has already been checked
* @param path string form of XPath from the root of the document
* @param instanceNSSet namespaces, with prefixes as in the instance
* @param mismatches Vector of all structural mismatches, being built up
* @throws MapperException if the instance mentions a namespace with URI not found in the mapping set
*/
private void checkElementMatch(Element el, ElementDef edd, String path, NamespaceSet instanceNSSet,
Vector<StructureMismatch> mismatches)
throws MapperException
{
// For checking multiplicity. key = prefixed name, as in the mapped structure; value = 'one', 'many'
Hashtable<String,String> elementOccs = new Hashtable<String,String>();
Hashtable<String,String> attributeOccs = new Hashtable<String,String>();
if (!edd.isExpanded())
{
// if the Element imports a mapping set, check the structure against that
if (edd.getImportMappingSet() != null)
{
MappedStructure ms = edd.getImportMappingSet().getImportedMappingSet();
if (ms != null ) ms.checkInstance(el, false, path,instanceNSSet, mismatches);
else mismatches.add(new StructureMismatch(path,StructureMismatch.STRUCTURE_MISSING_IMPORTED_MAPPING_SET,
edd.getImportMappingSet().getMappingSetURI(),""));
}
/* if the Element definition has not been expanded,
* and does not import a mapping set, it cannot be checked;do nothing */
}
// make all checks on this Element before any recursive descent
else if (edd.isExpanded())
{
// check for Elements not in the structure
for (int i = 0; i < el.getChildNodes().getLength(); i++)
{
Node nd = el.getChildNodes().item(i);
// convert namespace prefixes to those used in the mapping set
String name = convertToMappedStructurePrefix(nd.getNodeName(),instanceNSSet,false);
if (nd instanceof Element)
{
// check there is a child of this name in the structure
if (edd.getNamedChildElement(name) == null)
mismatches.add(new StructureMismatch(path,StructureMismatch.STRUCTURE_UNEXPECTED_NAME,"",name));
// if there is such a child, record that the instance has one or many
else if (elementOccs.get(name) == null) elementOccs.put(name,"one");
else if (elementOccs.get(name).equals("one")) elementOccs.put(name,"many");
}
}
// check for attributes not in the structure; allow namespace attributes
for (int i = 0; i < el.getAttributes().getLength();i++)
{
Node nd = el.getAttributes().item(i);
boolean isNamespaceAttribute = ((nd.getNodeName().equals("xmlns"))|(nd.getNodeName().startsWith("xmlns:")));
if ((nd instanceof Attr) && !(isNamespaceAttribute))
{
String name = convertToMappedStructurePrefix(nd.getNodeName(),instanceNSSet,true);
// check there is an attribute of this name in the structure
if (edd.getNamedAttribute(name) == null)
mismatches.add(new StructureMismatch(path,StructureMismatch.STRUCTURE_UNEXPECTED_NAME,"",name));
// if there is such an attribute, record that the instance has it
else attributeOccs.put(name,"one");
}
}
// check multiplicities of child elements
for (Iterator<ElementDef> it = edd.getChildElements().iterator(); it.hasNext();)
{
ElementDef cd = it.next();
String name = cd.getName();
String occs = elementOccs.get(name);
if ((cd.getMinMultiplicity() == MinMult.ONE) && (occs == null))
mismatches.add(new StructureMismatch(path,StructureMismatch.STRUCTURE_MISSING,name,""));
if ((cd.getMaxMultiplicity() == MaxMult.ONE) && (occs != null) && (occs.equals("many")))
mismatches.add(new StructureMismatch(path,StructureMismatch.STRUCTURE_REPEATED,name,""));
}
/* check existence of required attributes.
* In structure definitions, 'xsi:type' is given min multiplicity 1 so that
* mappings can depend on it and generation will work; but since it does not
* a required attribute, there should be no warning when it is missing. */
for (Iterator<AttributeDef> it = edd.getAttributeDefs().iterator(); it.hasNext();)
{
AttributeDef ad = it.next();
if ((ad.getMinMultiplicity() == MinMult.ONE)
&& (attributeOccs.get(ad.getName())== null)
&& (!(ad.getName().equals("xsi:type"))))
mismatches.add(new StructureMismatch(path,StructureMismatch.STRUCTURE_MISSING,ad.getName(),""));
}
// recursive descent of the instance tree
for (int i = 0; i < el.getChildNodes().getLength(); i++)
{
Node nd = el.getChildNodes().item(i);
String name = nd.getNodeName();
String newPath = path + "/" + name;
if ((nd instanceof Element) && (edd.getNamedChildElement(name) != null))
checkElementMatch((Element)nd,edd.getNamedChildElement(name),newPath,instanceNSSet,mismatches);
}
}
}
/** if an element or attribute name in an XML instance has a prefix,
* convert the prefix to that used in the mapping set
* @param name the name, with prefix as in the instance
* @param instanceNSSet the namespace URIs and prefixes used in the instance
* @param isAttribute true if this is an attribute name
* @return the name with prefix as in the mapping set
* @throws MapperException if a namespace URI in the instance cannot be matched in hte mapping set
*/
private String convertToMappedStructurePrefix(String name, NamespaceSet instanceNSSet, boolean isAttribute) throws MapperException
{
String convName = name;
StringTokenizer st = new StringTokenizer(name,":");
// if there is no prefix
if (st.countTokens() == 1)
{
// a namespace with no prefix may not exist; if so, do nothing
namespace noPrefix = instanceNSSet.getByPrefix("");
// if an attribute name has no prefix, it is in no namespace; so do not try to convert it
if ((noPrefix != null) && !isAttribute)
{
String prefix = getMappingSetPrefix(noPrefix.URI());
if (prefix == null) throw new MapperException("Cannot find namespace with URI '"
+ noPrefix.URI() + "' in mapping set " + getMappingSetName());
convName = addPrefix(prefix,st.nextToken());
}
}
else if (st.countTokens() == 2)
{
namespace withPrefix = instanceNSSet.getByPrefix(st.nextToken());
if (withPrefix != null)
{
String prefix = getMappingSetPrefix(withPrefix.URI());
if (prefix == null) throw new MapperException("Cannot find namespace with URI '"
+ withPrefix.URI() + "'");
convName = addPrefix(prefix,st.nextToken());
}
}
return convName;
}
/**
* @param uri the uri of namespace
* @return the prefix used for this URI in the mapping set; or null if the URI is not found
*/
private String getMappingSetPrefix(String uri)
{
String prefix = null;
if (getMappingParameters() != null)
for (Iterator<Namespace> it = getMappingParameters().getNameSpaces().iterator();it.hasNext();)
{
Namespace ns = it.next();
if (ns.getURL().equals(uri)) prefix = ns.getPrefix();
}
return prefix;
}
/**
* add a prefix to a local element or attribute name
* @param prefix; must not be null. "" if there is no prefix.
* @param localName
* @return the prefixed name
*/
private String addPrefix(String prefix, String localName)
{
if (prefix.equals("")) return localName;
return (prefix + ":" + localName);
}
//---------------------------------------------------------------------------------------------
// validating XML Instances against an XML schema
//---------------------------------------------------------------------------------------------
/**
* validate an XML instance against the schema which defines this mapped structure,
* if there is such a schema. If there is no schema, return an empty list.
* (Not yet tested outside Eclipse)
* @param the root element of the XML instance
* @return a Vector of SchemaMismatch objects, which wrap org.eclipse.emf.ecore.util.Diagnostic
*/
public Vector<SchemaMismatch> schemaValidate(Element instanceRoot) throws MapperException
{
Vector<SchemaMismatch> mismatches = new Vector<SchemaMismatch>();
// if there is no XML schema, return an empty list
if ((getStructureType() == StructureType.XSD) && (getStructureURL() != null) && (!getStructureURL().equals("")))
{
URI schemaURI = URI.createURI(getStructureURL());
mismatches = XMLUtil.schemaValidate(instanceRoot, schemaURI);
}
return mismatches;
}
//---------------------------------------------------------------------------------------------
// the class model view
//---------------------------------------------------------------------------------------------
private boolean classModelViewIsRefreshed = false;
/**
* @return true if the set of mappings visible to the class model view had been refreshed since
* this mapping set was opened with an editor, or since a mapping was added or removed
*/
public boolean classModelViewIsRefreshed() {return classModelViewIsRefreshed;}
/**
* set the variable which defines the result of classModelViewIsRefreshed;
* It is false when this mapping set is created, and should be set false when
* any mappings are edited.
* set it true when the class model view is refreshed
* @param fresh
*/
public void setClassModelViewIsRrefreshed(boolean fresh)
{classModelViewIsRefreshed = fresh;}
//--------------------------------------------------------------------------------------
// mappings to database structures
//---------------------------------------------------------------------------------------
/**
* set a database Structure
*/
public void setDBStructure(DBStructure dbStructure)
{
setTopElementName("database");
setRootElement(dbStructure.getDatabaseStructure());
}
//--------------------------------------------------------------------------------------
// for translation
//---------------------------------------------------------------------------------------
/**
* If true, the XML writing procedures which were last created
* are still current and are in the location writeProceduresURI() -
* so they do not need to be re-created before running a trnalsation or generating
* XSLT
* @return true if the mapping set has not been edited since the write procedures were created
*/
public boolean hasCurrentWriteProcedures() {return false;}
/**
* @return the URI of the XML writing pporcedures, if they exist - or "" if they do not
*/
public String writeProceduresURI() {return("");}
/**
* @return all the mapping sets imported by any Element in this mapping set.
* key = URI string of the mapping set
* value = the mapping set
*/
public Hashtable<String,MappedStructure> getDirectImportedMappingSets()
{
Hashtable<String,MappedStructure> impSets = new Hashtable<String,MappedStructure>();
for (Iterator<EObject> it = ModelUtil.getEObjectsUnder(this,
MapperPackage.Literals.IMPORT_MAPPING_SET).iterator();it.hasNext();)
{
ImportMappingSet ims = (ImportMappingSet)it.next();
String path = ims.getMappingSetURI().toString();
if (impSets.get(path) == null)
{
MappedStructure ms = ims.getImportedMappingSet();
if (ms != null) impSets.put(path, ms);
else System.out.println("Found no imported mapping set at "+ path);
}
}
return impSets;
}
private Hashtable<String,MappedStructure> impMSByCSet = new Hashtable<String,MappedStructure>();
private Hashtable<String,ImportMappingSet> impMSObjectByCSet = null;
/**
* @param cSet a (class, subset)
* @return if there is an imported mapping set for the (class,subset) return it;
* otherwise return null
*/
public MappedStructure getDirectImportedMappingSet(ClassSet cSet) throws MapperException
{
MappedStructure imported = impMSByCSet.get(cSet.stringForm());
if (imported == null)
{
// first call; set up table of imported mapping set URLs
if (impMSObjectByCSet == null)
{
impMSObjectByCSet = new Hashtable<String,ImportMappingSet>();
for (Iterator<EObject> it = ModelUtil.getEObjectsUnder(this,
MapperPackage.Literals.IMPORT_MAPPING_SET).iterator();it.hasNext();)
{
ImportMappingSet ims = (ImportMappingSet)it.next();
String path = ims.getMappingSetURI().toString();
List<ParameterClassValue> pvList = ims.getParameterClassValues();
if (pvList.size() != 1) throw new MapperException("Imported mapping set at '"
+ path + "' has " + pvList.size() + " parameter class values, but should have 1.");
ParameterClassValue pv = pvList.get(0);
ClassSet cs = pv.getClassSet();
impMSObjectByCSet.put(cs.stringForm(), ims);
}
}
// all calls; see if there is an imported mapping set for this class set
ImportMappingSet imscs = impMSObjectByCSet.get(cSet.stringForm());
if (imscs != null)
{
imported = imscs.getImportedMappingSet();
impMSByCSet.put(cSet.stringForm(),imported);
}
}
return imported;
}
/**
* @return all the mapping sets imported directly or indirectly by this
* mapping set, including itself, with no duplicates
* key = URI string of the mapping set
* value = the mapping set
*/
public Hashtable<String,MappedStructure> getAllImportedMappingSets()
{
Hashtable<String,MappedStructure> allSets = new Hashtable<String,MappedStructure>();
recordMappingSets(this,allSets);
return allSets;
}
/**
* record this mapping set and all those it imports,
* directly or indirectly, removing duplicates
* @param mappedStructure start mapping set
* @param mappingSets built up to record all the mapping sets
*/
private void recordMappingSets(MappedStructure mappedStructure,
Hashtable<String,MappedStructure> mappingSets)
{
String location = mappedStructure.eResource().getURI().toString();
// cut off recursion if the mapping set is recorded already - avoid infinite loops
if (mappingSets.get(location) == null)
{
mappingSets.put(location, mappedStructure);
for (Enumeration<MappedStructure> en = mappedStructure.getDirectImportedMappingSets().elements();en.hasMoreElements();)
{
MappedStructure ms = en.nextElement();
recordMappingSets(ms,mappingSets);
}
}
}
/**
* @return the root Element of the write procedures file which was made from this
* MappedStructure (its location and name are known automatically from the
* location and name of this resource)
* @throws MapperException if the Procedures file cannot be found
*/
public Element procedureFileRoot() throws MapperException
{
// find the file location of this resource
URI uri = eResource().getURI();
String location = uri.toString();
if (FileUtil.isInEclipse())
location = FileUtil.editURIConverter().normalize(uri).toString();
// calculate the location of the procedures file
String procLocation = FileUtil.wProcLocation(location);
// return its root Element
return XMLUtil.getRootElement(procLocation);
}
/**
* For use only inside Eclipse; outside Eclipse returns true.
* @return true if this mapping set has been edited since the last
* compilation (creation of the WProc file), or if the WProc file does not exist.
*
* When projects are imported into a namespace, I assume the wproc files are up to date;
* but the timestamps will be set by the import process and are equal to those of the mapper files.
*
* So a wproc file is considered up to date if its last modified time is up
* to 10 seconds before the last modified time of the mapper file - i.e I
* assume it takes at least 10 seconds to modify a mapper file.
*/
public boolean hasChangedSinceCompile()
{
// if there is a java mapping class, you never need a wproc file
if ((getMappingParameters() != null)
&& (getMappingParameters().getMappingClass() != null)
&& (!getMappingParameters().getMappingClass().equals(""))) return false;
// if not in eclipse, get one anyway
if (!FileUtil.isInEclipse()) return true;
// bug here comparing getTimeStamp() (for a resource) to getLocalTimeStamp() (for an Ifile)
long wpDate = EclipseFileUtil.wProcFileDate(this);
if (wpDate == 0) return true; // when the WProc file does not exist
long mapperDate = eResource().getTimeStamp();
// the wproc file is allowed to be up to 10 seconds older than the mapper file
int timeLag = 10000;
return (mapperDate > wpDate + timeLag);
}
/**
* @return the name of the mapping set
*/
public String getMappingSetName()
{
String name = "";
String url = eResource().getURI().toString();
StringTokenizer st = new StringTokenizer(url,"/\\");
while(st.hasMoreTokens()) name = st.nextToken();
return name;
}
/**
* Get a special mapping class, givne its name.
* Usually use Class.forNameI(), but for the FHIR mapping class, use the classLoader of the plugin
* @param javaClassName
* @return
* @throws MapperException
*/
private Class<?> getMappingClass(String javaClassName) throws MapperException
{
Class<?> theClass = null;
// special case for the FHIR Mapping class; use the class loader of the FHIR plugin
if (javaClassName.equals("com.openMap1.mapper.fhir.FHIRMapper"))
{
Bundle bundle = Platform.getBundle("com.openMap1.mapper.fhir");
if (bundle != null)
{
try {theClass = bundle.loadClass(javaClassName);}
catch (ClassNotFoundException ex)
{throw new MapperException("FHIR plugin cannot load mapping class '" + javaClassName + "': " + ex.getMessage());}
}
else if (bundle == null) throw new MapperException("FHIR plugin is not present in Eclipse.");
}
// other mapping classes; try to load by Class.forName(..)
else
{
try {theClass = Class.forName(javaClassName);}
catch (ClassNotFoundException ex)
{throw new MapperException("Failed to find mapping class '" + javaClassName + "': " + ex.getMessage());}
}
return theClass;
}
/**
* return the XML reader for the mapping set -
* either an MDLXOReader from the mappings, or a
* instance of a supplied Java class implementing XOReader
* @param dataSource the source of information to be read in
* @param classModelRoot (optional) root of the class model;
* if null the MappedStructure will attempt to find te class model root for itself
* (make it non-null for standalone applications, where the platform:resource URL
* used in the mapping set will not work)
*/
public XOReader getXOReader(Object dataSource, EPackage classModelRoot, messageChannel mc) throws MapperException
{
XOReader reader = null;
Object instance = null;
/* if the class model root is non-null, use it to override whatever
* the mapping set would try to find (useful for standalone applications, where
* the mapping set may try to use an Eclipse platform: resource URL) */
if (classModelRoot == null) classModelRoot = getClassModelRoot();
else setClassModelRoot(classModelRoot);
String mappingClass = null;
if ( (getMappingParameters() != null) &&
(!getMappingParameters().getMappingClass().equals("")))
mappingClass = getMappingParameters().getMappingClass();
// if the mapped structure defines a different Java class to read XML, as if through mappings; make an instance of the class
if (mappingClass != null)
{
// make the class
String javaClassName = mappingClass;
Class<?> theClass = getMappingClass(javaClassName);
/* make an instance of the class; assume the class
* has two constructors - the first with four Parameters,
* which are the same as the MDLXOReader constructor below */
String stage = "";
int arg = 0;
try
{
Constructor<?>[] constructors = theClass.getConstructors();
// try all constructors, looking for one with 4 arguments
boolean foundConstructor = false;
for (int c = 0; c < constructors.length;c++)
{
Class<?>[] parameterTypes = constructors[c].getParameterTypes();
if (parameterTypes.length == 4)
{
foundConstructor = true;
stage = " class cast";
// the next 4 calls will throw a class cast exception if the argument types do not match
arg = 1;parameterTypes[0].cast(dataSource);
arg = 2;parameterTypes[1].cast(this);
arg = 3;parameterTypes[2].cast(classModelRoot);
arg = 4;parameterTypes[3].cast(mc);
stage = " set";
Object[] initArgs = new Object[4];
arg = 1;initArgs[0] = dataSource;
arg = 2;initArgs[1] = this;
arg = 3;initArgs[2]= classModelRoot;
arg = 4;initArgs[3]= mc;
for (int i = 0; i < 4;i++)
{
boolean nonull = (initArgs[i] != null);
}
stage = " make instance";
arg = 0;
instance = constructors[c].newInstance(initArgs);
}
}
if (!foundConstructor) throw new MapperException("Found no constructor with 4 parameters");
}
catch (InvocationTargetException ex)
{
Exception cause = (Exception)ex.getCause();
cause.printStackTrace();
Exception target = (Exception)ex.getTargetException();
System.out.println("Mapper class exception: " + cause.getMessage());
throw new MapperException("Mapper class exception at stage " + stage + ": " + cause.getMessage() + ";" + target.getMessage());
}
catch (Exception ex)
{
System.out.println("Mapper class Exception");
ex.printStackTrace();
throw new MapperException("Failed to make reader instance of mapping class '" + javaClassName
+ "': at stage " + stage + ", argument " + arg + ": " + ex.getMessage());
}
// check that the class implements XOReader
if (instance == null)
{throw new MapperException("Null reader instance of mapping class '" + javaClassName + "'");}
if (instance instanceof XOReader) reader = (XOReader)instance;
else throw new MapperException("Supplied mapping class '" + javaClassName + "' does not implement the XOReader interface." );
}
// more usual case - a mapped MDLXOReader
else
{
// check the class of the data source; but it can be null, for RDBMS sources
if ((dataSource != null) &&
(!(dataSource instanceof Element))) throw new MapperException("Data source for mappings is not an XML Element");
reader = new MDLXOReader((Element)dataSource,this,classModelRoot,mc);
}
return reader;
}
/**
* @param oGet an objectGetter which gives the XMLWriter the object to be written to XML
* @param classModelRoot (optional) root of the class model. If null, this
* mappedStructure will attempt to find the class model root from its URL.
* (supply the class model root for standalone applications, where the platform:resource URL in the
* mapping set may not work)
* @param mc message channel for error messages
* @return the XML Writer for the mapping set - either a MappedXMLWriter
* using the mappings, or an instance of a supplied Java class implementing XMLWriter
* @throws MapperException
*/
public XMLWriter getXMLWriter(objectGetter oGet,EPackage classModelRoot, messageChannel mc, boolean runTracing) throws MapperException
{
XMLWriter writer = null;
Object instance = null;
Boolean doTracing = new Boolean(runTracing);
/* if a non-null class model root has been supplied, make it override whatever
* the mapping set may try to find (mainly for standalone applications,
* where the platform:resource URL in the mapping set will not work */
if (classModelRoot == null) classModelRoot = getClassModelRoot();
else setClassModelRoot(classModelRoot);
// if the mapped structure defines a Java class to read XML, as if through mappings
if ( (getMappingParameters() != null) &&
(!getMappingParameters().getMappingClass().equals("")))
{
// make the class
String javaClassName = getMappingParameters().getMappingClass();
Class<?> theClass = getMappingClass(javaClassName);
/* make an instance of the class; try all constructors,
* looking for one with with five Parameters,
* which are the same as the MappedXMLWriter constructor below */
String stage = "";
int arg = 0;
try
{
Constructor<?>[] constructors = theClass.getConstructors();
boolean constructorFound = false;
for (int c = 0; c < constructors.length;c++)
{
Class<?>[] parameterTypes = constructors[c].getParameterTypes();
if (parameterTypes.length == 5)
{
constructorFound = true;
stage = " class cast";
// the next 5 calls will throw a class cast exception if the argument types do not match
arg = 1; parameterTypes[0].cast(oGet);
arg = 2;parameterTypes[1].cast(this);
arg = 3;parameterTypes[2].cast(classModelRoot);
arg = 4;parameterTypes[3].cast(mc);
arg = 5;parameterTypes[4].cast(doTracing);
stage = " set";
Object[] initArgs = new Object[5];
arg = 1;initArgs[0] = oGet;
arg = 2;initArgs[1] = this;
arg = 3;initArgs[2]= classModelRoot;
arg = 4;initArgs[3]= mc;
arg = 5;initArgs[4]= doTracing;
stage = " make instance";
arg = 0;
instance = constructors[c].newInstance(initArgs);
}
}
if (!constructorFound) throw new MapperException("Found no constructor with 5 arguments");
}
catch (Exception ex)
{
throw new MapperException("Failed to make writer instance of mapping class '" + javaClassName
+ "': at stage " + stage + ", argument " + arg + ": " + ex.getMessage());
}
// check that the class implements XMLWriter
if (instance == null)
{throw new MapperException("Null writer instance of mapping class '" + javaClassName + "'");}
if (instance instanceof XMLWriter) writer = (XMLWriter)instance;
else throw new MapperException("Supplied mapping class '" + javaClassName + "' does not implement the XMLWriter interface." );
}
// usual case - a mapped XMLWriter
else
{
writer = new MappedXMLWriter(oGet,this,classModelRoot,mc, runTracing);
}
return writer;
}
/**
* @return true if reading and writing XML into the class model is
* done by a hand-coded Java class, rather than by the mapping-driven
* code in the tools
*/
public boolean isJavaMapper()
{
boolean isJava = false;
if ( (getMappingParameters() != null) &&
(!getMappingParameters().getMappingClass().equals(""))) isJava = true;
return isJava;
}
/**
* @return a namespace set including all the namespaces on the Global Mapping parameters
* @throws MapperException
*/
public NamespaceSet getNamespaceSet() throws MapperException
{
NamespaceSet NSSet = new NamespaceSet();
if ((getMappingParameters() != null) && (getMappingParameters().getNameSpaces() != null))
for (Iterator<Namespace> it = getMappingParameters().getNameSpaces().iterator(); it.hasNext();)
{
Namespace NS = it.next();
NSSet.addNamespace(new namespace(NS.getPrefix(),NS.getURL()));
}
return NSSet;
}
/**
* @return true if the mapping set declares a wrapper class
*/
public boolean hasWrapperClass()
{
if (getMappingParameters() == null) return false;
String javaClassName = getMappingParameters().getWrapperClass();
return (!(javaClassName.equals("")));
}
/**
*
* @param spare spare argument for the instance of the wrapper class, in case needed
* @return an instance of the wrapper class for this mapping set
*/
public MapperWrapper getWrapper(Object spare) throws MapperException
{
/* if there is already a wrapper instance, its 'spare' object argument
* (usually an MDLXOReader) will need to be refreshed. */
if (wrapper != null)
{
wrapper.resetSpareArgument(spare);
}
else if (wrapper == null)
{
Object instance = null;
if (getMappingParameters() == null) return null;
String javaClassName = getMappingParameters().getWrapperClass();
if (javaClassName.equals("")) return null;
// make the class
Class<?> theClass = null;
try {theClass = Class.forName(javaClassName);}
catch (ClassNotFoundException ex)
{throw new MapperException("Failed to find wrapper class '" + javaClassName + "': " + ex.getMessage());}
/* make an instance of the class; there should be one constructor with two
* parameters, the first of which is a MappedStructure; and there may be others,
* not used here, which must not have just 2 arguments */
String stage = "";
int arg = 0;
try
{
Constructor<?>[] constructors = theClass.getConstructors();
boolean constructorFound = false;
for (int c = 0; c < constructors.length;c++)
{
Class<?>[] parameterTypes = constructors[c].getParameterTypes();
if (parameterTypes.length == 2)
{
constructorFound = true;
stage = " class cast";
// the next calls will throw a class cast exception if the argument type does not match
arg = 1; parameterTypes[0].cast(this);
arg = 2; parameterTypes[1].cast(spare);
stage = " set";
Object[] initArgs = new Object[2];
arg = 1;initArgs[0] = this;
arg = 2;initArgs[1] = spare;
stage = " make instance";
arg = 0;
instance = constructors[c].newInstance(initArgs);
}
}
if (!constructorFound) throw new MapperException("Found no constructor for wrapper class with 2 arguments");
}
catch (Exception ex)
{
ex.printStackTrace();
throw new MapperException("Failed to make instance of wrapper class '" + javaClassName
+ "': at stage " + stage + ", argument " + arg + ": " + ex.getMessage());
}
// check that the class implements MapperWrapper
if (instance == null)
{throw new MapperException("Null instance of wrapper class '" + javaClassName + "'");}
if (instance instanceof MapperWrapper) wrapper = (MapperWrapper)instance;
else throw new MapperException("Supplied wrapper class '" + javaClassName
+ "' does not implement the MapperWrapper interface." );
}
return wrapper;
}
/**
* @return an instance of the wrapper class for this mapping set,
* with the usual choice for the second 'spare' argument of the constructor
* (the String name of the top ElementDef)
*/
public MapperWrapper getWrapper() throws MapperException
{
String spare = "";
if (getRootElement() != null) spare = rootElement.getName();
if ((wrapper == null) && (hasWrapperClass()))
{
wrapper = getWrapper(spare);
}
/* if there is already a wrapper instance, its 'spare' object argument
* (maybe an MDLXOReader) will need to be refreshed. */
else if ((wrapper != null) && (hasWrapperClass()))
{
wrapper.resetSpareArgument(spare);
}
return wrapper;
}
/**
*
* @param root root of the input XML document
* @return the input XML pjut throught thew input wrapper transform, if there is one
* @throws MapperException
*/
public Element getInWrappedXML(Element root) throws MapperException
{
if (getWrapper() != null) return getWrapper().transformIn(root).getDocumentElement();
else return root;
}
/**
* @param instancePath the path to a data instance (typically got from a file choose dialogue)
* @return the XML document root Element to be given to the XOReader. This is either the root of the document at
* the given location (if there is no wrapper class);
* or if there is a wrapper class, it is the root of the Document got by applying the wrapper
* 'in' transform to the file whose location is given
*/
public Element getXMLRoot(String instancePath) throws MapperException
{
Element XMLRoot = null;
String instanceLocation = instancePath;
if (instanceLocation == null) throw new MapperException("Null location for data instance");
/* sometimes the path comes from a file dialogue , so is absolute; but if
* it is a 'platform:/resource' path, it needs to be converted to absolute */
if (instanceLocation.startsWith("platform:"))
{
URI XMLURI = URI.createURI(instancePath);
instanceLocation = FileUtil.editURIConverter().normalize(XMLURI).toFileString();
}
if (hasWrapperClass()) try
{
MapperWrapper wrapper = getWrapper();
Object input = null;
if (wrapper.transformType() == AbstractMapperWrapper.XML_TYPE)
{
input = XMLUtil.getRootElement(instanceLocation);
if (input == null) throw new MapperException("Could not open XML");
}
else if (wrapper.transformType() == AbstractMapperWrapper.TEXT_TYPE)
{
input = new FileInputStream(new File(instanceLocation));
}
// apply the input transform
XMLRoot = applyInputTransform(input);
}
catch (Exception ex) {ex.printStackTrace();throw new MapperException(ex.getMessage());}
else
{
XMLRoot = XMLUtil.getRootElement(instanceLocation);
}
return XMLRoot;
}
/**
* @param stream input stream from a data instance
* @return the XML document root to be given to the XOReader. This is either the root of the document
* in the stream (if there is no wrapper class);
* or if there is a wrapper class, it is the root of the Document got by applying the wrapper
* 'in' transform to the stream
*/
public Element getXMLRoot(InputStream stream) throws MapperException
{
Element XMLRoot = null;
if (hasWrapperClass()) try
{
MapperWrapper wrapper = getWrapper();
Object input = null;
if (wrapper.transformType() == AbstractMapperWrapper.XML_TYPE)
{
input = XMLUtil.getRootElement(stream);
if (input == null) throw new MapperException("Could not open XML");
}
else if (wrapper.transformType() == AbstractMapperWrapper.TEXT_TYPE)
{
input = stream;
}
// apply the input transform
XMLRoot = applyInputTransform(input);
}
catch (Exception ex) {throw new MapperException(ex.getMessage());}
else
{
XMLRoot = XMLUtil.getRootElement(stream);
}
return XMLRoot;
}
private Element applyInputTransform(Object input) throws MapperException
{
Document inDoc = getWrapper().transformIn(input);
// simple implementation that seems to lose information with CCRTransform
//return inDoc.getDocumentElement();
/* try making a temporary file 'eclipseTempFile.xml' (not visible in Eclipse);
* solves the problem with CCRTransform, I know not why. */
String tempFileLocation = "";
if (FileUtil.isInEclipse())
{
tempFileLocation = EclipseFileUtil.workspaceRoot() + TEMPORARY_XML_FILE;
}
else
{
String mappingLocation = eResource().getURI().toString();
tempFileLocation = FileUtil.projectFolderLocation(mappingLocation) + TEMPORARY_XML_FILE;
}
XMLUtil.writeOutput(inDoc,tempFileLocation,true);
return XMLUtil.getRootElement(tempFileLocation);
}
/*copied this static string from class EclipseFileUtilinto this class,
* to avoid having to load EclipseFileUtil; not sure what Eclipse libraries it needs */
private static String TEMPORARY_XML_FILE = "/eclipseTempFile.xml";
/**
* @param outputRoot the root of an XML tree made by the XOWriter for this mapping set
* @param spare object to be passed to the output wrapper transform
* @return the result of applying the wrapper 'out' transformation ,if there is one.
* This result is either an XML Document (if there is no wrapper, or if the wrapper type is XMl)
* or a String[] array (if the wrapper type is text)
*/
public Object makeOutputObject(Element outputRoot, Object spare) throws MapperException
{
Object outputObj = null;
if (hasWrapperClass())
{
outputObj = getWrapper(spare).transformOut(outputRoot);
}
else
{
outputObj = outputRoot.getOwnerDocument();
}
return outputObj;
}
/**
* @return static constant from class AbstractMapperWrapper defining the file type - XML or text
*/
public int getInstanceFileType() throws MapperException
{
int type = AbstractMapperWrapper.XML_TYPE; // default if there is no wrapper class
if (this.hasWrapperClass())
{
type = getWrapper().transformType();
}
return type;
}
/**
* @return the (usually one) file extensions for input files to the
* XOReader - depending on whether this mapping set has a wrapper class
*/
public String[] getExtensions() throws MapperException
{
String[] exts = new String[1];
if (hasWrapperClass())
{
exts[0] = getWrapper().fileExtension();
}
else exts[0] = "*.xml";
return exts;
}
// for fast lookup of the subclasses of a class, including itself
private Hashtable<String,Vector<EClass>> allSubClasses = null;
/**
* @param ec a class
* @return a Vector of all classes which inherit from the class,
* including the class itself
*/
public Vector<EClass> getAllSubClasses(EClass ec) throws MapperException
{
if (ec == null) return new Vector<EClass>();
if ((allSubClasses == null)||(allSubClasses.size() == 0)) setUpSubClasses();
Vector<EClass> subclasses = allSubClasses.get(ModelUtil.getQualifiedClassName(ec));
/* this covers up for some failures - eg having the wrong top package, leading to no hits,
* by returning at least the class itself - better than nothing */
if (subclasses == null)
{
subclasses = new Vector<EClass>();
subclasses.add(ec);
}
return subclasses;
}
/**
* set up a Hashtable of all subclasses of any class, for use in getAllSubClasses.
*/
private void setUpSubClasses() throws MapperException
{
allSubClasses = new Hashtable<String,Vector<EClass>>();
for (Iterator<EClass> it = ModelUtil.getAllClasses(getClassModelRoot()).iterator(); it.hasNext();)
{
EClass subC = it.next();
String cName = ModelUtil.getQualifiedClassName(subC);
Vector<EClass> subclasses = allSubClasses.get(cName);
/* If a class is encountered before any of its proper subclasses,
* ensure it is counted amongst its own subclasses*/
if (subclasses == null)
{
subclasses = new Vector<EClass>();
subclasses.add(subC);
allSubClasses.put(cName,subclasses);
}
// getEAllSuperTypes does not return the class itself; only proper subclasses
for (Iterator<EClass> ic = subC.getEAllSuperTypes().iterator();ic.hasNext();)
{
EClass superC = ic.next();
String dName = ModelUtil.getQualifiedClassName(superC);
Vector<EClass> subclasses2 = allSubClasses.get(dName);
/* If a class is encountered after any of its proper subclasses,
* ensure it is counted amongst its own subclasses*/
if (subclasses2 == null)
{
subclasses2 = new Vector<EClass>();
subclasses2.add(superC);
}
subclasses2.add(subC);
allSubClasses.put(dName,subclasses2);
}
}
}
/**
* @return the number of mappable nodes (ElementDefs and AttributeDefs)
* in the whole tree, stopping the recursion at any repeated type
*/
public int countNodesInTree() throws MapperException
{
int count = 0;
if (getRootElement() != null)
{
Vector<String> typeNames = new Vector<String>();
count = getRootElement().countNodesInSubtree(typeNames, getStructureDefinition());
}
return count;
}
@SuppressWarnings("unused")
private void trace(String s) {System.out.println(s);}
} //MappedStructureImpl