[rhq] Branch 'release/jon3.1.x' - 4 commits - modules/core modules/enterprise

John Sanda jsanda at fedoraproject.org
Mon Aug 6 14:38:49 UTC 2012


 modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/DuplicateExpressionTypeException.java                                     |   38 
 modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/InvalidExpressionException.java                                           |   38 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java                            |    7 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java |    7 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java   |   21 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java |    8 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java                        |   13 
 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java        |    2 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java                |    2 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java               |    2 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java             |   83 +
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/InvalidExpressionException.java      |   38 
 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java    |  704 ++++++++++
 13 files changed, 910 insertions(+), 53 deletions(-)

New commits:
commit f4212820d19309632cbfd57882e1a77cc5dcd5f4
Author: John Sanda <jsanda at redhat.com>
Date:   Mon Jul 2 11:31:33 2012 -0400

    [BZ 826716] Improve error reporting in the UI

diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/DuplicateExpressionTypeException.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/DuplicateExpressionTypeException.java
new file mode 100644
index 0000000..4d51fc9
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/DuplicateExpressionTypeException.java
@@ -0,0 +1,38 @@
+/*
+ *
+ *  * RHQ Management Platform
+ *  * Copyright (C) 2005-2012 Red Hat, Inc.
+ *  * All rights reserved.
+ *  *
+ *  * This program is free software; you can redistribute it and/or modify
+ *  * it under the terms of the GNU General Public License as published by
+ *  * the Free Software Foundation version 2 of the License.
+ *  *
+ *  * This program is distributed in the hope that it will be useful,
+ *  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  * GNU General Public License for more details.
+ *  *
+ *  * You should have received a copy of the GNU General Public License
+ *  * along with this program; if not, write to the Free Software
+ *  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+package org.rhq.core.domain.resource.group;
+
+/**
+ * @author John Sanda
+ */
+public class DuplicateExpressionTypeException extends InvalidExpressionException {
+
+    private static final long serialVersionUID = 1L;
+
+    private DuplicateExpressionTypeException() {
+    }
+
+    public DuplicateExpressionTypeException(String predicate) {
+        super("You cannot specify multiple " + predicate + " expressions.");
+    }
+
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/InvalidExpressionException.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/InvalidExpressionException.java
new file mode 100644
index 0000000..600ba04
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/InvalidExpressionException.java
@@ -0,0 +1,38 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2008 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.core.domain.resource.group;
+
+public class InvalidExpressionException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    public InvalidExpressionException() {
+    }
+
+    public InvalidExpressionException(String message) {
+        super(message);
+    }
+
+    public InvalidExpressionException(Throwable cause) {
+        super(cause);
+    }
+
+    public InvalidExpressionException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java
index bd196fc..6cd1a43 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java
@@ -27,6 +27,7 @@ import org.rhq.core.domain.resource.group.GroupDefinition;
 import org.rhq.core.domain.resource.group.ResourceGroup;
 import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
 import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
 
 /**
  * @author Greg Hinkle
@@ -64,9 +65,11 @@ public interface ResourceGroupGWTService extends RemoteService {
 
     void setAssignedResources(int groupId, int[] resourceIds, boolean setType) throws RuntimeException;
 
-    void recalculateGroupDefinitions(int[] groupDefinitionIds) throws RuntimeException;
+    void recalculateGroupDefinitions(int[] groupDefinitionIds)
+        throws DuplicateExpressionTypeException, RuntimeException;
 
-    void updateGroupDefinition(GroupDefinition groupDefinition) throws RuntimeException;
+    void updateGroupDefinition(GroupDefinition groupDefinition)
+        throws DuplicateExpressionTypeException, RuntimeException;
 
     void updateResourceGroup(ResourceGroup group) throws RuntimeException;
 
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java
index ff3cab2..74484dd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java
@@ -33,6 +33,7 @@ import com.smartgwt.client.rpc.RPCResponse;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
 
 import org.rhq.core.domain.criteria.ResourceGroupDefinitionCriteria;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
 import org.rhq.core.domain.resource.group.GroupDefinition;
 import org.rhq.core.domain.util.PageList;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
@@ -154,7 +155,11 @@ public class GroupDefinitionDataSource extends RPCDataSource<GroupDefinition, Re
             new AsyncCallback<Void>() {
                 @Override
                 public void onFailure(Throwable caught) {
-                    CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_saveFailure(name), caught);
+                    if (caught instanceof DuplicateExpressionTypeException) {
+                        CoreGUI.getMessageCenter().notify(new Message(caught.getMessage(), Message.Severity.Warning));
+                    } else {
+                        CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_saveFailure(name), caught);
+                    }
                 }
 
                 @Override
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java
index 38b5165..0661533 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java
@@ -18,6 +18,9 @@
  */
 package org.rhq.enterprise.gui.coregui.client.inventory.groups.definitions;
 
+import java.util.Date;
+import java.util.Set;
+
 import com.google.gwt.user.client.History;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.smartgwt.client.types.ListGridFieldType;
@@ -26,20 +29,23 @@ import com.smartgwt.client.widgets.grid.CellFormatter;
 import com.smartgwt.client.widgets.grid.HoverCustomizer;
 import com.smartgwt.client.widgets.grid.ListGridField;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
+
 import org.rhq.core.domain.authz.Permission;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.PermissionsLoadedListener;
 import org.rhq.enterprise.gui.coregui.client.PermissionsLoader;
 import org.rhq.enterprise.gui.coregui.client.ViewPath;
-import org.rhq.enterprise.gui.coregui.client.components.table.*;
+import org.rhq.enterprise.gui.coregui.client.components.table.AbstractTableAction;
+import org.rhq.enterprise.gui.coregui.client.components.table.EscapedHtmlCellFormatter;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableActionEnablement;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableSection;
+import org.rhq.enterprise.gui.coregui.client.components.table.TimestampCellFormatter;
 import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
 import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
 import org.rhq.enterprise.gui.coregui.client.util.TableUtility;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
-
-import java.util.Date;
-import java.util.Set;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
 
 /**
  * @author Greg Hinkle
@@ -156,7 +162,12 @@ public class GroupDefinitionListView extends TableSection<GroupDefinitionDataSou
 
                 resourceGroupManager.recalculateGroupDefinitions(groupDefinitionIds, new AsyncCallback<Void>() {
                     public void onFailure(Throwable caught) {
-                        CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_recalcFailureSelection(), caught);
+                        if (caught instanceof DuplicateExpressionTypeException) {
+                            CoreGUI.getMessageCenter().notify(new Message(caught.getMessage(),
+                                Message.Severity.Warning));
+                        } else {
+                            CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_recalcFailureSelection(), caught);
+                        }
                     }
 
                     public void onSuccess(Void result) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java
index f55c37a..c417426 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java
@@ -61,6 +61,7 @@ import com.smartgwt.client.widgets.layout.HLayout;
 
 import org.rhq.core.domain.authz.Permission;
 import org.rhq.core.domain.criteria.ResourceGroupDefinitionCriteria;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
 import org.rhq.core.domain.resource.group.GroupCategory;
 import org.rhq.core.domain.resource.group.GroupDefinition;
 import org.rhq.core.domain.util.PageList;
@@ -239,7 +240,11 @@ public class SingleGroupDefinitionView extends LocatableVLayout implements Bookm
             new AsyncCallback<Void>() {
                 @Override
                 public void onFailure(Throwable caught) {
-                    CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_recalcFailure(), caught);
+                    if (caught instanceof DuplicateExpressionTypeException) {
+                        CoreGUI.getMessageCenter().notify(new Message(caught.getMessage(), Message.Severity.Warning));
+                    } else {
+                        CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_recalcFailure(), caught);
+                    }
                 }
 
                 @Override
@@ -487,6 +492,7 @@ public class SingleGroupDefinitionView extends LocatableVLayout implements Bookm
                     public void onFailure(Throwable caught) {
                         CoreGUI.getErrorHandler().handleError(
                             MSG.view_dynagroup_loadDefinitionFailure(String.valueOf(groupDefinitionId)), caught);
+
                         History.back();
                     }
 
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java
index b098980..8c5c54d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java
@@ -29,6 +29,7 @@ import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTService;
 import org.rhq.enterprise.gui.coregui.server.util.SerialUtility;
 import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
 import org.rhq.enterprise.server.resource.group.definition.GroupDefinitionManagerLocal;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
 import org.rhq.enterprise.server.util.LookupUtil;
 
 /**
@@ -146,20 +147,28 @@ public class ResourceGroupGWTServiceImpl extends AbstractGWTServiceImpl implemen
         }
     }
 
-    public void updateGroupDefinition(GroupDefinition groupDefinition) throws RuntimeException {
+    public void updateGroupDefinition(GroupDefinition groupDefinition)
+        throws DuplicateExpressionTypeException, RuntimeException {
         try {
             definitionManager.updateGroupDefinition(getSessionSubject(), groupDefinition);
         } catch (Throwable t) {
+            if (t instanceof DuplicateExpressionTypeException) {
+                throw (DuplicateExpressionTypeException) t;
+            }
             throw getExceptionToThrowToClient(t);
         }
     }
 
-    public void recalculateGroupDefinitions(int[] groupDefinitionIds) throws RuntimeException {
+    public void recalculateGroupDefinitions(int[] groupDefinitionIds)
+        throws DuplicateExpressionTypeException, RuntimeException {
         try {
             for (int nextGroupDefinitionId : groupDefinitionIds) {
                 definitionManager.calculateGroupMembership(getSessionSubject(), nextGroupDefinitionId);
             }
         } catch (Throwable t) {
+            if (t instanceof DuplicateExpressionTypeException) {
+                throw (DuplicateExpressionTypeException) t;
+            }
             throw getExceptionToThrowToClient(t);
         }
     }
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java
index 262c173..b3a1edd 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java
@@ -31,7 +31,7 @@ import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
 import org.rhq.enterprise.server.resource.group.ResourceGroupUpdateException;
 import org.rhq.enterprise.server.resource.group.definition.GroupDefinitionManagerLocal;
 import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionException;
-import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
 import org.rhq.enterprise.server.util.LookupUtil;
 
 public class EditGroupDefinitionGeneralPropertiesUIBean {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java
index 3776c70..190a169 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java
@@ -62,7 +62,7 @@ import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefini
 import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionNotFoundException;
 import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionUpdateException;
 import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
-import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
 import org.rhq.enterprise.server.resource.group.definition.mbean.GroupDefinitionRecalculationThreadMonitor;
 import org.rhq.enterprise.server.resource.group.definition.mbean.GroupDefinitionRecalculationThreadMonitorMBean;
 import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java
index d83c77c..b1d0d1d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java
@@ -33,7 +33,7 @@ import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefini
 import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionNotFoundException;
 import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionUpdateException;
 import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
-import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
 
 @Local
 public interface GroupDefinitionManagerLocal {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java
deleted file mode 100644
index 2b34b05..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *
- *  * RHQ Management Platform
- *  * Copyright (C) 2005-2012 Red Hat, Inc.
- *  * All rights reserved.
- *  *
- *  * This program is free software; you can redistribute it and/or modify
- *  * it under the terms of the GNU General Public License as published by
- *  * the Free Software Foundation version 2 of the License.
- *  *
- *  * This program is distributed in the hope that it will be useful,
- *  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *  * GNU General Public License for more details.
- *  *
- *  * You should have received a copy of the GNU General Public License
- *  * along with this program; if not, write to the Free Software
- *  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-package org.rhq.enterprise.server.resource.group.definition.framework;
-
-/**
- * @author John Sanda
- */
-public class DuplicateExpressionTypeException extends InvalidExpressionException {
-
-    private static final long serialVersionUID = 1L;
-
-    private DuplicateExpressionTypeException() {
-    }
-
-    public DuplicateExpressionTypeException(String predicate) {
-        super("You cannot specify multiple " + predicate + " expressions.");
-    }
-
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
index 925d59d..7f42f55 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
@@ -28,7 +28,7 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.TreeSet;
+import java.util.TreeMap;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -39,6 +39,8 @@ import org.apache.commons.logging.LogFactory;
 
 import org.rhq.core.domain.measurement.AvailabilityType;
 import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
 import org.rhq.enterprise.server.common.EntityManagerFacadeLocal;
 import org.rhq.enterprise.server.util.LookupUtil;
 import org.rhq.enterprise.server.util.QueryUtility;
@@ -93,7 +95,7 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
 
     private EntityManagerFacadeLocal entityManagerFacade;
 
-    private Set<String> resourceExpressions = new TreeSet<String>();
+    private Map<String, String> resourceExpressions = new TreeMap<String, String>();
 
     public ExpressionEvaluator() {
         /*
@@ -129,69 +131,77 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
          */
         whereStatics.add("res.inventoryStatus = org.rhq.core.domain.resource.InventoryStatus.COMMITTED");
 
-        resourceExpressions.add("res.id");
-        resourceExpressions.add("child.id");
-        resourceExpressions.add("res.parentResource.id");
-        resourceExpressions.add("res.parentResource.parentResource.id");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.id");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.id");
-
-        resourceExpressions.add("res.name");
-        resourceExpressions.add("child.name");
-        resourceExpressions.add("res.parentResource.name");
-        resourceExpressions.add("res.parentResource.parentResource.name");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.name");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.name");
-
-        resourceExpressions.add("res.version");
-        resourceExpressions.add("child.version");
-        resourceExpressions.add("res.parentResource.version");
-        resourceExpressions.add("res.parentResource.parentResource.version");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.version");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.version");
-
-
-        resourceExpressions.add("res.resourceType.plugin");
-        resourceExpressions.add("res.resourceType.name");
-        resourceExpressions.add("child.resourceType.plugin");
-        resourceExpressions.add("child.resourceType.name");
-        resourceExpressions.add("res.parentResource.resourceType.plugin");
-        resourceExpressions.add("res.parentResource.resourceType.name");
-        resourceExpressions.add("res.parentResource.parentResource.resourceType.plugin");
-        resourceExpressions.add("res.parentResource.parentResource.resourceType.name");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.plugin");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.name");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.plugin");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.name");
-
-
-        resourceExpressions.add("res.resourceType.category");
-        resourceExpressions.add("child.resourceType.category");
-        resourceExpressions.add("res.parentResource.resourceType.category");
-        resourceExpressions.add("res.parentResource.parentResource.resourceType.category");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.category");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.category");
-
-        resourceExpressions.add("avail.availabilityType");
-        resourceExpressions.add("child.avail.availabilityType");
-        resourceExpressions.add("res.parentResource.avail.availabilityType");
-        resourceExpressions.add("res.parentResource.parentResource.avail.availabilityType");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.avail.availabilityType");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.avail.availabilityType");
-
-        resourceExpressions.add("trait.value");
-        resourceExpressions.add("child.trait.value");
-        resourceExpressions.add("res.parentResource.trait.value");
-        resourceExpressions.add("res.parentResource.parentResource.trait.value");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.trait.value");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.trait.value");
-
-        resourceExpressions.add("simple.name");
-        resourceExpressions.add("child.simple.name");
-        resourceExpressions.add("res.parentResource.simple.name");
-        resourceExpressions.add("res.parentResource.parentResource.simple.name");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.simple.name");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.simple.name");
+        resourceExpressions.put("res.id", "resource id");
+        resourceExpressions.put("child.id", "resource id");
+        resourceExpressions.put("res.parentResource.id", "resource id");
+        resourceExpressions.put("res.parentResource.parentResource.id", "resource id");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.id", "resource id");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.id", "resource id");
+
+        resourceExpressions.put("res.name", "resource name");
+        resourceExpressions.put("child.name", "resource name");
+        resourceExpressions.put("res.parentResource.name", "resource name");
+        resourceExpressions.put("res.parentResource.parentResource.name", "resource name");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.name", "resource name");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.name",
+            "resource name");
+
+        resourceExpressions.put("res.version", "resource version");
+        resourceExpressions.put("child.version", "resource version");
+        resourceExpressions.put("res.parentResource.version", "resource version");
+        resourceExpressions.put("res.parentResource.parentResource.version", "resource version");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.version", "resource version");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.version",
+            "resource version");
+
+        resourceExpressions.put("res.resourceType.plugin", "resource type");
+        resourceExpressions.put("res.resourceType.name", "resource type");
+        resourceExpressions.put("child.resourceType.plugin", "resource type");
+        resourceExpressions.put("child.resourceType.name", "resource type");
+        resourceExpressions.put("res.parentResource.resourceType.plugin", "resource type");
+        resourceExpressions.put("res.parentResource.resourceType.name", "resource type");
+        resourceExpressions.put("res.parentResource.parentResource.resourceType.plugin", "resource type");
+        resourceExpressions.put("res.parentResource.parentResource.resourceType.name", "resource type");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.resourceType.plugin",
+            "resource type");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.resourceType.name", "resource type");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.resourceType.plugin",
+            "resource type");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.resourceType.name",
+            "resource type");
+
+        resourceExpressions.put("res.resourceType.category", "resource category");
+        resourceExpressions.put("child.resourceType.category", "resource category");
+        resourceExpressions.put("res.parentResource.resourceType.category", "resource category");
+        resourceExpressions.put("res.parentResource.parentResource.resourceType.category", "resource category");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.resourceType.category",
+            "resource category");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.resourceType.category",
+            "resource category");
+
+        resourceExpressions.put("avail.availabilityType", "availability");
+        resourceExpressions.put("child.avail.availabilityType", "availability");
+        resourceExpressions.put("res.parentResource.avail.availabilityType", "availability");
+        resourceExpressions.put("res.parentResource.parentResource.avail.availabilityType", "availability");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.avail.availabilityType",
+            "availability");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.avail.availabilityType",
+            "availability");
+
+        resourceExpressions.put("trait.value", "trait");
+        resourceExpressions.put("child.trait.value", "trait");
+        resourceExpressions.put("res.parentResource.trait.value", "trait");
+        resourceExpressions.put("res.parentResource.parentResource.trait.value", "trait");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.trait.value", "trait");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.trait.value", "trait");
+
+        resourceExpressions.put("simple.name", "configuration");
+        resourceExpressions.put("child.simple.name", "configuration");
+        resourceExpressions.put("res.parentResource.simple.name", "configuration");
+        resourceExpressions.put("res.parentResource.parentResource.simple.name", "configuration");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.simple.name", "configuration");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.simple.name",
+            "configuration");
     }
 
     public class Result {
@@ -231,7 +241,7 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
      *
      * @return a reference to itself, so that method chaining can be used
      *
-     * @throws InvalidExpressionException if the expression can not be parsed for any reason, the message will try to
+     * @throws org.rhq.core.domain.resource.group.InvalidExpressionException if the expression can not be parsed for any reason, the message will try to
      *                                    get the details as to the parse failure
      */
     public ExpressionEvaluator addExpression(String expression) throws InvalidExpressionException {
@@ -779,8 +789,8 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
                     + "] for predicate population");
             }
 
