/*
* 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.ui.wizards;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.mapping.Mapping;
import org.eclipse.emf.mapping.MappingRoot;
import org.eclipse.xsd.XSDElementDeclaration;
import org.teiid.core.designer.ModelerCoreException;
import org.teiid.core.designer.PluginUtil;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.container.Container;
import org.teiid.designer.core.resource.xmi.MtkXmiResourceImpl;
import org.teiid.designer.core.validation.rules.StringNameValidator;
import org.teiid.designer.core.workspace.ModelProject;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.mapping.factory.ITreeToRelationalMapper;
import org.teiid.designer.mapping.factory.MappingClassBuilderStrategy;
import org.teiid.designer.mapping.factory.MappingClassFactory;
import org.teiid.designer.mapping.factory.ModelMapperFactory;
import org.teiid.designer.mapping.factory.TreeMappingAdapter;
import org.teiid.designer.metamodels.core.ModelAnnotation;
import org.teiid.designer.metamodels.core.ModelType;
import org.teiid.designer.metamodels.relational.BaseTable;
import org.teiid.designer.metamodels.relational.Column;
import org.teiid.designer.metamodels.relational.DirectionKind;
import org.teiid.designer.metamodels.relational.ForeignKey;
import org.teiid.designer.metamodels.relational.PrimaryKey;
import org.teiid.designer.metamodels.relational.Procedure;
import org.teiid.designer.metamodels.relational.ProcedureParameter;
import org.teiid.designer.metamodels.relational.ProcedureResult;
import org.teiid.designer.metamodels.relational.RelationalEntity;
import org.teiid.designer.metamodels.transformation.InputBinding;
import org.teiid.designer.metamodels.transformation.InputParameter;
import org.teiid.designer.metamodels.transformation.InputSet;
import org.teiid.designer.metamodels.transformation.MappingClass;
import org.teiid.designer.metamodels.transformation.MappingClassColumn;
import org.teiid.designer.metamodels.transformation.MappingClassSet;
import org.teiid.designer.metamodels.transformation.TransformationContainer;
import org.teiid.designer.metamodels.transformation.TransformationFactory;
import org.teiid.designer.metamodels.transformation.TransformationMappingRoot;
import org.teiid.designer.metamodels.transformation.TreeMappingRoot;
import org.teiid.designer.metamodels.xml.XmlDocument;
import org.teiid.designer.metamodels.xml.XmlDocumentBuilderImpl;
import org.teiid.designer.metamodels.xml.XmlDocumentFactory;
import org.teiid.designer.metamodels.xml.XmlDocumentPackage;
import org.teiid.designer.metamodels.xml.XmlElement;
import org.teiid.designer.metamodels.xml.XmlRoot;
import org.teiid.designer.metamodels.xsd.XsdBuilderOptions;
import org.teiid.designer.metamodels.xsd.XsdSchemaBuilderImpl;
import org.teiid.designer.transformation.util.AttributeMappingHelper;
import org.teiid.designer.transformation.util.TransformationHelper;
import org.teiid.designer.ui.UiConstants;
import org.teiid.designer.ui.viewsupport.ModelUtilities;
import org.teiid.designer.webservice.util.WebServiceBuildOptions;
/**
* Helper class used by the Generate Web Service Schemas Wizard
*
* @since 8.0
*/
public class GenerateXsdHelper {
public static boolean HEADLESS = false;
private static final String DOC_SUFFIX = UiConstants.Util.getString("GenerateXsdWizard.docSuffix"); //$NON-NLS-1$
private static final String OUTPUT_SUFFIX = UiConstants.Util.getString("GenerateXsdWizard.outSuffix"); //$NON-NLS-1$
private static final String INSTANCE_SUFFIX = UiConstants.Util.getString("GenerateXsdWizard.instanceSuffix"); //$NON-NLS-1$
private static final String NESTED_SUFFIX = UiConstants.Util.getString("GenerateXsdWizard.nestedSuffix"); //$NON-NLS-1$
private static final String IN_MSG = UiConstants.Util.getString("GenerateXsdWizard.inMsg"); //$NON-NLS-1$
private static final String OUT_MSG = UiConstants.Util.getString("GenerateXsdWizard.outMsg"); //$NON-NLS-1$
private static final String DOCUMENT_SUFFIX = UiConstants.Util.getString("GenerateXsdWizard.documentSuffix"); //$NON-NLS-1$
private static final String GET_PREFIX = UiConstants.Util.getString("GenerateXsdWizard.getPrefix"); //$NON-NLS-1$
private static final String XSD_EXTENSION = ModelUtilities.DOT_XSD_FILE_EXTENSION;
private static final String XMI_EXTENSION = ModelUtilities.DOT_MODEL_FILE_EXTENSION;
private final XsdSchemaBuilderImpl xsdBuilder;
private final XsdBuilderOptions ops;
private final MultiStatus result;
private final PluginUtil Util = UiConstants.Util;
private MtkXmiResourceImpl xmlResource;
private ModelResource xmlModelResource;
// Map of output XmlDocuments to input global Elements
private final HashMap outputToInputMappings = new HashMap();
private IProgressMonitor monitor;
public GenerateXsdHelper( final XsdSchemaBuilderImpl xsdBuilder,
final XsdBuilderOptions ops,
final MultiStatus result ) {
CoreArgCheck.isNotNull(xsdBuilder);
CoreArgCheck.isNotNull(ops);
this.xsdBuilder = xsdBuilder;
this.ops = ops;
this.result = result == null ? new MultiStatus(UiConstants.PLUGIN_ID, 0, Util.getString("GenerateXsdWizard.result"), null) : result; //$NON-NLS-1$
}
public HashMap execute( final IProgressMonitor monitor ) {
this.monitor = (monitor == null) ? new NullProgressMonitor() : monitor;
// Don't save if we still have to generate the SQL.
final boolean genSql = ops.genSql();
final boolean genWS = ops.genWs();
final boolean buildXml = ops.genXml();
final boolean doSave = !genSql && !genWS;
// If the user elected to build XML, execute that build.
if (buildXml) {
HashMap xsdMappings = xsdBuilder.getOutputToInputMappings();
buildDocuments(ops, xsdBuilder.getRootElements(), xsdMappings, doSave);
}
// Update the monitor
this.monitor.worked(1);
// If the user elected to generate default SQL, generate that SQL for all mapping classes
if (genSql) {
generateSql(ops);
}
return outputToInputMappings;
}
// ******************** Helper methods for building XML ********************
/**
* This method will build XML Document models using the builder options to determine whether to build many models with one doc
* each or a single model with many docs.
*
* @param ops - XsdBuilderOptions used to determine how to build documents
* @param roots - the XsdElementDefinitions to use as root elements
* @param xsdMappings = the output Xsd Global Element to input Xsd Global Element mappings
* @param doSave - the flag to specify whether Resources should be saved. Should be true if will not be saved by subsequent
* operation.
*/
private void buildDocuments( final XsdBuilderOptions ops,
final Collection roots,
final HashMap xsdMappings,
final boolean doSave ) {
if (roots == null || roots.isEmpty()) {
return;
}
final boolean genWs = ops.genWs();
monitor.beginTask(Util.getString("GenerateXsdWizard.buildingDocs", roots.size()), roots.size()); //$NON-NLS-1$
// Initialize the XmlDocumentBuilder
XmlDocumentBuilderImpl builder = new XmlDocumentBuilderImpl();
XmlDocumentFactory factory = XmlDocumentFactory.eINSTANCE;
for (Iterator iter = roots.iterator(); iter.hasNext();) {
final XSDElementDeclaration schemaRootElement = (XSDElementDeclaration)iter.next();
if (xmlResource == null) {
// initialize the resource if we have not alrady done so:
initDocResources(schemaRootElement, ops);
}
final Object inputGlobalElement = xsdMappings.get(schemaRootElement);
try {
XmlDocument document = factory.createXmlDocument();
document.setName(schemaRootElement.getName() + DOCUMENT_SUFFIX);
if (xmlResource != null) {
xmlResource.getContents().add(document);
}
// Create the output document to input global element mapping
if (genWs) {
outputToInputMappings.put(document, inputGlobalElement);
}
// Create the document root.
XmlRoot docRoot = factory.createXmlRoot();
docRoot.setName(schemaRootElement.getName());
docRoot.setXsdComponent(schemaRootElement);
document.setRoot(docRoot);
// Pass the root into the builder and execute the build
builder.buildDocument(docRoot, monitor);
if (!HEADLESS) {
// Build the mapping classes
final ITreeToRelationalMapper mapper = ModelMapperFactory.createModelMapper(document);
new MappingClassFactory(mapper).generateMappingClasses(docRoot,
MappingClassBuilderStrategy.compositorStrategy,
true);
}
} catch (Exception e) {
final String msg = Util.getString("GenerateXsdWizard.errBuild"); //$NON-NLS-1$
addStatus(IStatus.ERROR, msg, e);
}
}
if (doSave) {
doSave();
}
}
private void addStatus( final int severity,
final String msg,
final Throwable ex ) {
result.add(new Status(severity, result.getPlugin(), 0, msg, ex));
}
/**
* Method to actually create the ModelResoruce (Resource in headless mode) for a XMLDocument model
*
* @param element - The XSDElementDeclaration to use as context.
* @param ops - The XsdBuilderOptions object to use for creation options
*/
private void initDocResources( final XSDElementDeclaration element,
final XsdBuilderOptions ops ) {
final String parentLocation = ops.getParentPath();
String mdlName = null;
String fileName;
if (ops.genOutput()) {
// Use the model name specified in the Options
mdlName = ops.getOutputModelName();
mdlName = mdlName.replaceAll(XSD_EXTENSION, new String());
fileName = parentLocation + File.separator + mdlName + DOC_SUFFIX + XMI_EXTENSION;
} else {
// Use the Element name as the model name
mdlName = element.getName();
fileName = parentLocation + File.separator + element.getName() + DOC_SUFFIX + XMI_EXTENSION;
}
// create for existing file
IWorkspaceRoot wsroot = ModelerCore.getWorkspace().getRoot();
File check = new File(fileName);
if (check.exists()) {
final String fileExists = Util.getString("GenerateXsdWizard.docExists", fileName); //$NON-NLS-1$
addStatus(IStatus.ERROR, fileExists, null);
return;
}
if (HEADLESS) {
// Don't assume ModelResources so we can UnitTest
try {
Container cntr = ModelerCore.getModelContainer();
xmlResource = (MtkXmiResourceImpl)cntr.getOrCreateResource(URI.createFileURI(fileName));
} catch (Exception err) {
addStatus(IStatus.ERROR, err.getMessage(), err);
}
} else {
IFile resource = wsroot.getFileForLocation(new Path(fileName));
// Create the ModelResource
xmlModelResource = ModelerCore.create(resource);
if (xmlModelResource != null) {
try {
// Add a status that the model was created.
addStatus(IStatus.INFO, Util.getString("GenerateXsdWizard.newModel", resource.getName()), null); //$NON-NLS-1$
xmlResource = (MtkXmiResourceImpl)xmlModelResource.getEmfResource();
} catch (ModelerCoreException err) {
Util.log(IStatus.ERROR, err, err.getMessage());
}
}
}
if (xmlResource != null) {
try {
// Set the ModelAnnotation info.
final ModelAnnotation ma = xmlModelResource.getModelAnnotation();
ma.setPrimaryMetamodelUri(XmlDocumentPackage.eNS_URI);
ma.setModelType(ModelType.VIRTUAL_LITERAL);
} catch (ModelerCoreException err) {
final String msg = Util.getString("GenerateXsdWizard.errModelImport"); //$NON-NLS-1$
addStatus(IStatus.ERROR, msg, err);
}
}
}
// ******************** Helper methods for generating default SQL ********************
/**
* Root method to drive the creation of default SQL in the XmlDoc mapping class transformatins.
*
* @param docModels - Collection of XmlDocument model Model Resources
* @param ops - The XsdBuilderOptions to use to drive generation options
* @param messages - The StringBuffer to use for user messages.
*/
private void generateSql( final XsdBuilderOptions ops ) {
final boolean genWs = ops.genWs();
// Build name map to expidte root lookup by Name
final HashMap nameMap = buildRootNameMap(ops);
final Collection mappingRoots = getMappingRoots();
if (nameMap.isEmpty() || mappingRoots.isEmpty()) {
return;
}
// Initialize the Progress Monitor
this.monitor.beginTask(Util.getString("GenerateXsdWizard.genSqlSts", mappingRoots.size()), mappingRoots.size()); //$NON-NLS-1$
final Iterator mappingRootIt = mappingRoots.iterator();
while (mappingRootIt.hasNext()) {
final TransformationMappingRoot nextRoot = (TransformationMappingRoot)mappingRootIt.next();
final EObject target = nextRoot.getTarget();
if (target instanceof MappingClass) {
// Find the corresponding source for the MappingClass target
final MappingClass mc = (MappingClass)target;
RelationalEntity source = (RelationalEntity)nameMap.get(mc.getName());
if (source == null) {
// No exact match found, try more generic search
source = deepSearchNameMap(nameMap, mc.getName());
}
if (source instanceof ProcedureResult) {
TransformationHelper.createTransformation(target, ((ProcedureResult)source).getProcedure());
} else {
TransformationHelper.createTransformation(target, source);
}
generateSql(mc, source, nextRoot);
}
}
if (!genWs) {
doSave();
}
}
/*
* No exact match found in name map, look for closest match. This would occur if two
* mapping classes had the same name the name validator would result in the second getting
* a unique name with an integer appended.
*
* Search the name map keys and look for the first match where the mapping class name begins
* with the relational entity name.
*/
private RelationalEntity deepSearchNameMap( final HashMap nameMap,
final String mcName ) {
if (mcName == null || nameMap == null) {
return null;
}
final Iterator keys = nameMap.keySet().iterator();
String match = null;
while (match == null && keys.hasNext()) {
final String next = (String)keys.next();
if (mcName.startsWith(next)) {
match = next;
}
}
if (match != null) {
return (RelationalEntity)nameMap.get(match);
}
return null;
}
public void doSave() {
if (xmlModelResource != null) {
try {
xmlModelResource.save(this.monitor, true);
xmlModelResource.getEmfResource().setModified(false);
} catch (Exception e) {
final String saveError = Util.getString("GenerateXsdWizard.errSave"); //$NON-NLS-1$
addStatus(IStatus.ERROR, saveError, e);
}
this.monitor.worked(1);
}
}
/**
* Check to see if all the input / output datatypes match. If not, we need to create custom SQL.
*
* @param mc - The MappingClass target
* @param source - The Source of the transformation
* @param root - The TransformationMappingRoot for the given transformation
*/
private void generateSql( final MappingClass mc,
final RelationalEntity source,
final TransformationMappingRoot root ) {
// Create defaultSql to use in the event of any exceptions
final String defaultSql = "SELECT * FROM "; //$NON-NLS-1$
final StringBuffer newSql = new StringBuffer(defaultSql);
final Collection mappingsForProcParams = new ArrayList();
try {
final Iterator mcCols = mc.getColumns().iterator();
int index = 0;
int outCount = 0;
final List outCols = getOutParams(source);
while (mcCols.hasNext()) {
final MappingClassColumn next = (MappingClassColumn)mcCols.next();
if (source instanceof ProcedureResult) {
final ProcedureResult procResult = (ProcedureResult)source;
if (index >= procResult.getColumns().size()) {
// This is a procedure parameter mark the XMLElement as exclude from doc
mappingsForProcParams.add(next);
}
} else if (source instanceof Procedure) {
if (outCount++ >= outCols.size()) {
// This is a procedure parameter mark the XMLElement as exclude from doc
mappingsForProcParams.add(next);
}
}
index++;
}
if( source instanceof ProcedureResult) {
newSql.append(TransformationHelper.getSqlEObjectFullName(((ProcedureResult)source).getProcedure()));
} else {
newSql.append(TransformationHelper.getSqlEObjectFullName(source));
}
// Handle the input sets for the non-flat scenario
if (!ops.isFlat()) {
final MappingClassSet mcs = mc.getMappingClassSet();
final EObject target = mcs == null ? null : mcs.getTarget();
if (target instanceof XmlDocument) {
final XmlDocument doc = (XmlDocument)target;
final TreeMappingAdapter tma = new TreeMappingAdapter(doc);
final List parents = tma.getParentMappingClasses(mc, doc, false);
if (parents.size() > 0) {
final Collection cols = getInputColumns(parents, source);
addInputColsAndCriteria(cols, mc, newSql, source);
}
}
}
// Update the XML Elements for all the outPut Procedure Parameters
updateElementsForParams(mappingsForProcParams, root);
TransformationHelper.setSelectSqlString(root, newSql.toString(), false, this);
AttributeMappingHelper.updateAttributeMappings(root, this);
} catch (Exception e) {
// Use the default SQL and log msg.
final String msg = Util.getString("GenerateXsdWizard.errSql"); //$NON-NLS-1$
addStatus(IStatus.ERROR, msg, e);
TransformationHelper.setSelectSqlString(root, defaultSql, false, this);
}
}
// ******************** Utility and Helper Methods ********************
private void addInputColsAndCriteria( final Collection inputCols,
final MappingClass mc,
final StringBuffer sql,
final RelationalEntity source ) {
final InputSet is = mc.getInputSet();
final Iterator cols = inputCols.iterator();
final StringBuffer crit = new StringBuffer();
if (cols.hasNext()) {
crit.append(" where "); //$NON-NLS-1$
}
int colCount = 0;
while (cols.hasNext()) {
final MappingClassColumn nextCol = (MappingClassColumn)cols.next();
final String colName = nextCol.getName();
// Create the inputParam
final InputParameter nxt = TransformationFactory.eINSTANCE.createInputParameter();
nxt.setName(colName);
nxt.setType(nextCol.getType());
is.getInputParameters().add(nxt);
// Create the input binding
final InputBinding binding = TransformationFactory.eINSTANCE.createInputBinding();
binding.setInputParameter(nxt);
binding.setMappingClassColumn(nextCol);
binding.setMappingClassSet(mc.getMappingClassSet());
// Append the criteria
crit.append("input."); //$NON-NLS-1$
crit.append(colName);
crit.append("="); //$NON-NLS-1$
crit.append(TransformationHelper.getSqlEObjectFullName(source));
crit.append("."); //$NON-NLS-1$
crit.append(getPKColName(source, colCount, colName));
colCount++;
if (cols.hasNext()) {
crit.append(" and "); //$NON-NLS-1$
}
} // while
if (colCount > 1) {
// Log a warning that assumptions where made creating Criteria
final String msg = UiConstants.Util.getString("GenerateXsdHelper.criteriaAssumptions", mc.getName()); //$NON-NLS-1$
addStatus(IStatus.WARNING, msg, null);
}
if (crit.length() > 0) {
sql.append(crit.toString());
}
}
private String getPKColName( final RelationalEntity source,
final int index,
final String defaultName ) {
if (source instanceof BaseTable && ((BaseTable)source).getPrimaryKey() != null) {
final List pkCols = ((BaseTable)source).getPrimaryKey().getColumns();
if (pkCols.size() > index) {
final Column col = (Column)pkCols.get(index);
return col.getName();
}
}
// Could not find a matching PK column for the given source and index
return defaultName;
}
private Collection getInputColumns( final List mcs,
final RelationalEntity source ) {
for (int i = mcs.size(); i > 0; i--) {
final MappingClass mc = (MappingClass)mcs.get(i - 1);
final Collection result = getInputColumns(mc, source);
if (result.size() != 0) {
return result;
}
}
return new ArrayList();
}
/*
* For the given Mapping class find the set of Columns that should be used to create input set
* columns by traversing the PK -> FK relationship on the given relatinal entity (if a table).
* This is in effect climbing up one level on the relational side that is used to build the
* XML.
*/
private Collection getInputColumns( final MappingClass mc,
final RelationalEntity source ) {
final Collection result = new ArrayList();
if (source instanceof BaseTable) {
// Only possible for Tables... Find the PK -> FK relationship
final PrimaryKey pk = ((BaseTable)source).getPrimaryKey();
if (pk != null && !pk.getForeignKeys().isEmpty()) {
// If the FK column names exist on the Mapping class, include them for
// Input Set Col creation
final Iterator fks = pk.getForeignKeys().iterator();
while (fks.hasNext()) {
final ForeignKey nxtFK = (ForeignKey)fks.next();
final Collection fkColNames = getFKColNames(nxtFK);
final Iterator cols = mc.getColumns().iterator();
// Only use the names if all columns match
while (cols.hasNext()) {
final MappingClassColumn col = (MappingClassColumn)cols.next();
final String name = col.getName();
if (fkColNames.contains(name)) {
result.add(col);
// We've found a matching column for every FK col... we are done
if (result.size() == fkColNames.size()) {
return result;
}
}
}
// We didn't find a match for every FK Col... clear the list and try the next FK
result.clear();
}
}
}
return result;
}
final Collection getFKColNames( final ForeignKey fk ) {
final HashSet result = new HashSet();
final Iterator cols = fk.getColumns().iterator();
while (cols.hasNext()) {
final Column col = (Column)cols.next();
result.add(col.getName());
} // while
return result;
}
/**
* Build a map of names to Physical sources
*
* @param ops
* @return the map of names to Physical sources
* @since 4.1
*/
private HashMap buildRootNameMap( final XsdBuilderOptions ops ) {
final Collection roots = ops.getRoots();
if (roots == null || roots.isEmpty()) {
return new HashMap();
}
final StringNameValidator nameValidator = new StringNameValidator();
final HashMap nameMap = new HashMap(roots.size());
final Iterator rootIt = roots.iterator();
while (rootIt.hasNext()) {
RelationalEntity next = (RelationalEntity)rootIt.next();
final String nestedName = next.getName() + NESTED_SUFFIX;
final String globalName = next.getName() + INSTANCE_SUFFIX;
String nestedUniqueName = nameValidator.createValidUniqueName(nestedName);
if (nestedUniqueName == null) {
nestedUniqueName = nestedName;
}
nameMap.put(nestedUniqueName, next);
String globalUniqueName = nameValidator.createValidUniqueName(globalName);
if (globalUniqueName == null) {
globalUniqueName = globalName;
}
nameMap.put(globalUniqueName, next);
if (ops.genInput() && next instanceof ProcedureResult) {
final Procedure proc = ((ProcedureResult)next).getProcedure();
nameMap.put(proc.getName(), proc);
}
}
return nameMap;
}
private List getOutParams( final RelationalEntity entity ) {
final List result = new ArrayList();
if (entity instanceof Procedure) {
final Procedure proc = (Procedure)entity;
final Iterator params = proc.getParameters().iterator();
while (params.hasNext()) {
final ProcedureParameter next = (ProcedureParameter)params.next();
final DirectionKind dir = next.getDirection();
if (dir == DirectionKind.OUT_LITERAL || dir == DirectionKind.INOUT_LITERAL) {
result.add(next);
}
}
}
return result;
}
/**
* Mark all XML Elements mapped to Procedure Params as "Exclude From Document
*
* @param theMappingColumns
* @param root
*/
private void updateElementsForParams( final Collection theMappingColumns,
final MappingRoot root ) {
final MappingRoot treeRoot = getTreeMappingRoot(root);
if (treeRoot == null) {
return;
}
List columnMappings = treeRoot.getNested();
if (!columnMappings.isEmpty()) {
for (int size = columnMappings.size(), i = 0; i < size; i++) {
Mapping mapping = (Mapping)columnMappings.get(i);
Iterator columns = mapping.getInputs().iterator();
while (columns.hasNext()) {
final MappingClassColumn mappingColumn = (MappingClassColumn)columns.next();
if (theMappingColumns.contains(mappingColumn)) {
final Iterator outputs = mapping.getOutputs().iterator();
while (outputs.hasNext()) {
final XmlElement element = (XmlElement)outputs.next();
element.setExcludeFromDocument(true);
}
}
}
}
}
}
private MappingRoot getTreeMappingRoot( MappingRoot root ) {
TransformationContainer cntr = null;
EObject parent = root;
while (parent != null && cntr == null) {
if (parent instanceof TransformationContainer) {
cntr = (TransformationContainer)parent;
}
parent = parent.eContainer();
}
if (cntr == null) {
return null;
}
final Iterator roots = cntr.getTransformationMappings().iterator();
while (roots.hasNext()) {
Object next = roots.next();
if (next instanceof TreeMappingRoot) {
final TreeMappingRoot tmr = (TreeMappingRoot)next;
if (root.getOutputs().containsAll(tmr.getInputs())) {
return tmr;
}
}
}
return null;
}
/**
* Find all the TransformationMappingRoots within the xmlResource.
*
* @param docModels
* @return the Collection of TransformationMappingRoots
*/
private Collection getMappingRoots() {
if (xmlResource == null) {
return Collections.EMPTY_LIST;
}
final Collection mappingRoots = new HashSet();
final Iterator rsrcIt = xmlResource.getContents().iterator();
while (rsrcIt.hasNext()) {
final Object next = rsrcIt.next();
if (next instanceof TransformationContainer) {
final TransformationContainer tc = (TransformationContainer)next;
mappingRoots.addAll(tc.getTransformationMappings());
}
}
return mappingRoots;
}
private ModelProject getModelProject( EObject eObj ) {
final Resource rsrc = eObj.eResource();
ModelProject prj = null;
if (rsrc == null) {
return null;
}
final ModelResource mr = ModelerCore.getModelEditor().findModelResource(rsrc);
if (mr != null) {
prj = mr.getModelProject();
}
return prj;
}
public Collection createWebServiceBuildOptions( final HashMap outDocToInElementMappings,
final XsdBuilderOptions ops ) {
CoreArgCheck.isNotNull(outDocToInElementMappings);
CoreArgCheck.isNotNull(ops);
if (!ops.genWs()) {
return Collections.EMPTY_LIST;
}
final String rootModelName = ops.getRootModelName();
final String wsModelName = ops.getWsModelName();
final ArrayList options = new ArrayList();
final Iterator mappings = outDocToInElementMappings.entrySet().iterator();
ModelProject project = null;
while (mappings.hasNext()) {
final WebServiceBuildOptions option = new WebServiceBuildOptions();
final Map.Entry next = (Map.Entry)mappings.next();
final XmlDocument outDoc = (XmlDocument)next.getKey();
if (outDoc != null && outDoc.getRoot() != null) {
final XmlRoot root = outDoc.getRoot();
final XSDElementDeclaration inElement = (XSDElementDeclaration)next.getValue();
final XSDElementDeclaration outElement = (XSDElementDeclaration)root.getXsdComponent();
option.setModel(wsModelName);
if (project == null) {
project = getModelProject(outDoc);
}
option.setCurrentProject(project);
option.setOperationOutputMessageElem(outElement);
option.setOperationOutputXmlDoc(outDoc);
option.setOperationOutputMessageName(outElement.getName() + OUT_MSG);
if (inElement != null) {
option.setOperationInputMessageElem(inElement);
option.setOperationInputMessageName(inElement.getName() + IN_MSG);
}
// if the root.getName() contains an _Output, let's remove it
String interfaceName = null;
if (rootModelName != null) {
interfaceName = rootModelName + "_" + root.getName(); //$NON-NLS-1$
} else {
interfaceName = root.getName();
}
int osIndex = interfaceName.indexOf(OUTPUT_SUFFIX);
if (osIndex > -1) {
interfaceName = interfaceName.substring(0, osIndex);
}
option.setInterface(interfaceName);
String operationName = GET_PREFIX + root.getName();
int onIndex = operationName.indexOf(OUTPUT_SUFFIX);
if (onIndex > -1) {
operationName = operationName.substring(0, onIndex);
}
option.setOperationName(operationName);
if (project != null) options.add(option);
else {
if (HEADLESS) {
options.add(option);
} else {
final String msg = Util.getString("GenerateXsdWizard.invalidWsOption", root.getName()); //$NON-NLS-1$
addStatus(IStatus.ERROR, msg, null);
}
}
}
}
// Let's order the collection of options alphabetically based on operationName
Object[] optionsArray = options.toArray();
Arrays.sort(optionsArray);
Collection sortedOptions = new ArrayList(options.size());
for (int i = 0; i < optionsArray.length; i++) {
sortedOptions.add(optionsArray[i]);
}
return sortedOptions;
}
}