package org.teiid.designer.jdbc.relational.util; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.teiid.core.designer.plugin.PluginUtilities; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.jdbc.JdbcSource; import org.teiid.designer.jdbc.relational.ModelerJdbcRelationalConstants; import org.teiid.designer.jdbc.relational.RelationalModelProcessor; import org.teiid.designer.jdbc.relational.impl.RelationalModelProcessorImpl; import org.teiid.designer.metamodels.relational.util.RelationalTypeMapping; import org.teiid.designer.metamodels.relational.util.RelationalTypeMappingImpl; /** * This class provides a static way to manage the extension contributions for the <code>RelationalModelProcessor</code>. * * This includes utility methods for storing the list of display labels for the contributions for the UI and methods * to return a model processor based on the extension's display label as well as processor type (i.e. translator) * * * * @since 8.0 */ public class JdbcModelProcessorManager { /** * The identifiers for all ModelerCore extension points */ public static class EXTENSION_POINT { /** Extension point for the model validation service implementation */ public static class MODEL_PROCESSOR { public static class ATTRIBUTES { public static final String NAME = "name"; //$NON-NLS-1$ } public static class ELEMENTS { public static final String PROCESSOR_CLASS = "processorClass"; //$NON-NLS-1$ public static final String PROCESSOR_TYPE = "processorType"; //$NON-NLS-1$ } public static final String ID = "modelProcessor"; //$NON-NLS-1$ public static final String UNIQUE_ID = ModelerJdbcRelationalConstants.PLUGIN_ID + DELIMITER + ID; } } /** * Delimiter used by extension/extension point declarations */ public static final String DELIMITER = "."; //$NON-NLS-1$ public static final String JDBC_DEFAULT = "JDBC (default)"; //$NON-NLS-1$ public static final String JDBC_TYPE = "JDBC"; //$NON-NLS-1$ private static Map<String, IExtension> processorExtensionMap; private static Map<String, String> processorNameMap; private static boolean processorsLoaded = false; /** * Create a new {@link RelationalModelProcessor Relational model processor} that can transform * {@link org.teiid.designer.jdbc.metadata.JdbcDatabase JDBC metadata} into a * {@link org.teiid.designer.metamodels.relational.RelationalPackage Relational} model. * <p> * This method attempts to find the model processor that is best suited for the supplied source. It does so by searching for * the first <code>org.teiid.designer.jdbc.relational.modelProcessor</code> extension that is defined to work with the * JdbcSource's {@link JdbcSource#getDriverClass()} * </p> * * @param source the JdbcSource; may be null if the default processor should be used * @return the new model processor */ public static RelationalModelProcessor createRelationalModelProcessor() { return createRelationalModelProcessor(RelationalTypeMappingImpl.getInstance(), JDBC_TYPE); } /** * Create a new {@link RelationalModelProcessor Relational model processor} that can transform * {@link org.teiid.designer.jdbc.metadata.JdbcDatabase JDBC metadata} into a * {@link org.teiid.designer.metamodels.relational.RelationalPackage Relational} model. * <p> * This method attempts to find the model processor that is best suited for the supplied source. This method requires * a processor type that matches one of the contribution extensions and is akin to translator type. These include * types like "oracle", "sybase", etc. The helper method JdbcTranslatorHelper.getModelProcessorType() can be * used to discover the processor type given a Connection Profile. * </p> * * @param mapping the RelationalTypeMapping that should be used * @param processorType * @return the new model processor */ public static RelationalModelProcessor createRelationalModelProcessor( final RelationalTypeMapping mapping, final String processorType) { RelationalModelProcessor processor = getProcessor(processorType); // Attempt to set the type mapping if (mapping != null && processor instanceof RelationalModelProcessorImpl) { ((RelationalModelProcessorImpl)processor).setTypeMapping(mapping); } return processor; } /** * Create a new {@link RelationalModelProcessor Relational model processor} that can transform * {@link org.teiid.designer.jdbc.metadata.JdbcDatabase JDBC metadata} into a * {@link org.teiid.designer.metamodels.relational.RelationalPackage Relational} model. * <p> * @param source * @param processorType * @return the new model processor */ public static RelationalModelProcessor createRelationalModelProcessor( final String processorType ) { return createRelationalModelProcessor(RelationalTypeMappingImpl.getInstance(), processorType); } /** * Return the cached list of Names for the contributed {@link RelationalModelProcessor Relational model processor}. * @return the list of processor names */ public static Collection<String> getMetadataProcessorNames() { loadProcessors(); return processorNameMap.values(); } /** * Return the cached list of valid types for the contributed {@link RelationalModelProcessor Relational model processor}. * @return the list of processor types */ public static Collection<String> getMetadataProcessorTypes() { loadProcessors(); return processorExtensionMap.keySet(); } private static RelationalModelProcessor getProcessor(IExtension extension) { final IConfigurationElement[] elems = extension.getConfigurationElements(); Object result = null; for (int j = 0; j < elems.length; j++) { final IConfigurationElement elem = elems[j]; final String elemName = elem.getName(); if (elemName == null) { continue; } if (elemName.equals(JdbcModelProcessorManager.EXTENSION_POINT.MODEL_PROCESSOR.ELEMENTS.PROCESSOR_CLASS)) { final String attribName = JdbcModelProcessorManager.EXTENSION_POINT.MODEL_PROCESSOR.ATTRIBUTES.NAME; try { result = elem.createExecutableExtension(attribName); } catch (Throwable e) { ModelerJdbcRelationalConstants.Util.log(e); } } } if( result instanceof RelationalModelProcessor ) { return (RelationalModelProcessor)result; } return null; } private static RelationalModelProcessor getProcessor(String key) { loadProcessors(); IExtension extension = processorExtensionMap.get(key); if( extension != null ) { RelationalModelProcessor processor = getProcessor(extension); if( processor != null) { return processor; } } return new RelationalModelProcessorImpl(); } /** * Returns a valid processor name given a processor type. If no unique name is found, it will return the default * JDBC type * * @param type * @return the processor's display name */ public static String getProcessorNameWithType(String type) { loadProcessors(); for( String nextKey : processorNameMap.keySet() ) { String nextValue = processorNameMap.get(nextKey); if( nextKey.equalsIgnoreCase(type) ) { return nextValue; } } return JDBC_DEFAULT; } /** * Returns a valid processor type given the processor's display name * * @param nameKey * @return the processors type */ public static String getProcessorTypeWithName(String nameKey) { loadProcessors(); for( String nextKey : processorNameMap.keySet() ) { String nextValue = processorNameMap.get(nextKey); if( nextValue.equalsIgnoreCase(nameKey) ) { return nextKey; } } return JDBC_TYPE; } private static void loadProcessors() { if( !processorsLoaded ) { processorExtensionMap = new HashMap<String, IExtension>(); processorNameMap = new HashMap<String, String>(); final IExtension[] extensions = PluginUtilities.getExtensions(JdbcModelProcessorManager.EXTENSION_POINT.MODEL_PROCESSOR.UNIQUE_ID); for (int i = 0; i < extensions.length; i++) { final IExtension extension = extensions[i]; final IConfigurationElement[] elems = extension.getConfigurationElements(); String processorType = null; String processorName = extension.getLabel(); for (int j = 0; j < elems.length; j++) { final IConfigurationElement elem = elems[j]; final String elemName = elem.getName(); if (elemName == null) { continue; } if (elemName.equals(JdbcModelProcessorManager.EXTENSION_POINT.MODEL_PROCESSOR.ELEMENTS.PROCESSOR_TYPE)) { processorType = elem.getAttribute(ModelerCore.EXTENSION_POINT.ASSOCIATION_PROVIDER.ATTRIBUTES.NAME); } } if( processorName != null && processorType != null ) { processorExtensionMap.put(processorType, extension); processorNameMap.put(processorType, processorName); } } processorNameMap.put(JDBC_TYPE, JDBC_DEFAULT); processorsLoaded = true; } } }