### Eclipse Workspace Patch 1.0
#P org.teiid.designer.ui
Index: src/com/metamatrix/modeler/ui/actions/INewChildAction.java
===================================================================
--- src/com/metamatrix/modeler/ui/actions/INewChildAction.java	(revision 1783)
+++ src/com/metamatrix/modeler/ui/actions/INewChildAction.java	(working copy)
@@ -7,6 +7,7 @@
  */
 package com.metamatrix.modeler.ui.actions;
 
+import org.eclipse.core.resources.IFile;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.jface.action.IAction;
 
@@ -23,5 +24,14 @@
      * @return true if this action should be added to the New Child menu, false if it should not.
      */
     boolean canCreateChild(EObject parent);
+    
+    /**
+     * <p>Determine if this action should be displayed in the New Child menu based on the specified
+     * parent ModelResource.  This method is called every time the New Child menu is created.</p>
+     * <p> NOTE: this method should not check the read-only status of the specified EObject or it's 
+     * IResource.  That check is performed by the ModelerActionService. 
+     * @return true if this action should be added to the New Child menu, false if it should not.
+     */
+    boolean canCreateChild(IFile modelFile);
 
 }
Index: src/com/metamatrix/modeler/ui/actions/ModelerActionService.java
===================================================================
--- src/com/metamatrix/modeler/ui/actions/ModelerActionService.java	(revision 1783)
+++ src/com/metamatrix/modeler/ui/actions/ModelerActionService.java	(working copy)
@@ -651,14 +651,18 @@
                                 HashMap actionMap = new HashMap();
                                 Iterator iter = descriptors.iterator();
                                 while (iter.hasNext()) {
-                                    NewChildAction action = new NewChildAction(resource, (Command)iter.next());
-                                    actionMap.put(action.getText(), action);
-                                    action.selectionChanged(getWorkbenchWindow().getPartService().getActivePart(), theSelection);
-
-                                    // disable if read-only. obj should be EObject or an IResource.
-                                    if (isReadOnly) {
-                                        action.setEnabled(false);
-                                    }
+                                	Command nextCommand = (Command)iter.next();
+                                	if( !nextCommand.getLabel().equalsIgnoreCase("schema")  //$NON-NLS-1$
+                                			&& !nextCommand.getLabel().equalsIgnoreCase("catalog") ) { //$NON-NLS-1$
+	                                    NewChildAction action = new NewChildAction(resource, nextCommand);
+	                                    actionMap.put(action.getText(), action);
+	                                    action.selectionChanged(getWorkbenchWindow().getPartService().getActivePart(), theSelection);
+	
+	                                    // disable if read-only. obj should be EObject or an IResource.
+	                                    if (isReadOnly) {
+	                                        action.setEnabled(false);
+	                                    }
+                                	}
                                 }
 
                                 // sort the keys of the actionMap to put them in alphabetical order
@@ -668,6 +672,18 @@
                                     // add each action to the menu
                                     menu.add((IAction)actionMap.get(iter.next()));
                                 }
+                                
+                                // get the NewChildAction extensions and populate with any actions
+                                // Note: these should not be sorted - they always go on the bottom of the menu
+                                for (int i = 0; i < getNewChildExtensions().length; ++i) {
+                                    INewChildAction action = getNewChildExtensions()[i];
+                                    if (action.canCreateChild((IFile)obj)) {
+                                        menu.add(action);
+                                        if (isReadOnly) {
+                                            action.setEnabled(false);
+                                        }
+                                    }
+                                }
 
                             }
                         } else {
Index: src/com/metamatrix/modeler/ui/i18n.properties
===================================================================
--- src/com/metamatrix/modeler/ui/i18n.properties	(revision 1783)
+++ src/com/metamatrix/modeler/ui/i18n.properties	(working copy)
@@ -1434,4 +1434,21 @@
 NewModelProjectWizard.initialMessage=Click Finish to create folders for your new project
 NewModelProjectWizard.noFoldersMessage=No folders will be created
 NewModelProjectWizard.zeroLengthFolderNameError=ERROR: All folder names must contain one or more valid characters
-NewModelProjectWizard.duplicateFolderNameError=ERROR: Cannot create duplicate folders with name: {0}
\ No newline at end of file
+NewModelProjectWizard.duplicateFolderNameError=ERROR: Cannot create duplicate folders with name: {0}
+
+CreatePushdownFunctionAction.exceptionMessage=Error creating pushdown function
+CreatePushdownFunctionAction.title = Source Function
+PushdownFunctionInputDialog.title=Create Source Function
+PushdownFunctionInputDialog.headerTitle=Create New Source Function
+PushdownFunctionInputDialog.initialMessage=Enter valid name, define parameters and set properties
+PushdownFunctionInputDialog.name=Name
+PushdownFunctionInputDialog.inputParameters=Input Parameters
+PushdownFunctionInputDialog.include=Include
+PushdownFunctionInputDialog.dataType=Data Type
+PushdownFunctionInputDialog.length=Length
+PushdownFunctionInputDialog.returnParameter=Return Parameter
+PushdownFunctionInputDialog.properties=Properties
+PushdownFunctionInputDialog.nameInSource=Name In Source
+PushdownFunctionInputDialog.deterministic=Deterministic
+PushdownFunctionInputDialog.description=Description
+PushdownFunctionInputDialog.pressOkToFinish=Press OK to finish
Index: src/com/metamatrix/modeler/internal/ui/PluginConstants.java
===================================================================
--- src/com/metamatrix/modeler/internal/ui/PluginConstants.java	(revision 1783)
+++ src/com/metamatrix/modeler/internal/ui/PluginConstants.java	(working copy)
@@ -98,6 +98,7 @@
         String COLLAPSE_ALL_ICON = CVIEW16 + "collapseall.gif"; //$NON-NLS-1$
 
         String MODEL_STATISTICS_ICON = CVIEW16 + "statistics.gif"; //$NON-NLS-1$
+        String NEW_PUSHDOWN_FUNCTION = OBJ16 + "PushdownFunction.gif"; //$NON-NLS-1$
         String BUILD_MODEL_IMPORTS_ICON = OBJ16 + "Imports.gif"; //$NON-NLS-1$
         String FIND = CVIEW16 + "find.gif"; //$NON-NLS-1$
         String FIND_REPLACE = CVIEW16 + "find_replace.gif"; //$NON-NLS-1$
Index: src/com/metamatrix/modeler/internal/ui/viewsupport/ModelObjectUtilities.java
===================================================================
--- src/com/metamatrix/modeler/internal/ui/viewsupport/ModelObjectUtilities.java	(revision 1783)
+++ src/com/metamatrix/modeler/internal/ui/viewsupport/ModelObjectUtilities.java	(working copy)
@@ -51,6 +51,7 @@
 import com.metamatrix.common.xmi.XMIHeader;
 import com.metamatrix.core.util.CoreArgCheck;
 import com.metamatrix.metamodels.core.ModelType;
+import com.metamatrix.metamodels.relational.Procedure;
 import com.metamatrix.metamodels.xsd.XsdUtil;
 import com.metamatrix.modeler.core.ModelerCore;
 import com.metamatrix.modeler.core.ModelerCoreException;
@@ -329,6 +330,10 @@
             || TransformationHelper.isSqlInputSet(eObject)) {
             return false;
         }
