/*
* 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.metamodels.relational.extension;
import org.eclipse.core.resources.IResource;
import org.eclipse.emf.ecore.EObject;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.extension.EmfModelObjectExtensionAssistant;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.core.workspace.ModelUtil;
import org.teiid.designer.extension.ExtensionConstants;
import org.teiid.designer.extension.ExtensionPlugin;
import org.teiid.designer.extension.properties.ModelExtensionPropertyDefinition;
import org.teiid.designer.extension.registry.ModelExtensionRegistry;
import org.teiid.designer.metamodels.core.ModelType;
import org.teiid.designer.metamodels.relational.DirectionKind;
import org.teiid.designer.metamodels.relational.ForeignKey;
import org.teiid.designer.metamodels.relational.Procedure;
import org.teiid.designer.metamodels.relational.ProcedureParameter;
import org.teiid.designer.metamodels.relational.RelationalPackage;
import org.teiid.designer.metamodels.relational.Table;
import org.teiid.designer.metamodels.relational.View;
/**
* @since 8.0
*
*/
public class RelationalModelExtensionAssistant extends EmfModelObjectExtensionAssistant {
private static String getPropertyId(final String propName) {
return ModelExtensionPropertyDefinition.Utils.getPropertyId(RelationalModelExtensionConstants.NAMESPACE_PROVIDER,
propName);
}
private enum PropertyName {
AGGREGATE(getPropertyId("aggregate")), //$NON-NLS-1$
ALLOWS_ORDER_BY(getPropertyId("allows-orderby")), //$NON-NLS-1$
ALLOWS_DISTINCT(getPropertyId("allows-distinct")), //$NON-NLS-1$
ANALYTIC(getPropertyId("analytic")), //$NON-NLS-1$
DECOMPOSABLE(getPropertyId("decomposable")), //$NON-NLS-1$
DETERMINISTIC(getPropertyId("deterministic")), //$NON-NLS-1$
NATIVE_QUERY(getPropertyId("native-query")), //$NON-NLS-1$
NON_PREPARED(getPropertyId("non-prepared")), //$NON-NLS-1$
USES_DISTINCT_ROWS(getPropertyId("uses-distinct-rows")), //$NON-NLS-1$
VARARGS(getPropertyId("varargs")), //$NON-NLS-1$
NULL_ON_NULL(getPropertyId("null-on-null")), //$NON-NLS-1$
JAVA_CLASS(getPropertyId("java-class")), //$NON-NLS-1$
JAVA_METHOD(getPropertyId("java-method")), //$NON-NLS-1$
FUNCTION_CATEGORY(getPropertyId("function-category")), //$NON-NLS-1$
UDF_JAR_PATH(getPropertyId("udfJarPath")), //$NON-NLS-1$
ALLOW_JOIN(getPropertyId("allow-join")), //$NON-NLS-1$
NATIVE_TYPE(getPropertyId("native_type")), //$NON-NLS-1$
GLOBAL_TEMP_TABLE(getPropertyId("global-temp-table")), //$NON-NLS-1$
ALLOW_MATVIEW_MANAGEMENT(getPropertyId("ALLOW_MATVIEW_MANAGEMENT")), //$NON-NLS-1$
MATVIEW_STATUS_TABLE(getPropertyId("MATVIEW_STATUS_TABLE")), //$NON-NLS-1$
MATVIEW_BEFORE_LOAD_SCRIPT(getPropertyId("MATVIEW_BEFORE_LOAD_SCRIPT")), //$NON-NLS-1$
MATVIEW_LOAD_SCRIPT(getPropertyId("MATVIEW_LOAD_SCRIPT")), //$NON-NLS-1$
MATVIEW_AFTER_LOAD_SCRIPT(getPropertyId("MATVIEW_AFTER_LOAD_SCRIPT")), //$NON-NLS-1$
MATVIEW_SHARE_SCOPE(getPropertyId("MATVIEW_SHARE_SCOPE")), //$NON-NLS-1$
MATERIALIZED_STAGE_TABLE(getPropertyId("MATERIALIZED_STAGE_TABLE")), //$NON-NLS-1$
ON_VDB_START_SCRIPT(getPropertyId("ON_VDB_START_SCRIPT")), //$NON-NLS-1$
ON_VDB_DROP_SCRIPT(getPropertyId("ON_VDB_DROP_SCRIPT")), //$NON-NLS-1$
MATVIEW_ONERROR_ACTION(getPropertyId("MATVIEW_ONERROR_ACTION")), //$NON-NLS-1$
MATVIEW_TTL(getPropertyId("MATVIEW_TTL")); //$NON-NLS-1$
public static boolean same(final PropertyName propName,
final String value) {
return propName.toString().equals(value);
}
private final String propName;
private PropertyName(final String propName) {
this.propName = propName;
}
/**
* {@inheritDoc}
*
* @see java.lang.Enum#toString()
*/
@Override
public String toString() {
return this.propName;
}
}
public static RelationalModelExtensionAssistant getRelationalAssistant() {
final ModelExtensionRegistry registry = ExtensionPlugin.getInstance().getRegistry();
final String prefix = RelationalModelExtensionConstants.NAMESPACE_PROVIDER.getNamespacePrefix();
return (RelationalModelExtensionAssistant)registry.getModelExtensionAssistant(prefix);
}
/**
* Saves the relational MED to a model if necessary.
* @param model the model being checked (can be <code>null</code>)
* @throws Exception if there is an error applying MED
*/
public void applyMedIfNecessary(final IResource model) throws Exception {
if (model != null) {
final ModelResource modelResource = ModelerCore.getModelWorkspace().findModelResource(model);
if (modelResource != null && !modelResource.isReadOnly()) {
if ((ModelType.PHYSICAL_LITERAL == modelResource.getModelType() || ModelType.VIRTUAL_LITERAL == modelResource.getModelType())
&& RelationalPackage.eNS_URI.equals(modelResource.getPrimaryMetamodelUri()) && !supportsMyNamespace(model)) {
saveModelExtensionDefinition(model);
}
}
}
}
/**
* {@inheritDoc}
*
* @see org.teiid.designer.core.extension.EmfModelObjectExtensionAssistant#getPropertyDefinition(java.lang.Object, java.lang.String)
*/
@Override
protected ModelExtensionPropertyDefinition getPropertyDefinition(final Object modelObject,
final String propId) throws Exception {
CoreArgCheck.isInstanceOf(EObject.class, modelObject);
// make sure there is a property definition first
final ModelExtensionPropertyDefinition propDefn = super.getPropertyDefinition(modelObject, propId);
if (propDefn != null) {
// View objects in virtual models should not have extension properties
if (ModelUtil.isVirtual(modelObject) && (modelObject instanceof View)) {
return null;
}
boolean isPhysical = ModelUtil.isPhysical(modelObject);
boolean isFunction = false;
if( modelObject instanceof Procedure ) {
isFunction = ((Procedure)modelObject).isFunction();
}
// must be a table or a procedure in a physical model to have these properties
if (PropertyName.same(PropertyName.NATIVE_QUERY, propId)) {
if (((modelObject instanceof Table) || (modelObject instanceof Procedure)) && isPhysical) {
return propDefn;
}
// EObject should not have the native query property definition
return null;
}
// must be a table and physical
if (PropertyName.same(PropertyName.GLOBAL_TEMP_TABLE, propId)) {
if (( modelObject instanceof Table ) && !isPhysical) {
return propDefn;
}
// EObject should not have the native query property definition
return null;
}
// must be a table or a procedure in a physical model to have these properties
if (PropertyName.same(PropertyName.NATIVE_TYPE, propId)) {
if (modelObject instanceof ProcedureParameter && isPhysical &&
((ProcedureParameter)modelObject).getDirection() == DirectionKind.OUT_LITERAL) {
return propDefn;
}
// EObject should not have the native query property definition
return null;
}
// must be a procedure in a physical model to have these properties
if (PropertyName.same(PropertyName.ALLOW_JOIN, propId)) {
if ((modelObject instanceof ForeignKey) && isPhysical) {
return propDefn;
}
// EObject should not have these property definitions
return null;
}
// must be a procedure in a physical model to have these properties
if (PropertyName.same(PropertyName.NON_PREPARED, propId)) {
if ((modelObject instanceof Procedure) && isPhysical) {
return propDefn;
}
// EObject should not have these property definitions
return null;
}
// 'UDF' properties are supported in physical or virtual models now, when function=true
if ( PropertyName.same(PropertyName.JAVA_CLASS, propId) || PropertyName.same(PropertyName.JAVA_METHOD, propId)
|| PropertyName.same(PropertyName.FUNCTION_CATEGORY, propId) || PropertyName.same(PropertyName.UDF_JAR_PATH, propId)
|| PropertyName.same(PropertyName.VARARGS, propId) || PropertyName.same(PropertyName.NULL_ON_NULL, propId)
|| PropertyName.same(PropertyName.DETERMINISTIC, propId) || PropertyName.same(PropertyName.AGGREGATE, propId)) {
if ((modelObject instanceof Procedure) && isFunction) {
return propDefn;
}
// make sure model object does not have these extension properties for when function is false
removeProperty(modelObject, PropertyName.DETERMINISTIC.toString());
removeProperty(modelObject, PropertyName.JAVA_CLASS.toString());
removeProperty(modelObject, PropertyName.JAVA_METHOD.toString());
removeProperty(modelObject, PropertyName.FUNCTION_CATEGORY.toString());
removeProperty(modelObject, PropertyName.UDF_JAR_PATH.toString());
removeProperty(modelObject, PropertyName.VARARGS.toString());
removeProperty(modelObject, PropertyName.NULL_ON_NULL.toString());
removeProperty(modelObject, PropertyName.AGGREGATE.toString());
removeProperty(modelObject, PropertyName.ANALYTIC.toString());
removeProperty(modelObject, PropertyName.ALLOWS_ORDER_BY.toString());
removeProperty(modelObject, PropertyName.USES_DISTINCT_ROWS.toString());
removeProperty(modelObject, PropertyName.DECOMPOSABLE.toString());
removeProperty(modelObject, PropertyName.ALLOWS_DISTINCT.toString());
// EObject should not have these property definitions
return null;
}
if (PropertyName.same(PropertyName.ANALYTIC, propId) || PropertyName.same(PropertyName.ALLOWS_ORDER_BY, propId)
|| PropertyName.same(PropertyName.USES_DISTINCT_ROWS, propId)
|| PropertyName.same(PropertyName.ALLOWS_DISTINCT, propId)
|| PropertyName.same(PropertyName.DECOMPOSABLE, propId)) {
if ((modelObject instanceof Procedure) ) {
// aggregate must be true to have the above properties
final String isAggregate = getPropertyValue(modelObject, PropertyName.AGGREGATE.toString());
if (Boolean.parseBoolean(isAggregate)) {
return propDefn;
}
// make sure model object does not have these extension properties for when aggregate is false
removeProperty(modelObject, PropertyName.ANALYTIC.toString());
removeProperty(modelObject, PropertyName.ALLOWS_ORDER_BY.toString());
removeProperty(modelObject, PropertyName.USES_DISTINCT_ROWS.toString());
removeProperty(modelObject, PropertyName.DECOMPOSABLE.toString());
removeProperty(modelObject, PropertyName.ALLOWS_DISTINCT.toString());
}
// EObject should not have the requested property definition
return null;
}
// MATERIALIZED VIEW PROPERTIES
if( ( modelObject instanceof Table ) && isPhysical) {
// remove if physical table
if ( PropertyName.same(PropertyName.MATERIALIZED_STAGE_TABLE, propId) ||
PropertyName.same(PropertyName.MATVIEW_AFTER_LOAD_SCRIPT, propId) ||
PropertyName.same(PropertyName.MATVIEW_BEFORE_LOAD_SCRIPT, propId) ||
PropertyName.same(PropertyName.MATVIEW_LOAD_SCRIPT, propId) ||
PropertyName.same(PropertyName.MATVIEW_ONERROR_ACTION, propId) ||
PropertyName.same(PropertyName.MATVIEW_SHARE_SCOPE, propId) ||
PropertyName.same(PropertyName.MATVIEW_STATUS_TABLE, propId) ||
PropertyName.same(PropertyName.MATVIEW_TTL, propId) ||
PropertyName.same(PropertyName.ON_VDB_DROP_SCRIPT, propId) ||
PropertyName.same(PropertyName.ON_VDB_START_SCRIPT, propId) ) {
removeProperty(modelObject, PropertyName.MATERIALIZED_STAGE_TABLE.toString());
removeProperty(modelObject, PropertyName.MATVIEW_AFTER_LOAD_SCRIPT.toString());
removeProperty(modelObject, PropertyName.MATVIEW_BEFORE_LOAD_SCRIPT.toString());
removeProperty(modelObject, PropertyName.MATVIEW_LOAD_SCRIPT.toString());
removeProperty(modelObject, PropertyName.MATVIEW_ONERROR_ACTION.toString());
removeProperty(modelObject, PropertyName.MATVIEW_SHARE_SCOPE.toString());
removeProperty(modelObject, PropertyName.MATVIEW_STATUS_TABLE.toString());
removeProperty(modelObject, PropertyName.MATVIEW_TTL.toString());
removeProperty(modelObject, PropertyName.ON_VDB_DROP_SCRIPT.toString());
removeProperty(modelObject, PropertyName.ON_VDB_START_SCRIPT.toString());
}
return null;
}
return propDefn;
}
// property definition not found
return null;
}
/**
* {@inheritDoc}
*
* @see org.teiid.designer.core.extension.EmfModelObjectExtensionAssistant#setPropertyValue(java.lang.Object, java.lang.String, java.lang.String)
*/
@Override
public void setPropertyValue(final Object modelObject,
final String propId,
final String newValue) throws Exception {
boolean isVirtual = ModelUtil.isVirtual(modelObject);
if( isVirtual && !PropertyName.same(PropertyName.NON_PREPARED, propId)) {
super.setPropertyValue(modelObject, propId, newValue);
} else if( !isVirtual && PropertyName.same(PropertyName.NATIVE_QUERY, propId)) {
super.setPropertyValue(modelObject, propId, newValue);
} else if( !isVirtual && PropertyName.same(PropertyName.NATIVE_TYPE, propId)) {
super.setPropertyValue(modelObject, propId, newValue);
}
// if setting aggregate to false remove these properties
if (PropertyName.same(PropertyName.AGGREGATE, propId) && !Boolean.parseBoolean(newValue)) {
removeProperty(modelObject, PropertyName.ANALYTIC.toString());
removeProperty(modelObject, PropertyName.ALLOWS_ORDER_BY.toString());
removeProperty(modelObject, PropertyName.USES_DISTINCT_ROWS.toString());
removeProperty(modelObject, PropertyName.ALLOWS_DISTINCT.toString());
removeProperty(modelObject, PropertyName.DECOMPOSABLE.toString());
}
}
/**
* {@inheritDoc}
* @param context the context of the operation
*
* @see org.teiid.designer.core.extension.EmfModelObjectExtensionAssistant#supportsMedOperation(java.lang.String, java.lang.Object)
*/
@Override
public boolean supportsMedOperation(String proposedOperationName,
Object context) {
CoreArgCheck.isNotEmpty(proposedOperationName, "proposedOperationName is empty"); //$NON-NLS-1$
return ExtensionConstants.MedOperations.SHOW_IN_REGISTRY.equals(proposedOperationName); // only show in registry
}
@Override
public boolean supportsProperty(Object modelObject, String propId)
throws Exception {
return getPropertyDefinition(modelObject, propId) != null;
}
}