/* * 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.core.metadata.runtime; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; import org.eclipse.core.runtime.IStatus; 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.EStructuralFeature; import org.teiid.core.designer.id.ObjectID; import org.teiid.core.designer.util.CoreArgCheck; import org.teiid.core.designer.util.CoreStringUtil; import org.teiid.designer.core.ModelEditor; import org.teiid.designer.core.ModelEditorImpl; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.index.IndexConstants; import org.teiid.designer.core.index.IndexingContext; import org.teiid.designer.core.index.WordEntry; import org.teiid.designer.core.metamodel.aspect.AspectManager; import org.teiid.designer.core.metamodel.aspect.sql.SqlAnnotationAspect; import org.teiid.designer.core.metamodel.aspect.sql.SqlAspect; import org.teiid.designer.core.metamodel.aspect.sql.SqlColumnAspect; import org.teiid.designer.core.metamodel.aspect.sql.SqlColumnSetAspect; import org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect; import org.teiid.designer.core.metamodel.aspect.sql.SqlForeignKeyAspect; import org.teiid.designer.core.metamodel.aspect.sql.SqlModelAspect; import org.teiid.designer.core.metamodel.aspect.sql.SqlProcedureAspect; import org.teiid.designer.core.metamodel.aspect.sql.SqlProcedureParameterAspect; import org.teiid.designer.core.metamodel.aspect.sql.SqlTableAspect; import org.teiid.designer.core.metamodel.aspect.sql.SqlTransformationAspect; import org.teiid.designer.core.metamodel.aspect.sql.SqlTransformationInfo; import org.teiid.designer.core.metamodel.aspect.sql.SqlUniqueKeyAspect; import org.teiid.designer.core.metamodel.aspect.sql.SqlVdbAspect; import org.teiid.designer.extension.ExtensionPlugin; import org.teiid.designer.extension.definition.ModelExtensionAssistant; import org.teiid.designer.extension.definition.ModelObjectExtensionAssistant; import org.teiid.designer.extension.properties.ModelExtensionPropertyDefinition; import org.teiid.designer.extension.registry.ModelExtensionRegistry; import org.teiid.designer.metadata.runtime.impl.RecordFactory; import org.teiid.designer.metamodels.core.Annotation; /** * RuntimeAdapter * * @since 8.0 */ public class RuntimeAdapter extends RecordFactory { private static HashMap metaClassUriMap = new HashMap(); // ================================================================================== // P U B L I C M E T H O D S // ================================================================================== /** * Create the {@link WordEntry} instance(s) to be used as the index file record(s) for * this SqlAspect instance. The word entries are added to the list provided by the calling method. * * @param sqlAspect * @param modelPath * @param wordEntries the list to which WordEntry instances are added * @param addAllWords boolean indicating if certain types of indexes can be skipped based on type of indexer call this. */ public static void addIndexWord( final Object eObject, final IndexingContext context, final String modelPath, final Collection wordEntries ) { addIndexWord(eObject, context, modelPath, wordEntries, true); } /** * Create the {@link WordEntry} instance(s) to be used as the index file record. The * word entries are added to the list provided by the calling method. * * @param filePath The path to the file in the vdb * @param wordEntries the list to which WordEntry instances are added * @param addAllWords boolean indicating if certain types of indexes can be skipped based on type of indexer call this. */ public static void addFileIndexWord( final String filePath, final Collection wordEntries ) { // Construct a string containing the runtime metadata final StringBuffer sb = new StringBuffer(50); // append record header sb.append(IndexConstants.RECORD_TYPE.FILE); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the max set size sb.append(filePath); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); WordEntry wordEntry = new WordEntry(sb.toString().toCharArray()); wordEntries.add(wordEntry); } /** * Create the {@link WordEntry} instance(s) to be used as the index file record(s) for * this SqlAspect instance. The word entries are added to the list provided by the calling method. * * @param sqlAspect * @param modelPath * @param wordEntries the list to which WordEntry instances are added * @param addAllWords boolean indicating if certain types of indexes can be skipped based on type of indexer call this. */ public static void addIndexWord( final Object eObject, final IndexingContext context, final String modelPath, final Collection wordEntries, final boolean addAllWords ) { CoreArgCheck.isInstanceOf(EObject.class, eObject); SqlAspect sqlAspect = AspectManager.getSqlAspect((EObject)eObject); if (sqlAspect == null || !sqlAspect.isQueryable((EObject)eObject)) { return; } if (sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.COLUMN)) { addColumnWord((SqlColumnAspect)sqlAspect, (EObject)eObject, modelPath, wordEntries); } if (sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.TABLE)) { addTableWord((SqlTableAspect)sqlAspect, (EObject)eObject, context, modelPath, wordEntries); } if (sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.DATATYPE)) { addDatatypeWord((SqlDatatypeAspect)sqlAspect, (EObject)eObject, modelPath, wordEntries); } if (sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.CALLABLE)) { addCallableWord((SqlProcedureAspect)sqlAspect, (EObject)eObject, modelPath, wordEntries); } if (sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.CALLABLE_PARAMETER)) { addCallableParameterWord((SqlProcedureParameterAspect)sqlAspect, (EObject)eObject, modelPath, wordEntries); } if (sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.MODEL)) { addModelWord((SqlModelAspect)sqlAspect, (EObject)eObject, modelPath, wordEntries); } // these words are not needed for modeler indexing. if (addAllWords) { if (sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.UNIQUE_KEY) || sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.PRIMARY_KEY)) { addUniqueKeyWord((SqlUniqueKeyAspect)sqlAspect, (EObject)eObject, modelPath, wordEntries); } if (sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.INDEX) || sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.ACCESS_PATTERN) || sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.RESULT_SET)) { addColumnSetWord((SqlColumnSetAspect)sqlAspect, (EObject)eObject, modelPath, wordEntries); } if (sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.FOREIGN_KEY)) { addForeignKeyWord((SqlForeignKeyAspect)sqlAspect, (EObject)eObject, modelPath, wordEntries); } if (sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.SELECT_TRANSFORM) || sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.INSERT_TRANSFORM) || sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.UPDATE_TRANSFORM) || sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.DELETE_TRANSFORM) || sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.PROC_TRANSFORM) || sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.MAPPING_TRANSFORM)) { addTransformationWords((SqlTransformationAspect)sqlAspect, (EObject)eObject, context, modelPath, wordEntries); } if (sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.VDB_ARCHIVE)) { addVdbWord((SqlVdbAspect)sqlAspect, (EObject)eObject, modelPath, wordEntries); } if (sqlAspect.isRecordType(IndexConstants.RECORD_TYPE.ANNOTATION)) { addAnnotationWord((SqlAnnotationAspect)sqlAspect, (EObject)eObject, modelPath, wordEntries); } // add an extension property word for each EObject addPropertyWord(sqlAspect, (EObject)eObject, modelPath, wordEntries); } } /** * Create a {@link WordEntry} instance representing a model. This resulting WordEntry * is of the form: header|maxSetSize|boolean values|footer| */ public static void addModelWord( final SqlModelAspect aspect, final EObject eObject, final String modelPath, final Collection wordEntries ) { final String objectID = getObjectIdString(aspect.getObjectID(eObject)); // final EObject container = (eObject != null ? eObject.eContainer() : null); final String parentObjectID = null; // getObjectIdString(container); // The path returned from the aspect will be of the form Model/ModelAnnotation. We // only want the first segment for the model path. String fullName = aspect.getName(eObject); addModelWord(objectID, fullName, aspect.getNameInSource(eObject), parentObjectID, aspect.getMaxSetSize(eObject), aspect.getModelType(eObject), aspect.isVisible(eObject), aspect.supportsDistinct(eObject), aspect.supportsJoin(eObject), aspect.supportsOrderBy(eObject), aspect.supportsOuterJoin(eObject), aspect.supportsWhereAll(eObject), aspect.getPrimaryMetamodelUri(eObject), modelPath, wordEntries); } /** * Create a {@link WordEntry} instance representing a model. This resulting WordEntry * is of the form: header|maxSetSize|modelType|primaryMetamodelUri|boolean values|footer| */ static void addModelWord( final String objectID, final String fullName, final String nameInSource, final String parentObjectID, final int maxSetSize, final int modelType, final boolean isVisible, final boolean supportsDistinct, final boolean supportsJoin, final boolean supportsOrderBy, final boolean supportsOuterJoin, final boolean supportsWhereAll, final String primaryMetamodelUri, final String modelPath, final Collection wordEntries ) { // Construct a string containing the runtime metadata final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); appendWordHeader(IndexConstants.RECORD_TYPE.MODEL, objectID, fullName, nameInSource, parentObjectID, sb); // Append the max set size sb.append(maxSetSize); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the model type sb.append(modelType); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the primary metamodel Uri sb.append(primaryMetamodelUri); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the supports flags appendBoolean(isVisible, sb); appendBoolean(supportsDistinct, sb); appendBoolean(supportsJoin, sb); appendBoolean(supportsOrderBy, sb); appendBoolean(supportsOuterJoin, sb); appendBoolean(supportsWhereAll, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the footer appendWordFooter(modelPath, fullName, sb); addNewWordEntryToList(objectID, sb, wordEntries); } /** * Create a {@link WordEntry} instance representing a VDB archive. This resulting * WordEntry is of the form: header|version|identifer|producerName|producerVersion|provider|timeLastChanged| * timeLastProduced|modelIDs|description|footer| */ public static void addVdbWord( final SqlVdbAspect aspect, final EObject eObject, final String modelPath, final Collection wordEntries ) { final String objectID = getObjectIdString(aspect.getObjectID(eObject)); final String parentObjectID = null; // getObjectIdString(container); final String fullName = aspect.getFullName(eObject); final String name = aspect.getName(eObject); addVdbWord(objectID, fullName, aspect.getNameInSource(eObject), parentObjectID, aspect.getVersion(eObject), aspect.getIdentifier(eObject), aspect.getDescription(eObject), aspect.getProducerName(eObject), aspect.getProducerVersion(eObject), aspect.getProvider(eObject), aspect.getTimeLastChanged(eObject), aspect.getTimeLastProduced(eObject), aspect.getModelIDs(eObject), modelPath, name, wordEntries); } /** * Create a {@link WordEntry} instance representing a VDB archive. This resulting * WordEntry is of the form: header|version|identifer|producerName|producerVersion|provider|timeLastChanged| * timeLastProduced|modelIDs|description|footer| */ static void addVdbWord( final String objectID, final String fullName, final String nameInSource, final String parentObjectID, final String version, final String identifier, final String description, final String producerName, final String producerVersion, final String provider, final String timeLastChanged, final String timeLastProduced, final List modelIDs, final String modelPath, final String name, final Collection wordEntries ) { // Construct a string containing the runtime metadata final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); appendWordHeader(IndexConstants.RECORD_TYPE.VDB_ARCHIVE, objectID, fullName, nameInSource, parentObjectID, sb); // Append the version appendObject(version, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the identifier appendObject(identifier, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the producerName appendObject(producerName, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the producerVersion appendObject(producerVersion, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the provider appendObject(provider, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the timeLastChanged appendObject(timeLastChanged, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the timeLastProduced appendObject(timeLastProduced, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the modelIDs appendIDs(modelIDs, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the description appendObject(description, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the footer appendWordFooter(modelPath, name, sb); addNewWordEntryToList(objectID, sb, wordEntries); } /** * Create a {@link WordEntry} instance representing a transformation. This resulting * WordEntry is of the form: recordType|upperFullName|objectID|fullName|nameInSource|parentObjectID| * transformationType|transformedObjectID|transformation|bindingNames|schemaPaths|footer| */ public static void addTransformationWords( final SqlTransformationAspect aspect, final EObject eObject, final IndexingContext context, final String modelPath, final Collection wordEntries ) { final EObject virtualTable = (EObject)aspect.getTransformedObject(eObject); if (virtualTable == null) { return; } if (context != null) { if (context.hasTransformation(virtualTable)) { return; } context.addTargetTransform(virtualTable, eObject); } final String upperName = aspect.getFullName(eObject).toUpperCase(); final String transformedObjectID = getObjectIdString(virtualTable); final String transformationObjectID = getObjectIdString(eObject); final String name = aspect.getName(eObject); String[] types = aspect.getTransformationTypes(eObject); if (types != null) { for (int i = 0; i < types.length; i++) { // do not add words for transformations that are not allowed if (types[i].equals(SqlTransformationAspect.Types.INSERT) && !aspect.isInsertAllowed(eObject)) { continue; } if (types[i].equals(SqlTransformationAspect.Types.UPDATE) && !aspect.isUpdateAllowed(eObject)) { continue; } if (types[i].equals(SqlTransformationAspect.Types.DELETE) && !aspect.isDeleteAllowed(eObject)) { continue; } SqlTransformationInfo transInfo = aspect.getTransformationInfo(eObject, context, types[i]); if (transInfo != null && !CoreStringUtil.isEmpty(transInfo.getSqlTransform())) { String sqlTransform = transInfo.getSqlTransform(); List bindingNames = transInfo.getBindings(); List schemaPaths = transInfo.getSchemaPaths(); addTransformationWord(upperName, types[i], transformationObjectID, transformedObjectID, sqlTransform, bindingNames, schemaPaths, modelPath, name, wordEntries); } } } } /** * Create a {@link WordEntry} instance representing a transformation. This resulting * WordEntry is of the form: recordType|upperFullName|objectID|fullName|nameInSource|parentObjectID| * transformationType|transformedObjectID|transformation|bindingNames|schemaPaths|footer| */ static void addTransformationWord( final String upperName, final String tranformType, final String transformationObjectID, final String transformedObjectID, final String transformation, final List bindings, final List schemaPaths, final String modelPath, final String name, final Collection wordEntries ) { // Construct a string containing the runtime metadata final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); // Append the record type if (tranformType.equals(SqlTransformationAspect.Types.SELECT)) { sb.append(IndexConstants.RECORD_TYPE.SELECT_TRANSFORM); } else if (tranformType.equals(SqlTransformationAspect.Types.INSERT)) { sb.append(IndexConstants.RECORD_TYPE.INSERT_TRANSFORM); } else if (tranformType.equals(SqlTransformationAspect.Types.UPDATE)) { sb.append(IndexConstants.RECORD_TYPE.UPDATE_TRANSFORM); } else if (tranformType.equals(SqlTransformationAspect.Types.DELETE)) { sb.append(IndexConstants.RECORD_TYPE.DELETE_TRANSFORM); } else if (tranformType.equals(SqlTransformationAspect.Types.PROCEDURE)) { sb.append(IndexConstants.RECORD_TYPE.PROC_TRANSFORM); } else if (tranformType.equals(SqlTransformationAspect.Types.MAPPING)) { sb.append(IndexConstants.RECORD_TYPE.MAPPING_TRANSFORM); } sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // append fully qualified name of the virtual group appendObject(upperName, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the transformed object ID sb.append(transformedObjectID); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the transformed object ID sb.append(transformationObjectID); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // append the sql transformation appendObject(transformation, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // append the binding Names appendStrings(bindings, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // append the schemaPaths appendStrings(schemaPaths, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the footer appendWordFooter(modelPath, name, sb); addNewWordEntryToList(transformedObjectID, sb, wordEntries); } /** * Create a {@link WordEntry} instance representing a model. This resulting WordEntry * is of the form: header|isFunction|parameterIDs|resultSetID|footer| */ public static void addCallableWord( final SqlProcedureAspect aspect, final EObject eObject, final String modelPath, final Collection wordEntries ) { final String objectID = getObjectIdString(aspect.getObjectID(eObject)); // final EObject container = (eObject != null ? eObject.eContainer() : null); final String parentObjectID = null; // getObjectIdString(container); final String fullName = aspect.getFullName(eObject); final String name = aspect.getName(eObject); // Construct a string containing the runtime metadata final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); appendWordHeader(IndexConstants.RECORD_TYPE.CALLABLE, objectID, fullName, aspect.getNameInSource(eObject), parentObjectID, sb); // append booleans // append boolean indicating if the procedure is a function appendBoolean(aspect.isFunction(eObject), sb); // append boolean indicating if the procedure is virtual appendBoolean(aspect.isVirtual(eObject), sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the UUIDs of the parameter references appendIDs(aspect.getParameters(eObject), sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the UUID of the resultSet appendID(aspect.getResult(eObject), sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append procedure update count sb.append(aspect.getUpdateCount(eObject)); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the footer appendWordFooter(modelPath, name, sb); addNewWordEntryToList(objectID, sb, wordEntries); } /** * Create a {@link WordEntry} instance representing a model. This resulting WordEntry * is of the form: header|defaultValue|dataType|length|radix|scale|nullable|precision|position|paramType|isOptional|footer| */ public static void addCallableParameterWord( final SqlProcedureParameterAspect aspect, final EObject eObject, final String modelPath, final Collection wordEntries ) { final String objectID = getObjectIdString(aspect.getObjectID(eObject)); final String parentObjectID = getObjectIdString(aspect.getParentObjectID(eObject)); // final EObject container = (eObject != null ? eObject.eContainer() : null); // final String parentObjectID = getObjectIdString(container); final String fullName = aspect.getFullName(eObject); final String name = aspect.getName(eObject); // Construct a string containing the runtime metadata final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); appendWordHeader(IndexConstants.RECORD_TYPE.CALLABLE_PARAMETER, objectID, fullName, aspect.getNameInSource(eObject), parentObjectID, sb); // Append the defaultvalue of the parameter appendObject(aspect.getDefaultValue(eObject), sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the datatye of the parameter appendObject(aspect.getRuntimeType(eObject), sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the datatye uuid of the parameter appendObject(aspect.getDatatypeObjectID(eObject), sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the length sb.append(aspect.getLength(eObject)); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the radix sb.append(aspect.getRadix(eObject)); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the scale sb.append(aspect.getScale(eObject)); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the nullability sb.append(aspect.getNullType(eObject)); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the precision sb.append(aspect.getPrecision(eObject)); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the position sb.append(aspect.getPosition(eObject)); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the parameter type sb.append(aspect.getType(eObject)); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the parameter isOptional value appendBoolean(aspect.isOptional(eObject), sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the footer appendWordFooter(modelPath, name, sb); addNewWordEntryToList(objectID, sb, wordEntries); } /** * Create a {@link WordEntry} instance representing a table. This resulting WordEntry * is of the form: header|cardinality|boolean * values|columnIDs|primaryKeyID|foreignKeyIDs|indexIDs|uniqueKeyIDs|accessPatternIDs|materializedTableIDs|footer| */ public static void addTableWord( final SqlTableAspect aspect, final EObject eObject, final IndexingContext context, final String modelPath, final Collection wordEntries ) { final String objectID = getObjectIdString(aspect.getObjectID(eObject)); final String name = aspect.getName(eObject); final String parentObjectID = null; // getObjectIdString(container); final String fullName = aspect.getFullName(eObject); final String primaryKeyID = getObjectIdString(aspect.getPrimaryKey(eObject)); String materializedTableID = null; final boolean isMaterialized = aspect.isMaterialized(eObject); // Append the UUIDs of the materialized table references if (isMaterialized ) { // Check for an annotation for this EObject materializedTableID = aspect.getMaterializedTableId(eObject); } addTableWord(objectID, fullName, aspect.getNameInSource(eObject), parentObjectID, aspect.getCardinality(eObject), aspect.getTableType(eObject), aspect.isVirtual(eObject), aspect.isSystem(eObject), isMaterialized, aspect.supportsUpdate(eObject), primaryKeyID, aspect.getColumns(eObject), aspect.getForeignKeys(eObject), aspect.getIndexes(eObject), aspect.getUniqueKeys(eObject), aspect.getAccessPatterns(eObject), materializedTableID, modelPath, name, wordEntries); } /** * Create a {@link WordEntry} instance representing a table. This resulting WordEntry * is of the form: header|cardinality|boolean * values|columnIDs|primaryKeyID|foreignKeyIDs|indexIDs|uniqueKeyIDs|accessPatternIDs * |materializedTableID|materializedStageTableID|footer| */ static void addTableWord( final String objectID, final String fullName, final String nameInSource, final String parentObjectID, final int cardinality, final int tableType, final boolean isVirtual, final boolean isSystem, final boolean isMaterialized, final boolean supportsUpdate, final String primaryKeyID, final List columnIDs, final Collection foreignKeyIDs, final Collection indexIDs, final Collection uniqueKeyIDs, final Collection accessPatternIDs, final String materializedTableID, final String modelPath, final String name, final Collection wordEntries ) { // Construct a string containing the runtime metadata final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); appendWordHeader(IndexConstants.RECORD_TYPE.TABLE, objectID, fullName, nameInSource, parentObjectID, sb); // Append the cardinality sb.append(cardinality); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the tableType sb.append(tableType); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the supports flags appendBoolean(isVirtual, sb); appendBoolean(isSystem, sb); appendBoolean(supportsUpdate, sb); appendBoolean(isMaterialized, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the UUIDs of the column references appendIDs(Collections.EMPTY_LIST, sb); // DFF 01/06/04 - Deprecated the TableRecord.getColumnIDs method as a // partial fix for defect 10861. Storing the list of column UUIDs may // create an index record longer than the allowable INDEX_RECORD_BLOCK_SIZE. // Retrieving the list of columns owned by table can be achieved by // querying for columns with the fully qualified table as the parent name. // appendIDs(columnIDs,sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the UUID of the primary key appendID(primaryKeyID, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the UUIDs of the foreign key references appendIDs(foreignKeyIDs, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the UUIDs of the index references appendIDs(indexIDs, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the UUIDs of the unique key references appendIDs(uniqueKeyIDs, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the UUIDs of the access pattern references appendIDs(accessPatternIDs, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the UUIDs of the materialized table reference appendID(materializedTableID, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the UUIDs of the materialized stage table reference appendID(null, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the footer appendWordFooter(modelPath, name, sb); addNewWordEntryToList(objectID, sb, wordEntries); } /** * Create a {@link WordEntry} instance representing a column. This resulting WordEntry * is of the form: header|boolean values|nullType|searchType| * length|scale|precision|charOctetLength|radix|distinctValues|nullValues * |minValue|maxValue|format|datatype|defaultValue|footer| */ public static void addColumnWord( final SqlColumnAspect aspect, final EObject eObject, final String modelPath, final Collection wordEntries ) { final String objectID = getObjectIdString(aspect.getObjectID(eObject)); final String parentObjectID = getObjectIdString(aspect.getParentObjectID(eObject)); final String name = aspect.getName(eObject); final String fullName = aspect.getFullName(eObject); final String minValue = (aspect.getMinValue(eObject) != null ? aspect.getMinValue(eObject).toString() : null); final String maxValue = (aspect.getMaxValue(eObject) != null ? aspect.getMaxValue(eObject).toString() : null); final String defaultValue = (aspect.getDefaultValue(eObject) != null ? aspect.getDefaultValue(eObject).toString() : null); addColumnWord(objectID, fullName, aspect.getNameInSource(eObject), parentObjectID, aspect.isSelectable(eObject), aspect.isUpdatable(eObject), aspect.getNullType(eObject), aspect.isAutoIncrementable(eObject), aspect.isCaseSensitive(eObject), aspect.isSigned(eObject), aspect.isCurrency(eObject), aspect.isFixedLength(eObject), aspect.isTranformationInputParameter(eObject), aspect.getSearchType(eObject), aspect.getLength(eObject), aspect.getScale(eObject), aspect.getPrecision(eObject), aspect.getCharOctetLength(eObject), aspect.getRadix(eObject), aspect.getDistinctValues(eObject), aspect.getNullValues(eObject), minValue, maxValue, aspect.getFormat(eObject), aspect.getRuntimeType(eObject), aspect.getNativeType(eObject), aspect.getDatatypeObjectID(eObject), defaultValue, aspect.getPosition(eObject), modelPath, name, wordEntries); } /** * Create a {@link WordEntry} instance representing a column. This resulting WordEntry * is of the form: header|boolean values|nullType|searchType| * length|scale|precision|charOctetLength|radix|distinctValues|nullValues * |minValue|maxValue|format|datatype|nativeType|defaultValue|footer| */ static void addColumnWord( final String objectID, final String fullName, final String nameInSource, final String parentObjectID, final boolean isSelectable, final boolean isUpdatable, final int nullType, final boolean isAutoIncrementable, final boolean isCaseSensitive, final boolean isSigned, final boolean isCurrency, final boolean isFixedLength, final boolean isTranformationInputParameter, final int searchType, final int length, final int scale, final int precision, final int charOctetLength, final int radix, final int distinctValues, final int nullValues, final String minValue, final String maxValue, final String format, final String runtimeType, final String nativeType, final String datatypeObjectID, final String defaultValue, final int position, final String modelPath, final String name, final Collection wordEntries ) { // Construct a string containing the runtime metadata final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); appendWordHeader(IndexConstants.RECORD_TYPE.COLUMN, objectID, fullName, nameInSource, parentObjectID, sb); // Append the supports flags appendBoolean(isSelectable, sb); appendBoolean(isUpdatable, sb); appendBoolean(isAutoIncrementable, sb); appendBoolean(isCaseSensitive, sb); appendBoolean(isSigned, sb); appendBoolean(isCurrency, sb); appendBoolean(isFixedLength, sb); appendBoolean(isTranformationInputParameter, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the nullType sb.append(nullType); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the searchType sb.append(searchType); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the length sb.append(length); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the scale sb.append(scale); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the precision sb.append(precision); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the position sb.append(position); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the charOctetLength sb.append(charOctetLength); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the radix sb.append(radix); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the distinctValues sb.append(distinctValues); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the nullValues sb.append(nullValues); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the minValue appendObject(minValue, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the maxValue appendObject(maxValue, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the format appendObject(format, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the runtime type appendObject(runtimeType, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the native type appendObject(nativeType, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the ObjectID of the datatype appendObject(datatypeObjectID, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the default value appendObject(defaultValue, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the footer appendWordFooter(modelPath, name, sb); addNewWordEntryToList(objectID, sb, wordEntries); } /** * Create a {@link WordEntry} instance representing a index, access pattern or * resultSet. This resulting WordEntry is of the form: header|columnIDs|footer| */ public static void addColumnSetWord( final SqlColumnSetAspect aspect, final EObject eObject, final String modelPath, final Collection wordEntries ) { final String objectID = getObjectIdString(aspect.getObjectID(eObject)); final String parentObjectID = getObjectIdString(aspect.getParentObjectID(eObject)); // final EObject container = (eObject != null ? eObject.eContainer() : null); // final String parentObjectID = getObjectIdString(container); final String fullName = aspect.getFullName(eObject); final String name = aspect.getName(eObject); char recordType = IndexConstants.RECORD_TYPE.INDEX; if (aspect.isRecordType(IndexConstants.RECORD_TYPE.ACCESS_PATTERN)) { recordType = IndexConstants.RECORD_TYPE.ACCESS_PATTERN; } if (aspect.isRecordType(IndexConstants.RECORD_TYPE.RESULT_SET)) { recordType = IndexConstants.RECORD_TYPE.RESULT_SET; } addColumnSetWord(recordType, objectID, fullName, aspect.getNameInSource(eObject), parentObjectID, aspect.getColumns(eObject), modelPath, name, wordEntries); } /** * Create a {@link WordEntry} instance representing a primaryKey, uniqueKey, index, or * access pattern. This resulting WordEntry is of the form: header|columnIDs|footer| */ static void addColumnSetWord( final char recordType, final String objectID, final String fullName, final String nameInSource, final String parentObjectID, final List columnIDs, final String modelPath, final String name, final Collection wordEntries ) { // Construct a string containing the runtime metadata final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); appendWordHeader(recordType, objectID, fullName, nameInSource, parentObjectID, sb); // Append the UUIDs of the column references appendIDs(columnIDs, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the footer appendWordFooter(modelPath, name, sb); addNewWordEntryToList(objectID, sb, wordEntries); } /** * Create a {@link WordEntry} instance representing a uniqueKey. This resulting * WordEntry is of the form: header|columnIDs|foreignKeyIDs|footer| */ public static void addUniqueKeyWord( final SqlUniqueKeyAspect aspect, final EObject eObject, final String modelPath, final Collection wordEntries ) { final String objectID = getObjectIdString(aspect.getObjectID(eObject)); final String parentObjectID = getObjectIdString(aspect.getParentObjectID(eObject)); final String name = aspect.getName(eObject); final String fullName = aspect.getFullName(eObject); char recordType = IndexConstants.RECORD_TYPE.PRIMARY_KEY; if (aspect.isRecordType(IndexConstants.RECORD_TYPE.UNIQUE_KEY)) { recordType = IndexConstants.RECORD_TYPE.UNIQUE_KEY; } addUniqueKeyWord(recordType, objectID, fullName, aspect.getNameInSource(eObject), parentObjectID, aspect.getColumns(eObject), aspect.getForeignKeys(eObject), modelPath, name, wordEntries); } /** * Create a {@link WordEntry} instance representing a uniqueKey. This resulting * WordEntry is of the form: header|columnIDs|foreignKeyIDs|footer| */ static void addUniqueKeyWord( final char recordType, final String objectID, final String fullName, final String nameInSource, final String parentObjectID, final List columnIDs, final List foreignKeyIDs, final String modelPath, final String name, final Collection wordEntries ) { // Construct a string containing the runtime metadata final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); appendWordHeader(recordType, objectID, fullName, nameInSource, parentObjectID, sb); // Append the UUIDs of the column references appendIDs(columnIDs, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the UUID of the unique key appendIDs(foreignKeyIDs, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the footer appendWordFooter(modelPath, name, sb); addNewWordEntryToList(objectID, sb, wordEntries); } /** * Create a {@link WordEntry} instance representing a foreignKey. This resulting * WordEntry is of the form: header|columnIDs|uniqueKeyID|footer| */ public static void addForeignKeyWord( final SqlForeignKeyAspect aspect, final EObject eObject, final String modelPath, final Collection wordEntries ) { final String objectID = getObjectIdString(aspect.getObjectID(eObject)); final String parentObjectID = getObjectIdString(aspect.getParentObjectID(eObject)); final String name = aspect.getName(eObject); final String fullName = aspect.getFullName(eObject); final String uniqueKeyID = (aspect.getUniqueKey(eObject) != null ? getObjectIdString(aspect.getUniqueKey(eObject)) : null); addForeignKeyWord(objectID, fullName, aspect.getNameInSource(eObject), parentObjectID, aspect.getColumns(eObject), uniqueKeyID, modelPath, name, wordEntries); } /** * Create a {@link WordEntry} instance representing a foreignKey. This resulting * WordEntry is of the form: header|columnIDs|uniqueKeyID|footer| */ static void addForeignKeyWord( final String objectID, final String fullName, final String nameInSource, final String parentObjectID, final List columnIDs, final String uniqueKeyID, final String modelPath, final String name, final Collection wordEntries ) { // Construct a string containing the runtime metadata final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); appendWordHeader(IndexConstants.RECORD_TYPE.FOREIGN_KEY, objectID, fullName, nameInSource, parentObjectID, sb); // Append the UUIDs of the column references appendIDs(columnIDs, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the UUID of the unique key appendObject(uniqueKeyID, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the footer appendWordFooter(modelPath, name, sb); addNewWordEntryToList(objectID, sb, wordEntries); } /** * Create a {@link WordEntry} instance representing a datatype. This resulting * WordEntry is of the form: recordType|datatypeID|basetypeID|fullName|objectID|nameInSource|varietyType|varietyProps| * runtimeTypeName|javaClassName|type|searchType|nullType|booleanValues|length|precisionLength| * scale|radix|primitiveTypeID|footer| */ public static void addDatatypeWord( final SqlDatatypeAspect aspect, final EObject eObject, final String modelPath, final Collection wordEntries ) { final String objectID = getObjectIdString(aspect.getObjectID(eObject)); final EObject container = (eObject != null ? eObject.eContainer() : null); final String parentObjectID = getObjectIdString(container); final String fullName = aspect.getFullName(eObject); final String name = aspect.getName(eObject); // System.out.println(aspect.getDatatypeID(eObject)+", "+aspect.getBasetypeID(eObject)+", "+aspect.getPrimitiveTypeID(eObject)); addDatatypeWord(objectID, fullName, aspect.getNameInSource(eObject), parentObjectID, aspect.getLength(eObject), aspect.getPrecisionLength(eObject), aspect.getScale(eObject), aspect.getRadix(eObject), aspect.isSigned(eObject), aspect.isAutoIncrement(eObject), aspect.isCaseSensitive(eObject), aspect.getType(eObject), aspect.getSearchType(eObject), aspect.getNullType(eObject), aspect.getJavaClassName(eObject), aspect.getRuntimeTypeName(eObject), aspect.getDatatypeID(eObject), aspect.getBasetypeID(eObject), aspect.getPrimitiveTypeID(eObject), aspect.getVarietyType(eObject), aspect.getVarietyProps(eObject), modelPath, name, wordEntries); } /** * Create a {@link WordEntry} instance representing a datatype. This resulting * WordEntry is of the form: recordType|datatypeID|basetypeID|fullName|objectID|nameInSource|varietyType|varietyProps| * runtimeTypeName|javaClassName|type|searchType|nullType|booleanValues|length|precisionLength| * scale|radix|primitiveTypeID|footer| */ static void addDatatypeWord( final String objectID, final String fullName, final String nameInSource, final String parentObjectID, final int length, final int precisionLength, final int scale, final int radix, final boolean isSigned, final boolean isAutoIncrement, final boolean isCaseSensitive, final short type, final short searchType, final short nullType, final String javaClassName, final String runtimeTypeName, final String datatypeID, final String baseTypeID, final String primitiveTypeID, final short varietyType, final List varietyProps, final String modelPath, final String name, final Collection wordEntries ) { // Construct a string containing the runtime metadata final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); sb.append(IndexConstants.RECORD_TYPE.DATATYPE); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the datatype and basetype identifiers appendObject(datatypeID, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); appendObject(baseTypeID, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the fullName/objectID/nameInSource appendObject(fullName, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); appendObject(objectID, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); appendObject(nameInSource, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the variety type and its properties sb.append(varietyType); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); appendIDs(varietyProps, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the runtime type and java class names appendObject(runtimeTypeName, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); appendObject(javaClassName, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the datatype type sb.append(type); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the search type sb.append(searchType); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the null type sb.append(nullType); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the boolean flags appendBoolean(isSigned, sb); appendBoolean(isAutoIncrement, sb); appendBoolean(isCaseSensitive, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the length sb.append(length); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the precision length sb.append(precisionLength); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the scale sb.append(scale); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the radix sb.append(radix); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the primitive type identifier appendObject(primitiveTypeID, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the footer appendWordFooter(modelPath, name, sb); addNewWordEntryToList(objectID, sb, wordEntries); } /** * Create a {@link WordEntry} instance representing a annotation. This resulting * WordEntry is of the form: recordType|objectID|propertyName|value|isExtention|footer| */ public static void addPropertyWord( final SqlAspect sqlAspect, final EObject eObject, final String modelPath, final Collection wordEntries ) { EObject extObject = null; try { ModelEditor editor = ModelerCore.getModelEditor(); extObject = editor.getExtension(eObject); } catch (Exception e) { ModelerCore.Util.log(IStatus.ERROR, e, e.getMessage()); } Collection propertyNames = new LinkedList(); String objectID = getObjectIdString(eObject); String name = sqlAspect.getName(eObject); if (extObject != null) { final EClass eClass = extObject.eClass(); for (final Iterator featureIter = eClass.getEAttributes().iterator(); featureIter.hasNext();) { final EStructuralFeature feature = (EStructuralFeature)featureIter.next(); Object key = feature.getName(); Object value = extObject.eGet(feature); if (key == null || value == null) { continue; } String propName = key.toString(); String propValue = value.toString(); if (CoreStringUtil.isEmpty(propName) || CoreStringUtil.isEmpty(propValue)) { continue; } if (feature.isMany()) { EList valueList = (EList)value; if (valueList.isEmpty()) { continue; } for (final Iterator valueIter = eClass.getEAttributes().iterator(); valueIter.hasNext();) { value = valueIter.next(); if (value != null && CoreStringUtil.isEmpty(value.toString())) { // add property word addPropertyWord(objectID, name, propName, value.toString(), true, modelPath, wordEntries); } } } else { // add property word addPropertyWord(objectID, name, propName, propValue, true, modelPath, wordEntries); } // collect properties added propertyNames.add(propName); } } // Now we look for extension properties ModelExtensionRegistry registry = ExtensionPlugin.getInstance().getRegistry(); String metaclassName = eObject.getClass().getName(); for (ModelExtensionAssistant tempAssistant : registry.getModelExtensionAssistants(metaclassName)) { if (!(tempAssistant instanceof ModelObjectExtensionAssistant)) { continue; } ModelObjectExtensionAssistant assistant = (ModelObjectExtensionAssistant)tempAssistant; try { // gets the current value and if missing in EObject the default property value Properties extensionProperties = assistant.getPropertyValues(eObject); if( extensionProperties == null ) { continue; } for (String propName : extensionProperties.stringPropertyNames()) { ModelExtensionPropertyDefinition propDefn = registry.getPropertyDefinition(metaclassName, propName); // make sure the property should be indexed if (!propDefn.shouldBeIndexed()) { continue; } String propValue = extensionProperties.getProperty(propName); // don't index if there is no value if (CoreStringUtil.isEmpty(propValue)) { continue; } if (!propertyNames.contains(propName)) { String propKey = ModelExtensionPropertyDefinition.Utils.getIndexedId(assistant.getModelExtensionDefinition(), propDefn.getSimpleId()); addPropertyWord(objectID, name, propKey, propValue, true, modelPath, wordEntries); propertyNames.add(propName); } } } catch (Exception e) { ModelerCore.Util.log(IStatus.ERROR, e, e.getMessage()); } } } /** * Create a {@link WordEntry} instance representing a annotation. This resulting * WordEntry is of the form: recordType|objectID|propertyName|value|isExtention|footer| */ public static void addPropertyWord( final String objectID, final String name, final String propName, final String propValue, final boolean isExtention, final String modelPath, final Collection wordEntries ) { if (CoreStringUtil.isEmpty(propName) || CoreStringUtil.isEmpty(propValue)) { return; } // Construct a string containing the runtime metadata final StringBuffer sb = new StringBuffer(30); // Append the property type sb.append(IndexConstants.RECORD_TYPE.PROPERTY); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the objectID to the record appendObject(objectID, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the property key appendObject(propName, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the property value appendObject(propValue, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the is extention value appendBoolean(isExtention, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the footer appendWordFooter(modelPath, name, sb); addNewWordEntryToList(objectID, sb, wordEntries); } /** * Create a {@link WordEntry} instance representing a annotation. This resulting * WordEntry is of the form: header|description|footer| */ public static void addAnnotationWord( final SqlAnnotationAspect aspect, final EObject eObject, final String modelPath, final Collection wordEntries ) { final String objectID = getObjectIdString(aspect.getObjectID(eObject)); final String parentObjectID = null; // getObjectIdString(aspect.getParentObjectID(eObject)); final String fullName = aspect.getFullName(eObject); final String name = aspect.getName(eObject); // If the target of the annotation does not get output to an index file // then the annotation should not get output. We can determine whether // the target is getting output by checking if there is a SqlAspect for it. if (eObject instanceof Annotation) { final Annotation annotation = (Annotation)eObject; final EObject target = annotation.getAnnotatedObject(); if (target != null) { SqlAspect sqlAspect = AspectManager.getSqlAspect(target); if (sqlAspect != null && !sqlAspect.isQueryable(target)) { return; } } } addAnnotationWord(objectID, fullName, aspect.getNameInSource(eObject), parentObjectID, aspect.getDescription(eObject), modelPath, name, wordEntries); } /** * Create a {@link WordEntry} instance representing a annotation. This resulting * WordEntry is of the form: header|description|footer| */ static void addAnnotationWord( final String objectID, final String fullName, final String nameInSource, final String parentObjectID, final String description, final String modelPath, final String name, final Collection wordEntries ) { // Do not create the annotation word if there is no description to store if (CoreStringUtil.isEmpty(description)) { return; } // Construct a string containing the runtime metadata final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); appendWordHeader(IndexConstants.RECORD_TYPE.ANNOTATION, objectID, fullName, nameInSource, parentObjectID, sb); // Append the description appendObject(description, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); // Append the footer appendWordFooter(modelPath, name, sb); addNewWordEntryToList(objectID, sb, wordEntries); } /** * Split the specified WordEntry into multiple WordEntry instances if it exceeds the allowable INDEX_RECORD_BLOCK_SIZE. If the * entry length does not exceed INDEX_RECORD_BLOCK_SIZE then the original entry will be the only item returned in the list. * * @param wordEntry * @param blockSize */ public static List splitWordEntry( final String objectID, final WordEntry wordEntry, final int blockSize ) { CoreArgCheck.isNotNull(objectID); CoreArgCheck.isNotNull(wordEntry); String entryStr = wordEntry.toString(); int length = entryStr.length(); // If the WordEntry is empty ... if (length == 0) { return Collections.EMPTY_LIST; } // If the WordEntry size fits within a single block ... // (length != blockSize because the char[blockSize] is // reserved for a special continuation character. It is // the presence or absence of this character that indicates // whether the WordEntry is continued onto the next entry). List result = new ArrayList(9); if (length < blockSize) { result.add(wordEntry); return result; } // Ensure that the specified block size is large enough for // for the continuation header, trailer, and at least 1 character // from the WordEntry CoreArgCheck.isTrue(blockSize >= (objectID.length() + 8), "Block size " + blockSize + " is too small"); //$NON-NLS-1$ //$NON-NLS-2$ char[] origEntry = entryStr.toCharArray(); // Split the WordEntry into multiple entries ... int segCount = 1; char recordType = origEntry[0]; StringBuffer sb = new StringBuffer(blockSize); for (int i = 0; i < origEntry.length; i++) { char c = origEntry[i]; sb.append(c); if ((sb.length() == (blockSize - 1)) && (i < origEntry.length - 1)) { appendContinuationTrailer(blockSize, sb); WordEntry partialEntry = new WordEntry(sb.toString().toCharArray()); result.add(partialEntry); sb.setLength(0); appendContinuationHeader(recordType, objectID, segCount, sb); segCount++; } } // Add in the last segment ... if (sb.length() > 0) { WordEntry partialEntry = new WordEntry(sb.toString().toCharArray()); result.add(partialEntry); } return result; } // ================================================================================== // P R O T E C T E D M E T H O D S // ================================================================================== /** * Append the index record version information to the StringBuffer. The version information consists of 3 characters, the * first being a special marker character followed by two integer value characters for a version range of [0-99]. Version * values less than 10 will be preceeded by a 0 character. * * @param indexVersion * @param sb * @since 4.2 */ protected static void appendIndexVersion( final int indexVersion, final StringBuffer sb ) { // The range of index versions is [0,99] CoreArgCheck.isTrue(indexVersion > -1 && indexVersion < 100, "Index version " + indexVersion + " out of range. (0 - 99)"); //$NON-NLS-1$ //$NON-NLS-2$ sb.append(IndexConstants.RECORD_STRING.INDEX_VERSION_MARKER); if (indexVersion < 10) { sb.append(Integer.toString(0)); sb.append(Integer.toString(indexVersion)); } else { sb.append(Integer.toString(indexVersion)); } } protected static void appendObject( final Object obj, final StringBuffer sb ) { if (obj != null) { // MyDefect : 18119 decoded %20 white space. String objectString = obj.toString(); if (obj instanceof URI) { objectString = URI.decode(objectString); } if (objectString.length() == 0) { sb.append(IndexConstants.RECORD_STRING.SPACE); } sb.append(objectString); } else { sb.append(IndexConstants.RECORD_STRING.SPACE); } } protected static void appendBoolean( final boolean b, final StringBuffer sb ) { if (b) { sb.append(IndexConstants.RECORD_STRING.TRUE); } else { sb.append(IndexConstants.RECORD_STRING.FALSE); } } /** * Concatenate the identifiers for each object in the collection */ protected static void appendStrings( final Collection objs, final StringBuffer sb ) { if (objs == null || objs.isEmpty()) { sb.append(IndexConstants.RECORD_STRING.SPACE); return; } // Remove any null or empty strings final List tmp = new ArrayList(objs); for (Iterator iter = tmp.iterator(); iter.hasNext();) { String obj = (String)iter.next(); if (obj == null || obj.trim().length() == 0) { iter.remove(); } } // Return if the final list is empty if (tmp.isEmpty()) { sb.append(IndexConstants.RECORD_STRING.SPACE); return; } // Append the remaining strings for (Iterator iter = tmp.iterator(); iter.hasNext();) { String obj = (String)iter.next(); sb.append(obj); if (iter.hasNext()) { sb.append(IndexConstants.RECORD_STRING.LIST_DELIMITER); } } } /** * Concatenate the identifiers for each object in the collection */ protected static void appendStrings( final Map objs, final int indexVersionNumber, final StringBuffer sb ) { if (objs == null || objs.isEmpty()) { sb.append(IndexConstants.RECORD_STRING.SPACE); return; } for (Iterator entryIter = objs.entrySet().iterator(); entryIter.hasNext();) { Map.Entry mapEntry = (Map.Entry)entryIter.next(); if (mapEntry == null) { continue; } Object key = mapEntry.getKey(); Object value = mapEntry.getValue(); if (key == null || value == null) { sb.append(IndexConstants.RECORD_STRING.SPACE); if (entryIter.hasNext()) { sb.append(IndexConstants.RECORD_STRING.LIST_DELIMITER); } continue; } // add prop values to the string sb.append(key.toString()); sb.append(IndexConstants.RECORD_STRING.PROP_DELIMITER); sb.append(value.toString()); if (entryIter.hasNext()) { sb.append(IndexConstants.RECORD_STRING.LIST_DELIMITER); } } } /** * Concatenate the identifiers for each object in the collection */ protected static void appendIDs( final Collection objs, final StringBuffer sb ) { if (objs == null || objs.isEmpty()) { sb.append(IndexConstants.RECORD_STRING.SPACE); return; } // Remove any null or empty strings final List tmp = new ArrayList(objs); for (Iterator iter = tmp.iterator(); iter.hasNext();) { String obj = getObjectIdString(iter.next()); if (obj == null || obj.trim().length() == 0) { iter.remove(); } } // Return if the final list is empty if (tmp.isEmpty()) { sb.append(IndexConstants.RECORD_STRING.SPACE); return; } // Append the remaining strings for (Iterator iter = tmp.iterator(); iter.hasNext();) { Object obj = iter.next(); appendID(obj, sb); if (iter.hasNext()) { sb.append(IndexConstants.RECORD_STRING.LIST_DELIMITER); } } } protected static void appendID( final Object obj, final StringBuffer sb ) { String id = getObjectIdString(obj); if (id == null || id.length() == 0) { sb.append(IndexConstants.RECORD_STRING.SPACE); } else { sb.append(id); } } protected static String getObjectIdString( final Object obj ) { if (obj == null) { return null; } if (obj instanceof EClass) { return null; } else if (obj instanceof EObject) { ModelEditor modelEditor = ModelerCore.getModelEditor(); if (modelEditor instanceof ModelEditorImpl) return ((ModelEditorImpl)modelEditor).getSearchIndexObjectID((EObject)obj); } else if (obj instanceof ObjectID) { return obj.toString(); } else if (obj instanceof String) { return (String)obj; } return null; } /** * Concatenate the identifiers for each object in the collection */ protected static void appendURIs( final Collection objs, final int indexVersionNumber, final StringBuffer sb ) { if (objs == null || objs.isEmpty()) { sb.append(IndexConstants.RECORD_STRING.SPACE); return; } // Remove any null or empty strings final List tmp = new ArrayList(objs); for (Iterator iter = tmp.iterator(); iter.hasNext();) { String obj = getObjectIdString(iter.next()); if (obj == null || obj.trim().length() == 0) { iter.remove(); } } // Return if the final list is empty if (tmp.isEmpty()) { sb.append(IndexConstants.RECORD_STRING.SPACE); return; } // Append the remaining strings for (Iterator iter = tmp.iterator(); iter.hasNext();) { Object obj = iter.next(); appendURI(obj, sb, false); if (iter.hasNext()) { sb.append(IndexConstants.RECORD_STRING.LIST_DELIMITER); } } } protected static void appendURI( final Object obj, final StringBuffer sb, final boolean isMetaClass ) { String id = getObjectURIString(obj, isMetaClass); if (id == null || id.length() == 0) { sb.append(IndexConstants.RECORD_STRING.SPACE); } else { sb.append(id); } } protected static String getObjectURIString( final Object obj, final boolean isMetaClass ) { if (obj == null) { return null; } if (obj instanceof EObject) { // If metaclass, look in cache first if (isMetaClass) { String cachedUri = (String)metaClassUriMap.get(((EClass)obj).getName()); if (cachedUri != null) { return cachedUri; } } // If haven't returned, create a new URI EObject eObj = (EObject)obj; String theUri = ModelerCore.getModelEditor().getUri(eObj).toString(); if (isMetaClass) { // Add new URI to cache metaClassUriMap.put(((EClass)obj).getName(), theUri); } return theUri; } else if (obj instanceof URI) { return obj.toString(); } else if (obj instanceof String) { return (String)obj; } return null; } protected static Properties getProperties( final String values, final int indexVersionNumber ) { final char listDelimiter = getListDelimiter(indexVersionNumber); final char propDelimiter = getPropDelimiter(indexVersionNumber); return getProperties(values, listDelimiter, propDelimiter); } protected static Properties getProperties( final String values, final char listDelimiter, final char propDelimiter ) { Properties props = new Properties(); if (CoreStringUtil.isEmpty(values)) { return props; } if (values.length() == 1 && values.charAt(0) == IndexConstants.RECORD_STRING.SPACE) { return props; } final List tokens = CoreStringUtil.split(values, String.valueOf(listDelimiter)); for (Iterator iter = tokens.iterator(); iter.hasNext();) { String token = (String)iter.next(); if (token != null) { final List propTokens = CoreStringUtil.split(token, String.valueOf(propDelimiter)); if (propTokens.size() == 2) { props.put(propTokens.get(0), propTokens.get(1)); } } } return props; } protected static char getPropDelimiter( final int indexVersionNumber ) { if (indexVersionNumber < DELIMITER_INDEX_VERSION) { return IndexConstants.RECORD_STRING.PROP_DELIMITER_OLD; } return IndexConstants.RECORD_STRING.PROP_DELIMITER; } /** * Add new WordEntry instance to the specified list. If the size of the WordEntry exceeds the allowable block size then the * entry is split into multiple entries and each one added to the list. * * @param objectID * @param sb * @param wordEntries */ protected static void addNewWordEntryToList( final String objectID, final StringBuffer sb, final Collection wordEntries ) { String word = sb.toString().trim(); if (!CoreStringUtil.isEmpty(word)) { // ModelerCore.Util.log(" >> RA.addNewWord..() Word = " + word); WordEntry wordEntry = new WordEntry(word.toCharArray()); if (word.length() < INDEX_RECORD_BLOCK_SIZE) { wordEntries.add(wordEntry); return; } List splitEntries = splitWordEntry(objectID, wordEntry, INDEX_RECORD_BLOCK_SIZE); for (Iterator iter = splitEntries.iterator(); iter.hasNext();) { WordEntry entry = (WordEntry)iter.next(); wordEntries.add(entry); } } } // ================================================================================== // P R I V A T E M E T H O D S // ================================================================================== /** * Create the initial "header" portion of an index record. This header is common to all record types and is of the form: * recordType|upperFullName|objectID|fullName|nameInSource|parentObjectID */ private static void appendWordHeader( final char recordType, final String objectID, final String fullName, final String nameInSource, final String parentObjectID, final StringBuffer sb ) { sb.append(recordType); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); String upperName = (fullName != null ? fullName.toUpperCase() : null); appendObject(upperName, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); appendObject(objectID, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); appendObject(fullName, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); appendObject(nameInSource, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); appendObject(parentObjectID, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); } /** * Create the initial "footer" portion of an index record. This footer is common to all record types and is of the form: * modelPath|name */ private static void appendWordFooter( final String modelPath, final String name, final StringBuffer sb ) { sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); appendObject(modelPath, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); appendObject(name, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); appendIndexVersion(getCurrentIndexVersionNumber(), sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); } /** * Create the continuation "header" portion of an index record. This header is used to prefix a record that is a continuation * of another record and is of the form: RECORD_CONTINUATION|objectID|segmentCount| */ private static void appendContinuationHeader( final char recordType, final String objectID, final int segCount, final StringBuffer sb ) { sb.append(IndexConstants.RECORD_TYPE.RECORD_CONTINUATION); sb.append(recordType); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); appendObject(objectID, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); sb.append(segCount); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); } /** * Pad the string buffer with spaces out to blockSize -1 and then add the RECORD_CONTINUATION at the blockSize index. */ private static void appendContinuationTrailer( final int blockSize, final StringBuffer sb ) { int blanksToAdd = blockSize - sb.length() - 1; CoreArgCheck.isTrue(blanksToAdd >= 0, "Blanks to add must be >= 0"); //$NON-NLS-1$ for (int i = 0; i < blanksToAdd; i++) { sb.append(' '); } sb.append(IndexConstants.RECORD_TYPE.RECORD_CONTINUATION); } // ================================================================================== // T E S T M E T H O D S // ================================================================================== public static WordEntry createTestWordEntry( final char recordType, final int numFields, final String fieldValue ) { final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); sb.append(recordType); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); for (int i = 0; i < numFields; i++) { appendObject(fieldValue, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); } appendIndexVersion(getCurrentIndexVersionNumber(), sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); return new WordEntry(sb.toString().toCharArray()); } public static WordEntry createTestWordEntry( final char recordType, final int numFields, final Collection fieldValue ) { final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); sb.append(recordType); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); int indexVersion = getCurrentIndexVersionNumber(); for (int i = 0; i < numFields; i++) { appendStrings(fieldValue, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); } appendIndexVersion(indexVersion, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); return new WordEntry(sb.toString().toCharArray()); } public static WordEntry createTestWordEntry( final char recordType, final int numFields, final Map fieldValue ) { final StringBuffer sb = new StringBuffer(getIniitalBufferSize()); sb.append(recordType); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); int indexVersion = getCurrentIndexVersionNumber(); for (int i = 0; i < numFields; i++) { appendStrings(fieldValue, indexVersion, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); } appendIndexVersion(indexVersion, sb); sb.append(IndexConstants.RECORD_STRING.RECORD_DELIMITER); return new WordEntry(sb.toString().toCharArray()); } /* * Defect 22774 - added this getter to centralize the initial buffer size and upped it from 100 to 500 chars. Most index strings * are larger than 100 chars. */ protected static int getIniitalBufferSize() { return 500; } }