+        
+        if( eObject instanceof Procedure && ((Procedure)eObject).isFunction() ) {
+        	return false;
+        }
 
         boolean hasValidQuery = true;
         if (TransformationHelper.isVirtualSqlTable(eObject) && !TransformationHelper.isXmlDocument(eObject)
Index: src/com/metamatrix/modeler/internal/ui/viewsupport/RelationalObjectFactory.java
===================================================================
--- src/com/metamatrix/modeler/internal/ui/viewsupport/RelationalObjectFactory.java	(revision 0)
+++ src/com/metamatrix/modeler/internal/ui/viewsupport/RelationalObjectFactory.java	(revision 0)
@@ -0,0 +1,318 @@
+/*
+ * 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 com.metamatrix.modeler.internal.ui.viewsupport;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+
+import com.metamatrix.core.util.I18nUtil;
+import com.metamatrix.metamodels.core.Annotation;
+import com.metamatrix.metamodels.relational.BaseTable;
+import com.metamatrix.metamodels.relational.Column;
+import com.metamatrix.metamodels.relational.DirectionKind;
+import com.metamatrix.metamodels.relational.Procedure;
+import com.metamatrix.metamodels.relational.ProcedureParameter;
+import com.metamatrix.metamodels.relational.RelationalFactory;
+import com.metamatrix.metamodels.relational.RelationalPackage;
+import com.metamatrix.metamodels.relational.View;
+import com.metamatrix.modeler.core.ModelerCore;
+import com.metamatrix.modeler.core.ModelerCoreException;
+import com.metamatrix.modeler.core.util.ModelContents;
+import com.metamatrix.modeler.core.util.ModelResourceContainerFactory;
+import com.metamatrix.modeler.core.workspace.ModelResource;
+import com.metamatrix.modeler.core.workspace.ModelWorkspaceException;
+import com.metamatrix.modeler.ui.UiConstants;
+
+
+
+/** 
+ * @since 4.2
+ */
+public class RelationalObjectFactory {
+    //============================================================================================================================
+    // Static Constants
+    
+    private static final String I18N_PREFIX             = I18nUtil.getPropertyPrefix(RelationalObjectFactory.class);
+    public static final String RELATIONAL_PACKAGE_URI	= RelationalPackage.eNS_URI;
+    public static final RelationalFactory factory = RelationalFactory.eINSTANCE;
+    
+    public static final int UNKNOWN = -1;
+    
+    public static final int BASE_TABLE = 10;
+    public static final int VIEW = 11;
+    public static final int INDEX = 12;
+    public static final int COLUMN = 13;
+    public static final int UNIQUE_KEY = 14;
+    public static final int PRIMARY_KEY = 15;
+    public static final int PROCEDURE = 16;
+    public static final int PARAMETER = 17;
+
+    public static final String BASE_TABLE_STRING = "TABLE"; //$NON-NLS-1$
+    public static final String VIEW_STRING = "VIEW"; //$NON-NLS-1$
+    public static final String INDEX_STRING = "INDEX"; //$NON-NLS-1$
+    public static final String COLUMN_STRING = "COLUMN"; //$NON-NLS-1$
+    public static final String UNIQUE_KEY_STRING = "UNIQUEKEY"; //$NON-NLS-1$
+    public static final String PRIMARY_KEY_STRING = "PRIMARYKEY"; //$NON-NLS-1$
+    public static final String SCHEMA_STRING = "SCHEMA"; //$NON-NLS-1$
+    public static final String CATALOG_STRING = "CATALOG"; //$NON-NLS-1$
+    public static final String PROCEDURE_STRING = "PROCEDURE"; //$NON-NLS-1$
+    public static final String PARAMETER_STRING = "PARAMETER"; //$NON-NLS-1$
+    
+    private static final String GET_MODEL_CONTENTS_ERROR 	= "getModelContentsError"; //$NON-NLS-1$
+    private static final String ADD_VALUE_ERROR         	= "addValueError"; //$NON-NLS-1$
+    
+   
+    //============================================================================================================================
+    // Static Methods
+    
+//    private static String getString(final String id) {
+//        return UiConstants.Util.getString(I18N_PREFIX + id);
+//    }
+    
+    private static String getString(final String id, Object obj) {
+        return UiConstants.Util.getString(I18N_PREFIX + id, obj);
+    }
+    
+    private static String getString(String id, Object value, Object value2) {
+        return UiConstants.Util.getString(I18N_PREFIX + id, value, value2);
+    }
+    
+    private static boolean isTransactionable = ModelerCore.getPlugin() != null;
+    
+    private EObject defaultDatatype;
+    private int defaultLength;
+    
+    private final ModelResource modelResource;
+    
+    /** 
+     * 
+     * @since 4.2
+     */
+    public RelationalObjectFactory(ModelResource modelResource) {
+        super();
+        this.modelResource = modelResource;
+    }
+    
+    public BaseTable createBaseTable(
+    		String name, 
+    		String description, 
+    		boolean supportsUpdate) {
+    	
+        BaseTable baseTable = (BaseTable)factory.createBaseTable();
+        if( baseTable != null ) {
+            baseTable.setName(name);
+            baseTable.setSupportsUpdate(supportsUpdate);
+            
+            // SET PARENT
+            addValue(modelResource, baseTable, getModelResourceContents(modelResource));
+            
+            addDescription(baseTable, description);
+        }
+        
+        return baseTable;
+    }
+    
+    public View createView(
+    		String name, 
+    		String description, 
+    		boolean supportsUpdate) {
+    	
+    	View view = (View)factory.createView();
+        if( view != null ) {
+        	view.setName(name);
+        	view.setSupportsUpdate(supportsUpdate);
+        	
+        	// SET PARENT
+            addValue(modelResource, view, getModelResourceContents(modelResource));
+            
+            addDescription(view, description);
+        }
+        
+        return view;
+    }
+    
+    public Procedure createProcedure(
+    		String name, 
+    		String description) {
+    	Procedure procedure = (Procedure)factory.createProcedure();
+    	
+        if( procedure != null ) {
+        	procedure.setName(name);
+        	
+        	// SET PARENT
+            addValue(modelResource, procedure, getModelResourceContents(modelResource));
+
+            addDescription(procedure, description);
+        }
+        
+        return procedure;
+    }
+    
+    public Procedure createPushdownFunction(
+    		String name, 
+    		String description) {
+    	Procedure procedure = (Procedure)createProcedure(name, description);
+    	procedure.setFunction(true);
+        
+        return procedure;
+    }
+    
+//    public EObject createIndex(ModelResource modelResource, String name, String description, Object parent) {
+//        Index index = factory.createIndex();
+//        if( index != null ) {
+//            index.setName(name);
+//            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( parent instanceof ModelResource ) {
+//            	addValue(parent, index, getModelResourceContents(modelResource));
+//            } else if( parent instanceof Schema ) {
+//                index.setSchema((Schema)parent);
+//                addValue(parent, index, ((Schema)parent).getIndexes());
+//            } else if( parent instanceof Catalog ) {
+//                index.setCatalog((Catalog)parent);
+//                addValue(parent, index, ((Catalog)parent).getIndexes());
+//            }
+//
+//            addDescription(modelResource, index, description);
+//        }
+//        
+//        return index;
+//    }
+    
+    public Column createColumn(
+    		String name, 
+    		String description, 
+    		EObject viewOrBaseTable,
+    		boolean useDefaultDatatype, 
+    		EObject datatype,
+    		int length ) {
+    	
+        Column column = factory.createColumn();
+        if( column != null ) {
+        	column.setName(name);
+            
+        	// SET DATATYPE AND LENGTH
+            if( datatype != null)
+            	column.setType(datatype);
+            else {
+                if( useDefaultDatatype && defaultDatatype != null ) {
+                	column.setType(defaultDatatype);
+                }
+            }
+            if( length > 0 )
+            	column.setLength(length);
+            else if( useDefaultDatatype ) {
+            	column.setLength(defaultLength);
+            }
+            
+            // SET PARENT
+            if( viewOrBaseTable instanceof BaseTable ) {
+            	addValue(viewOrBaseTable, column, ((BaseTable)viewOrBaseTable).getColumns());
+            } else if( viewOrBaseTable instanceof View ) {
+            	addValue(viewOrBaseTable, column, ((View)viewOrBaseTable).getColumns());
+            }
+            
+            addDescription(column, description);
+        }
+        return column;
+    }
+    
+    public  ProcedureParameter createParameter(
+    		String name, 
+    		String description, 
+    		boolean isOutput,
+    		Procedure procedure,
+    		boolean useDefaultDatatype, 
+    		EObject datatype,
+    		int length ) {
+    	
+        ProcedureParameter param = factory.createProcedureParameter();
+        if( param != null ) {
+            param.setName(name);
+            
+            // SET DATATYPE AND LENGTH
+            if( datatype != null)
+            	param.setType(datatype);
+            else {
+                if( useDefaultDatatype && defaultDatatype != null ) {
+                	param.setType(defaultDatatype);
+                }
+            }
+            if( length > 0 )
+            	param.setLength(length);
+            else if( useDefaultDatatype ) {
+            	param.setLength(defaultLength);
+            }
+            if( isOutput ) {
+            	param.setDirection(DirectionKind.RETURN_LITERAL);
+            } else {
+            	param.setDirection(DirectionKind.IN_LITERAL);
+            }
+            
+            // SET PARENT
+            addValue(procedure, param, ((Procedure)procedure).getParameters());
+
+            addDescription(param, description);
+        }
+        
+        return param;
+    }
+    
+//    public static EObject createBaseTable(final String name, final boolean supportsUpdate) {
+//    	BaseTable bt = factory.createBaseTable();
+//    	bt.setName(name);
+//    	bt.setSupportsUpdate(supportsUpdate);
+//    	return bt;
+//    }
+    
+    private void addDescription(EObject eObject, String description) {
+        if( this.modelResource != null && description != null && description.length() > 0 ) {
+            final ModelContents contents = ModelerCore.getModelEditor().getModelContents(modelResource);
+            Annotation newAnnot = ModelResourceContainerFactory.createNewAnnotation(eObject, contents.getAnnotationContainer(true));
+            newAnnot.setDescription(description);
+        }
+    }
+    
+    public EList getModelResourceContents(ModelResource resource ) {
+    	EList eList = null;
+    	
+    	try {
+			eList = resource.getEmfResource().getContents();
+		} catch (ModelWorkspaceException e) {
+			 UiConstants.Util.log(IStatus.ERROR, e, getString(GET_MODEL_CONTENTS_ERROR, resource));
+		}
+		
+		return eList;
+    }
+    
+    public void addValue(final Object owner, final Object value, EList feature) {
+        try {
+            if( isTransactionable ) {
+                ModelerCore.getModelEditor().addValue(owner, value, feature);
+            } else {
+                feature.add(value);
+            }
+        } catch (ModelerCoreException err) {
+            UiConstants.Util.log(IStatus.ERROR, err, getString(ADD_VALUE_ERROR, value, owner));
+        }
+    }
+    
+}
Index: src/com/metamatrix/modeler/internal/ui/actions/CreatePushdownFunctionAction.java
===================================================================
--- src/com/metamatrix/modeler/internal/ui/actions/CreatePushdownFunctionAction.java	(revision 0)
+++ src/com/metamatrix/modeler/internal/ui/actions/CreatePushdownFunctionAction.java	(revision 0)
@@ -0,0 +1,676 @@
+/*
+ * 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 com.metamatrix.modeler.internal.ui.actions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.designer.udf.UdfManager;
+
+import com.metamatrix.core.util.StringUtilities;
+import com.metamatrix.metamodels.relational.Procedure;
+import com.metamatrix.metamodels.relational.util.ParameterData;
+import com.metamatrix.metamodels.relational.util.PushdownFunctionData;
+import com.metamatrix.modeler.core.ModelerCore;
+import com.metamatrix.modeler.core.workspace.ModelResource;
+import com.metamatrix.modeler.core.workspace.ModelWorkspaceException;
+import com.metamatrix.modeler.internal.core.workspace.ModelObjectAnnotationHelper;
+import com.metamatrix.modeler.internal.ui.PluginConstants;
+import com.metamatrix.modeler.internal.ui.editors.ModelEditor;
+import com.metamatrix.modeler.internal.ui.viewsupport.ModelIdentifier;
+import com.metamatrix.modeler.internal.ui.viewsupport.ModelUtilities;
+import com.metamatrix.modeler.internal.ui.viewsupport.RelationalObjectFactory;
+import com.metamatrix.modeler.ui.UiConstants;
+import com.metamatrix.modeler.ui.UiPlugin;
+import com.metamatrix.modeler.ui.actions.INewChildAction;
+import com.metamatrix.modeler.ui.actions.INewSiblingAction;
+import com.metamatrix.modeler.ui.editors.ModelEditorManager;
+import com.metamatrix.ui.internal.eventsupport.SelectionUtilities;
+import com.metamatrix.ui.internal.util.WidgetFactory;
+import com.metamatrix.ui.text.StyledTextEditor;
+
+/**
+ * Action and dialog designed to help create relational source model Pushdown functions.
+ * 
+ * Basically, this provides users the ability to model functions defined in databases and use the function call within
+ * virtual table or procedure SQL statements/transformations. (see {@link UdfManager})
+ */
+public class CreatePushdownFunctionAction extends Action implements INewChildAction, INewSiblingAction { // ISelectionListener, Comparable, ISelectionAction, 
+	private IFile selectedModel;
+	public static ModelObjectAnnotationHelper ANNOTATION_HELPER = new ModelObjectAnnotationHelper();
+	public static final String TITLE = UiConstants.Util.getString("CreatePushdownFunctionAction.title"); //$NON-NLS-1$
+	 
+	private Collection<String> datatypes;
+	 
+	public CreatePushdownFunctionAction() {
+		super(TITLE);
+		setImageDescriptor(UiPlugin.getDefault().getImageDescriptor( PluginConstants.Images.NEW_PUSHDOWN_FUNCTION));
+		
+		Set<String> unsortedDatatypes = DataTypeManager.getAllDataTypeNames();
+		datatypes = new ArrayList<String>();
+		
+		String[] sortedStrings = unsortedDatatypes.toArray(new String[unsortedDatatypes.size()]);
+		Arrays.sort(sortedStrings);
+		for( String dType : sortedStrings ) {
+			datatypes.add(dType);
+		}
+	}
+
+//	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+//       boolean enable = isApplicable(selection);
+//       setEnabled(enable);
+//	}
+	
+    /* (non-Javadoc)
+     * @see com.metamatrix.modeler.ui.actions.INewChildAction#canCreateChild(org.eclipse.emf.ecore.EObject)
+     */
+    public boolean canCreateChild(EObject parent) {
+    	return false;
+    }
+    
+    /* (non-Javadoc)
+     * @see com.metamatrix.modeler.ui.actions.INewChildAction#canCreateChild(org.eclipse.core.resources.IFile)
+     */
+    public boolean canCreateChild(IFile modelFile) {
+    	return isApplicable(new StructuredSelection(modelFile));
+    }
+    /* (non-Javadoc)
+     * @see com.metamatrix.modeler.ui.actions.INewSiblingAction#canCreateChild(org.eclipse.emf.ecore.EObject)
+     */
+    public boolean canCreateSibling(EObject parent) {
+    	//Convert eObject selection to IFile
+    	ModelResource mr = ModelUtilities.getModelResourceForModelObject(parent);
+    	if( mr != null ) {
+    		IFile modelFile = null;
+    		
+    		try {
+				modelFile = (IFile)mr.getCorrespondingResource();
+			} catch (ModelWorkspaceException ex) {
+				UiConstants.Util.log(ex);
+			}
+    		if( modelFile != null ) {
+    			return isApplicable(new StructuredSelection(modelFile));
+    		}
+    	}
+    	
+    	return false;
+    }
+
+	@Override
+   public void run() {
+		if( selectedModel != null ) {
+	        ModelResource mr = ModelUtilities.getModelResource(selectedModel);
+	        final Shell shell = UiPlugin.getDefault().getCurrentWorkbenchWindow().getShell();
+	        
+	        PushdownFunctionData data = new PushdownFunctionData();
+	        data.setToDefault(StringUtilities.EMPTY_STRING, StringUtilities.EMPTY_STRING,1, 5);
+	        
+	        PushdownFunctionInputDialog dialog = new PushdownFunctionInputDialog(shell, data);
+	        
+	        dialog.open();
+	        
+	        if (dialog.getReturnCode() == Window.OK) {
+	        	createProcedureInTxn(mr, data);
+	        }
+		}
+		
+	}
+
+	
+    private void createProcedureInTxn(ModelResource modelResource, PushdownFunctionData data) {
+        boolean requiredStart = ModelerCore.startTxn(true, true, "Create Pushdown Function", this); //$NON-NLS-1$
+        boolean succeeded = false;
+        try {
+            ModelEditor editor = ModelEditorManager.getModelEditorForFile((IFile)modelResource.getCorrespondingResource(), true);
+            if (editor != null) {
+                boolean isDirty = editor.isDirty();
+
+                RelationalObjectFactory factory = new RelationalObjectFactory(modelResource);
+                
+    	        // Create input parameters
+                Procedure pfd = (Procedure)factory.createPushdownFunction(data.getName(), data.getDescription());
+    	        for( ParameterData paramData : data.getInputParameters() ) {
+    	        	if( paramData.isIncluded() ) {
+    	        	EObject dType = data.getDatatype(paramData.getType());
+    	        	factory.createParameter(paramData.getName(), null, false, pfd, false, dType, paramData.getLength());
+    	        	}
+    	        }
+    	        // Set output/return parameter
+    	        EObject returnParamDatatype = data.getDatatype(data.getReturnParameterType());
+    	        factory.createParameter(data.getReturnParameterName(), null, true, pfd, false, returnParamDatatype, data.getReturnParameterLength());
+    	        
+    	        // Set other properties
+    	        if( data.getNameInSource() != null && data.getNameInSource().length() > 0 ) {
+    	        	pfd.setNameInSource(data.getNameInSource());
+    	        }
+    	        // Set extended properties
+    	        ANNOTATION_HELPER.addProperty(pfd, PushdownFunctionData.DETERMINISTIC_PROPERTY_KEY, Boolean.toString(data.getDeterministic()));
+
+                if (!isDirty && editor.isDirty()) {
+                    editor.doSave(new NullProgressMonitor());
+                }
+                succeeded = true;
+            }
+        } catch (Exception e) {
+            MessageDialog.openError(Display.getCurrent().getActiveShell(),
+            		UiConstants.Util.getString("CreatePushdownFunctionAction.exceptionMessage"), e.getMessage()); //$NON-NLS-1$
+            IStatus status = new Status(IStatus.ERROR, UiConstants.PLUGIN_ID,
+            		UiConstants.Util.getString("CreatePushdownFunctionAction.exceptionMessage"), e); //$NON-NLS-1$
+            UiConstants.Util.log(status);
+
+            return;
+        } finally {
+            // if we started the txn, commit it.
+            if (requiredStart) {
+                if (succeeded) {
+                    ModelerCore.commitTxn();
+                } else {
+                    ModelerCore.rollbackTxn();
+                }
+            }
+        }
+    }
+   
+//	public int compareTo(Object o) {
+//		if( o instanceof String) {
+//			return getText().compareTo((String)o);
+//		}
+//		
+//		if( o instanceof Action ) {
+//			return getText().compareTo( ((Action)o).getText() );
+//		}
+//		return 0;
+//	}
+	
+	
+	public boolean isApplicable(ISelection selection) {
+       boolean result = false;
+       if ( ! SelectionUtilities.isMultiSelection(selection) ) {
+           Object obj = SelectionUtilities.getSelectedObject(selection);
+           if ( obj instanceof IFile && ModelUtilities.isModelFile((IFile) obj) &&
+           		ModelIdentifier.isRelationalSourceModel((IResource)obj)) {
+        	   this.selectedModel = (IFile) obj;
+               result = true;
+           }
+       }
+       
+       return result;
+	}
+
+	class PushdownFunctionInputDialog extends TitleAreaDialog {
+
+	    private final String TITLE = UiConstants.Util.getString("PushdownFunctionInputDialog.title"); //$NON-NLS-1$
+	    
+	    private PushdownFunctionData data;
+
+	    private Button deterministic, OKButton;
+	    private Collection<ParameterRow> input_rows = new ArrayList<CreatePushdownFunctionAction.ParameterRow>(5);
+	    private ParameterRow return_row;
+	    private boolean isControlComplete = false;
+	    
+	    public PushdownFunctionInputDialog(Shell parentShell, PushdownFunctionData data) {
+	        super(parentShell);
+	        this.setTitle(TITLE);
+	        this.data = data;
+	        setShellStyle(getShellStyle() | SWT.RESIZE);
+	    }
+	    
+	    @Override
+	    protected void configureShell( Shell shell ) {
+	        super.configureShell(shell);
+	        shell.setText(TITLE);
+	    }
+	    
+	    /* (non-Javadoc)
+	     * @see org.eclipse.jface.window.Window#createDialogArea(org.eclipse.swt.widgets.Composite)
+	     */
+	    @Override
+	    protected Control createDialogArea(Composite parent) {
+	    	
+	        Composite mainPanel = (Composite)super.createDialogArea(parent);
+	        this.setTitle(UiConstants.Util.getString("PushdownFunctionInputDialog.headerTitle")); //$NON-NLS-1$
+	        this.setMessage(UiConstants.Util.getString("PushdownFunctionInputDialog.initialMessage")); //$NON-NLS-1$
+	        //add controls to composite as necessary
+	        GridLayout gridLayout = new GridLayout();
+	        gridLayout.numColumns = 2;
+	        mainPanel.setLayout(gridLayout);
+	        GridData mainGD = new GridData(GridData.FILL_BOTH);
+	        mainGD.minimumWidth = 500;
+	        mainPanel.setLayoutData(mainGD);
+
+	        Group nameGroup = WidgetFactory.createGroup(mainPanel, UiConstants.Util.getString("PushdownFunctionInputDialog.name"), GridData.FILL_HORIZONTAL, 2, 1); //$NON-NLS-1$
+
+	        final Text pdfName = WidgetFactory.createTextField(nameGroup, 0);
+	        if( data.getName() != null) {
+	        	pdfName.setText(data.getName());
+	        }
+	        pdfName.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+	        pdfName.addModifyListener(new ModifyListener() {
+				public void modifyText(ModifyEvent e) {
+					data.setName(pdfName.getText());
+					validate();
+				}
+			});
+	        
+	        Group inputParamsGroup = WidgetFactory.createGroup(mainPanel, 
+	        		UiConstants.Util.getString("PushdownFunctionInputDialog.inputParameters"), GridData.FILL_HORIZONTAL, 2, 4); //$NON-NLS-1$
+	        
+	        WidgetFactory.createLabel(inputParamsGroup, UiConstants.Util.getString("PushdownFunctionInputDialog.include")); //$NON-NLS-1$
+	        WidgetFactory.createLabel(inputParamsGroup, UiConstants.Util.getString("PushdownFunctionInputDialog.name")); //$NON-NLS-1$
+	        WidgetFactory.createLabel(inputParamsGroup, UiConstants.Util.getString("PushdownFunctionInputDialog.dataType")); //$NON-NLS-1$
+	        WidgetFactory.createLabel(inputParamsGroup, UiConstants.Util.getString("PushdownFunctionInputDialog.length")); //$NON-NLS-1$
+
+	        int numInitialRows = data.getInputParameters().size();
+	        ParameterData[] inputData = data.getInputParameters().toArray(new ParameterData[numInitialRows]);
+	        
+	        int lastIncludeIndex = 0;
+	        boolean foundLastIncludeIndex = false;
+	        for( int i=0; i< 5; i++ ) {
+	        	ParameterRow inputRow = new ParameterRow(i, inputData[i], this, inputParamsGroup, false);
+	        	if( i < numInitialRows ) {
+	        		if( lastIncludeIndex == -1 && !inputData[i].isIncluded() ) {
+	        			lastIncludeIndex = i-1;
+	        			foundLastIncludeIndex = true;
+	        		}
+	        		
+	        		if( foundLastIncludeIndex && i == (lastIncludeIndex+1) ) {
+	        			inputRow.enable();
+	        		}
+	        	} 
+	        	this.input_rows.add(inputRow);
+	        }
+	        if( lastIncludeIndex == 0 ) {
+	        	ParameterRow[] rows = this.input_rows.toArray(new ParameterRow[5]);
+	        	rows[0].enable();
+	        	rows[1].enable();
+	        }
+	        
+	        Group returnParamsGroup = WidgetFactory.createGroup(mainPanel, UiConstants.Util.getString("PushdownFunctionInputDialog.returnParameter"), GridData.FILL_HORIZONTAL, 2, 3); //$NON-NLS-1$
+	        
+	        WidgetFactory.createLabel(returnParamsGroup, UiConstants.Util.getString("PushdownFunctionInputDialog.name")); //$NON-NLS-1$
+	        WidgetFactory.createLabel(returnParamsGroup, UiConstants.Util.getString("PushdownFunctionInputDialog.dataType")); //$NON-NLS-1$
+	        WidgetFactory.createLabel(returnParamsGroup, UiConstants.Util.getString("PushdownFunctionInputDialog.length")); //$NON-NLS-1$
+	        
+	        return_row = new ParameterRow(0, data.getReturnParameterData(), this, returnParamsGroup, true);
+	        return_row.enable();
+	        
+	        Group propertiesGroup = WidgetFactory.createGroup(mainPanel, UiConstants.Util.getString("PushdownFunctionInputDialog.properties"), GridData.FILL_BOTH, 2, 2); //$NON-NLS-1$
+	        
+	        WidgetFactory.createLabel(propertiesGroup, UiConstants.Util.getString("PushdownFunctionInputDialog.nameInSource")); //$NON-NLS-1$
+	        final Text nameInSourceText = WidgetFactory.createTextField(propertiesGroup, 0);
+	        if( data.getNameInSource() != null) {
+	        	nameInSourceText.setText(data.getNameInSource());
+	        }
+	        nameInSourceText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+	        nameInSourceText.addModifyListener(new ModifyListener() {
+				public void modifyText(ModifyEvent e) {
+					data.setNameInSource(nameInSourceText.getText());
+					validate();
+				}
+			});
+	        
+	        deterministic = new Button(propertiesGroup, SWT.CHECK | SWT.RIGHT); //
+	        deterministic.setText(UiConstants.Util.getString("PushdownFunctionInputDialog.deterministic")); //WidgetFactory.createCheckBox(propertiesGroup, "Deterministic", 0, 2); //$NON-NLS-1$
+	        deterministic.addSelectionListener(new SelectionAdapter() {
+				@Override
+				public void widgetSelected(SelectionEvent e) {
+					data.setDeterministic(deterministic.getSelection());
+				}
+			});
+	        
+
+	        
+	        Group descriptionGroup = WidgetFactory.createGroup(mainPanel, UiConstants.Util.getString("PushdownFunctionInputDialog.description"), GridData.FILL_HORIZONTAL, 2, 1); //$NON-NLS-1$
+	        GridData gdd = new GridData(GridData.FILL_BOTH);
+	        gdd.heightHint = 80;
+	        descriptionGroup.setLayoutData(gdd);
+	        
+	        StyledTextEditor textEditor = new StyledTextEditor(descriptionGroup, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
+	        GridData gdt = new GridData(GridData.FILL_BOTH);
+	        gdt.heightHint = 80;
+	        gdt.horizontalSpan = 1;
+	        textEditor.setLayoutData(gdt);
+	        textEditor.setEditable(true);
+	        textEditor.setAllowFind(false);
+	        textEditor.getTextWidget().setWordWrap(true);
+	        if( data.getDescription() != null) {
+	        	textEditor.setText(data.getDescription());
+	        }
+	        
+	        isControlComplete = true;
+	        return mainPanel;
+	    }
+	    
+	    public PushdownFunctionData getData() {
+	    	return this.data;
+	    }
+	    
+	    protected void inputIncludeSelected(int rowID, boolean value) {
+	    	ParameterRow[] rows = input_rows.toArray(new ParameterRow[5]);
+	    	switch(rowID) {
+		    	case 0: {
+		    		// user checked first parameter.  If FALSE, then it was true and we need to disable ALL other rows
+		    		if( !value ) {
+		    			for( int i=1; i<5; i++ ) {
+		    				rows[i].exclude();
+		    				rows[i].disable();
+		    			}
+		    		} else {
+		    			// DO INCLUDE
+		    			rows[1].exclude();
+		    			rows[1].enable();
+		    			for( int i=2; i<5; i++ ) {
+		    				rows[i].exclude();
+		    				rows[i].disable();
+		    			}
+		    		}
+		    	} break;
+		    	case 1: {
+		    		// user checked second parameter.  If FALSE, then it was true and we need to disable ALL other rows
+		    		if( !value ) {
+		    			for( int i=2; i<5; i++ ) {
+		    				rows[i].exclude();
+		    				rows[i].disable();
+		    			}
+		    		} else {
+		    			// DO INCLUDE
+		    			rows[2].exclude();
+		    			rows[2].enable();
+		    			for( int i=3; i<5; i++ ) {
+		    				rows[i].exclude();
+		    				rows[i].disable();
+		    			}
+		    		}
+		    	} break;
+		    	case 2: {
+		    		// user checked second parameter.  If FALSE, then it was true and we need to disable ALL other rows
+		    		if( !value ) {
+		    			for( int i=3; i<5; i++ ) {
+		    				rows[i].exclude();
+		    				rows[i].disable();
+		    			}
+		    		} else {
+		    			// DO INCLUDE
+		    			rows[3].exclude();
+		    			rows[3].enable();
+		    			for( int i=4; i<5; i++ ) {
+		    				rows[i].exclude();
+		    				rows[i].disable();
+		    			}
+		    		}
+		    	} break;
+		    	case 3: {
+		    		// user checked second parameter.  If FALSE, then it was true and we need to disable ALL other rows
+		    		if( !value ) {
+		    			for( int i=4; i<5; i++ ) {
+		    				rows[i].exclude();
+		    				rows[i].disable();
+		    			}
+		    		} else {
+		    			// DO INCLUDE
+		    			rows[4].exclude();
+		    			rows[4].enable();
+		    		}
+		    	} break;
+	    	}
+	    	validate();
+	    }
+	    
+	    protected void validate() {
+	    	
+	    	String message = UiConstants.Util.getString("PushdownFunctionInputDialog.pressOkToFinish"); //$NON-NLS-1$
+
+	    	if( this.isControlComplete ) {
+		    	IStatus status = this.data.validate();
+		    	
+		    	if( status.getSeverity() != IStatus.OK ) {
+		    		this.setErrorMessage(status.getMessage());
+		    		this.OKButton.setEnabled(false);
+		    	} else {
+		    		this.setErrorMessage(null);
+		    		setMessage(message);
+		    		this.OKButton.setEnabled(true);
+		    	}
+	    	}
+	    			
+	    }
+	    
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
+		 */
+	    @Override
+		protected void createButtonsForButtonBar(Composite parent) {
+			this.OKButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
+					true);
+			createButton(parent, IDialogConstants.CANCEL_ID,
+					IDialogConstants.CANCEL_LABEL, false);
+			this.OKButton.setEnabled(false);
+		}
+	}
+	
+	class ParameterRow {
+		final private int rowID;
+		
+		private PushdownFunctionInputDialog dialog;
+		
+		private Button includeCB;
+	    private Text nameText;
+	    private Combo typeCombo;
+	    private Text typeLengthText;
+	    
+	    private ParameterData data;
+		private String defaultType = "string"; //$NON-NLS-1$
+		private int defaultLength = 255;
+		
+		private boolean include;
+		
+		public ParameterRow(int rowID, ParameterData data, PushdownFunctionInputDialog dialog, Composite parent, boolean isReturn) {
+			super();
+			this.dialog = dialog;
+			this.rowID = rowID;
+			this.data = data;
+			
+			createControl(parent, isReturn);
+			
+			initData();
+			disable();
+		}
+		
+		public ParameterData getData() {
+			return this.data;
+		}
+		
+		public void initData() {
+			if( data != null ) {
+				if( data.getName() != null) {
+					if( data.getName() != null ) {
+						nameText.setText(data.getName());
+					}
+				}
+	        	if( data.getType() != null ) {
+	        		String comboValue = defaultType;
+	    	        if( typeCombo != null && data.getType() != null ) {
+	    	        	comboValue = data.getType();
+	    	        }
+	        		int stringIndex = 0;
+	    	        int counter = 0;
+	        		for( String type : datatypes ) {
+	    	        	if( type.equalsIgnoreCase(comboValue) ) {
+	    	        		stringIndex = counter;
+	    	        	}
+	    	        	counter++;
+	    	        }
+	    	        typeCombo.select(stringIndex);
+	        	}
+	        	typeLengthText.setText(Integer.toString(data.getLength()));
+	        	if( data.isIncluded() ) {
+	        		enable();
+	        		include();
+	        	} else {
+	        		exclude();
+	        		disable();
+	        	}
+	        }
+		}
+		
+		public int getRowID() {
+			return this.rowID;
+		}
+		
+		private void createControl(Composite parent, boolean isReturn) {
+			
+			if( !isReturn ) {
+				this.includeCB = WidgetFactory.createCheckBox(parent, " ", 0, false); //$NON-NLS-1$
+		        this.includeCB.addSelectionListener(new SelectionAdapter() {
+
+		            @Override
+		            public void widgetSelected(final SelectionEvent event) {
+		            	boolean value = includeCB.getSelection();
+		            	if( value ) {
+		            		data.include();
+		            	} else {
+		            		exclude();
+		            	}
+		                dialog.inputIncludeSelected(rowID, includeCB.getSelection());
+		            }
+		        });
+			}
+			
+			this.nameText = WidgetFactory.createTextField(parent, 0);
+			this.nameText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+	        if( this.data != null && this.data.getName() != null) {
+	        	this.nameText.setText(data.getName());
+	        }
+	        this.nameText.addModifyListener(new ModifyListener() {
+				public void modifyText(ModifyEvent e) {
+					data.setName(nameText.getText()); 
+					validate();
+				}
+			});
+	        
+	        this.typeCombo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
+	        //combo_1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+	        int stringIndex = 0;
+	        int counter = 0;
+	        String comboValue = defaultType;
+	        if( this.typeCombo != null && this.data.getType() != null ) {
+	        	comboValue = this.data.getType();
+	        }
+	        for( String type : datatypes ) {
+	        	this.typeCombo.add(type);
+	        	
+	        	if( type.equalsIgnoreCase(comboValue) ) {
+	        		stringIndex = counter;
+	        	}
+	        	counter++;
+	        }
+	        this.typeCombo.select(stringIndex);
+	        this.typeCombo.addSelectionListener(new SelectionAdapter() {
+				@Override
+				public void widgetSelected(SelectionEvent e) {
+					data.setType(typeCombo.getItem(typeCombo.getSelectionIndex()));
+					validate();
+				}
+			});
+	        this.typeLengthText = WidgetFactory.createTextField(parent);
+	        GridData gd1 = new GridData();
+	        gd1.minimumWidth = 60;
+	        gd1.widthHint = 60;
+	        this.typeLengthText.setLayoutData(gd1);
+	        if( data != null) {
+	        	this.typeLengthText.setText(Integer.toString(data.getLength()));
+	        } else {
+	        	this.typeLengthText.setText(Integer.toString(defaultLength));
+	        }
+	        this.typeLengthText.addModifyListener(new ModifyListener() {
+				public void modifyText(ModifyEvent e) {
+					if( typeLengthText.getText().length() > 0 ) {
+						data.setLength(Integer.parseInt(typeLengthText.getText()) );
+					} else {
+						data.setLength(0);
+					}
+					validate();
+				}
+			});
+		}
+		
+		public void disable() {
+			if( this.includeCB != null ) {
+				this.includeCB.setEnabled(false);
+			}
+    		this.nameText.setEnabled(false);
+    		this.typeCombo.setEnabled(false);
+    		this.typeLengthText.setEnabled(false);
+		}
+		
+		public void enable() {
+			if( this.includeCB != null ) {
+				this.includeCB.setEnabled(true);
+			}
+			this.nameText.setEnabled(true);
+    		this.typeCombo.setEnabled(true);
+    		this.typeLengthText.setEnabled(true);
+		}
+		
+		private void validate() {
+			dialog.validate();
+		}
+		
+		public void include() {
+			data.include();
+			if( this.includeCB != null ) {
+				this.includeCB.setSelection(data.isIncluded());
+			}
+		}
+		
+		public void exclude() {
+			data.exclude();
+			if( this.includeCB != null ) {
+				this.includeCB.setSelection(data.isIncluded());
+			}
+		}
+		
+		public boolean isIncluded() {
+			return this.include;
+		}
+	}
+}
+
Index: plugin.properties
===================================================================
--- plugin.properties	(revision 1783)
+++ plugin.properties	(working copy)
@@ -181,7 +181,7 @@
 openMetadataSearchAction.tip=Open Metadata Search Page
 
 #=================================================================================================================================
-# Metadata Favories Action Set
+# Metadata Favories Action SetChild
 
 addToMetadataFavoritesAction.name   = Add to Metadata Favorites
 addToMetadataFavoritesAction.label   = Add to Metadata Favorites
@@ -277,3 +277,9 @@
 renameCommand.name = Rename Model Object...
 renameCommand.description = Rename the selected model object
 
+createPushdownFunctionAction.name = Create Source Function
+createPushdownFunctionAction.label = Create Source Function
+createPushdownFunctionAction.tooltip = Create Source Function for selected source model
+newChildPushdownFunction=Source Function
+newSiblingPushdownFunction=Source Function
+
Index: plugin.xml
===================================================================
--- plugin.xml	(revision 1783)
+++ plugin.xml	(working copy)
@@ -917,7 +917,25 @@
          label="%setDatatypeModelingAction.label">
       </specialAction>
    </extension>
+	<extension
+         id="newChildPushdownFunction"
+         name="%newChildPushdownFunction"
+         point="org.teiid.designer.ui.newChildAction">
+      <class
+            name="com.metamatrix.modeler.internal.ui.actions.CreatePushdownFunctionAction">
+      </class>
+   </extension>
+
+   <extension
+         id="newSiblingPushdownFunction"
+         name="%newSiblingPushdownFunction"
+         point="org.teiid.designer.ui.newSiblingAction">
+      <class
+            name="com.metamatrix.modeler.internal.ui.actions.CreatePushdownFunctionAction">
+      </class>
+   </extension>
 
+
 <!-- Adding Model Explorer action to show/hide non-model files -->
 	<extension
 		point = "org.eclipse.ui.viewActions">
#P org.teiid.designer.udf
Index: src/org/teiid/designer/udf/UdfManager.java
===================================================================
--- src/org/teiid/designer/udf/UdfManager.java	(revision 1779)
+++ src/org/teiid/designer/udf/UdfManager.java	(working copy)
@@ -12,6 +12,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.Properties;
 import java.util.Set;
 
 import org.eclipse.core.internal.resources.Marker;
@@ -27,8 +28,8 @@
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.resource.Resource;
 import org.teiid.metadata.FunctionMethod;
-import org.teiid.metadata.FunctionParameter;
 import org.teiid.metadata.FunctionMethod.Determinism;
+import org.teiid.metadata.FunctionParameter;
 import org.teiid.query.function.FunctionDescriptor;
 import org.teiid.query.function.FunctionLibrary;
 import org.teiid.query.function.FunctionTree;
@@ -36,14 +37,22 @@
 import org.teiid.query.function.UDFSource;
 
 import com.metamatrix.core.modeler.util.FileUtils;
-import com.metamatrix.core.util.ModelType;
+import com.metamatrix.core.util.StringUtilities;
+import com.metamatrix.metamodels.core.ModelType;
 import com.metamatrix.metamodels.function.ScalarFunction;
+import com.metamatrix.metamodels.relational.DirectionKind;
+import com.metamatrix.metamodels.relational.Procedure;
+import com.metamatrix.metamodels.relational.ProcedureParameter;
+import com.metamatrix.metamodels.relational.RelationalPackage;
+import com.metamatrix.metamodels.relational.util.PushdownFunctionData;
 import com.metamatrix.modeler.core.ModelerCore;
 import com.metamatrix.modeler.core.ModelerCoreException;
+import com.metamatrix.modeler.core.util.ModelObjectCollector;
 import com.metamatrix.modeler.core.util.ModelVisitor;
 import com.metamatrix.modeler.core.util.ModelVisitorProcessor;
 import com.metamatrix.modeler.core.workspace.ModelResource;
 import com.metamatrix.modeler.core.workspace.ModelWorkspaceException;
+import com.metamatrix.modeler.internal.core.workspace.ModelObjectAnnotationHelper;
 import com.metamatrix.modeler.internal.core.workspace.ModelUtil;
 import com.metamatrix.modeler.internal.core.workspace.ModelWorkspaceManager;
 import com.metamatrix.modeler.internal.core.workspace.ResourceChangeUtilities;
@@ -55,6 +64,8 @@
     
     public static final SystemFunctionManager SYSTEM_FUNCTION_MANAGER = new SystemFunctionManager();
     
+    private static final ModelObjectAnnotationHelper ANNOTATION_HELPER = new ModelObjectAnnotationHelper();
+    
     private FunctionLibrary systemFunctionLibrary;
    
     /**
@@ -361,10 +372,131 @@
         		functionTrees.add(tree);
         	}
         }
+        
+        // Now walk "Source relational models" to search for new Procedures that have FUNCTION = true set
+        
+        for( ModelResource sourceModel : getSourceRelationalModels() ) {
+        	
+    		IMarker[] markers = getMarkers(sourceModel);
+    		
+    		String schema = FileUtils.getFilenameWithoutExtension(sourceModel.getItemName());
+    		FunctionTree tree = new FunctionTree(schema, new UDFSource(Collections.EMPTY_LIST), false);
+    		
+    		for( Procedure procedure : getPushdownFunctions(sourceModel) ) {
+    			// Also the Function's input parameters AND it's return parameter (if non-null) need to be error free
+    			
+    			ProcedureWrapper wrappedProcedure = new ProcedureWrapper(procedure);
+    			
+    			if( !isFunctionObjectErrorFree(wrappedProcedure.getReturnParameter(), markers, sourceModel) ||
+    					wrappedProcedure.getReturnParameter() == null || 
+    				!isFunctionObjectErrorFree(wrappedProcedure.getReturnParameter(), markers, sourceModel)) {
+    				continue;
+    			}
+    			String description = null;
+    			
+    			try {
+					description = ModelerCore.getModelEditor().getDescription(procedure);
+				} catch (ModelerCoreException ex) {
+					UdfPlugin.UTIL.log(ex);
+				}
+    			
+				boolean functionPamameterHasError = false;
+				
+    			Collection<FunctionParameter> fParams = new ArrayList<FunctionParameter>();
+    			
+    			for( ProcedureParameter inputParam : wrappedProcedure.getInputParameters() ) {
+    				String dTypeName = ModelerCore.getModelEditor().getName(inputParam.getType());
+					fParams.add(new FunctionParameter(inputParam.getName(), dTypeName));
+					// If any function parameter has an error don't add this
+					if( !functionPamameterHasError && !isFunctionObjectErrorFree(inputParam, markers, sourceModel)){
+						functionPamameterHasError = true;
+					}
+    			}
+    			
+    			if( functionPamameterHasError ) {
+    				continue;
+    			}
+    			
+    			String dTypeName = ModelerCore.getModelEditor().getName(wrappedProcedure.getReturnParameter().getType());
+    			String returnParamName = ModelerCore.getModelEditor().getName(wrappedProcedure.getReturnParameter());
+    			FunctionParameter outputParam = new FunctionParameter(returnParamName, dTypeName); 
+    			
+    			// Set the category name as the Model Name
+    			String category = sourceModel.getItemName();
+    			if( category.endsWith(".xmi")) { //$NON-NLS-1$
+    				category = category.replaceAll(".xmi", StringUtilities.EMPTY_STRING); //$NON-NLS-1$
+    			}
+    			
+    			FunctionMethod fMethod = 
+    				new FunctionMethod(
+    						wrappedProcedure.getName(), 
+    						description, 
+    						category, 
+    						null, 
+    						null, 
+    						null,
+    						fParams.toArray(new FunctionParameter[0]),
+    						outputParam,
+    					    false,
+    						null
+    						);
+    			fMethod.setPushDown(Boolean.toString(true));
+    			if( wrappedProcedure.isDeterministic() ) {
+    				fMethod.setDeterminism(Determinism.DETERMINISTIC);
+    			} else {
+    				fMethod.setDeterminism(Determinism.NONDETERMINISTIC);
+    			}
+    			
+    			FunctionDescriptor fd = tree.addFunction(schema, null, fMethod);
+    			fd.setMetadataID(procedure);
+    		}
+    		functionTrees.add(tree);
+        }
 
         return new FunctionLibrary(SYSTEM_FUNCTION_MANAGER.getSystemFunctions(), functionTrees.toArray(new FunctionTree[functionTrees.size()]));
     }
     
+    private Collection<Procedure> getPushdownFunctions(ModelResource sourceModel) {
+    	Collection<Procedure> functions = new ArrayList<Procedure>();
+    	
+    	try {
+        	
+        	final ModelObjectCollector moc = new ModelObjectCollector(sourceModel.getEmfResource());
+            for( Object eObj : moc.getEObjects()){
+            	if( eObj instanceof Procedure ) {
+            		if( ((Procedure)eObj).isFunction()) {
+            			functions.add((Procedure)eObj);
+            		}
+            	}
+            }
+		} catch (CoreException ex) {
+            UdfPlugin.UTIL.log(ex);
+		}
+    	return functions;
+    }
+    
+    private Collection<ModelResource> getSourceRelationalModels() {
+    	Collection<ModelResource> sources = new ArrayList<ModelResource>();
+    	
+    	try {
+			ModelResource[] allModels = ModelWorkspaceManager.getModelWorkspaceManager().getModelWorkspace().getModelResources();
+			
+			for( ModelResource model : allModels ) {
+				String uri = model.getPrimaryMetamodelUri();
+				if( RelationalPackage.eNS_URI.equalsIgnoreCase(uri) &&
+					model.getModelType() == ModelType.PHYSICAL_LITERAL ) {
+					sources.add(model);
+				}
+			}
+			
+		} catch (CoreException ex) {
+            UdfPlugin.UTIL.log(ex);
+		}
+    	
+    	
+    	return sources;
+    }
+    
     private ScalarFunction[] getScalarFunctions(ModelResource mr) {
         	ScalarFunctionFinder visitor = new ScalarFunctionFinder();
         	final int mode = ModelVisitorProcessor.MODE_VISIBLE_CONTAINMENTS;   // show only those objects visible to user
@@ -411,4 +543,57 @@
 		}
     	
     }
+    
+    class ProcedureWrapper {
+    	Procedure procedure;
+    	ProcedureParameter returnParam;
+    	Collection<ProcedureParameter> inputParams;
+    	boolean deterministic = false;
+    	
+    	public ProcedureWrapper(Procedure procedure) {
+    		super();
+    		this.procedure = procedure;
+    		init();
+    	}
+    	
+    	private void init() {
+    		inputParams = new ArrayList<ProcedureParameter>();
+    		for( Object obj : procedure.getParameters() ) {
+    			ProcedureParameter param = (ProcedureParameter)obj;
+    			if( param.getDirection() == DirectionKind.IN_LITERAL ) {
+    				inputParams.add(param);
+    			} else if( param.getDirection() == DirectionKind.RETURN_LITERAL) {
+    				returnParam = param;
+    			}
+    		}
+    		try {
+				Properties props = ANNOTATION_HELPER.getExtendedProperties(procedure);
+				
+				if( props != null && props.size() > 0 ) {
+					Object determValue = props.get(PushdownFunctionData.DETERMINISTIC_PROPERTY_KEY);
+					if( determValue != null ) {
+						deterministic = Boolean.valueOf((String)determValue);
+					}
+				}
+			} catch (ModelerCoreException ex) {
+				UdfPlugin.UTIL.log(ex);
+			}
+    	}
+    	
+    	public ProcedureParameter getReturnParameter() {
+    		return this.returnParam;
+    	}
+    	
+    	public Collection<ProcedureParameter> getInputParameters() {
+    		return this.inputParams;
+    	}
+    	
+    	public String getName() {
+    		return ModelerCore.getModelEditor().getName(procedure);
+    	}
+    	
+    	public boolean isDeterministic() {
+    		return this.deterministic;
+    	}
+    }
 }
Index: META-INF/MANIFEST.MF
===================================================================
--- META-INF/MANIFEST.MF	(revision 1765)
+++ META-INF/MANIFEST.MF	(working copy)
@@ -14,7 +14,8 @@
  org.eclipse.emf.common,
  org.eclipse.core.resources,
  org.eclipse.core.runtime,
- org.teiid.designer.metamodels.function
+ org.teiid.designer.metamodels.function,
+ org.teiid.designer.metamodels.relational
 Export-Package: org.teiid.designer.udf
 Bundle-ActivationPolicy: lazy
 Bundle-Activator: org.teiid.designer.udf.UdfPlugin
#P org.teiid.designer.metamodels.relational
Index: plugin.xml
===================================================================
--- plugin.xml	(revision 1784)
+++ plugin.xml	(working copy)
@@ -25,12 +25,14 @@
       <alternateUri>
          mtkplugin:///com.metamatrix.metamodels.Relational
       </alternateUri>
+      <!-- 
       <rootEntityClass
             name="com.metamatrix.metamodels.relational.Catalog">
       </rootEntityClass>
       <rootEntityClass
             name="com.metamatrix.metamodels.relational.Schema">
       </rootEntityClass>
+      -->
       <rootEntityClass
             name="com.metamatrix.metamodels.relational.BaseTable">
       </rootEntityClass>
@@ -43,9 +45,6 @@
       <rootEntityClass
             name="com.metamatrix.metamodels.relational.Procedure">
       </rootEntityClass>
-      <rootEntityClass
-            name="com.metamatrix.metamodels.relational.LogicalRelationship">
-      </rootEntityClass>
       <properties
             createAsPhysical="true"
             requiresProxies="false"
Index: src/com/metamatrix/metamodels/relational/util/ParameterData.java
===================================================================
--- src/com/metamatrix/metamodels/relational/util/ParameterData.java	(revision 0)
+++ src/com/metamatrix/metamodels/relational/util/ParameterData.java	(revision 0)
@@ -0,0 +1,80 @@
+/*
+ * 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 com.metamatrix.metamodels.relational.util;
+
+/**
+ * Class to hold basic Pushdown-function parameter data structure and method access to key values
+ */
+public class ParameterData {
+	private String name;
+	private String type;
+	private int length;
+	private boolean include;
+	
+	public ParameterData() {
+		super();
+	}
+	
+	public ParameterData(String name, String type, int length) {
+		super();
+		this.name = name;
+		this.type = type;
+		if( this.type == null ) {
+			this.type = PushdownFunctionData.DEFAULT_TYPE;
+		}
+		this.length = length;
+	}
+
+	public String getName() {
+		return this.name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getType() {
+		return this.type;
+	}
+
+	public void setType(String type) {
+		this.type = type;
+	}
+
+	public int getLength() {
+		return this.length;
+	}
+
+	public void setLength(int length) {
+		this.length = length;
+	}
+	
+	public void include() {
+		this.include = true;
+	}
+	
+	public void exclude() {
+		this.include = false;
+	}
+	
+	public boolean isIncluded() {
+		return this.include;
+	}
+	
+	@Override
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		sb.append("ParameterData:") //$NON-NLS-1$
+		.append("\n  NAME = ").append(getName()) //$NON-NLS-1$
+		.append("\n  TYPE = ").append(getType()) //$NON-NLS-1$
+		.append("\n  LENGTH = ").append(Integer.toString(getLength())) //$NON-NLS-1$
+		.append("\n  INCLUDED = ").append(isIncluded()); //$NON-NLS-1$
+		
+		return sb.toString();
+	}
+}
Index: src/com/metamatrix/metamodels/relational/util/PushdownFunctionData.java
===================================================================
--- src/com/metamatrix/metamodels/relational/util/PushdownFunctionData.java	(revision 0)
+++ src/com/metamatrix/metamodels/relational/util/PushdownFunctionData.java	(revision 0)
@@ -0,0 +1,263 @@
+/*
+ * 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 com.metamatrix.metamodels.relational.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.ecore.EObject;
+
+import com.metamatrix.core.util.CoreArgCheck;
+import com.metamatrix.core.util.StringUtilities;
+import com.metamatrix.metamodels.relational.RelationalPlugin;
+import com.metamatrix.modeler.core.ModelerCore;
+import com.metamatrix.modeler.core.ModelerCoreException;
+import com.metamatrix.modeler.core.validation.rules.StringNameValidator;
+
+/**
+ * Class to hold basic Pushdown-function data structure and method access to key values
+ */
+
+public class PushdownFunctionData {
+	String name;
+	String description;
+	boolean deterministic;
+	String nameInSource;
+	
+	Collection<ParameterData> inputParameters;
+	ParameterData returnParameter;
+	public static String DEFAULT_TYPE = "string"; //$NON-NLS-1$
+	public static int DEFAULT_LENGTH = 255;
+	public static String DETERMINISTIC_PROPERTY_KEY = "ext-custom:determistic"; //$NON-NLS-1$
+	
+	private StringNameValidator validator = new StringNameValidator(1, 200, false);
+    	
+	public PushdownFunctionData() {
+		super();
+		this.inputParameters = new ArrayList<ParameterData>();
+	}
+	
+	public void setToDefault(String name, String description, int numParams, int maxParams) {
+		setName(name);
+		setDescription(description);
+		ParameterData param = null;
+		Collection<ParameterData> params = new ArrayList<ParameterData>(5);
+		for( int i=0; i<numParams; i++ ) {
+    		//param = new ParameterData("param_"+Integer.toString(i+1), defaultType, defaultLength);
+    		param = new ParameterData(StringUtilities.EMPTY_STRING, PushdownFunctionData.DEFAULT_TYPE, PushdownFunctionData.DEFAULT_LENGTH);
+    		param.include();
+    		params.add(param);
+		}
+		for( int i=numParams; i<maxParams; i++ ) {
+			//param = new ParameterData("param_"+Integer.toString(i+1), defaultType, defaultLength);
+			param = new ParameterData(StringUtilities.EMPTY_STRING, PushdownFunctionData.DEFAULT_TYPE, PushdownFunctionData.DEFAULT_LENGTH);
+			params.add(param);
+		}
+		setInputParameters(params);
+		setReturnParameterName(StringUtilities.EMPTY_STRING);
+		setReturnParameterLength(PushdownFunctionData.DEFAULT_LENGTH);
+		setReturnParameterType(PushdownFunctionData.DEFAULT_TYPE);
+	}
+
+	public String getName() {
+		return this.name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+	
+	public String getDescription() {
+		return this.description;
+	}
+
+	public void setDescription(String description) {
+		this.description = description;
+	}
+	
+	public String getNameInSource() {
+		return this.nameInSource;
+	}
+
+	public void setNameInSource(String nameInSource) {
+		this.nameInSource = nameInSource;
+	}
+	
+	public boolean getDeterministic() {
+		return this.deterministic;
+	}
+
+	public void setDeterministic(boolean deterministic) {
+		this.deterministic = deterministic;
+	}
+
+	public String getReturnParameterName() {
+		if( this.returnParameter != null ) {
+			return this.returnParameter.getName();
+		}
+		return null;
+	}
+	
+	public ParameterData getReturnParameterData() {
+		return this.returnParameter;
+	}
+
+	public void setReturnParameterName(String returnParameterName) {
+		if( this.returnParameter == null ) {
+			this.returnParameter = new ParameterData(returnParameterName, PushdownFunctionData.DEFAULT_TYPE, PushdownFunctionData.DEFAULT_LENGTH);
+		} else {
+			this.returnParameter.setName(returnParameterName);
+		}
+	}
+
+	public String getReturnParameterType() {
+		if( this.returnParameter != null ) {
+			return this.returnParameter.getType();
+		}
+		return null;
+	}
+	
+	public int getReturnParameterLength() {
+		if( this.returnParameter != null ) {
+			return this.returnParameter.getLength();
+		}
+		return 255;
+	}
+	
+	public void setReturnParameterLength(int length) {
+		if( this.returnParameter != null ) {
+			this.returnParameter.setLength(length);
+		}
+	}
+
+	public void setReturnParameterType(String returnParameterType) {
+		if( this.returnParameter != null ) {
+			this.returnParameter.setType(returnParameterType);
+		}
+	}
+
+	public Collection<ParameterData> getInputParameters() {
+		return this.inputParameters;
+	}
+	
+	public void addInputParameter(String name, String type, int length) {
+		CoreArgCheck.isNotNull(name, "name"); //$NON-NLS-1$
+		CoreArgCheck.isNotNull(name, "type"); //$NON-NLS-1$
+		if( !inputParameterExists(name) ) {
+			this.inputParameters.add(new ParameterData(name, type, length));
+		}
+	}
+	
+	public void setInputParameters(Collection<ParameterData> params) {
+		this.inputParameters.clear();
+		this.inputParameters.addAll(params);
+	}
+	
+	public void addInputParameter(ParameterData param) {
+		CoreArgCheck.isNotNull(param, "data"); //$NON-NLS-1$
+		if( !inputParameterExists(param.getName()) ) {
+			this.inputParameters.add(param);
+		}
+	}
+	
+	public boolean inputParameterExists(String name) {
+		for( ParameterData data : this.inputParameters ) {
+			if( data.getName().equalsIgnoreCase(name) ) {
+				return true;
+			}
+		}
+		
+		return false;
+	}
+	
+	public ParameterData getParameterData(int index) {
+		int nParams = this.inputParameters.size();
+		
+		if( index < nParams) {
+			return (ParameterData)((ArrayList)this.inputParameters).get(index);
+		}
+		
+		return null;
+	}
+	
+	public void setInputParameterData(int index, String name, String type, int length) {
+		int nParams = this.inputParameters.size();
+		
+		if( index < nParams) {
+			ParameterData data = (ParameterData)((ArrayList)this.inputParameters).get(index);
+			data.setName(name);
+			data.setType(type);
+			data.setLength(length);
+		}
+	}
+	
+	public void removeInputLastParameter() {
+		// Should only remove the "last" parameter in the lists
+		int nParams = this.inputParameters.size();
+		
+		if( nParams > 0 ) {
+			((ArrayList)this.inputParameters).remove(nParams-1);
+		}
+	}
+	
+	/**
+	 * 
+	 * @return status the IStatus
+	 */
+	public IStatus validate() {
+		IStatus status = new Status(IStatus.OK, RelationalPlugin.PLUGIN_ID, "OK"); //$NON-NLS-1$
+		
+		String errorMessage = this.validator.checkValidName(this.name);
+		
+		if( errorMessage != null ) {
+			return new Status(IStatus.ERROR, RelationalPlugin.PLUGIN_ID, errorMessage);
+		}
+		Collection<String> paramNames = new ArrayList<String>();
+		for( ParameterData param : getInputParameters() ) {
+			if( param.isIncluded() ) {
+    			errorMessage = this.validator.checkValidName(param.getName());
+    			if( errorMessage != null ) {
+        			return new Status(IStatus.ERROR, RelationalPlugin.PLUGIN_ID,
+        					RelationalPlugin.Util.getString("PushdownFunctionData.invalidInputParameterName", errorMessage)); //$NON-NLS-1$
+        		}
+    			int length = param.getLength();
+    			if( length < 0 || length > 65000 ) {
+    				return new Status(IStatus.ERROR, RelationalPlugin.PLUGIN_ID,
+    						RelationalPlugin.Util.getString("PushdownFunctionData.invalidParameterLength", Integer.toString(length))); //$NON-NLS-1$
+    			}
+    			if( paramNames.contains(param.getName().toUpperCase())) {
+    				return new Status(IStatus.ERROR, RelationalPlugin.PLUGIN_ID, 
+    						RelationalPlugin.Util.getString("PushdownFunctionData.duplicateInputParameterName", param.getName())); //$NON-NLS-1$
+    			}
+    			
+    			paramNames.add(param.getName().toUpperCase());
+			}
+		}
+		errorMessage = this.validator.checkValidName(getReturnParameterName());
+		if( errorMessage != null ) {
+			return new Status(IStatus.ERROR, RelationalPlugin.PLUGIN_ID, 
+					RelationalPlugin.Util.getString("PushdownFunctionData.invalidReturnParameterName", errorMessage)); //$NON-NLS-1$
+		}
+
+		return status;
+	}
+	
+	public EObject getDatatype(String type) {
+		EObject datatype = null;
+		
+		try {
+			datatype = ModelerCore.getBuiltInTypesManager().findDatatype(type);
+		} catch (ModelerCoreException ex) {
+			// TODO Auto-generated catch block
+			ex.printStackTrace();
+		}
+		return datatype;
+	}
+}
Index: src/com/metamatrix/metamodels/relational/aspects/validation/rules/ProcedureParametersRule.java
===================================================================
--- src/com/metamatrix/metamodels/relational/aspects/validation/rules/ProcedureParametersRule.java	(revision 1765)
+++ src/com/metamatrix/metamodels/relational/aspects/validation/rules/ProcedureParametersRule.java	(working copy)
@@ -69,6 +69,27 @@
                 return;                
             }
         }