-            if (resourceExpressions.contains(predicateName) && whereConditions.containsKey(predicateName)) {
-                throw new DuplicateExpressionTypeException(predicateName);
+            if (resourceExpressions.containsKey(predicateName) && whereConditions.containsKey(predicateName)) {
+                throw new DuplicateExpressionTypeException(resourceExpressions.get(predicateName));
             }
 
             whereConditions.put(predicateName, argumentName);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/InvalidExpressionException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/InvalidExpressionException.java
deleted file mode 100644
index 06c7558..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/InvalidExpressionException.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.server.resource.group.definition.framework;
-
-public class InvalidExpressionException extends Exception {
-    private static final long serialVersionUID = 1L;
-
-    public InvalidExpressionException() {
-    }
-
-    public InvalidExpressionException(String message) {
-        super(message);
-    }
-
-    public InvalidExpressionException(Throwable cause) {
-        super(cause);
-    }
-
-    public InvalidExpressionException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
index 76c5824..a1c8a65 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
@@ -24,9 +24,9 @@ import java.util.List;
 
 import org.testng.annotations.Test;
 
-import org.rhq.enterprise.server.resource.group.definition.framework.DuplicateExpressionTypeException;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
 import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
-import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
 import org.rhq.enterprise.server.test.AbstractEJB3Test;
 import org.rhq.enterprise.server.util.QueryUtility;
 


commit 17a3b79efa50c1822489f75c3fc0a57333764710
Author: John Sanda <jsanda at redhat.com>
Date:   Wed Jun 27 14:19:03 2012 -0400

    [BZ 826716] Adding tests for plugin and resource config expressions.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
index 32565b6..925d59d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
@@ -178,6 +178,20 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
         resourceExpressions.add("res.parentResource.parentResource.avail.availabilityType");
         resourceExpressions.add("res.parentResource.parentResource.parentResource.avail.availabilityType");
         resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.avail.availabilityType");
+
+        resourceExpressions.add("trait.value");
+        resourceExpressions.add("child.trait.value");
+        resourceExpressions.add("res.parentResource.trait.value");
+        resourceExpressions.add("res.parentResource.parentResource.trait.value");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.trait.value");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.trait.value");
+
+        resourceExpressions.add("simple.name");
+        resourceExpressions.add("child.simple.name");
+        resourceExpressions.add("res.parentResource.simple.name");
+        resourceExpressions.add("res.parentResource.parentResource.simple.name");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.simple.name");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.simple.name");
     }
 
     public class Result {
@@ -549,10 +563,6 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
                 addJoinCondition(JoinCondition.AVAILABILITY);
                 populatePredicateCollections(JoinCondition.AVAILABILITY.alias + ".availabilityType", type);
             } else if (context == ParseContext.Trait) {
-                if (whereConditions.containsKey(TRAIT_ALIAS + ".value")) {
-                    throw new InvalidExpressionException("Cannot have multiple trait expressions.");
-                }
-
                 // SELECT res.id FROM Resource res JOIN res.schedules sched, sched.definition def, MeasurementDataTrait trait
                 // WHERE def.name = :arg1 AND trait.value = :arg2 AND trait.schedule = sched AND trait.id.timestamp =
                 // (SELECT max(mdt.id.timestamp) FROM MeasurementDataTrait mdt WHERE sched.id = mdt.schedule.id)
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
index 78ee34f..76c5824 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
@@ -29,7 +29,6 @@ import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionE
 import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
 import org.rhq.enterprise.server.test.AbstractEJB3Test;
 import org.rhq.enterprise.server.util.QueryUtility;
-import org.rhq.test.TransactionCallback;
 
 public class ExpressionEvaluatorTest extends AbstractEJB3Test {
 
@@ -158,7 +157,7 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
             "   AND simple.name = simpleDef.name AND simpleDef.type != 'PASSWORD' " }, };
     }
 
