moving ConditionEvaluator to ConditionTypeEvaluator; creating ConditionsEvaluator to merge (by delegation) the functionality of the ConditionTypeEvaluator and the LogicalOperationEvaluator


git-svn-id: https://svn.apache.org/repos/asf/ant/antlibs/props/trunk@916874 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/docs/index.html b/docs/index.html
index 571ed49..c025b72 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -129,6 +129,14 @@
             setting the given attibute values and evaluates to either
             Boolean.TRUE or Boolean.FALSE.  Usage looks
             like <em>${os(family=unix)}</em> / <em>${!os(family=unix)}</em>.
+            Additionally, logical operations are supported.
+            In order of precedence, these are !, &, ^, and |, with +
+            being a secondary alias for & since & is a special character
+            to the XML format. When you want to combine logical operations
+            with typed Ant conditions, the typed conditions should be
+            specified as nested properties and the <a href="#nested">nested
+            evaluator</a> should be included with your active
+            PropertyHelper delegates.
             This is probably most useful together with the
             <code>if</code>/<code>unless</code> attributes of tasks or targets.
         </td>
diff --git a/src/main/org/apache/ant/props/ConditionEvaluator.java b/src/main/org/apache/ant/props/ConditionTypeEvaluator.java
similarity index 96%
rename from src/main/org/apache/ant/props/ConditionEvaluator.java
rename to src/main/org/apache/ant/props/ConditionTypeEvaluator.java
index 6cb6020..48a3f4c 100644
--- a/src/main/org/apache/ant/props/ConditionEvaluator.java
+++ b/src/main/org/apache/ant/props/ConditionTypeEvaluator.java
@@ -36,7 +36,7 @@
  * <code>[!]<em>condition</em>(<em>attribute</em>=<em>value</em>)</code>,
  * for example <code>os(family=unix)</code> or <code>!os(family=unix)</code>.
  */