+        
+        // Need to validate for Pushdown Functions if "FUNCTION = TRUE" property set
+        // 1) Can have multiple input parameters
+        // 2) Requires "Output Parameter" and CANNOT have multiple
+        if( procedure.isFunction() ) {
+        	paramIter = procedure.getParameters().iterator();
+            while(paramIter.hasNext()) {
+            	ProcedureParameter param = (ProcedureParameter) paramIter.next();
+            	DirectionKind direction = param.getDirection();
+            	int directionKind = direction.getValue();
+            	if( directionKind == DirectionKind.INOUT ||
+            		directionKind == DirectionKind.OUT || 
+            		directionKind == DirectionKind.UNKNOWN ) {
+                    ValidationProblem problem = new ValidationProblemImpl(0, IStatus.ERROR, RelationalPlugin.Util.getString("ProcedureParametersRule.Procedure_{0}_is_defined_as_function_and_can_only_have_in_parameters_and_one_return_parameter",  new Object[]{procedure.getName()})); //$NON-NLS-1$
+                    result.addProblem(problem);
+
+            	}
+            }
+        }
+        
+        
 		// add the result to the context
 		context.addResult(result);
     }
Index: src/com/metamatrix/metamodels/relational/i18n.properties
===================================================================
--- src/com/metamatrix/metamodels/relational/i18n.properties	(revision 1765)
+++ src/com/metamatrix/metamodels/relational/i18n.properties	(working copy)
@@ -343,6 +343,8 @@
 ProcedureParametersRule.Parameter_{0}_does_not_have_a_direction._1=Parameter {0} does not have a direction.
 ProcedureParametersRule.Parameter_{0}_has_an_UNKNOWN_direction._1=Parameter {0} has an UNKNOWN direction.
 ProcedureParametersRule.Procedure_{0}_has_more_than_one_parameter_with_RETURN_direction._1=Procedure {0} has more than one parameter with RETURN direction.