-//    @Test(groups = "integration.session")
+    @Test(groups = "integration.session")
     public void testWellFormedExpressions() throws Exception {
 
         String[][] successTestCases = getSuccessTestCases();
@@ -215,7 +214,7 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
         }
     }
 
-//    @Test(groups = "integration.session")
+    @Test(groups = "integration.session")
     public void testTokenizer() {
 
         String[] input = { "resource.child.name", //
@@ -257,15 +256,6 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
         }
     }
 
-    private void executeAndRollback(TransactionCallback callback) throws Exception {
-        try {
-            getTransactionManager().begin();
-            callback.execute();
-        } finally {
-            getTransactionManager().rollback();
-        }
-    }
-
     private static interface ExpressionGenerator {
         String[] getExpressions();
     }
@@ -284,34 +274,86 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
         }
     }
 
-    @Test(expectedExceptions = InvalidExpressionException.class,
-        expectedExceptionsMessageRegExp = ".*Cannot have multiple trait expressions.*")
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
     public void doNotAllowMultipleResourceTraitExpressions() throws Exception {
-        executeAndRollback(new TransactionCallback() {
+        evaluateExpressions(new ExpressionGenerator() {
             @Override
-            public void execute() throws Exception {
-                ExpressionEvaluator evaluator = new ExpressionEvaluator();
-                evaluator.addExpression("resource.trait[agentHomeDirectory] = /var/rhq-agent");
-                evaluator.addExpression("resource.trait[reasonForLastRestart] = OOMError");
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.trait[agentHomeDirectory] = /var/rhq-agent",
+                    "resource.trait[reasonForLastRestart] = OOMError"
+                };
+            }
+        });
+    }
 
-                evaluator.execute();
-                evaluator.iterator().next();
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourceTraitExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.child.trait[agentHomeDirectory] = /var/rhq-agent",
+                    "resource.child.trait[reasonForLastRestart] = OOMError"
+                };
             }
         });
     }
 
