[170557] Extension Properties View Fixes
diff --git a/bundles/org.eclipse.wst.xsd.ui/src-adt-xsd/org/eclipse/wst/xsd/ui/internal/text/XSDModelQueryExtension.java b/bundles/org.eclipse.wst.xsd.ui/src-adt-xsd/org/eclipse/wst/xsd/ui/internal/text/XSDModelQueryExtension.java
index 471dce6..dc0690c 100644
--- a/bundles/org.eclipse.wst.xsd.ui/src-adt-xsd/org/eclipse/wst/xsd/ui/internal/text/XSDModelQueryExtension.java
+++ b/bundles/org.eclipse.wst.xsd.ui/src-adt-xsd/org/eclipse/wst/xsd/ui/internal/text/XSDModelQueryExtension.java
@@ -9,32 +9,31 @@
  *     IBM Corporation - Initial API and implementation
  *******************************************************************************/
 package org.eclipse.wst.xsd.ui.internal.text;
-
 import java.util.ArrayList;
 import java.util.List;
 import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension.ModelQueryExtension;
+import org.eclipse.wst.xsd.ui.internal.common.properties.sections.appinfo.custom.NodeFilter;
+import org.eclipse.wst.xsd.ui.internal.editor.XSDEditorPlugin;
 import org.eclipse.wst.xsd.ui.internal.util.TypesHelper;
 import org.eclipse.xsd.XSDSchema;
+import org.eclipse.xsd.util.XSDConstants;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
-
 public class XSDModelQueryExtension extends ModelQueryExtension