+ProcedureParametersRule.Procedure_{0}_is_defined_as_function_and_can_only_have_in_parameters_and_one_return_parameter=Invalid parameter directions. {0} is defined as a function and can only \
+	have IN parameters and one RETURN parameter
 TableChildrenUpdatabilityRule.The_table_{0},_is_updatable_but_does_not_have_any_updatable_columns._1=The table {0}, is updatable but does not have any updatable columns.
 ColumnDatatypeRule.Column_{0}__s_type_attribute_is_not_an_instance_of_XSDSimpleTypeDefinition_1=Column {0}''s type attribute is not an instance of XSDSimpleTypeDefinition
 UniqueKeyColumnsRule.Unique_key_{0}_may_not_reference_column_{1}_from_a_different_table_1=Unique key ''{0}'' may not reference column ''{1}'' from a different table
@@ -355,3 +357,8 @@
 
 ColumnNativeTypeRule.emptyValueMsg=Native type has an empty value. Enter a non-empty value or reset to the default value by using the Properties View context menu.
 ColumnNativeTypeRule.invalidCharactersMsg=Native type contains invalid characters. Enter a value containing only alphabetic or numeric characters.
+
+PushdownFunctionData.invalidInputParameterName = Invalid Input Parameter name
+PushdownFunctionData.invalidParameterLength = Invalid length = {0}.   0 > length < 65000
+PushdownFunctionData.duplicateInputParameterName = Error: Duplicate input parameter name [{0}]
+PushdownFunctionData.invalidReturnParameterName = Invalid Return Parameter name
Index: src/com/metamatrix/metamodels/relational/provider/ProcedureItemProvider.java
===================================================================
--- src/com/metamatrix/metamodels/relational/provider/ProcedureItemProvider.java	(revision 1765)
+++ src/com/metamatrix/metamodels/relational/provider/ProcedureItemProvider.java	(working copy)
@@ -124,6 +124,9 @@
      */
     @Override
     public Object getImage( Object object ) {
+    	if( ((Procedure)object).isFunction() ) {
+    		return getResourceLocator().getImage("full/obj16/PushdownFunction");  //$NON-NLS-1$
+    	}
         return getResourceLocator().getImage("full/obj16/Procedure"); //$NON-NLS-1$
     }
 