-    @Test(expectedExceptions = InvalidExpressionException.class,
-        expectedExceptionsMessageRegExp = ".*Cannot have multiple trait expressions.*")
-    public void doNotAllowMultiplParentResourceTraitExpressions() throws Exception {
-        executeAndRollback(new TransactionCallback() {
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourceTraitExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
             @Override
-            public void execute() throws Exception {
-                ExpressionEvaluator evaluator = new ExpressionEvaluator();
-                evaluator.addExpression("resource.parent.trait[agentHomeDirectory] = /var/rhq-agent");
-                evaluator.addExpression("resource.parent.trait[reasonForLastRestart] = OOMError");
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.parent.trait[agentHomeDirectory] = /var/rhq-agent",
+                    "resource.parent.trait[reasonForLastRestart] = OOMError"
+                };
+            }
+        });
+    }
 
-                evaluator.execute();
-                evaluator.iterator().next();
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourceTraitExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.grandParent.trait[agentHomeDirectory] = /var/rhq-agent",
+                    "resource.grandParent.trait[reasonForLastRestart] = OOMError"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourceTraitExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.greatGrandParent.trait[agentHomeDirectory] = /var/rhq-agent",
+                    "resource.greatGrandParent.trait[reasonForLastRestart] = OOMError"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourceTraitExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.greatGreatGrandParent.trait[agentHomeDirectory] = /var/rhq-agent",
+                    "resource.greatGreatGrandParent.trait[reasonForLastRestart] = OOMError"
+                };
             }
         });
     }
