/*
* 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.ui.wizards;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.util.ModelContents;
import org.teiid.designer.core.util.ModelResourceContainerFactory;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.core.workspace.ModelWorkspaceException;
import org.teiid.designer.metamodels.core.Annotation;
import org.teiid.designer.metamodels.core.ModelType;
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.Index;
import org.teiid.designer.metamodels.relational.Procedure;
import org.teiid.designer.metamodels.relational.RelationalFactory;
import org.teiid.designer.metamodels.relational.RelationalPackage;
import org.teiid.designer.metamodels.relational.Schema;
import org.teiid.designer.metamodels.relational.View;
import org.teiid.designer.relational.ui.UiConstants;
import org.teiid.designer.relational.ui.textimport.ColumnRowObject;
import org.teiid.designer.relational.ui.textimport.IndexRowObject;
import org.teiid.designer.relational.ui.textimport.RelationalRowFactory;
import org.teiid.designer.tools.textimport.ui.wizards.AbstractObjectProcessor;
import org.teiid.designer.tools.textimport.ui.wizards.AbstractRowObject;
import org.teiid.designer.tools.textimport.ui.wizards.IRowObject;
import org.teiid.designer.ui.viewsupport.ModelUtilities;
/**
* @since 8.0
*/
public class RelationalObjectProcessor extends AbstractObjectProcessor {
//============================================================================================================================
// Static Constants
private static final String XMI_EXTENSION = "xmi";//$NON-NLS-1$
private static final String I18N_PREFIX = "RelationalObjectProcessor"; //$NON-NLS-1$
private static final String SEPARATOR = "."; //$NON-NLS-1$
public static final String RELATIONAL_PACKAGE_URI = RelationalPackage.eNS_URI;
public static final RelationalFactory factory = RelationalFactory.eINSTANCE;
public static final int UNKNOWN = RelationalRowFactory.UNKNOWN;
public static final int SCHEMA = RelationalRowFactory.SCHEMA;
public static final int CATALOG = RelationalRowFactory.CATALOG;
public static final int BASE_TABLE = RelationalRowFactory.BASE_TABLE;
public static final int VIEW = RelationalRowFactory.VIEW;
public static final int INDEX = RelationalRowFactory.INDEX;
public static final int COLUMN = RelationalRowFactory.COLUMN;
//============================================================================================================================
// Static Methods
private List otherModifiedResources = new ArrayList();
private IProgressMonitor monitor;
/**
*
* @since 4.2
*/
public RelationalObjectProcessor() {
super();
}
public Collection createRowObjsFromStrings(Collection rowStrings) {
Iterator iter = rowStrings.iterator();
String nextStr = null;
RelationalRowFactory factory = new RelationalRowFactory();
Collection stringRows = new ArrayList();
IRowObject nextRow = null;
while( iter.hasNext() ) {
nextStr = (String)iter.next();
nextRow = factory.createRowObject(nextStr);
if( nextRow != null && nextRow.isValid() )
stringRows.add(nextRow);
else {
logParsingError(nextStr);
}
}
return stringRows;
}
public void generateObjsFromRowObjs(ModelResource targetResource, Object location, Collection rowObjects,
boolean useStringDefaultDatatype, EObject defaultDatatype, int defaultLength) {
int iRow = 0;
Iterator iter = rowObjects.iterator();
AbstractRowObject nextRow = null;
EObject newObject = null;
Object finalLocation = null;
HashMap columnMap = new HashMap();
EObject lastEContainer = null;
String sSize = Integer.toString(rowObjects.size());
while( iter.hasNext() ) {
iRow++;
nextRow = (AbstractRowObject)iter.next();
finalLocation = location;
if( monitor != null ) {
monitor.worked(1);
monitor.subTask(UiConstants.Util.getString(I18N_PREFIX + SEPARATOR + "incrementalProgress", Integer.toString(iRow), sSize, nextRow.getName())); //$NON-NLS-1$
}
// if row has a location defined
if( nextRow.getLocation() != null ) {
String rowLocation = nextRow.getLocation();
finalLocation = getOrCreateLocation(rowLocation, factory);
if( finalLocation != null ) {
ModelResource actualModelResource = targetResource;
if(finalLocation instanceof ModelResource) {
actualModelResource = (ModelResource)finalLocation;
} else {
// get the seg index to the model
int modelSegIndex = getModelPathIndex(rowLocation);
IPath locPath = new Path(rowLocation);
actualModelResource = getModelResource(locPath.uptoSegment(modelSegIndex).toOSString());
}
if( !targetResource.equals(actualModelResource) && !otherModifiedResources.contains(actualModelResource)) {
otherModifiedResources.add(actualModelResource);
}
} else {
// If we couldn't create one, we use the selected existing one, just to be safe.
finalLocation = location;
}
}
switch( nextRow.getObjectType() ) {
case SCHEMA: {
newObject = createEObject(factory, finalLocation, nextRow, null, false, null, 0);
} break;
case CATALOG: {
newObject = createEObject(factory, finalLocation, nextRow, null, false, null, 0);
} break;
case VIEW:
case BASE_TABLE: {
newObject = createEObject(factory, finalLocation, nextRow, null,
useStringDefaultDatatype, defaultDatatype, defaultLength);
// New table or view, so any indexes for a new table will not use "old" columns.
columnMap.clear();
lastEContainer = newObject;
} break;
case INDEX: {
newObject = createEObject(factory, finalLocation, nextRow, columnMap,
useStringDefaultDatatype, defaultDatatype, defaultLength);
lastEContainer = newObject;
} break;
case COLUMN: {
newObject = createEObject(factory, lastEContainer, nextRow, null,
useStringDefaultDatatype, defaultDatatype, defaultLength);
columnMap.put(nextRow.getName(), newObject);
} break;
case UNKNOWN:
default: {
} break;
}
if( monitor.isCanceled() ) {
break;
}
}
}
private EObject createEObject(RelationalFactory factory, Object location, IRowObject someRow, HashMap columnMap,
boolean useStringDefaultDatatype, EObject defaultDatatype, int defaultLength) {
EObject newEObject = null;
ModelResource modelResrc = null;
if(location instanceof ModelResource) {
modelResrc = (ModelResource)location;
} else if(location instanceof EObject) {
modelResrc = ModelerCore.getModelEditor().findModelResource((EObject)location);
}
switch(someRow.getObjectType()) {
case CATALOG: {
Catalog catalog = (Catalog)createCatalog(someRow.getName());
if( catalog != null ) {
newEObject = catalog;
if( location instanceof ModelResource ) {
addValue(location, catalog, getModelResourceContents((ModelResource)location));
}
if(modelResrc!=null) {
createAnnotation(modelResrc, catalog, someRow.getDescription());
}
}
} break;
case SCHEMA: {
Catalog cat = null;
if( location instanceof Catalog)
cat = (Catalog)location;
Schema schema = (Schema)createSchema(someRow.getName(), cat);
if( schema != null ) {
newEObject = schema;
if( location instanceof ModelResource ) {
addValue(location, schema, getModelResourceContents((ModelResource)location));
} else if( location instanceof Catalog ) {
addValue(location, schema, ((Catalog)location).getSchemas());
}
if(modelResrc!=null) {
createAnnotation(modelResrc, schema, someRow.getDescription());
}
}
} break;
case BASE_TABLE: {
BaseTable bt = (BaseTable)createBaseTable(someRow.getName(), false);
if( bt != null ) {
newEObject = bt;
if( location instanceof ModelResource ) {
addValue(location, bt, getModelResourceContents((ModelResource)location));
} else if( location instanceof Schema ) {
addValue(location, bt, ((Schema)location).getTables());
} else if( location instanceof Catalog ) {
addValue(location, bt, ((Catalog)location).getTables());
}
if(modelResrc!=null) {
createAnnotation(modelResrc, bt, someRow.getDescription());
}
}
} break;
case VIEW: {
} break;
case INDEX: {
IndexRowObject row = (IndexRowObject)someRow;
Index index = factory.createIndex();
if( index != null ) {
newEObject = index;
index.setName(row.getName());
index.setUnique(row.isUnique());
// let's walk through the columnNames for the index
// and get the EObject out of the columnMap
if( columnMap != null && !columnMap.isEmpty() ) {
Iterator iter = row.getColumnNames().iterator();
while( iter.hasNext() ) {
String nextName = (String)iter.next();
EObject eObj = (EObject)columnMap.get(nextName);
if( eObj != null ) {
addValue(index, eObj, index.getColumns());
}
}
}
if( location instanceof ModelResource ) {
addValue(location, index, getModelResourceContents((ModelResource)location));
} else if( location instanceof Schema ) {
index.setSchema((Schema)location);
addValue(location, index, ((Schema)location).getIndexes());
} else if( location instanceof Catalog ) {
index.setCatalog((Catalog)location);
addValue(location, index, ((Catalog)location).getIndexes());
}
if(modelResrc!=null) {
createAnnotation(modelResrc, index, row.getDescription());
}
}
} break;
case COLUMN: {
ColumnRowObject row = (ColumnRowObject)someRow;
Column col = factory.createColumn();
if( col != null ) {
newEObject = col;
col.setName(row.getName());
if( row.getDatatype() != null)
col.setType(row.getDatatype());
else {
if( useStringDefaultDatatype &&
defaultDatatype != null ) {
col.setType(defaultDatatype);
}
}
if( row.getLength() > 0 )
col.setLength(row.getLength());
else if( useStringDefaultDatatype ) {
col.setLength(defaultLength);
}
if( location instanceof BaseTable ) {
addValue(location, col, ((BaseTable)location).getColumns());
} else if( location instanceof View ) {
addValue(location, col, ((View)location).getColumns());
}
if(modelResrc!=null) {
createAnnotation(modelResrc, col, row.getDescription());
}
}
} break;
default:
break;
}
return newEObject;
}
public static EObject createBaseTable(final String name, final boolean supportsUpdate) {
BaseTable bt = factory.createBaseTable();
bt.setName(name);
bt.setSupportsUpdate(supportsUpdate);
return bt;
}
public static EObject createProcedure(final String name) {
Procedure proc = factory.createProcedure();
proc.setName(name);
return proc;
}
public static EObject createSchema(final String name, Catalog catalog) {
Schema newSchema = factory.createSchema();
newSchema.setName(name);
if( catalog != null )
newSchema.setCatalog(catalog);
return newSchema;
}
private EObject createSchema(Object parent, String folderName, RelationalFactory factory) {
Schema newSchema = factory.createSchema();
newSchema.setName(folderName);
if( parent instanceof Catalog ) {
addValue(parent, newSchema, ((Catalog)parent).getSchemas());
} else if( parent instanceof ModelResource ) {
addValue(parent, newSchema, getModelResourceContents((ModelResource)parent));
}
return newSchema;
}
public static EObject createCatalog(final String name) {
Catalog newCatalog = factory.createCatalog();
newCatalog.setName(name);
return newCatalog;
}
private void createAnnotation(ModelResource targetResource, EObject eObject, String description) {
if( description != null && description.length() > 0 ) {
final ModelContents contents = ModelerCore.getModelEditor().getModelContents(targetResource);
Annotation newAnnot = ModelResourceContainerFactory.createNewAnnotation(eObject, contents.getAnnotationContainer(true));
newAnnot.setDescription(description);
}
}
public void setProgressMonitor(IProgressMonitor monitor) {
this.monitor = monitor;
}
public static boolean isSchema(final Object obj) {
return obj instanceof Schema;
}
public static boolean isCatalog(final Object obj) {
return obj instanceof Catalog;
}
public static EList getTablesEList(final Object obj) {
if( isSchema(obj) ) {
return ((Schema)obj).getTables();
} else if( isCatalog(obj) ) {
((Catalog)obj).getTables();
}
return null;
}
public List getOtherModifiedResources() {
return otherModifiedResources;
}
/**
* handler for Create Relationships Model Button pressed
*/
private ModelResource createRelationalModel(IResource targetRes, String sNewRelationshipModelName ) {
ModelResource mr = constructRelationalModel(targetRes , sNewRelationshipModelName );
// Save Relationship Model
try {
if( mr != null ) {
mr.save( null, false );
}
} catch (ModelWorkspaceException mwe) {
UiConstants.Util.log( mwe );
}
return mr;
}
/**
* Create a Relationships Model with the supplied name, in the desired project
* @param targetProj the project resource under which to create the model
* @param modelName the model name to create
* @return the newly-created ModelResource
*/
public ModelResource constructRelationalModel( IResource targetRes, String sModelName ) {
IPath relativeModelPath = targetRes.getProjectRelativePath().append( sModelName ).addFileExtension(XMI_EXTENSION);
final IFile modelFile = targetRes.getProject().getFile( relativeModelPath );
final ModelResource resrc = ModelerCore.create( modelFile );
try {
resrc.getModelAnnotation().setPrimaryMetamodelUri( RELATIONAL_PACKAGE_URI );
resrc.getModelAnnotation().setModelType(ModelType.PHYSICAL_LITERAL);
ModelUtilities.initializeModelContainers(resrc, "Create Model Containers", this); //$NON-NLS-1$
} catch ( ModelWorkspaceException mwe ) {
mwe.printStackTrace();
}
return resrc;
}
/**
* Find the model (if one exists) along the provided path string. Return the index of the path segment
* that is the model. If no model was found, return value is -1.
* @param path the path string which may have a model in it.
* @return the path segment index of the model, -1 if none found.
*/
private int getModelPathIndex(String pathStr) {
int modelIndex = -1;
// Walk the segments one at a time, starting at last one.
ModelResource mr = null;
IPath path = new Path(pathStr);
int nSegs = path.segmentCount();
if( nSegs > 1 ) {
// First find and open the project (first segment) and open it.
String projSeg = path.segment(0);
// Check if Project exists - if it doesnt, create it.
IProject existProj = ModelerCore.getWorkspace().getRoot().getProject(projSeg);
if( !existProj.exists() ) {
existProj = createProject(existProj, new NullProgressMonitor());
}
// If project exists, continue processing
if( existProj.exists() ) {
if( !existProj.isOpen() ) {
try {
existProj.open(new NullProgressMonitor());
} catch (CoreException e) {
UiConstants.Util.log(e);
}
}
for(int i=nSegs; i>1; i--) {
IPath workingPath = path.uptoSegment(i);
String osPathStr = workingPath.toOSString();
if(osPathStr!=null && osPathStr.length()>0) {
mr = getModelResource(osPathStr);
}
if(mr!=null) {
modelIndex = i;
break;
}
}
}
}
return modelIndex;
}
private Object getOrCreateLocation(String location, RelationalFactory factory) {
ModelResource mr = null;
IPath locPath = new Path(location);
int nSegs = locPath.segmentCount();
int modelSegIndex = getModelPathIndex(location);
// If model was found along the path, use it
if(modelSegIndex!=-1) {
mr = getModelResource(locPath.uptoSegment(modelSegIndex).toOSString());
// Provided path goes beyond the Model - need to create schema under it.
if(nSegs>modelSegIndex) {
// If we are here, then we need to create folders
int nFolders = nSegs - modelSegIndex;
EObject folderEObject = null;
Object parent = mr;
for( int i=0; i<nFolders; i++ ) {
// First find folder EObject
String sFolderPath = locPath.uptoSegment(modelSegIndex+1 + i).toOSString();
folderEObject = getEObject(sFolderPath);
if( folderEObject == null ) {
// Create a Schema here (Assume it's a schema not a catalog)
folderEObject = createSchema(parent, locPath.segment(modelSegIndex+i), factory);
if( i == nFolders - 1)
return folderEObject;
parent = folderEObject;
} else {
parent = folderEObject;
if( i == nFolders - 1)
return folderEObject;
}
}
// Provided path stops at the Model, just return the Model.
} else {
return mr;
}
// Model not found, assume a new model is to be created under project
} else {
String projSeg = locPath.segment(0);
// Check if Project exists
IProject existProj = ModelerCore.getWorkspace().getRoot().getProject(projSeg);
if( !existProj.exists() )
existProj = createProject(existProj, new NullProgressMonitor());
if( existProj.exists() ) {
if( !existProj.isOpen() ) {
try {
existProj.open(new NullProgressMonitor());
} catch (CoreException e) {
UiConstants.Util.log(e);
}
}
// We shouldn't have to create one and we should expect the model to not exist
IPath modelPath = new Path(locPath.segment(1)).addFileExtension(XMI_EXTENSION);
if( !existProj.exists(modelPath) ) { //new Path(locPath.segment(1)) )) {
// Need to create model here with this name
mr = createRelationalModel(existProj, locPath.segment(1));
} else {
mr = getModelResource(locPath.uptoSegment(2).toOSString());
}
if( nSegs == 2 )
return mr;
// If we are here, then we need to create folders
int nFolders = nSegs - 2;
EObject folderEObject = null;
Object parent = mr;
for( int i=0; i<nFolders; i++ ) {
// First find folder EObject
String sFolderPath = locPath.uptoSegment(3 + i).toOSString();
folderEObject = getEObject(sFolderPath);
if( folderEObject == null ) {
// Create a Schema here (Assume it's a schema not a catalog)
folderEObject = createSchema(parent, locPath.segment(2+i), factory);
if( i == nFolders - 1)
return folderEObject;
parent = folderEObject;
} else {
parent = folderEObject;
if( i == nFolders - 1)
return folderEObject;
}
}
}
}
// We shouldn't get here, so log a message
UiConstants.Util.log(IStatus.ERROR, "Problems creating non existing folder or model for new relationship. Path = " + location); //$NON-NLS-1$
return null;
}
}