#P org.teiid.designer.transformation.ui
Index: src/com/metamatrix/modeler/transformation/ui/util/FunctionModelNotificationHandler.java
===================================================================
--- src/com/metamatrix/modeler/transformation/ui/util/FunctionModelNotificationHandler.java	(revision 1779)
+++ src/com/metamatrix/modeler/transformation/ui/util/FunctionModelNotificationHandler.java	(working copy)
@@ -23,13 +23,20 @@
 import org.eclipse.emf.ecore.EStructuralFeature;
 import org.eclipse.emf.ecore.resource.Resource;
 
+import com.metamatrix.metamodels.core.ModelType;
+import com.metamatrix.metamodels.function.FunctionParameter;
+import com.metamatrix.metamodels.function.ReturnParameter;
 import com.metamatrix.metamodels.function.ScalarFunction;
+import com.metamatrix.metamodels.relational.Procedure;
+import com.metamatrix.metamodels.relational.ProcedureParameter;
+import com.metamatrix.metamodels.relational.RelationalPackage;
 import com.metamatrix.metamodels.transformation.SqlAlias;
 import com.metamatrix.metamodels.transformation.SqlTransformation;
 import com.metamatrix.metamodels.transformation.SqlTransformationMappingRoot;
 import com.metamatrix.modeler.core.ModelerCore;
 import com.metamatrix.modeler.core.notification.util.NotificationUtilities;
 import com.metamatrix.modeler.core.query.QueryValidator;