@@ -748,6 +790,174 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
         });
     }
 
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleResourcePluginConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.pluginConfiguration[x] = 1",
+                    "resource.pluginConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourcePluginConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.child.pluginConfiguration[x] = 1",
+                    "resource.child.pluginConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourcePluginConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.parent.pluginConfiguration[x] = 1",
+                    "resource.parent.pluginConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourcePluginConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.grandParent.pluginConfiguration[x] = 1",
+                    "resource.grandParent.pluginConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourcePluginConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGrandParent.pluginConfiguration[x] = 1",
+                    "resource.greatGrandParent.pluginConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourcePluginConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGreatGrandParent.pluginConfiguration[x] = 1",
+                    "resource.greatGreatGrandParent.pluginConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleResourceConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.resourceConfiguration[x] = 1",
+                    "resource.resourceConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourceConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.child.resourceConfiguration[x] = 1",
+                    "resource.child.resourceConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourceConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.parent.resourceConfiguration[x] = 1",
+                    "resource.parent.resourceConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourceConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.grandParent.resourceConfiguration[x] = 1",
+                    "resource.grandParent.resourceConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourceConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGrandParent.resourceConfiguration[x] = 1",
+                    "resource.greatGrandParent.resourceConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourceConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGreatGrandParent.resourceConfiguration[x] = 1",
+                    "resource.greatGreatGrandParent.resourceConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
     private String cleanUp(String result) {
         return result.replaceAll("\\s+", " ").trim();
     }