-public class ConditionEvaluator extends RegexBasedEvaluator {
+public class ConditionTypeEvaluator extends RegexBasedEvaluator {
     private static final Pattern COMMA = Pattern.compile(",");
     private static final Pattern EQ = Pattern.compile("=");
 
@@ -64,9 +64,9 @@
     ;
 
     /**
-     * Create a new ConditionEvaluator instance.
+     * Create a new ConditionTypeEvaluator instance.
      */
-    public ConditionEvaluator() {
+    public ConditionTypeEvaluator() {
         super(PATTERN);
     }
 
diff --git a/src/main/org/apache/ant/props/ConditionsEvaluator.java b/src/main/org/apache/ant/props/ConditionsEvaluator.java
new file mode 100644
index 0000000..44ebe3c
--- /dev/null
+++ b/src/main/org/apache/ant/props/ConditionsEvaluator.java
@@ -0,0 +1,38 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ *

+ */

+package org.apache.ant.props;

+

+import org.apache.ant.props.DelegatingPropertyEvaluator;

+

+/**

+ * PropertyEvaluator that delegates to ConditionTypeEvaluator

+ * and LogicalOperationEvaluator for a more all-encompassing

+ * treatment of condition processing.  Wants NestedPropertyExpander.

+ */

+public class ConditionsEvaluator extends DelegatingPropertyEvaluator {

+    /**

+     * Construct a new ConditionsEvaluator.

+     */

+    public ConditionsEvaluator() {

+        addDelegate(new ConditionTypeEvaluator());

+        addDelegate(new LogicalOperationEvaluator());

+    }

+

+}

diff --git a/src/main/org/apache/ant/props/antlib.xml b/src/main/org/apache/ant/props/antlib.xml
index 3946873..93ab748 100644
--- a/src/main/org/apache/ant/props/antlib.xml
+++ b/src/main/org/apache/ant/props/antlib.xml
@@ -22,5 +22,5 @@
   <typedef name="stringops" classname="org.apache.ant.props.stringops.StringOperationsEvaluator" />
   <typedef name="types" classname="org.apache.ant.props.ComponentTypeEvaluator" />
   <typedef name="encodeURL" classname="org.apache.ant.props.EncodeURLEvaluator" />
-  <typedef name="conditions" classname="org.apache.ant.props.ConditionEvaluator" />
+  <typedef name="conditions" classname="org.apache.ant.props.ConditionsEvaluator" />
 </antlib>
diff --git a/src/tests/antunit/condition-test.xml b/src/tests/antunit/condition-type-test.xml
similarity index 95%
rename from src/tests/antunit/condition-test.xml
rename to src/tests/antunit/condition-type-test.xml
index 984e911..3d4a081 100644
--- a/src/tests/antunit/condition-test.xml
+++ b/src/tests/antunit/condition-type-test.xml
@@ -1,109 +1,111 @@
-<?xml version="1.0"?>
-<!--
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
--->
-<project xmlns:au="antlib:org.apache.ant.antunit"
-         xmlns:props="antlib:org.apache.ant.props" default="antunit">
-  <propertyhelper>
-    <props:conditions />
-    <props:nested />
-  </propertyhelper>
-
-  <target name="if-available"
-          if="${available(classname=org.apache.ant.props.ConditionEvaluator)}">
-    <property name="testAvailable.pass" value="true" />
-  </target>
-
-  <target name="unless-available"
-          unless="${available(classname=org.apache.ant.props.ConditionEvaluator)}">
-    <property name="testAvailable.fail" value="true" />
-  </target>
-
-  <target name="testAvailable" depends="if-available,unless-available">
-    <au:assertTrue>
-      <and>
-        <istrue value="${testAvailable.pass}" />
-        <not><istrue value="${testAvailable.fail}" /></not>
-      </and>
-    </au:assertTrue>
-  </target>
-
-  <target name="set-prop">
-    <property name="foo" value="bar"/>
-  </target>
-
-  <target name="if-equals" if="${equals(arg1=bar,arg2=${foo})}">
-    <property name="testTrueEquals.pass" value="true" />
-  </target>
-
-  <target name="unless-equals" unless="${equals(arg1=bar,arg2=${foo})}">
-    <property name="testFalseEquals.pass" value="true" />
-  </target>
-
-  <target name="testTrueEquals" depends="set-prop,if-equals,unless-equals">
-    <au:assertTrue>
-      <istrue value="${testTrueEquals.pass}" />
-    </au:assertTrue>
-  </target>
-
-  <target name="testFalseEquals" depends="if-equals,unless-equals"
-          description="Pass is inconclusive">
-    <au:assertTrue>
-      <istrue value="${testFalseEquals.pass}" />
-    </au:assertTrue>
-  </target>
-
-  <target name="testEvalToTextFalse">
-    <au:assertTrue>
-      <!-- equals takes objects; embedding values in () forces string conversion -->
-      <equals arg1="(false)" arg2="(${equals(arg1=bar,arg2=${foo})})" />
-    </au:assertTrue>
-  </target>
-
-  <target name="testEvalToTextTrue" depends="set-prop">
-    <au:assertTrue>
-      <!-- equals takes objects; embedding values in () forces string conversion -->
-      <equals arg1="(true)" arg2="(${equals(arg1=bar,arg2=${foo})})" />
-    </au:assertTrue>
-  </target>
-
-  <target name="testIsTrue" depends="set-prop">
-    <au:assertTrue>
-      <istrue value="${equals(arg1=bar,arg2=${foo})}" />
-    </au:assertTrue>
-  </target>
-
-  <target name="testNotIsTrue" description="Pass is inconclusive">
-    <au:assertFalse>
-      <istrue value="${equals(arg1=bar,arg2=${foo})}" />
-    </au:assertFalse>
-  </target>
-
-  <target name="antunit">
-    <antunit xmlns="antlib:org.apache.ant.antunit">
-      <plainlistener />
-      <file file="${ant.file}" xmlns="antlib:org.apache.tools.ant" />
-    </antunit>
-  </target>
-
-  <target name="testNegation">
-    <property name="foo" value="false" />
-    <au:assertTrue>
-      <istrue value="${!istrue(value=${foo})}" />
-    </au:assertTrue>
-  </target>
-
-</project>
+<?xml version="1.0"?>

+<!--

+   Licensed to the Apache Software Foundation (ASF) under one or more

+   contributor license agreements.  See the NOTICE file distributed with

+   this work for additional information regarding copyright ownership.

+   The ASF licenses this file to You under the Apache License, Version 2.0

+   (the "License"); you may not use this file except in compliance with

+   the License.  You may obtain a copy of the License at

+

+       http://www.apache.org/licenses/LICENSE-2.0

+

+   Unless required by applicable law or agreed to in writing, software

+   distributed under the License is distributed on an "AS IS" BASIS,

+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+   See the License for the specific language governing permissions and

+   limitations under the License.

+-->

+<project xmlns:au="antlib:org.apache.ant.antunit"

+         xmlns:props="antlib:org.apache.ant.props" default="antunit">

+  <typedef name="condition-type"

+           classname="org.apache.ant.props.ConditionTypeEvaluator" />

+  <propertyhelper>

+    <condition-type />

+    <props:nested />

+  </propertyhelper>

+

+  <target name="if-available"

+          if="${available(classname=org.apache.ant.props.ConditionTypeEvaluator)}">

+    <property name="testAvailable.pass" value="true" />

+  </target>

+

+  <target name="unless-available"

+          unless="${available(classname=org.apache.ant.props.ConditionTypeEvaluator)}">

+    <property name="testAvailable.fail" value="true" />

+  </target>

+

+  <target name="testAvailable" depends="if-available,unless-available">

+    <au:assertTrue>

+      <and>

+        <istrue value="${testAvailable.pass}" />

+        <not><istrue value="${testAvailable.fail}" /></not>

+      </and>

+    </au:assertTrue>

+  </target>

+

+  <target name="set-prop">

+    <property name="foo" value="bar"/>

+  </target>

+

+  <target name="if-equals" if="${equals(arg1=bar,arg2=${foo})}">

+    <property name="testTrueEquals.pass" value="true" />

+  </target>

+

+  <target name="unless-equals" unless="${equals(arg1=bar,arg2=${foo})}">

+    <property name="testFalseEquals.pass" value="true" />

+  </target>

+

+  <target name="testTrueEquals" depends="set-prop,if-equals,unless-equals">

+    <au:assertTrue>

+      <istrue value="${testTrueEquals.pass}" />

+    </au:assertTrue>

+  </target>

+

+  <target name="testFalseEquals" depends="if-equals,unless-equals"

+          description="Pass is inconclusive">

+    <au:assertTrue>

+      <istrue value="${testFalseEquals.pass}" />

+    </au:assertTrue>

+  </target>

+

+  <target name="testEvalToTextFalse">

+    <au:assertTrue>

+      <!-- equals takes objects; embedding values in () forces string conversion -->

+      <equals arg1="(false)" arg2="(${equals(arg1=bar,arg2=${foo})})" />

+    </au:assertTrue>

+  </target>

+

+  <target name="testEvalToTextTrue" depends="set-prop">

+    <au:assertTrue>

+      <!-- equals takes objects; embedding values in () forces string conversion -->

+      <equals arg1="(true)" arg2="(${equals(arg1=bar,arg2=${foo})})" />

+    </au:assertTrue>

+  </target>

+

+  <target name="testIsTrue" depends="set-prop">

+    <au:assertTrue>

+      <istrue value="${equals(arg1=bar,arg2=${foo})}" />

+    </au:assertTrue>

+  </target>

+

+  <target name="testNotIsTrue" description="Pass is inconclusive">

+    <au:assertFalse>

+      <istrue value="${equals(arg1=bar,arg2=${foo})}" />

+    </au:assertFalse>

+  </target>

+

+  <target name="antunit">

+    <antunit xmlns="antlib:org.apache.ant.antunit">

+      <plainlistener />

+      <file file="${ant.file}" xmlns="antlib:org.apache.tools.ant" />

+    </antunit>

+  </target>

+

+  <target name="testNegation">

+    <property name="foo" value="false" />

+    <au:assertTrue>

+      <istrue value="${!istrue(value=${foo})}" />

+    </au:assertTrue>

+  </target>

+

+</project>

diff --git a/src/tests/antunit/condition-test.xml b/src/tests/antunit/conditions-test.xml
similarity index 74%
copy from src/tests/antunit/condition-test.xml
copy to src/tests/antunit/conditions-test.xml
index 984e911..216614e 100644
--- a/src/tests/antunit/condition-test.xml
+++ b/src/tests/antunit/conditions-test.xml
@@ -1,109 +1,113 @@
-<?xml version="1.0"?>
-<!--
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
--->
-<project xmlns:au="antlib:org.apache.ant.antunit"
-         xmlns:props="antlib:org.apache.ant.props" default="antunit">
-  <propertyhelper>
-    <props:conditions />
-    <props:nested />
-  </propertyhelper>
-
-  <target name="if-available"
-          if="${available(classname=org.apache.ant.props.ConditionEvaluator)}">
-    <property name="testAvailable.pass" value="true" />
-  </target>
-
-  <target name="unless-available"
-          unless="${available(classname=org.apache.ant.props.ConditionEvaluator)}">
-    <property name="testAvailable.fail" value="true" />
-  </target>
-
-  <target name="testAvailable" depends="if-available,unless-available">
-    <au:assertTrue>
-      <and>
-        <istrue value="${testAvailable.pass}" />
-        <not><istrue value="${testAvailable.fail}" /></not>
-      </and>
-    </au:assertTrue>
-  </target>
-
-  <target name="set-prop">
-    <property name="foo" value="bar"/>
-  </target>
-
-  <target name="if-equals" if="${equals(arg1=bar,arg2=${foo})}">
-    <property name="testTrueEquals.pass" value="true" />
-  </target>
-
-  <target name="unless-equals" unless="${equals(arg1=bar,arg2=${foo})}">
-    <property name="testFalseEquals.pass" value="true" />
-  </target>
-
-  <target name="testTrueEquals" depends="set-prop,if-equals,unless-equals">
-    <au:assertTrue>
-      <istrue value="${testTrueEquals.pass}" />
-    </au:assertTrue>
-  </target>
-
-  <target name="testFalseEquals" depends="if-equals,unless-equals"
-          description="Pass is inconclusive">
-    <au:assertTrue>
-      <istrue value="${testFalseEquals.pass}" />
-    </au:assertTrue>
-  </target>
-
-  <target name="testEvalToTextFalse">
-    <au:assertTrue>
-      <!-- equals takes objects; embedding values in () forces string conversion -->
-      <equals arg1="(false)" arg2="(${equals(arg1=bar,arg2=${foo})})" />
-    </au:assertTrue>
-  </target>
-
-  <target name="testEvalToTextTrue" depends="set-prop">
-    <au:assertTrue>
-      <!-- equals takes objects; embedding values in () forces string conversion -->
-      <equals arg1="(true)" arg2="(${equals(arg1=bar,arg2=${foo})})" />
-    </au:assertTrue>
-  </target>
-
-  <target name="testIsTrue" depends="set-prop">
-    <au:assertTrue>
-      <istrue value="${equals(arg1=bar,arg2=${foo})}" />
-    </au:assertTrue>
-  </target>
-
-  <target name="testNotIsTrue" description="Pass is inconclusive">
-    <au:assertFalse>
-      <istrue value="${equals(arg1=bar,arg2=${foo})}" />
-    </au:assertFalse>
-  </target>
-
-  <target name="antunit">
-    <antunit xmlns="antlib:org.apache.ant.antunit">
-      <plainlistener />
-      <file file="${ant.file}" xmlns="antlib:org.apache.tools.ant" />
-    </antunit>
-  </target>
-
-  <target name="testNegation">
-    <property name="foo" value="false" />
-    <au:assertTrue>
-      <istrue value="${!istrue(value=${foo})}" />
-    </au:assertTrue>
-  </target>
-
-</project>
+<?xml version="1.0"?>

+<!--

+   Licensed to the Apache Software Foundation (ASF) under one or more

+   contributor license agreements.  See the NOTICE file distributed with

+   this work for additional information regarding copyright ownership.

+   The ASF licenses this file to You under the Apache License, Version 2.0

+   (the "License"); you may not use this file except in compliance with

+   the License.  You may obtain a copy of the License at

+

+       http://www.apache.org/licenses/LICENSE-2.0

+

+   Unless required by applicable law or agreed to in writing, software

+   distributed under the License is distributed on an "AS IS" BASIS,

+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+   See the License for the specific language governing permissions and

+   limitations under the License.

+-->

+<project xmlns:au="antlib:org.apache.ant.antunit"

+         xmlns:props="antlib:org.apache.ant.props" default="antunit">

+

+  <propertyhelper>

+    <props:conditions />

+    <props:nested />

+  </propertyhelper>

+

+  <target name="if-available"

+          if="${${available(classname=org.apache.ant.props.ConditionsEvaluator)} | false}">

+    <property name="testAvailable.pass" value="true" />

+  </target>

+

+  <target name="unless-available"

+          unless="${${available(classname=org.apache.ant.props.ConditionsEvaluator)} &amp; true}">

+    <property name="testAvailable.fail" value="true" />

+  </target>

+

+  <target name="testAvailable" depends="if-available,unless-available">

+    <propertyhelper>

+      <props:stringops />

+    </propertyhelper>

+    <au:assertTrue>

+      <istrue value="${${testAvailable.pass:-false} &amp; !${testAvailable.fail:-false}}" />

+    </au:assertTrue>

+  </target>

+

+  <target name="set-prop">

+    <property name="foo" value="bar" />

+  </target>

+

+  <target name="if-equals" if="${${equals(arg1=bar,arg2=${foo})} | false}">

+    <property name="testTrueEquals.pass" value="true" />

+  </target>

+

+  <target name="unless-equals"

+          unless="${${equals(arg1=bar,arg2=${foo})} &amp; true}">

+    <property name="testFalseEquals.pass" value="true" />

+  </target>

+

+  <target name="testTrueEquals" depends="set-prop,if-equals,unless-equals">

+    <au:assertTrue>

+      <istrue value="${testTrueEquals.pass}" />

+    </au:assertTrue>

+  </target>

+

+  <target name="testFalseEquals" depends="if-equals,unless-equals"

+          description="Pass is inconclusive">

+    <au:assertTrue>

+      <istrue value="${testFalseEquals.pass}" />

+    </au:assertTrue>

+  </target>

+

+  <target name="testEvalToTextFalse">

+    <au:assertTrue>

+      <!-- equals takes objects; embedding values in () forces string conversion -->

+      <equals arg1="(false)"

+              arg2="(${${equals(arg1=bar,arg2=${foo})} &amp; true})" />

+    </au:assertTrue>

+  </target>

+

+  <target name="testEvalToTextTrue" depends="set-prop">

+    <au:assertTrue>

+      <!-- equals takes objects; embedding values in () forces string conversion -->

+      <equals arg1="(true)"

+              arg2="(${${equals(arg1=bar,arg2=${foo})} | false})" />

+    </au:assertTrue>

+  </target>

+

+  <target name="testIsTrue" depends="set-prop">

+    <au:assertTrue>

+      <istrue value="${${equals(arg1=bar,arg2=${foo})} | false}" />

+    </au:assertTrue>

+  </target>

+

+  <target name="testNotIsTrue" description="Pass is inconclusive">

+    <au:assertFalse>

+      <istrue value="${${equals(arg1=bar,arg2=${foo})} &amp; true}" />

+    </au:assertFalse>

+  </target>

+

+  <target name="antunit">

+    <antunit xmlns="antlib:org.apache.ant.antunit">

+      <plainlistener />

+      <file file="${ant.file}" xmlns="antlib:org.apache.tools.ant" />

+    </antunit>

+  </target>

+

+  <target name="testNegation">

+    <property name="foo" value="false" />

+    <au:assertTrue>

+      <istrue value="${!${istrue(value=${foo})}}" />

+    </au:assertTrue>

+  </target>

+

+</project>