+import com.metamatrix.modeler.core.util.ModelObjectCollector;
 import com.metamatrix.modeler.core.workspace.ModelResource;
 import com.metamatrix.modeler.core.workspace.ModelWorkspaceException;
 import com.metamatrix.modeler.internal.core.builder.ModelBuildUtil;
@@ -57,6 +64,19 @@
  */
 public class FunctionModelNotificationHandler implements IModelNotificationHandler, UiConstants {
     
+	private boolean isFunctionModelObject( Object obj) {
+    	if( obj instanceof ScalarFunction || 
+    		   obj instanceof FunctionParameter || 
+    		   obj instanceof ReturnParameter ) {
+    		return true;
+    	} else if( obj instanceof Procedure ) {
+    		return ((Procedure)obj).isFunction();
+    	} else if(obj instanceof ProcedureParameter) {
+    		return ((ProcedureParameter)obj).getProcedure().isFunction();
+    	}
+    	return false;
+    }
+	
     /* 
      * Get all Function Model object change Notifications.
      * @param notifications the collection of all notifications
@@ -74,7 +94,7 @@
                 // Get the object that was changed
                 Object changedObj = ModelerCore.getModelEditor().getChangedObject(notification);
                 // changed object -
-                if (TransformationHelper.isFunctionModelObject(changedObj) ) {
+                if (isFunctionModelObject(changedObj) ) {
                 	if (result == null) {
                         result = new ArrayList(notifications.size());
                     }
@@ -118,7 +138,7 @@
             			// Get the dependent resources
 	            	} else if( changedObj instanceof EmfResource ) {
 	            		ModelResource mr = ModelUtilities.getModelResource((Resource)changedObj, false);
-	                	if( ModelIdentifier.isFunctionModel(mr) ) {
+	                	if( ModelIdentifier.isFunctionModel(mr) || isSourceModelWithPushdownFunction(mr) ) {
 	                		changedModelResource = mr;
 	                	}
 	            	}
@@ -157,7 +177,7 @@
             	ModelResource changedModelResource = null;
             	
             	try {
-	            	if( changedObj instanceof ScalarFunction ) {
+	            	if( changedObj instanceof EObject && isFunction((EObject)changedObj)) {
 	            		EObject eObject = (EObject)changedObj;
 	            		final EStructuralFeature nameFeature = ModelerCore.getModelEditor().getNameFeature(eObject);
 	            		// check that the change was to the "name" property
@@ -394,7 +414,7 @@
 
 	@Override
 	public boolean shouldHandleChangedObject(Object object) {
-		return TransformationHelper.isFunctionModelObject(object);
+		return isFunctionModelObject(object);
 	}
 
 	private void updateSqlInTransaction(EObject mappingRoot, int sqlType, String sql, boolean significant, Object txnSource) {
@@ -527,4 +547,38 @@
         }
 		
 	}
+	
+	private boolean isSourceModelWithPushdownFunction(ModelResource modelResource) {
+		try {
+			String uri = modelResource.getPrimaryMetamodelUri();
+			if( ! RelationalPackage.eNS_URI.equalsIgnoreCase(uri) &&
+				! (modelResource.getModelType() == ModelType.PHYSICAL_LITERAL) ) {
+				return false;
+			}
+	        	
+	    	final ModelObjectCollector moc = new ModelObjectCollector(modelResource.getEmfResource());
+	        for( Object eObj : moc.getEObjects()){
+	        	if( eObj instanceof Procedure ) {
+	        		if( ((Procedure)eObj).isFunction()) {
+	        			return true;
+	        		}
+	        	}
+	        }
+		} catch (ModelWorkspaceException ex) {
+			Util.log(IStatus.ERROR, ex, ex.getMessage());
+		}
+    	
+    	return false;
+	}
+	
+	private boolean isFunction(EObject eObject) {
+		if( eObject instanceof ScalarFunction ) {
+			return true;
+		} else if( eObject instanceof Procedure &&
+				   ((Procedure)eObject).isFunction()) {
+			return true;
+    	}
+		
+		return false;
+	}
 }
Index: src/com/metamatrix/modeler/transformation/ui/util/TransformationNotificationListener.java
===================================================================
--- src/com/metamatrix/modeler/transformation/ui/util/TransformationNotificationListener.java	(revision 1779)
+++ src/com/metamatrix/modeler/transformation/ui/util/TransformationNotificationListener.java	(working copy)
@@ -208,6 +208,8 @@
         // Do a first-pass - ignore irrelevant notifications
         // --------------------------------------------------------
         Collection validNotifications = filterNotifications(notifications);
+        
+        Collection originalNotifications = new ArrayList(validNotifications);
         // ----------------------------------------
         // Process remaining valid notifications
         // ----------------------------------------
@@ -329,7 +331,7 @@
             // ---------------------------------------------------------
             // Function Model Scalar Function or parameter changes
             // ---------------------------------------------------------
-            functionHandler.handleNotifications(validNotifications, source);
+            functionHandler.handleNotifications(originalNotifications, source);
         }
     }
 
#P org.teiid.designer.xml.ui
Index: src/com/metamatrix/modeler/internal/xml/ui/actions/BuildFromSchemaAction.java
===================================================================
--- src/com/metamatrix/modeler/internal/xml/ui/actions/BuildFromSchemaAction.java	(revision 1765)
+++ src/com/metamatrix/modeler/internal/xml/ui/actions/BuildFromSchemaAction.java	(working copy)
@@ -7,11 +7,13 @@
  */
 package com.metamatrix.modeler.internal.xml.ui.actions;
 
+import org.eclipse.core.resources.IFile;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.wizard.WizardDialog;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.ui.IWorkbenchWindow;
+
 import com.metamatrix.metamodels.xml.XmlDocumentNode;
 import com.metamatrix.modeler.internal.xml.ui.wizards.NumberOfLevelsWizard;
 import com.metamatrix.modeler.ui.actions.INewChildAction;
@@ -48,6 +50,13 @@
     	}
     	return canCreate;
     }
+    
+    /* (non-Javadoc)
+     * @see com.metamatrix.modeler.ui.actions.INewChildAction#canCreateChild(org.eclipse.core.resources.IFile)
+     */
+    public boolean canCreateChild(IFile parent) {
+    	return false;
+    }
 
 	public XmlDocumentNode getNode() {
 		return this.node;