commit 29eee0d0559f504df4e186f7585fe5ed16bb2b32
Author: John Sanda <jsanda at redhat.com>
Date:   Tue Jun 26 17:04:29 2012 -0400

    [BZ 667896] Adding more tests to verify we do not allow multiple expressions of the same type

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java
new file mode 100644
index 0000000..2b34b05
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java
@@ -0,0 +1,38 @@
+/*
+ *
+ *  * RHQ Management Platform
+ *  * Copyright (C) 2005-2012 Red Hat, Inc.
+ *  * All rights reserved.
+ *  *
+ *  * This program is free software; you can redistribute it and/or modify
+ *  * it under the terms of the GNU General Public License as published by
+ *  * the Free Software Foundation version 2 of the License.
+ *  *
+ *  * This program is distributed in the hope that it will be useful,
+ *  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  * GNU General Public License for more details.
+ *  *
+ *  * You should have received a copy of the GNU General Public License
+ *  * along with this program; if not, write to the Free Software
+ *  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+package org.rhq.enterprise.server.resource.group.definition.framework;
+
+/**
+ * @author John Sanda
+ */
+public class DuplicateExpressionTypeException extends InvalidExpressionException {
+
+    private static final long serialVersionUID = 1L;
+
+    private DuplicateExpressionTypeException() {
+    }
+
+    public DuplicateExpressionTypeException(String predicate) {
+        super("You cannot specify multiple " + predicate + " expressions.");
+    }
+
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
index 1f7e300..32565b6 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
@@ -28,6 +28,7 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -92,6 +93,8 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
 
     private EntityManagerFacadeLocal entityManagerFacade;
 
+    private Set<String> resourceExpressions = new TreeSet<String>();
+
     public ExpressionEvaluator() {
         /*
          * used LinkedHashMap for whereConditions on purpose so that the iterator will return them in the same order
@@ -125,6 +128,56 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
          * initialization for special handling that all dynagroups should get
          */
         whereStatics.add("res.inventoryStatus = org.rhq.core.domain.resource.InventoryStatus.COMMITTED");
+
+        resourceExpressions.add("res.id");
+        resourceExpressions.add("child.id");
+        resourceExpressions.add("res.parentResource.id");
+        resourceExpressions.add("res.parentResource.parentResource.id");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.id");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.id");
+
+        resourceExpressions.add("res.name");
+        resourceExpressions.add("child.name");
+        resourceExpressions.add("res.parentResource.name");
+        resourceExpressions.add("res.parentResource.parentResource.name");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.name");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.name");
+
+        resourceExpressions.add("res.version");
+        resourceExpressions.add("child.version");
+        resourceExpressions.add("res.parentResource.version");
+        resourceExpressions.add("res.parentResource.parentResource.version");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.version");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.version");
+
+
+        resourceExpressions.add("res.resourceType.plugin");
+        resourceExpressions.add("res.resourceType.name");
+        resourceExpressions.add("child.resourceType.plugin");
+        resourceExpressions.add("child.resourceType.name");
+        resourceExpressions.add("res.parentResource.resourceType.plugin");
+        resourceExpressions.add("res.parentResource.resourceType.name");
+        resourceExpressions.add("res.parentResource.parentResource.resourceType.plugin");
+        resourceExpressions.add("res.parentResource.parentResource.resourceType.name");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.plugin");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.name");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.plugin");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.name");
+
+
+        resourceExpressions.add("res.resourceType.category");
+        resourceExpressions.add("child.resourceType.category");
+        resourceExpressions.add("res.parentResource.resourceType.category");
+        resourceExpressions.add("res.parentResource.parentResource.resourceType.category");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.category");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.category");
+
+        resourceExpressions.add("avail.availabilityType");
+        resourceExpressions.add("child.avail.availabilityType");
+        resourceExpressions.add("res.parentResource.avail.availabilityType");
+        resourceExpressions.add("res.parentResource.parentResource.avail.availabilityType");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.avail.availabilityType");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.avail.availabilityType");
     }
 
     public class Result {
@@ -716,6 +769,10 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
                     + "] for predicate population");
             }
 
+            if (resourceExpressions.contains(predicateName) && whereConditions.containsKey(predicateName)) {
+                throw new DuplicateExpressionTypeException(predicateName);
+            }
+
             whereConditions.put(predicateName, argumentName);
             whereReplacements.put(argumentName, value);
 
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
index f0a64ff..78ee34f 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
@@ -24,10 +24,12 @@ import java.util.List;
 
 import org.testng.annotations.Test;
 
+import org.rhq.enterprise.server.resource.group.definition.framework.DuplicateExpressionTypeException;
 import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
 import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
 import org.rhq.enterprise.server.test.AbstractEJB3Test;
 import org.rhq.enterprise.server.util.QueryUtility;
