[292939] Improve the performance of metadata query
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/IMetaDataModelMergeAssistant.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/IMetaDataModelMergeAssistant.java
index d579a63..0a6a341 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/IMetaDataModelMergeAssistant.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/IMetaDataModelMergeAssistant.java
@@ -30,10 +30,10 @@
 	 * Method that will first check to see if an entity with the same id exists in the merged model. 
 	 * If not, it will add it.   The entities includeGroups are then also merged.
 	 * @param entity
-	 * @return flag indicating whether or not the entity was new and therefore added to the merged model
+	 * @return the merged model entity
 	 *  
 	 */
-	public boolean addEntity(Entity entity);
+	public Entity addEntity(Entity entity);
 	/**
 	 * Method will add an entity if not already existing in the merged model, and then check for an existing trait by id on the merged model's entity.
 	 * @param entity
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/MetaDataModelMergeAssistantImpl.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/MetaDataModelMergeAssistantImpl.java
index 49f9aa4..0c53521 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/MetaDataModelMergeAssistantImpl.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/MetaDataModelMergeAssistantImpl.java
@@ -51,7 +51,7 @@
 	 * Constructor.   Queries with search control limited to first found.
 	 * @param model
 	 */
-	public MetaDataModelMergeAssistantImpl(MetaDataModel model) {
+	public MetaDataModelMergeAssistantImpl(final MetaDataModel model) {
 		this.mergedModel = model;
 		entityVisitor = new SimpleEntityQueryVisitorImpl(new HierarchicalSearchControl(1, 
 			HierarchicalSearchControl.SCOPE_ALL_LEVELS));
@@ -72,7 +72,7 @@
 		return provider;
 	}
 
-	public void setSourceModelProvider(IMetaDataSourceModelProvider provider) {
+	public void setSourceModelProvider(final IMetaDataSourceModelProvider provider) {
 		this.provider = provider;
 	}
 
@@ -80,8 +80,8 @@
 	/* (non-Javadoc)
 	 * @see org.eclipse.jst.jsf.common.metadata.internal.IMetaDataModelMergeAssistant#addEntityGroup(org.eclipse.jst.jsf.common.metadata.EntityGroup)
 	 */
-	public void addEntityGroup(EntityGroup entityGroup) {
-		Model model = (Model)getMergedModel().getRoot();
+	public void addEntityGroup(final EntityGroup entityGroup) {
+		final Model model = (Model)getMergedModel().getRoot();
 		if (!isExistingEntityGroup(model, entityGroup)){
 			model.getEntityGroups().add(entityGroup);
 		}
@@ -90,17 +90,17 @@
 	/* (non-Javadoc)
 	 * @see org.eclipse.jst.jsf.common.metadata.internal.IMetaDataModelMergeAssistant#addEntity(org.eclipse.jst.jsf.common.metadata.Entity)
 	 */
-	public boolean addEntity(final Entity entity) {
+	public Entity addEntity(final Entity entity) {
 		Entity mmEntity = getMergedEntity(entity);
 		if (mmEntity == null){
-			addEntityAsNecessary((Entity)entity.eContainer(), entity);
-			return true;
+			mmEntity = addEntityAsNecessary((Entity)entity.eContainer(), entity);
+			return mmEntity;
 		}
 		addIncludeGroupsAsNecessary(mmEntity, entity);
-		return false;
+		return mmEntity;
 	}
 
-	public Entity getMergedEntity(Entity queryRoot, String entityKey){		
+	public Entity getMergedEntity(final Entity queryRoot, final String entityKey){		
 		Entity ret = null;
 		SimpleResultSet rs = (SimpleResultSet)entityVisitor.findEntities(queryRoot, entityKey);
 		try {
@@ -113,11 +113,11 @@
 		return ret;
 	}
 	private void addIncludeGroupsAsNecessary(final Entity mmEntity, final Entity entity) {
-		for (Iterator it=entity.getIncludeGroups().iterator();it.hasNext();){
-			IncludeEntityGroup grp = (IncludeEntityGroup)it.next();
+		for (final Iterator it=entity.getIncludeGroups().iterator();it.hasNext();){
+			final IncludeEntityGroup grp = (IncludeEntityGroup)it.next();
 			boolean found = false;
 			for (Iterator it2=mmEntity.getIncludeGroups().iterator();it2.hasNext();){
-				IncludeEntityGroup grp2 = (IncludeEntityGroup)it2.next();
+				final IncludeEntityGroup grp2 = (IncludeEntityGroup)it2.next();
 				if (grp2.equals(grp)){
 					found = true;
 					break;
@@ -154,9 +154,9 @@
 		return mmEntity;
 	}
 	
-	private boolean isExistingEntityGroup(Model model, EntityGroup entityGroup) {
+	private boolean isExistingEntityGroup(final Model model, final EntityGroup entityGroup) {
 		boolean found = false;
-		for(Iterator it=model.getEntityGroups().iterator();it.hasNext();){
+		for(final Iterator it=model.getEntityGroups().iterator();it.hasNext();){
 			if (entityGroup.getId().equals(((EntityGroup)it.next()).getId()))
 				return true;			
 		}
@@ -164,8 +164,8 @@
 	}
 
 	private Entity getExistingChildEntity(final Entity parent, final Entity entity) {
-		for(Iterator it=parent.getChildEntities().iterator();it.hasNext();){
-			Entity foundEntity = (Entity)it.next();
+		for(final Iterator it=parent.getChildEntities().iterator();it.hasNext();){
+			final Entity foundEntity = (Entity)it.next();
 			if (entity.getId().equals(foundEntity.getId()))
 				return foundEntity;			
 		}
@@ -173,8 +173,8 @@
 	}
 
 	private /*synchronized*/ Entity addEntityInternal(final Entity parent, final Entity entity) {
-		Copier copier = new Copier();
-		Entity mmEntity =(Entity)copier.copy(entity);
+		final Copier copier = new Copier();
+		final Entity mmEntity =(Entity)copier.copy(entity);
 		copier.copyReferences();
 		parent.getChildEntities().add(mmEntity);
 		return mmEntity;
@@ -183,8 +183,8 @@
 	/* (non-Javadoc)
 	 * @see org.eclipse.jst.jsf.common.metadata.internal.IMetaDataModelMergeAssistant#addTrait(org.eclipse.jst.jsf.common.metadata.Entity, org.eclipse.jst.jsf.common.metadata.Trait)
 	 */
-	public boolean addTrait(Entity entity, Trait trait) {
-		Entity returnedEntity = getMergedEntity(entity);
+	public boolean addTrait(final Entity entity, final Trait trait) {
+		final Entity returnedEntity = getMergedEntity(entity);
 		if (returnedEntity != null){
 			return addTraitAsNecessary(returnedEntity, trait);
 		}
@@ -193,7 +193,7 @@
 	
 
 	private boolean addTraitAsNecessary(Entity mergedEntity, Trait trait) {
-		Trait mmTrait = getMergedTrait(mergedEntity, trait);
+		final Trait mmTrait = getMergedTrait(mergedEntity, trait);
 		if (mmTrait == null){			
 			addTraitInternal(mergedEntity, trait);
 			return true;
@@ -206,7 +206,7 @@
 	 * @see org.eclipse.jst.jsf.common.metadata.internal.IMetaDataModelMergeAssistant#setMergeComplete()
 	 */
 	public void setMergeComplete() {
-		Model model = (Model)getMergedModel().getRoot();
+		final Model model = (Model)getMergedModel().getRoot();
 		if (model != null){
 			StandardModelFactory.debug(">> Begin processIncludeGroups for: "+getMergedModel().getModelKey(),StandardModelFactory.DEBUG_MD_LOAD); //$NON-NLS-1$
 			
@@ -226,8 +226,8 @@
 	 * @return merged Trait
 	 */
 	private Trait addTraitInternal(final Entity parent, final Trait trait) {
-		Copier copier = new Copier();
-		Trait mmTrait =(Trait)copier.copy(trait);
+		final Copier copier = new Copier();
+		final Trait mmTrait =(Trait)copier.copy(trait);
 		copier.copyReferences();
 		parent.getTraits().add(mmTrait);
 		//set the model key to know from where the trait came
@@ -242,13 +242,13 @@
 	 * @param entity
 	 * @return merged entity
 	 */
-	private Entity getMergedEntity(Entity entity){
+	private Entity getMergedEntity(final Entity entity){
 		if (entity instanceof Model)
 			return (Entity)mergedModel.getRoot();
 		
 		Entity ret = null;
-		String entityKey = getIdRelativeToRoot(entity);
-		SimpleResultSet rs = (SimpleResultSet)entityVisitor.findEntities((Entity)mergedModel.getRoot(), entityKey);
+		final String entityKey = getIdRelativeToRoot(entity);
+		final SimpleResultSet rs = (SimpleResultSet)entityVisitor.findEntities((Entity)mergedModel.getRoot(), entityKey);
 		try {
 			if (! rs.getResults().isEmpty()) 
 				ret = (Entity)rs.getResults().get(0);				
@@ -261,7 +261,7 @@
 	
 	private String getIdRelativeToRoot(final Entity entity) {
 		Entity e = entity;
-		StringBuffer buf = new StringBuffer();
+		final StringBuffer buf = new StringBuffer();
 		while (e.eContainer() != null){
 			buf.insert(0, e.getId());
 			if (e.eContainer()!=null && e.eContainer().eContainer() != null)
@@ -279,8 +279,8 @@
 	 * @param trait
 	 * @return merged Trait
 	 */
-	public Trait getMergedTrait(Entity entity, Trait trait){
-		SimpleResultSet rs = (SimpleResultSet)traitVisitor.findTraits(entity, trait.getId());
+	public Trait getMergedTrait(final Entity entity, final Trait trait){
+		final SimpleResultSet rs = (SimpleResultSet)traitVisitor.findTraits(entity, trait.getId());
 		Trait ret = null;
 		try {
 			if (! rs.getResults().isEmpty()) 
@@ -305,14 +305,14 @@
 
 	private void doIncludes(final Entity entity){
 		for (int j=0, groupsSize=entity.getIncludeGroups().size();j<groupsSize; j++){				
-			IncludeEntityGroup include = (IncludeEntityGroup)entity.getIncludeGroups().get(j);				
+			final IncludeEntityGroup include = (IncludeEntityGroup)entity.getIncludeGroups().get(j);				
 			if (include.getId() != null){
 				//is this a local merge?
 				if (include.getModelUri() == null||
 						(include.getModelUri()
 							.equals(getMergedModel()
 								.getModelKey().getUri())) ){
-					EntityGroup eg = ((Model)getMergedModel().getRoot()).findIncludeGroup(include.getId());
+					final EntityGroup eg = ((Model)getMergedModel().getRoot()).findIncludeGroup(include.getId());
 					addIncludeRefs(entity, eg);
 				} else //external model include
 					addIncludeRefs(entity, include);
@@ -325,15 +325,15 @@
 	 * @param include
 	 */
 	private void addIncludeRefs(final Entity entity, final IncludeEntityGroup include) {
-		ITaglibDomainMetaDataModelContext modelContext = new TaglibDomainMetaDataModelContextImpl(				
+		final ITaglibDomainMetaDataModelContext modelContext = new TaglibDomainMetaDataModelContextImpl(				
 				getMergedModel().getModelKey().getDomain(), 
 				getMergedModel().getModelKey().getProject(), 
 				include.getModelUri()
 		);
 		
-		Model externalModel = TaglibDomainMetaDataQueryHelper.getModel(modelContext);
+		final Model externalModel = TaglibDomainMetaDataQueryHelper.getModel(modelContext);
 		if (externalModel != null){
-			EntityGroup entityGroup = externalModel.findIncludeGroup(include.getId());		
+			final EntityGroup entityGroup = externalModel.findIncludeGroup(include.getId());		
 			addIncludeRefs(entity, entityGroup);
 		}
 		else {
@@ -362,15 +362,15 @@
 	}
 	
 	private void traverseAndAddIncludes(final Entity parent, final Entity entity){
-		Entity mergedEntity = addIncludedEntityAsNecessary(parent, entity);
+		final Entity mergedEntity = addIncludedEntityAsNecessary(parent, entity);
 		
 		for (final Iterator/*<Trait>*/ it=entity.getTraits().iterator();it.hasNext();){
-			Trait trait = (Trait)it.next();
+			final Trait trait = (Trait)it.next();
 			addTraitAsNecessary(mergedEntity, trait);
 		}
 		
 		for (final Iterator/*<EntityKey>*/ it=entity.getChildEntities().iterator();it.hasNext();){
-			Entity e = (Entity)it.next();
+			final Entity e = (Entity)it.next();
 			traverseAndAddIncludes(mergedEntity, e);//add as normal
 		}
 		
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/StandardMetaDataFilesTranslator.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/StandardMetaDataFilesTranslator.java
index f9869ff..6695ec5 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/StandardMetaDataFilesTranslator.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/StandardMetaDataFilesTranslator.java
@@ -29,25 +29,25 @@
  */
 public class StandardMetaDataFilesTranslator implements IMetaDataTranslator {
 
-	public boolean canTranslate(IMetaDataSourceModelProvider modelProvider) {
+	public boolean canTranslate(final IMetaDataSourceModelProvider modelProvider) {
 		if (modelProvider instanceof StandardMetaDataFilesProvider)
 			return true;
 		return false;
 	}
 	
-	public void translate(IMetaDataModelMergeAssistant assistant) {//TODO: throw proper errors
+	public void translate(final IMetaDataModelMergeAssistant assistant) {//TODO: throw proper errors
 		//null translate - sourceModel object are already Entities and traits
 		//traverse the tree and add to model
 		
 		//temp - throw proper errors 
 		//assert assistant.getSourceModel() instanceof ModelKeyDescriptor;
 		
-		MetaDataModel mm = assistant.getMergedModel();
-		Model mk = (Model)assistant.getSourceModelProvider().getSourceModel();
+		final MetaDataModel mm = assistant.getMergedModel();
+		final Model mk = (Model)assistant.getSourceModelProvider().getSourceModel();
 		if (mm.getRoot() == null) {
 			//create copy, otherwise source model becomes merged model because of reference
-			Copier copier = new Copier();		
-			Model newModel = (Model)copier.copy(mk.getModel());
+			final Copier copier = new Copier();		
+			final Model newModel = (Model)copier.copy(mk.getModel());
 			copier.copyReferences();
 			mm.setRoot(newModel);
 		}
@@ -66,23 +66,23 @@
 	 * @param assistant
 	 * @param entity
 	 */
-	protected void traverseAndAdd(IMetaDataModelMergeAssistant assistant, final Entity entity){
-		assistant.addEntity(entity);
+	protected void traverseAndAdd(final IMetaDataModelMergeAssistant assistant, final Entity entity){
+		final Entity mmEntity = assistant.addEntity(entity);
 		
 		if (entity instanceof Model){
-			Model model = (Model)entity;
+			final Model model = (Model)entity;
 			for (final Iterator/*EntityGroup*/ it=model.getEntityGroups().iterator();it.hasNext();){
 				assistant.addEntityGroup((EntityGroup)it.next());
 			}
 		}
 		
 		for (final Iterator/*<Trait>*/ it=entity.getTraits().iterator();it.hasNext();){
-			Trait trait = (Trait)it.next();
-			assistant.addTrait(entity, trait);
+			final Trait trait = (Trait)it.next();
+			assistant.addTrait(mmEntity, trait);
 		}
 		
 		for (final Iterator/*<EntityKey>*/ it=entity.getChildEntities().iterator();it.hasNext();){
-			Entity e = (Entity)it.next();
+			final Entity e = (Entity)it.next();
 			traverseAndAdd(assistant, e);
 		}
 		
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/impl/EntityImpl.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/impl/EntityImpl.java
index da0f6ee..ab8247d 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/impl/EntityImpl.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/impl/EntityImpl.java
@@ -2,7 +2,7 @@
  * <copyright>
  * </copyright>
  *
- * $Id: EntityImpl.java,v 1.7 2008/11/18 22:24:39 gkessler Exp $
+ * $Id: EntityImpl.java,v 1.8 2010/01/27 23:54:32 gkessler Exp $
  */
 package org.eclipse.jst.jsf.common.metadata.internal.impl;
 
@@ -26,6 +26,7 @@
 import org.eclipse.jst.jsf.common.metadata.Model;
 import org.eclipse.jst.jsf.common.metadata.Trait;
 import org.eclipse.jst.jsf.common.metadata.query.IEntityVisitor;
+import org.eclipse.jst.jsf.common.metadata.query.internal.IHierarchicalEntityVisitor;
 
 /**
  * <!-- begin-user-doc -->
@@ -231,36 +232,52 @@
 	 * <!-- end-user-doc -->
 	 * @generated NOT
 	 */
-	public void accept(IEntityVisitor visitor) {
-		if (visitor.stopVisiting())
-			return;
-		visitor.visit(this);
-		
+	private boolean accept(final IHierarchicalEntityVisitor visitor) {		
+		if (visitor.visitEnter( this )) {
+			acceptChildren(visitor);
+		}			
+		return visitor.visitLeave(this);
+	}
+	
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated NOT
+	 */
+	public void accept(final IEntityVisitor visitor) {
+		if (visitor instanceof IHierarchicalEntityVisitor) {			
+			accept((IHierarchicalEntityVisitor)visitor);
+		}
+		else {
+			if (visitor.stopVisiting())
+				return;
+			
+			visitor.visit(this);
+			if (visitor.stopVisiting())
+				return;
+			
+			acceptChildren(visitor);
+			
+			visitor.visitCompleted(this);
+		}
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated NOT
+	 */
+	private void acceptChildren(final IEntityVisitor visitor) {
 		if (!getChildEntities().isEmpty()){
-			for (Iterator/*<Entity>*/ it = getChildEntities().iterator(); it.hasNext();){
-				Entity k = (Entity)it.next();
+			for (final Iterator/*<Entity>*/ it = getChildEntities().iterator(); it.hasNext();){
+				final Entity k = (Entity)it.next();
 				k.accept(visitor);
 				if (visitor.stopVisiting())
 					return;
 			}
 		}
-//		if (!getIncludeGroups().isEmpty()){
-//			for (Iterator/*<IncludeEntityGroup>*/ it = getIncludeGroups().iterator(); it.hasNext();){
-//				IncludeEntityGroup entityGroup = (IncludeEntityGroup)it.next();
-//				Model m = getModel(entityGroup);
-//				if (m != null){
-//					Entity k = m.findIncludeGroup(entityGroup.getId());
-//					if (k != null){
-//						k.accept(visitor);
-//						if (visitor.stopVisiting())
-//							return;
-//					}
-//				}
-//			}
-//		}
-		visitor.visitCompleted(this);
 	}
-
+	
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/impl/ModelImpl.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/impl/ModelImpl.java
index ab3c51c..cfbb83e 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/impl/ModelImpl.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/internal/impl/ModelImpl.java
@@ -2,7 +2,7 @@
  * <copyright>
  * </copyright>
  *
- * $Id: ModelImpl.java,v 1.7 2008/11/18 22:24:39 gkessler Exp $
+ * $Id: ModelImpl.java,v 1.8 2010/01/27 23:54:32 gkessler Exp $
  */
 package org.eclipse.jst.jsf.common.metadata.internal.impl;
 
@@ -12,7 +12,6 @@
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.ecore.EClass;
 import org.eclipse.emf.ecore.util.EObjectResolvingEList;
-import org.eclipse.jst.jsf.common.metadata.Entity;
 import org.eclipse.jst.jsf.common.metadata.EntityGroup;
 import org.eclipse.jst.jsf.common.metadata.MetadataPackage;
 import org.eclipse.jst.jsf.common.metadata.Model;
@@ -221,26 +220,15 @@
 	}
 	/**
 	 * <!-- begin-user-doc -->
+	 * Due to a mistake in the EMF model, Model is not inheriting accept method from Entity.   This should be fixed.
 	 * <!-- end-user-doc -->
 	 * @generated NOT
 	 */
 
 	public void accept(IEntityVisitor visitor) {
-		if (visitor.stopVisiting())
-			return;
-		visitor.visit(this);
-		
-		if (!getChildEntities().isEmpty()){
-			for (Iterator/*<Entity>*/ it = getChildEntities().iterator(); it.hasNext();){
-				Entity k = (Entity)it.next();
-				k.accept(visitor);
-				if (visitor.stopVisiting())
-					return;
-			}
-		}
-
-		visitor.visitCompleted(this);
+		super.accept(visitor);
 	}
+	
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/query/internal/IHierarchicalEntityVisitor.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/query/internal/IHierarchicalEntityVisitor.java
new file mode 100644
index 0000000..b91fd9e
--- /dev/null
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/query/internal/IHierarchicalEntityVisitor.java
@@ -0,0 +1,24 @@
+package org.eclipse.jst.jsf.common.metadata.query.internal;
+
+import org.eclipse.jst.jsf.common.metadata.Entity;
+import org.eclipse.jst.jsf.common.metadata.query.IEntityVisitor;
+
+/**
+ * Provides the necessary hierarchical visitor interface methods to 
+ * provide conditional navigation of the entity hierarchy 
+ *
+ */
+public interface IHierarchicalEntityVisitor extends IEntityVisitor {
+	/**
+	 * @param entity
+	 * @return true if children should be traversed 
+	 */
+	boolean visitEnter(Entity entity); 
+	/**
+	 * @param entity
+	 * @return true when coming out of a branch
+	 */
+	boolean visitLeave(Entity entity);
+	
+
+}
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/query/internal/SimpleEntityQueryVisitorImpl.java b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/query/internal/SimpleEntityQueryVisitorImpl.java
index 19c8e6a..ea68a01 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/query/internal/SimpleEntityQueryVisitorImpl.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.common/src/org/eclipse/jst/jsf/common/metadata/query/internal/SimpleEntityQueryVisitorImpl.java
@@ -13,27 +13,28 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Stack;
+import java.util.StringTokenizer;
 
 import org.eclipse.jst.jsf.common.metadata.Entity;
-import org.eclipse.jst.jsf.common.metadata.EntityGroup;
 import org.eclipse.jst.jsf.common.metadata.query.AbstractEntityQueryVisitor;
 import org.eclipse.jst.jsf.common.metadata.query.IResultSet;
 
 
 /**
- * A simple metadata query visitor implementing {@link org.eclipse.jst.jsf.common.metadata.query.IEntityQueryVisitor} and {@link org.eclipse.jst.jsf.common.metadata.query.ITraitQueryVisitor}.
- * - simple find entity and traits by id only 	
- * - Does not allow for wild card searchs
- * 
+ * A simple metadata query visitor implementing {@link org.eclipse.jst.jsf.common.metadata.query.IEntityQueryVisitor} and {@link org.eclipse.jst.jsf.common.metadata.query.ITraitQueryVisitor}.<p>
+ * - simple find entity and traits by id only <br>	
+ * - does not allow for wild card searchs<br>
+ * <p>
  * 	TODO - fix for case-sensitivity   https://bugs.eclipse.org/bugs/show_bug.cgi?id=212794
+ * 
  */
-public class SimpleEntityQueryVisitorImpl extends AbstractEntityQueryVisitor  {
+public class SimpleEntityQueryVisitorImpl extends AbstractEntityQueryVisitor implements IHierarchicalEntityVisitor {
 	private HierarchicalSearchControl control;
 	private boolean _stop;
 
-	private EntityQueryComparator entityComparator;
+	private EntityQueryFilterVisitor entityQuery;
 	private List/*<Entity>*/ _entityResults;
+	private Entity initialEntityContext;
 
 	/**
 	 * Constructor that also creates a default SearchControl
@@ -47,7 +48,7 @@
 	 * Constructor
 	 * @param control
 	 */
-	public SimpleEntityQueryVisitorImpl(HierarchicalSearchControl control) {
+	public SimpleEntityQueryVisitorImpl(final HierarchicalSearchControl control) {
 		super();
 		this.control = control;
 	}
@@ -55,14 +56,15 @@
 	/* (non-Javadoc)
 	 * @see org.eclipse.jst.jsf.common.metadata.query.IEntityQueryVisitor#findEntities(org.eclipse.jst.jsf.common.metadata.Entity, java.lang.String)
 	 */
-	public IResultSet/*<Entity>*/ findEntities(Entity initialEntityContext,
-			String entityKey) {
+	public IResultSet/*<Entity>*/ findEntities(final Entity initialEntity,
+			final String entityKey) {
 		
 		resetQuery();
 		
-		if (initialEntityContext != null){
-			entityComparator = new EntityQueryComparator(entityKey);			
-			initialEntityContext.accept(this);			
+		if (initialEntity != null){
+			this.initialEntityContext = initialEntity;
+			entityQuery = new EntityQueryFilterVisitor(initialEntity.getId(), entityKey);			
+			initialEntity.accept(this);			
 		}
 		
 		return new SimpleResultSet(getInternalEntityResults());
@@ -80,25 +82,31 @@
 		return _entityResults;
 	}
 
+
+	public boolean visitEnter(final Entity entity) {
+		
+		if (entity == initialEntityContext)
+			return true;
+		
+		entityQuery.pushLevel();
+		if (entityQuery.canVisit(entity)) 
+			return entityQuery.visit(entity);
+		
+		return false;
+	}
+
+	public boolean visitLeave(Entity entity) {
+		checkShouldStopVisitingEntities();
+		if (entity != initialEntityContext)
+			entityQuery.popLevel();
+		return true;
+	}
+	
 	/* (non-Javadoc)
 	 * @see org.eclipse.jst.jsf.common.metadata.query.IEntityVisitor#visit(org.eclipse.jst.jsf.common.metadata.Entity)
 	 */
-	public void visit(Entity key) {		
-		switch (entityComparator.compareTo(key)){
-			case 0:
-				getInternalEntityResults().add(key);
-				break;
-			default:
-				break;
-
-		}
-		checkShouldStopVisitingEntities();
-	}
-	/* (non-Javadoc)
-	 * @see org.eclipse.jst.jsf.common.metadata.query.IEntityVisitor#visitCompleted(Entity entity)
-	 */
-	public void visitCompleted(Entity entity) {
-		entityComparator.popContext();
+	public void visit(final Entity key) {
+		//do nothing... all work now done in visitEnter/visitLeave
 	}
 	
 	/* (non-Javadoc)
@@ -110,72 +118,87 @@
 
 	private void checkShouldStopVisitingEntities(){
 		//implement how to set stop to signal to the entity accept() to skip visiting
-		if (control.getCountLimit()== getInternalEntityResults().size() && control.getCountLimit() != SearchControl.COUNT_LIMIT_NONE )
+		if (_stop == false
+				&& control.getCountLimit()== getInternalEntityResults().size() 
+				&& control.getCountLimit() != SearchControl.COUNT_LIMIT_NONE )
+			
 			_stop = true;
 	}
 
 	/**
-	 * Simple comparator that compares that an entity's id for with another.
-	 * Case-insensitive compare
-	 *
+	 * Visitor that filters and acts upon hierarchical data that compares that an entity's id for with another with case-insensitive compare
 	 */
-	private class EntityQueryComparator implements Comparable/*<Entity>*/{
+	private class EntityQueryFilterVisitor {
 
-		private String entityKey;
-		private EntityStack stack;
-
+		private String entityId;
+		private List<String> entityQueue;
+		private int curLevel = 0;
+		
 		/**
 		 * Constructor
-		 * @param entityKey
+		 * @param initialContextId - Entity id from which the query is rooted
+		 * @param queryKey - query key which may be compound ("A/B/C")
 		 */
-		public EntityQueryComparator(String entityKey){
-			this.entityKey = entityKey.toUpperCase();		
-			stack = new EntityStack();
+		public EntityQueryFilterVisitor(final String initialContextId, final String queryKey){			
+			init(initialContextId, queryKey);			
 		}
 		
-		public int compareTo(Object entity) {			
-			stack.push(entity);
-			return entityKey.compareTo(getRelativeId().toUpperCase());			
-		}
-		
-		/**
-		 * Pop stack
-		 */
-		public void popContext(){
-			stack.pop();
-		}
-		
-		private String getRelativeId(){
-			int size = stack.size();
-			int i = 1;
-			StringBuffer buf = new StringBuffer();
-			while(i < size){
-				Entity e = (Entity)stack.elementAt(i);
-				if (!(e instanceof EntityGroup)){
-					if (buf.length()>0) 
-						buf.append("/"); //$NON-NLS-1$
-					buf.append(e.getId());
-				}
-				i++;
+		private void init(final String initialContextId, final String key) {
+			entityQueue = new ArrayList<String>(3);
+			addLevel(initialContextId);
+			if (key == null || key.trim().equals("") || key.trim().equals("/")){  //$NON-NLS-1$ //$NON-NLS-2$
+				addLevel(""); //$NON-NLS-1$
 			}
-			return buf.toString();
+			else {
+				final StringTokenizer st = new StringTokenizer(key, "/"); //$NON-NLS-1$
+				String partialKey = st.nextToken();
+				addLevel(partialKey);
+				while (st.hasMoreElements()){
+					partialKey = st.nextToken();
+					addLevel(partialKey);
+				}
+			}
 		}
-	}
-	
-	/**
-	 * Stack used for determining relative key of an entity from the initial context.
-	 */
-	private class EntityStack extends Stack/*<Entity>*/ {
-		/**
-         * 
-         */
-        private static final long serialVersionUID = -6010267544968175003L;
 
-        /**
-         * Constructor
-         */
-        public EntityStack(){
-			super();
+		/**
+		 * @param entity
+		 * @return flag indicating that filter was passed and children may be visited
+		 */
+		public boolean canVisit(final Entity entity) {
+			// only one filter rule... does this entity id match the current level's entity id (case-insensitive) 
+			return entityId.compareTo(entity.getId().toUpperCase()) == 0;
+		}
+
+		/**
+		 * Operates on passed entity and determines if it should be part of the query results
+		 * @param entity
+		 * @return true if children of entity should be visited
+		 */
+		public boolean visit(final Entity entity) {
+			//one operation... if we have found the leaf-most entity in the query, add it to the results and go no deeper
+			if (curLevel == entityQueue.size() - 1) {
+				getInternalEntityResults().add(entity);
+				return false;
+			}
+			return true;
+		}
+
+		private void addLevel(final String key) {
+			entityQueue.add(key.toUpperCase());
+		}
+		
+		/**
+		 * Move up one level in the query 
+		 */
+		public void popLevel(){
+			entityId = entityQueue.get(--curLevel);
+		}
+		
+		/**
+		 * Move down one level in the query
+		 */
+		public void pushLevel() {
+			entityId = entityQueue.get(++curLevel);						
 		}
 	}