-{  
+{
   public XSDModelQueryExtension()
   {
   }
-  
+
   public String[] getAttributeValues(Element e, String namespace, String name)
   {
     List list = new ArrayList();
-
     String currentElementName = e.getLocalName();
     Node parentNode = e.getParentNode();
     String parentName = parentNode != null ? parentNode.getLocalName() : "";
-    
     if (checkName(name, "type"))
-    {      
+    {
       if (checkName(currentElementName, "attribute"))
       {
         list = getTypesHelper(e).getBuiltInTypeNamesList2();
@@ -47,18 +46,16 @@
         list.addAll(getTypesHelper(e).getUserComplexTypeNamesList());
       }
     }
-    else if (checkName(name, "blockDefault") ||
-             checkName(name, "finalDefault"))      
-    {    
-       list.add("#all");
-       list.add("substitution");
-       list.add("extension");
-       list.add("restriction");
-    }  
+    else if (checkName(name, "blockDefault") || checkName(name, "finalDefault"))
+    {
+      list.add("#all");
+      list.add("substitution");
+      list.add("extension");
+      list.add("restriction");
+    }
     else if (checkName(name, "namespace"))
     {
-      if (checkName(currentElementName, "any") || 
-          checkName(currentElementName, "anyAttribute"))
+      if (checkName(currentElementName, "any") || checkName(currentElementName, "anyAttribute"))
       {
         list.add("##any");
         list.add("##other");
@@ -75,7 +72,7 @@
     {
       list.add("0");
       list.add("1");
-    }    
+    }
     else if (checkName(name, "itemType"))
     {
       if (checkName(currentElementName, "list"))
@@ -158,32 +155,60 @@
         list = getTypesHelper(e).getGlobalElements();
       }
     }
-        
     String[] result = new String[list.size()];
     list.toArray(result);
     return result;
-  } 
+  }
+
+  public boolean isApplicableChildElement(Node parentNode, String namespace, String name)
+  {
+    if (XSDConstants.APPINFO_ELEMENT_TAG.equals(parentNode.getNodeName()) &&
+        XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001.equals(namespace))
+    {
+        return false;
+    }
+   
+    // we assume that other nodes don't want schema nodes as extension elements
+    // TODO... cs: we really need to define custimizations for filtering based on parent/child
+    // namespace pairs to accurately handle this    
+    String parentElementNamespaceURI = parentNode.getNamespaceURI();
+    if (!XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001.equals(parentElementNamespaceURI) &&
+        XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001.equals(namespace))
+    {
+       return false;   
+    }
+    
+    if (!XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001.equals(namespace))
+    {  
+      NodeFilter filter = XSDEditorPlugin.getPlugin().getNodeCustomizationRegistry().getNodeFilter(namespace);
+      if (filter != null)
+      {
+        return filter.isApplicableContext(parentNode, Node.ELEMENT_NODE, namespace, name);
+      }     
+    }
+     
+    return true;
+  }
 
   protected XSDSchema lookupOrCreateSchema(Document document)
-  {    
-    return XSDModelAdapter.lookupOrCreateSchema(document);   
+  {
+    return XSDModelAdapter.lookupOrCreateSchema(document);
   }
-  
+
   /**
    * @deprecated
    */
   protected XSDSchema lookupOrCreateSchemaForElement(Element element)
-  {            
+  {
     return lookupOrCreateSchema(element.getOwnerDocument());
-  }   
-   
+  }
+
   protected TypesHelper getTypesHelper(Element element)
   {
     XSDSchema schema = lookupOrCreateSchema(element.getOwnerDocument());
-    return new TypesHelper(schema);  
+    return new TypesHelper(schema);
   }
 
-  
   protected boolean checkName(String localName, String token)
   {
     if (localName != null && localName.trim().equals(token))
diff --git a/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/ExtensionsSection.java b/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/ExtensionsSection.java
index c894644..21ea1e7 100644
--- a/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/ExtensionsSection.java
+++ b/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/ExtensionsSection.java
@@ -13,13 +13,13 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-
 import org.eclipse.gef.commands.Command;
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.IStructuredContentProvider;
 import org.eclipse.jface.viewers.StructuredSelection;
 import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
 import org.eclipse.ui.IWorkbenchPart;
 import org.eclipse.wst.xsd.ui.internal.common.commands.AddExtensionAttributeCommand;
 import org.eclipse.wst.xsd.ui.internal.common.commands.AddExtensionCommand;
@@ -30,9 +30,11 @@
 import org.eclipse.wst.xsd.ui.internal.common.properties.sections.appinfo.AddExtensionsComponentDialog;
 import org.eclipse.wst.xsd.ui.internal.common.properties.sections.appinfo.CategoryProvider;
 import org.eclipse.wst.xsd.ui.internal.common.properties.sections.appinfo.DOMExtensionTreeLabelProvider;
+import org.eclipse.wst.xsd.ui.internal.common.properties.sections.appinfo.ExtensionItemFilter;
 import org.eclipse.wst.xsd.ui.internal.common.properties.sections.appinfo.ExtensionsSchemasRegistry;
 import org.eclipse.wst.xsd.ui.internal.common.properties.sections.appinfo.SpecificationForExtensionsSchema;
 import org.eclipse.wst.xsd.ui.internal.common.properties.sections.appinfo.XSDExtensionTreeContentProvider;
+import org.eclipse.wst.xsd.ui.internal.common.properties.sections.appinfo.custom.NodeFilter;
 import org.eclipse.wst.xsd.ui.internal.common.util.Messages;
 import org.eclipse.wst.xsd.ui.internal.editor.XSDEditorPlugin;
 import org.eclipse.wst.xsd.ui.internal.text.XSDModelAdapter;
@@ -56,15 +58,17 @@
   
   protected AddExtensionsComponentDialog createAddExtensionsComponentDialog()
   {
-    return new AddExtensionsComponentDialog(composite.getShell(), getExtensionsSchemasRegistry())
+    AddExtensionsComponentDialog dialog =  new AddExtensionsComponentDialog(composite.getShell(), getExtensionsSchemasRegistry())
     {
       protected IStructuredContentProvider getCategoryContentProvider()
       {
         return new XSDCategoryContentProvider();
       }
     };
+    dialog.addElementsTableFilter(new AddExtensionsComponentDialogFilter(input, dialog));    
+    return dialog;   
   }
-  
+   
   public void setInput(IWorkbenchPart part, ISelection selection)
   {
     super.setInput(part, selection); 
@@ -236,7 +240,44 @@
     {
       // Do nothing
 
-    }
+    }           
   }
+  
+  /**
+   * This filter is to be used by the dialog invoked when addButton is pressed
+   */
+  private class AddExtensionsComponentDialogFilter extends ViewerFilter
+  {
+    private Object input;
+    private AddExtensionsComponentDialog dialog;
+
+    public AddExtensionsComponentDialogFilter(Object input, AddExtensionsComponentDialog dialog)
+    {
+      this.input = input;
+      this.dialog = dialog;
+    }
+
+    public boolean select(Viewer viewer, Object parentElement, Object element)
+    {      
+      if (input instanceof XSDConcreteComponent &&
+          element instanceof XSDConcreteComponent)
+      {              
+        SpecificationForExtensionsSchema spec = dialog.getSelectedCategory();
+        // here we obtain the node filter that was registered for the applicable namespace
+        // notied
+        NodeFilter filter = XSDEditorPlugin.getPlugin().getNodeCustomizationRegistry().getNodeFilter(spec.getNamespaceURI());
+        if (filter instanceof ExtensionItemFilter)
+        {
+          ExtensionItemFilter extensionItemFilter = (ExtensionItemFilter)filter;
+          return extensionItemFilter.isApplicableContext((XSDConcreteComponent)input, (XSDConcreteComponent)element);               
+        }
+        else
+        {
+          // TODO cs: even if it's just a plain old NodeFilter we should still be able to use it! 
+        }
+      }
+      return true;
+    }
+  }  
 
 }
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/appinfo/AddExtensionsComponentDialog.java b/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/appinfo/AddExtensionsComponentDialog.java
index 8d4aef3..0978f7f 100644
--- a/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/appinfo/AddExtensionsComponentDialog.java
+++ b/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/appinfo/AddExtensionsComponentDialog.java
@@ -14,7 +14,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.StringTokenizer;
-
 import org.apache.xerces.dom.DocumentImpl;
 import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.preference.IPreferenceStore;
diff --git a/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/appinfo/ExtensionItemFilter.java b/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/appinfo/ExtensionItemFilter.java
new file mode 100644
index 0000000..c64970c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/appinfo/ExtensionItemFilter.java
@@ -0,0 +1,18 @@
+package org.eclipse.wst.xsd.ui.internal.common.properties.sections.appinfo;
+
+import org.eclipse.xsd.XSDConcreteComponent;
+
+// cs: This interface is intended to suppliment the NodeFilter class
+// that can be specified via the customization extensions point.
+// When the initial list of a category's objects is displayed 
+// we'll use a NodeFilter to prune the list.  If the NodeFilter
+// implements this interface we'll call this interface's isApplicableContext
+// method instead of the NodeFilter's DOM node based method.  This provides 
+// are a more convenient interface for clients who are only interested in 
+// filter the list presented via the AddExtensionComponentDialog.
+// See the class ExtensionsSection for more details.
+//
+public interface ExtensionItemFilter
+{
+  public boolean isApplicableContext(XSDConcreteComponent parent, XSDConcreteComponent candidate);
+}
diff --git a/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/appinfo/custom/NodeCustomizationRegistry.java b/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/appinfo/custom/NodeCustomizationRegistry.java
index 1189a4a..ca321b1 100644
--- a/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/appinfo/custom/NodeCustomizationRegistry.java
+++ b/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/appinfo/custom/NodeCustomizationRegistry.java
@@ -20,6 +20,7 @@
   private static final String NAMESPACE = "namespace"; //$NON-NLS-1$  
   private static final String LABEL_PROVIDER_CLASS_ATTRIBUTE_NAME = "labelProviderClass";     
   private static final String NODE_EDITOR_PROVIDER_CLASS_ATTRIBUTE_NAME = "nodeEditorProviderClass"; //$NON-NLS-1$
+  private static final String FILTER_CLASS_ATTRIBUTE_NAME = "filterClass"; 
 
 
   protected String extensionId;
@@ -33,10 +34,11 @@
   private class Descriptor
   {
     IConfigurationElement configurationElement;
-    
     NodeEditorProvider nodeEditorProvider;
+    NodeFilter nodeFilter;    
     boolean nodeEditorProviderFailedToLoad = false;
     boolean labelProviderFailedToLoad = false;
+    boolean nodeFilterFailedToLoad = false;    
     
     Descriptor(IConfigurationElement element)
     {
@@ -74,6 +76,22 @@
       }
       return null;
     }
+
+    public NodeFilter getNodeFilter()
+    {
+      if (!nodeEditorProviderFailedToLoad)
+      {  
+        try
+        {
+          nodeFilter = (NodeFilter)configurationElement.createExecutableExtension(FILTER_CLASS_ATTRIBUTE_NAME);
+        }
+        catch (Exception e) 
+        {
+          nodeEditorProviderFailedToLoad = true;
+        }
+      }
+      return nodeFilter;
+    }
   }
 
   
@@ -126,4 +144,14 @@
     }
     return null;    
   }
+  
+  public NodeFilter getNodeFilter(String namespace)
+  {
+    Descriptor descriptor = getDescriptor(namespace);
+    if (descriptor != null)
+    {  
+      return descriptor.getNodeFilter();       
+    }
+    return null;    
+  }
 }
diff --git a/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/appinfo/custom/NodeFilter.java b/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/appinfo/custom/NodeFilter.java
new file mode 100644
index 0000000..377ad25
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.ui/src-common/org/eclipse/wst/xsd/ui/internal/common/properties/sections/appinfo/custom/NodeFilter.java
@@ -0,0 +1,11 @@
+package org.eclipse.wst.xsd.ui.internal.common.properties.sections.appinfo.custom;
+
+import org.w3c.dom.Node;
+
+public class NodeFilter
+{  
+  public boolean isApplicableContext(Node parentNode, int nodeType, String namespace, String name)
+  {  
+    return true;
+  }
+}