+import org.rhq.test.TransactionCallback;
 
 public class ExpressionEvaluatorTest extends AbstractEJB3Test {
 
@@ -255,24 +257,495 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
         }
     }
 
-    @Test(expectedExceptions = InvalidExpressionException.class)
-    public void throwExceptionWhenMultipleResourceTraitsSpecified() throws Exception {
-        ExpressionEvaluator evaluator = new ExpressionEvaluator();
-        evaluator.addExpression("resource.trait[agentHomeDirectory] = /var/rhq-agent");
-        evaluator.addExpression("resource.trait[reasonForLastRestart] = OOMError");
+    private void executeAndRollback(TransactionCallback callback) throws Exception {
+        try {
+            getTransactionManager().begin();
+            callback.execute();
+        } finally {
+            getTransactionManager().rollback();
+        }
+    }
 
-        evaluator.execute();
-        evaluator.iterator().next();
+    private static interface ExpressionGenerator {
+        String[] getExpressions();
     }
 
-    @Test(expectedExceptions = InvalidExpressionException.class)
-    public void throwExceptionWhenMultipleResourceParentTraitsSpecified() throws Exception {
-        ExpressionEvaluator evaluator = new ExpressionEvaluator();
-        evaluator.addExpression("resource.parent.trait[agentHomeDirectory] = /var/rhq-agent");
-        evaluator.addExpression("resource.parent.trait[reasonForLastRestart] = OOMError");
+    private void evaluateExpressions(ExpressionGenerator generator) throws Exception {
+        try {
+            getTransactionManager().begin();
+            ExpressionEvaluator evaluator = new ExpressionEvaluator();
+            for (String expression : generator.getExpressions()) {
+                evaluator.addExpression(expression);
+            }
+            evaluator.execute();
+            evaluator.iterator().next();
+        } finally {
+            getTransactionManager().rollback();
+        }
+    }
+
+    @Test(expectedExceptions = InvalidExpressionException.class,
+        expectedExceptionsMessageRegExp = ".*Cannot have multiple trait expressions.*")
+    public void doNotAllowMultipleResourceTraitExpressions() throws Exception {
+        executeAndRollback(new TransactionCallback() {
+            @Override
+            public void execute() throws Exception {
+                ExpressionEvaluator evaluator = new ExpressionEvaluator();
+                evaluator.addExpression("resource.trait[agentHomeDirectory] = /var/rhq-agent");
+                evaluator.addExpression("resource.trait[reasonForLastRestart] = OOMError");
+
+                evaluator.execute();
+                evaluator.iterator().next();
+            }
+        });
+    }
+
+    @Test(expectedExceptions = InvalidExpressionException.class,
+        expectedExceptionsMessageRegExp = ".*Cannot have multiple trait expressions.*")
+    public void doNotAllowMultiplParentResourceTraitExpressions() throws Exception {
+        executeAndRollback(new TransactionCallback() {
+            @Override
+            public void execute() throws Exception {
+                ExpressionEvaluator evaluator = new ExpressionEvaluator();
+                evaluator.addExpression("resource.parent.trait[agentHomeDirectory] = /var/rhq-agent");
+                evaluator.addExpression("resource.parent.trait[reasonForLastRestart] = OOMError");
+
+                evaluator.execute();
+                evaluator.iterator().next();
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleResourceIdExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.id = 5",
+                    "resource.id = 6"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourceIdExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.child.id = 5",
+                    "resource.child.id = 6"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourceIdExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.parent.id = 5",
+                    "resource.parent.id = 6"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = InvalidExpressionException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourceIdExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.grandParent.id = 5",
+                    "resource.grandParent.id = 6"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourceIdExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGrandParent.id = 5",
+                    "resource.greatGrandParent.id = 6"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourceIdExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGreatGrandParent.id = 5",
+                    "resource.greatGreatGrandParent.id = 6"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleResourceNameExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.name = foo",
+                    "resource.name = bar"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourceNameExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.child.name = foo",
+                    "resource.child.name = bar"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourceNameExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.parent.name = foo",
+                    "resource.parent.name = bar"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourceNameExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.grandParent.name = foo",
+                    "resource.grandParent.name = bar"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourceNameExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGrandParent.name = foo",
+                    "resource.greatGrandParent.name = bar"
+                };
+            }
+        });
+    }
 
-        evaluator.execute();
-        evaluator.iterator().next();
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourceNameExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGreatGrandParent.name = foo",
+                    "resource.greatGreatGrandParent.name = bar"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleResourceTypeExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.type.plugin = rhq-agent",
+                    "resource.type.name = RHQ Agent",
+                    "resource.type.plugin = rhq-server",
+                    "resource.type.name = RHQ Server"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourceTypeExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.child.type.plugin = rhq-agent",
+                    "resource.child.type.name = RHQ Agent",
+                    "resource.child.type.plugin = rhq-server",
+                    "resource.child.type.name = RHQ Server"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourceTypeExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.parent.type.plugin = rhq-agent",
+                    "resource.parent.type.name = RHQ Agent",
+                    "resource.parent.type.plugin = rhq-server",
+                    "resource.parent.type.name = RHQ Server"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourceTypeExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.grandParent.type.plugin = rhq-agent",
+                    "resource.grandParent.type.name = RHQ Agent",
+                    "resource.grandParent.type.plugin = rhq-server",
+                    "resource.grandParent.type.name = RHQ Server"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourceTypeExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.greatGrandParent.type.plugin = rhq-agent",
+                    "resource.greatGrandParent.type.name = RHQ Agent",
+                    "resource.greatGrandParent.type.plugin = rhq-server",
+                    "resource.greatGrandParent.type.name = RHQ Server"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourceTypeExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.greatGreatGrandParent.type.plugin = rhq-agent",
+                    "resource.greatGreatGrandParent.type.name = RHQ Agent",
+                    "resource.greatGreatGrandParent.type.plugin = rhq-server",
+                    "resource.greatGreatGrandParent.type.name = RHQ Server"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleResourceCategoryExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.type.category = PLATFORM",
+                    "resource.type.category = SERVER"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourceCategoryExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.child.type.category = PLATFORM",
+                    "resource.child.type.category = SERVER"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourceCategoryExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.parent.type.category = PLATFORM",
+                    "resource.parent.type.category = SERVER"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourceCategoryExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.grandParent.type.category = PLATFORM",
+                    "resource.grandParent.type.category = SERVER"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourceCategoryExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGrandParent.type.category = PLATFORM",
+                    "resource.greatGrandParent.type.category = SERVER"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourceCategoryExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.greatGreatGrandParent.type.category = PLATFORM",
+                    "resource.greatGreatGrandParent.type.category = SERVER"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleResourceAvailabilityExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.availability = UP",
+                    "resource.availability = UNKNOWN"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourceAvailabilityExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.child.availability = UP",
+                    "resource.child.availability = UNKNOWN"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourceAvailabilityExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.parent.availability = UP",
+                    "resource.parent.availability = UNKNOWN"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourceAvailabilityExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.grandParent.availability = UP",
+                    "resource.grandParent.availability = UNKNOWN"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourceAvailabilityExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.greatGrandParent.availability = UP",
+                    "resource.greatGrandParent.availability = UNKNOWN"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourceAvailabilityExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.greatGreatGrandParent.availability = UP",
+                    "resource.greatGreatGrandParent.availability = UNKNOWN"
+                };
+            }
+        });
     }
 
     private String cleanUp(String result) {


commit 501156607c9d8a58b2c97ccabf42785744496ba6
Author: John Sanda <jsanda at redhat.com>
Date:   Fri Jun 22 21:33:59 2012 -0400

    [BZ 667896] Throw exception if multiple trait expressions specified

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
index 480c97f..1f7e300 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
@@ -496,6 +496,10 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
                 addJoinCondition(JoinCondition.AVAILABILITY);
                 populatePredicateCollections(JoinCondition.AVAILABILITY.alias + ".availabilityType", type);
             } else if (context == ParseContext.Trait) {
+                if (whereConditions.containsKey(TRAIT_ALIAS + ".value")) {
+                    throw new InvalidExpressionException("Cannot have multiple trait expressions.");
+                }
+
                 // SELECT res.id FROM Resource res JOIN res.schedules sched, sched.definition def, MeasurementDataTrait trait
                 // WHERE def.name = :arg1 AND trait.value = :arg2 AND trait.schedule = sched AND trait.id.timestamp =
                 // (SELECT max(mdt.id.timestamp) FROM MeasurementDataTrait mdt WHERE sched.id = mdt.schedule.id)
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
index fd3db2e..f0a64ff 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
@@ -25,6 +25,7 @@ import java.util.List;
 import org.testng.annotations.Test;
 
 import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
+import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
 import org.rhq.enterprise.server.test.AbstractEJB3Test;
 import org.rhq.enterprise.server.util.QueryUtility;
 
@@ -155,7 +156,7 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
             "   AND simple.name = simpleDef.name AND simpleDef.type != 'PASSWORD' " }, };
     }
 
