/* * 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.relational.model; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.emf.ecore.EObject; import org.eclipse.osgi.util.NLS; import org.teiid.core.designer.ModelerCoreException; import org.teiid.designer.core.ModelEditor; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.extension.ExtensionPlugin; import org.teiid.designer.extension.ModelExtensionAssistantAggregator; import org.teiid.designer.metamodels.relational.AccessPattern; import org.teiid.designer.metamodels.relational.BaseTable; import org.teiid.designer.metamodels.relational.Catalog; 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.Index; import org.teiid.designer.metamodels.relational.NullableType; 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.SearchabilityType; import org.teiid.designer.metamodels.relational.UniqueKey; import org.teiid.designer.metamodels.relational.View; import org.teiid.designer.relational.Messages; import org.teiid.designer.relational.RelationalConstants; import org.teiid.designer.relational.RelationalPlugin; /** * Factory for creating RelationalReference objects * This will create objects 'from scratch', or will create reference objects from EMF objects * * @since 8.2 */ public class RelationalReferenceFactory implements RelationalConstants { public static RelationalReferenceFactory INSTANCE = new RelationalReferenceFactory(); private ModelExtensionAssistantAggregator medAggregator = ExtensionPlugin.getInstance().getModelExtensionAssistantAggregator(); private ModelEditor getModelEditor() { return ModelerCore.getModelEditor(); } /** * Create the RelationalModel object representation of an EMF Model * @param modelResource the ModelResource * @return the RelationalModel object representation * @throws Exception the exception */ public RelationalModel createRelationalModel(ModelResource modelResource) throws Exception { String modelName = getModelEditor().getModelName(modelResource); RelationalModel relationalModel = new RelationalModel(modelName); // Some objects deferred since they reference other objects which must be created first Map<EObject,RelationalReference> deferredCreateMap = new HashMap<EObject,RelationalReference>(); // Process the primary objects List<EObject> rootEObjs = modelResource.getAllRootEObjects(); for(EObject eObj : rootEObjs) { Map<EObject,RelationalReference> deferredObjMap = createObject(eObj,null,relationalModel); if(!deferredObjMap.isEmpty()) { deferredCreateMap.putAll(deferredObjMap); } } // Now process all the 'deferred' objects. These are objects which reference other objects (which are required to exist first) createDeferredObjects(deferredCreateMap,relationalModel); return relationalModel; } /** * Create RelationalReference objects * @param node the provided EObject * @param model the RelationalModel being created * @param schema the schema * @return the map of EObjects which need to be deferred * @throws Exception */ protected Map<EObject,RelationalReference> createObject(EObject eObj, RelationalReference parent, RelationalModel model) throws Exception { Map<EObject,RelationalReference> deferredMap = new HashMap<EObject,RelationalReference>(); // ----------------------------------------------------------------------- // Standard DDL // ----------------------------------------------------------------------- if(eObj instanceof BaseTable) { BaseTable tableEObj = (BaseTable)eObj; // Create BaseTable with its columns and ext properties RelationalTable table = createBaseTable(tableEObj); // FKs, PK, AP are deferred List<ForeignKey> fks = tableEObj.getForeignKeys(); for(ForeignKey fk : fks) { deferredMap.put(fk, table); } List<AccessPattern> aps = tableEObj.getAccessPatterns(); for(AccessPattern ap : aps) { deferredMap.put(ap, table); } PrimaryKey pk = tableEObj.getPrimaryKey(); if(pk!=null) { deferredMap.put(pk, table); } if(parent!=null) { table.setParent(parent); } else { model.addChild(table); } } else if(eObj instanceof Procedure) { Procedure procEObj = (Procedure)eObj; // Create Procedure with its children and ext properties RelationalProcedure proc = createProcedure(procEObj); if(parent!=null) { proc.setParent(parent); } else { model.addChild(proc); } } else if(eObj instanceof Index) { Index indexEObj = (Index)eObj; deferredMap.put(indexEObj, null); } else if(eObj instanceof View) { View viewEObj = (View)eObj; // Create View with its children RelationalView view = createView(viewEObj); List<AccessPattern> aps = viewEObj.getAccessPatterns(); for(AccessPattern ap : aps) { deferredMap.put(ap, view); } if(parent!=null) { view.setParent(parent); } else { model.addChild(view); } } else if(eObj instanceof Catalog) { // resultObj = createCatalog(((Catalog)eObj)); } return deferredMap; } /** * Create deferred objects using the supplied map * @param deferredObjects the map of deferred EObjects * @param model the RelationalModel being created * @throws Exception */ protected void createDeferredObjects(Map<EObject,RelationalReference> deferredObjects, RelationalModel model) throws Exception { Collection<RelationalReference> allRefs = model.getAllReferences(); Set<EObject> eObjs = deferredObjects.keySet(); for(EObject eObj : eObjs) { if(eObj instanceof PrimaryKey) { RelationalTable table = (RelationalTable)deferredObjects.get(eObj); RelationalPrimaryKey pk = createPrimaryKey((PrimaryKey)eObj, table, allRefs); table.setPrimaryKey(pk); } else if(eObj instanceof ForeignKey) { RelationalTable table = (RelationalTable)deferredObjects.get(eObj); RelationalForeignKey fk = createForeignKey((ForeignKey)eObj, table, allRefs); table.addForeignKey(fk); } else if(eObj instanceof AccessPattern) { RelationalTable table = (RelationalTable)deferredObjects.get(eObj); RelationalAccessPattern ap = createAccessPattern((AccessPattern)eObj, table, allRefs); table.addAccessPattern(ap); } else if(eObj instanceof Index) { RelationalIndex index = createIndex((Index)eObj, allRefs); model.addChild(index); } } } /** * Create a Relational Table from EObject, including columns and ext properties * @param tableEObj the EMF object * @return the new RelationalTable */ public RelationalTable createBaseTable(BaseTable tableEObj) { RelationalTable table = new RelationalTable(); table.setName(tableEObj.getName()); table.setNameInSource(tableEObj.getNameInSource()); setDescription(table,tableEObj); table.setMaterialized(tableEObj.isMaterialized()); table.setCardinality(tableEObj.getCardinality()); table.setSupportsUpdate(tableEObj.isSupportsUpdate()); table.setSystem(tableEObj.isSystem()); List<Column> columns = tableEObj.getColumns(); for(Column column : columns) { RelationalColumn relColumn = createColumn(column); if(relColumn!=null) table.addColumn(relColumn); } // Set the extension properties setExtensionProperties(table,tableEObj); return table; } /** * Set Description on the RelationalReference by transferring it from the EObject. * @param relationalRef the RelationalReference * @param eObject the source EObject */ private void setDescription(RelationalReference relationalRef, EObject eObject) { try { // Set Description String desc = getModelEditor().getDescription(eObject); relationalRef.setDescription(desc); } catch (ModelerCoreException ex) { RelationalPlugin.Util.log(IStatus.ERROR, NLS.bind(Messages.relationalRefFactory_errorSettingDescription, relationalRef.getName())); relationalRef.setDescription(null); } } /** * Get the extension properties from the supplied EObject and set them on the supplied RelationalReference object * @param relationalRef the target RelationalReference * @param eObj the source EObject */ private void setExtensionProperties(RelationalReference relationalRef, EObject eObj) { Properties extProps = null; try { extProps = this.medAggregator.getPropertyValues(eObj); } catch (Exception ex) { RelationalPlugin.Util.log(IStatus.ERROR, NLS.bind(Messages.relationalRefFactory_errorGettingEmfExtProps, relationalRef.getName())); } relationalRef.setExtensionProperties(extProps); } /** * Create a RelationalIndex from an EMF Index * @param indexEObj the EMF index * @param allRefs list of all refs in the RelationalModel * @return the new RelationalIndex object */ public RelationalIndex createIndex(Index indexEObj, Collection<RelationalReference> allRefs) { RelationalIndex index = new RelationalIndex(); index.setName(indexEObj.getName()); index.setNameInSource(indexEObj.getNameInSource()); setDescription(index,indexEObj); index.setFilterCondition(indexEObj.getFilterCondition()); List<Column> columns = indexEObj.getColumns(); for(Column column : columns) { RelationalColumn relColumn = find(RelationalColumn.class, column, null, allRefs); if(relColumn==null) { RelationalPlugin.Util.log(IStatus.WARNING, NLS.bind(Messages.relationalRefFactory_columnNotFound_forIndexCreate, column.getName())); } else { relColumn.setParent(index); index.addColumn(relColumn); } } setExtensionProperties(index,indexEObj); return index; } /** * Create a RelationalView from an EMF View * @param viewEObj the EMF view * @return the new RelationalView object */ public RelationalView createView(View viewEObj) { RelationalView view = new RelationalView(); view.setName(viewEObj.getName()); view.setNameInSource(viewEObj.getNameInSource()); setDescription(view,viewEObj); view.setMaterialized(viewEObj.isMaterialized()); view.setCardinality(viewEObj.getCardinality()); view.setSupportsUpdate(viewEObj.isSupportsUpdate()); view.setSystem(viewEObj.isSystem()); List<Column> columns = viewEObj.getColumns(); for(Column column : columns) { RelationalColumn relColumn = createColumn(column); view.addColumn(relColumn); } setExtensionProperties(view,viewEObj); return view; } /** * Create a RelationalColumn from an EMF Column * @param columnEObj the EMF Column * @return the new RelationalColumn object */ public RelationalColumn createColumn(Column columnEObj) { RelationalColumn relCol = new RelationalColumn(); relCol.setName(columnEObj.getName()); relCol.setNameInSource(columnEObj.getNameInSource()); setDescription(relCol,columnEObj); relCol.setDefaultValue(columnEObj.getDefaultValue()); relCol.setCharacterSetName(columnEObj.getCharacterSetName()); relCol.setDistinctValueCount(columnEObj.getDistinctValueCount()); relCol.setLength(columnEObj.getLength()); relCol.setNativeType(columnEObj.getNativeType()); relCol.setMaximumValue(columnEObj.getMaximumValue()); relCol.setMinimumValue(columnEObj.getMinimumValue()); relCol.setPrecision(columnEObj.getPrecision()); relCol.setRadix(columnEObj.getRadix()); relCol.setScale(columnEObj.getScale()); relCol.setAutoIncremented(columnEObj.isAutoIncremented()); relCol.setCaseSensitive(columnEObj.isCaseSensitive()); relCol.setCurrency(columnEObj.isCurrency()); relCol.setLengthFixed(columnEObj.isFixedLength()); relCol.setSelectable(columnEObj.isSelectable()); relCol.setSigned(columnEObj.isSigned()); relCol.setUpdateable(columnEObj.isUpdateable()); NullableType nullType = columnEObj.getNullable(); relCol.setNullable(nullType.getLiteral()); SearchabilityType searchabilityType = columnEObj.getSearchability(); relCol.setSearchability(searchabilityType.getLiteral()); String dTypeName = getModelEditor().getName(columnEObj.getType()); relCol.setDatatype(dTypeName); setExtensionProperties(relCol,columnEObj); return relCol; } /** * Create a RelationalForeignKey from an EMF ForeignKey * @param fk the EMF ForeignKey * @param table the parent table * @param allRefs all RelationalReferences in the model * @return the new RelationalForeignKey object */ public RelationalForeignKey createForeignKey(ForeignKey fk, RelationalTable table, Collection<RelationalReference> allRefs) { RelationalForeignKey relFK = new RelationalForeignKey(); relFK.setName(fk.getName()); relFK.setNameInSource(fk.getNameInSource()); setDescription(relFK,fk); List<Column> columns = fk.getColumns(); for(Column column : columns) { RelationalColumn relColumn = find(RelationalColumn.class, column, table, allRefs); if(relColumn==null) { RelationalPlugin.Util.log(IStatus.WARNING, NLS.bind(Messages.relationalRefFactory_columnNotFound_forFKCreate, column.getName())); } else { relFK.addColumn(relColumn); } } UniqueKey uniqueKey = fk.getUniqueKey(); if(uniqueKey!=null) { String uniqueKeyName = uniqueKey.getName(); if(uniqueKeyName!=null) relFK.setUniqueKeyName(uniqueKeyName); BaseTable uniqueKeyTable = uniqueKey.getTable(); if(uniqueKeyTable!=null) { String uniqueKeyTableName = uniqueKeyTable.getName(); if(uniqueKeyTableName!=null) { relFK.setUniqueKeyTableName(uniqueKeyTableName); } } } setExtensionProperties(relFK,fk); return relFK; } /** * Create a RelationalPrimaryKey from an EMF PrimaryKey * @param pk the EMF PrimaryKey * @param table the parent table * @param allRefs all RelationalReferences in the model * @return the new RelationalPrimaryKey object */ public RelationalPrimaryKey createPrimaryKey(PrimaryKey pk, RelationalTable table, Collection<RelationalReference> allRefs) { RelationalPrimaryKey relPK = new RelationalPrimaryKey(); relPK.setName(pk.getName()); relPK.setNameInSource(pk.getNameInSource()); setDescription(relPK,pk); List<Column> columns = pk.getColumns(); for(Column column : columns) { RelationalColumn relColumn = find(RelationalColumn.class, column, table, allRefs); if(relColumn==null) { RelationalPlugin.Util.log(IStatus.WARNING, NLS.bind(Messages.relationalRefFactory_columnNotFound_forPKCreate, column.getName())); } else { relPK.addColumn(relColumn); } } setExtensionProperties(relPK,pk); return relPK; } /** * Create a RelationalAccessPattern from an EMF AccessPattern * @param ap the EMF AccessPattern * @param table the parent table * @param allRefs all RelationalReferences in the model * @return the new RelationalAccessPattern object */ public RelationalAccessPattern createAccessPattern(AccessPattern ap, RelationalTable table, Collection<RelationalReference> allRefs) { RelationalAccessPattern relAP = new RelationalAccessPattern(); relAP.setName(ap.getName()); relAP.setNameInSource(ap.getNameInSource()); setDescription(relAP,ap); List<Column> columns = ap.getColumns(); for(Column column : columns) { RelationalColumn relColumn = find(RelationalColumn.class, column, table, allRefs); if(relColumn==null) { RelationalPlugin.Util.log(IStatus.WARNING, NLS.bind(Messages.relationalRefFactory_columnNotFound_forAPCreate, column.getName())); } else { relAP.addColumn(relColumn); } } setExtensionProperties(relAP,ap); return relAP; } /** * Create a RelationalProcedure from an EMF Procedure * @param procEObj the EMF Procedure * @return the new RelationalProcedure object */ public RelationalProcedure createProcedure(Procedure procEObj) { RelationalProcedure proc = new RelationalProcedure(); proc.setName(procEObj.getName()); proc.setNameInSource(procEObj.getNameInSource()); setDescription(proc,procEObj); ProcedureResult procResult = procEObj.getResult(); if (procResult != null) { RelationalProcedureResultSet relProcResult = createProcedureResultSet(procResult); if(relProcResult!=null) { proc.setResultSet(relProcResult); } } List<ProcedureParameter> params = procEObj.getParameters(); for(ProcedureParameter param : params) { RelationalParameter relProcParam = createProcedureParameter(param); proc.addParameter(relProcParam); } setExtensionProperties(proc,procEObj); return proc; } /** * Create a RelationalProcedureResultSet from an EMF ProcedureResult * @param procResultSetEObj the EMF ProcedureResult * @return the new RelationalProcedureResultSet object */ public RelationalProcedureResultSet createProcedureResultSet(ProcedureResult procResultSetEObj) { RelationalProcedureResultSet relResultSet = new RelationalProcedureResultSet(); relResultSet.setName(procResultSetEObj.getName()); relResultSet.setNameInSource(procResultSetEObj.getNameInSource()); setDescription(relResultSet,procResultSetEObj); List<Column> columns = procResultSetEObj.getColumns(); for(Column column : columns) { RelationalColumn relColumn = createColumn(column); if(relColumn!=null) relResultSet.addColumn(relColumn); } setExtensionProperties(relResultSet,procResultSetEObj); return relResultSet; } /** * Create a RelationalParameter from an EMF ProcedureParameter * @param procParamEObj the EMF ProcedureParameter * @return the new RelationalParameter object */ public RelationalParameter createProcedureParameter(ProcedureParameter procParamEObj) { RelationalParameter relParam = new RelationalParameter(); relParam.setName(procParamEObj.getName()); relParam.setNameInSource(procParamEObj.getNameInSource()); setDescription(relParam,procParamEObj); relParam.setDirection(getDirectionKindStr(procParamEObj.getDirection())); relParam.setDefaultValue(procParamEObj.getDefaultValue()); relParam.setLength(procParamEObj.getLength()); relParam.setNativeType(procParamEObj.getNativeType()); relParam.setNullable(getNullableTypeStr(procParamEObj.getNullable())); relParam.setPrecision(procParamEObj.getPrecision()); relParam.setRadix(procParamEObj.getRadix()); relParam.setScale(procParamEObj.getScale()); String dTypeName = ModelerCore.getModelEditor().getName(procParamEObj.getType()); relParam.setDatatype(dTypeName); setExtensionProperties(relParam,procParamEObj); return relParam; } private String getDirectionKindStr(DirectionKind dir) { if(dir==DirectionKind.IN_LITERAL) { return DIRECTION.IN; } else if(dir==DirectionKind.INOUT_LITERAL) { return DIRECTION.IN_OUT; } else if(dir==DirectionKind.OUT_LITERAL) { return DIRECTION.OUT; } else if(dir==DirectionKind.RETURN_LITERAL) { return DIRECTION.RETURN; } return DIRECTION.UNKNOWN; } private String getNullableTypeStr(NullableType nType) { if(nType==NullableType.NULLABLE_LITERAL) { return NULLABLE.NULLABLE; } else if(nType==NullableType.NO_NULLS_LITERAL) { return NULLABLE.NO_NULLS; } return NULLABLE.NULLABLE_UNKNOWN; } /** * @param type type of RelationalReference to find * @param name the node name * @param node the AstNode * @param parent the parent reference * @param allModelRefs the collection of all model RelationalReferences * * @return RelationalReference which is a match * * @throws EntityNotFoundException * @throws CoreException */ protected <T extends RelationalReference> T find(Class<T> type, String name, EObject node, RelationalReference parent, Collection<RelationalReference> allModelRefs) { // Look through all refs list for a matching object for ( RelationalReference obj : allModelRefs) { if (type.isInstance(obj)) { T relEntity = (T)obj; if (relEntity.getName().equalsIgnoreCase(name)) { RelationalReference relParent = relEntity.getParent(); if(parent!=null) { if(relParent.getName().equalsIgnoreCase(parent.getName())) { return relEntity; } } else { return relEntity; } } } } return null; // throw new Exception(); // throw new EntityNotFoundException(I18n.format(DdlImporterI18n.ENTITY_NOT_FOUND_MSG, // type.getSimpleName(), // name, // DdlImporterI18n.MODEL, // parent == null ? getImporterManager().getModelName() : parent.getName(), // node.getProperty(StandardDdlLexicon.DDL_START_LINE_NUMBER).toString(), // node.getProperty(StandardDdlLexicon.DDL_START_COLUMN_NUMBER).toString())); } /** * @param type type of RelationalReference to find * @param eObj the EObject * @param parent the parent reference * @param allModelRefs the collection of all model RelationalReferences * @return RelationalReference which is a match * * @throws EntityNotFoundException * @throws CoreException */ protected <T extends RelationalReference> T find(Class<T> type, EObject eObj, RelationalReference parent, Collection<RelationalReference> allModelRefs) { return find(type, this.getModelEditor().getName(eObj), eObj, parent, allModelRefs); } /** * Create a Relational Model * @param modelName the name of the model * @return the new object */ public RelationalModel createModel(String modelName) { return new RelationalModel(modelName); } /** * Create a RelationalSchema * @return the new object */ public RelationalSchema createSchema( ) { return new RelationalSchema(); } /** * Create a RelationalTable * @return the new object */ public RelationalTable createBaseTable( ) { return new RelationalTable(); } /** * Create a Relational Table * @param name the name of the object * @return the new object */ public RelationalTable createBaseTable(String name) { return new RelationalTable(name); } /** * Create a RelationalView * @return the new object */ public RelationalView createView( ) { return new RelationalView(); } /** * Create a RelationalView * @param name the name of the object * @return the new object */ public RelationalView createView(String name) { return new RelationalView(name); } /** * Create a RelationalColumn * @return the new object */ public RelationalColumn createColumn( ) { return new RelationalColumn(); } /** * Create a RelationalAccessPattern * @return the new object */ public RelationalAccessPattern createAccessPattern( ) { return new RelationalAccessPattern(); } /** * Create a RelationalForeignKey * @return the new object */ public RelationalForeignKey createForeignKey( ) { return new RelationalForeignKey(); } /** * Create a RelationalIndex * @return the new object */ public RelationalIndex createIndex( ) { return new RelationalIndex(); } /** * Create a RelationalParameter * @return the new object */ public RelationalParameter createParameter( ) { return new RelationalParameter(); } /** * Create a Relational PrimaryKey * @return the new object */ public RelationalPrimaryKey createPrimaryKey( ) { return new RelationalPrimaryKey(); } /** * Create a RelationalProcedure * @return the new object */ public RelationalProcedure createProcedure( ) { return new RelationalProcedure(); } /** * Create a RelationalProcedureResultSet * @return the new object */ public RelationalProcedureResultSet createProcedureResultSet( ) { return new RelationalProcedureResultSet(); } /** * Create a RelationalUniqueConstraint * @return the new object */ public RelationalUniqueConstraint createUniqueConstraint( ) { return new RelationalUniqueConstraint(); } /** * Create a RelationalTable * @return the new object */ public RelationalViewTable createViewTable( ) { return new RelationalViewTable(); } /** * Create a RelationalTable * @return the new object */ public RelationalViewProcedure createViewProcedure( ) { return new RelationalViewProcedure(); } }