001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.tools.ant.types.resources.selectors;
019:
020: import java.util.Stack;
021: import java.util.Iterator;
022:
023: import org.apache.tools.ant.Project;
024: import org.apache.tools.ant.BuildException;
025: import org.apache.tools.ant.types.Comparison;
026: import org.apache.tools.ant.types.DataType;
027: import org.apache.tools.ant.types.Resource;
028: import org.apache.tools.ant.types.Quantifier;
029: import org.apache.tools.ant.types.ResourceCollection;
030: import org.apache.tools.ant.types.resources.Union;
031: import org.apache.tools.ant.types.resources.comparators.ResourceComparator;
032: import org.apache.tools.ant.types.resources.comparators.DelegatedResourceComparator;
033:
034: /**
035: * ResourceSelector that compares against "control" Resource(s)
036: * using ResourceComparators.
037: * @since Ant 1.7
038: */
039: public class Compare extends DataType implements ResourceSelector {
040:
041: private static final String ONE_CONTROL_MESSAGE = " the <control> element should be specified exactly once.";
042:
043: private DelegatedResourceComparator comp = new DelegatedResourceComparator();
044: private Quantifier against = Quantifier.ALL;
045:
046: private Comparison when = Comparison.EQUAL;
047:
048: private Union control;
049:
050: /**
051: * Add a ResourceComparator to this Compare selector.
052: * If multiple ResourceComparators are added, they will be processed in LIFO order.
053: * @param c the ResourceComparator to add.
054: */
055: public synchronized void add(ResourceComparator c) {
056: if (isReference()) {
057: throw noChildrenAllowed();
058: }
059: comp.add(c);
060: }
061:
062: /**
063: * Set the quantifier to be used. Default "all".
064: * @param against the Quantifier EnumeratedAttribute to use.
065: */
066: public synchronized void setAgainst(Quantifier against) {
067: if (isReference()) {
068: throw tooManyAttributes();
069: }
070: this .against = against;
071: }
072:
073: /**
074: * Set the comparison to be used. Default "equal".
075: * @param when the Comparison EnumeratedAttribute to use.
076: */
077: public synchronized void setWhen(Comparison when) {
078: if (isReference()) {
079: throw tooManyAttributes();
080: }
081: this .when = when;
082: }
083:
084: /**
085: * Create the nested control element. These are the
086: * resources to compare against.
087: * @return ResourceCollection.
088: */
089: public synchronized ResourceCollection createControl() {
090: if (isReference()) {
091: throw noChildrenAllowed();
092: }
093: if (control != null) {
094: throw oneControl();
095: }
096: control = new Union();
097: return control;
098: }
099:
100: //implement ResourceSelector; inherit doc
101: /** {@inheritDoc} */
102: public synchronized boolean isSelected(Resource r) {
103: if (isReference()) {
104: return ((ResourceSelector) getCheckedRef()).isSelected(r);
105: }
106: if (control == null) {
107: throw oneControl();
108: }
109: int t = 0, f = 0;
110: for (Iterator it = control.iterator(); it.hasNext();) {
111: if (when.evaluate(comp.compare(r, (Resource) it.next()))) {
112: t++;
113: } else {
114: f++;
115: }
116: }
117: return against.evaluate(t, f);
118: }
119:
120: /**
121: * Overrides the version from DataType
122: * to recurse on nested ResourceComparators.
123: * @param stk the stack of data types to use (recursively).
124: * @param p the project to use to dereference the references.
125: * @throws BuildException on error.
126: */
127: protected synchronized void dieOnCircularReference(Stack stk,
128: Project p) throws BuildException {
129: if (isChecked()) {
130: return;
131: }
132: if (isReference()) {
133: super .dieOnCircularReference(stk, p);
134: } else {
135: if (control != null) {
136: DataType.invokeCircularReferenceCheck(control, stk, p);
137: }
138: DataType.invokeCircularReferenceCheck(comp, stk, p);
139: setChecked(true);
140: }
141: }
142:
143: private BuildException oneControl() {
144: return new BuildException(super.toString()
145: + ONE_CONTROL_MESSAGE);
146: }
147: }
|