-    @Test(groups = "integration.session")
+//    @Test(groups = "integration.session")
     public void testWellFormedExpressions() throws Exception {
 
         String[][] successTestCases = getSuccessTestCases();
@@ -212,7 +213,7 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
         }
     }
 
-    @Test(groups = "integration.session")
+//    @Test(groups = "integration.session")
     public void testTokenizer() {
 
         String[] input = { "resource.child.name", //
@@ -254,6 +255,26 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
         }
     }
 
+    @Test(expectedExceptions = InvalidExpressionException.class)
+    public void throwExceptionWhenMultipleResourceTraitsSpecified() throws Exception {
+        ExpressionEvaluator evaluator = new ExpressionEvaluator();
+        evaluator.addExpression("resource.trait[agentHomeDirectory] = /var/rhq-agent");
+        evaluator.addExpression("resource.trait[reasonForLastRestart] = OOMError");
+
+        evaluator.execute();
+        evaluator.iterator().next();
+    }
+
+    @Test(expectedExceptions = InvalidExpressionException.class)
+    public void throwExceptionWhenMultipleResourceParentTraitsSpecified() throws Exception {
+        ExpressionEvaluator evaluator = new ExpressionEvaluator();
+        evaluator.addExpression("resource.parent.trait[agentHomeDirectory] = /var/rhq-agent");
+        evaluator.addExpression("resource.parent.trait[reasonForLastRestart] = OOMError");
+
+        evaluator.execute();
+        evaluator.iterator().next();
+    }
+
     private String cleanUp(String result) {
         return result.replaceAll("\\s+", " ").trim();
     }




More information about the rhq-commits mailing list