blob: 80a9f930ccd040baa97e52b15740110dcc2d23d5 [file] [log] [blame]
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed 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.policy.model;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.policy.util.PolicyRegistry;
/**
* AndCompositeAssertion represents either policy or a single policy
* alternative. It requires that all its terms are satisfied.
*/
public class AndCompositeAssertion extends CompositeAssertion implements Assertion {
public AndCompositeAssertion() {
}
/**
* Adds an Assertion to its terms list
* @param assertion Assertion to be added
*/
public void addTerm(Assertion assertion) {
if (!(isNormalized() && (assertion instanceof PrimitiveAssertion))) {
setNormalize(false);
}
super.addTerm(assertion);
}
/**
* Returns the intersection of self and argument against a
* specified Policy Registry.
*
* @param assertion the assertion to intersect with self
* @param reg a sepcified policy registry
* @return assertion the assertion which is equivalent to
* intersection between self and the argument
*/
public Assertion intersect(Assertion assertion, PolicyRegistry reg) {
CompositeAssertion normalizedMe = (CompositeAssertion) ((isNormalized()) ? this : normalize(reg));
if (!(normalizedMe instanceof AndCompositeAssertion)) {
return normalizedMe.intersect(assertion, reg);
}
if (assertion instanceof PrimitiveAssertion) {
QName qname = ((PrimitiveAssertion) assertion).getName();
Iterator iterator = getTerms().iterator();
boolean isMatch = false;
while (iterator.hasNext()) {
PrimitiveAssertion primTerm = (PrimitiveAssertion) iterator.next();
if (primTerm.getName().equals(qname)) {
isMatch = true;
break;
}
}
return (isMatch) ? normalizedMe : new XorCompositeAssertion();
}
CompositeAssertion target = (CompositeAssertion) assertion;
target = (CompositeAssertion) ((target.isNormalized()) ? target : target.normalize(reg));
if (target instanceof Policy) {
XorCompositeAssertion alters = (XorCompositeAssertion) target.getTerms().get(0);
return normalizedMe.intersect(alters);
} else if (target instanceof XorCompositeAssertion) {
XorCompositeAssertion result = new XorCompositeAssertion();
Iterator iterator = target.getTerms().iterator();
while (iterator.hasNext()) {
AndCompositeAssertion andTerm = (AndCompositeAssertion) iterator.next();
Assertion value = normalizedMe.intersect(andTerm);
if (value instanceof AndCompositeAssertion) {
result.addTerm(value);
}
}
return result;
}
if (normalizedMe.isEmpty()) {
return target;
}
if (target.isEmpty()) {
return normalizedMe;
}
List primTermsA = ((size() > target.size()) ? normalizedMe.getTerms() : target.getTerms());
List primTermsB = ((size() > target.size()) ? target.getTerms() : normalizedMe.getTerms());
boolean isMatch = true;
PrimitiveAssertion primTermA, primTermB;
QName qnameA, qnameB;
for (int i = 0; i < primTermsA.size(); i++) {
primTermA = (PrimitiveAssertion) primTermsA.get(i);
qnameA = primTermA.getName();
boolean flag = false;
for (int j = 0; j < primTermsB.size(); j++) {
primTermB = (PrimitiveAssertion) primTermsB.get(j);
qnameB = primTermB.getName();
if (qnameA.equals(qnameB)) {
flag = true;
break;
}
}
if (!flag) {
isMatch = false;
break;
}
}
if (isMatch) { // vocabulary matches
AndCompositeAssertion result = new AndCompositeAssertion();
result.addTerms(primTermsA);
result.addTerms(primTermsB);
return result;
}
return new XorCompositeAssertion(); // no behaviour is admisible
}
/**
* Returns an assertion which is equivalent to merge of self and the
* argument.
*
* @param assertion the assertion to be merged with
* @param reg the policy registry which the is used resolve external policy
* references
* @return assertion the resultant assertion which is equivalent to merge
* of self and argument
*/
public Assertion merge(Assertion assertion, PolicyRegistry reg) {
CompositeAssertion normalizedMe = (CompositeAssertion) ((isNormalized()) ? this : normalize(reg));
if (!(normalizedMe instanceof AndCompositeAssertion)) {
return normalizedMe.merge(assertion, reg);
}
if (assertion instanceof PrimitiveAssertion) {
AndCompositeAssertion andTerm = new AndCompositeAssertion();
andTerm.addTerm(assertion);
andTerm.addTerms(normalizedMe.getTerms());
andTerm.setNormalize(true);
return andTerm;
}
CompositeAssertion target = (CompositeAssertion) assertion;
target = (CompositeAssertion) ((target.isNormalized()) ? target : target.normalize(reg));
if (target instanceof Policy) {
XorCompositeAssertion xorTerm = (XorCompositeAssertion) target.getTerms().get(0);
return normalizedMe.merge(xorTerm);
} else if (target instanceof XorCompositeAssertion) {
XorCompositeAssertion xorTerm = new XorCompositeAssertion();
Iterator hisAndTerms = target.getTerms().iterator();
while (hisAndTerms.hasNext()) {
AndCompositeAssertion hisAndTerm = (AndCompositeAssertion) hisAndTerms.next();
xorTerm.addTerm(normalizedMe.merge(hisAndTerm));
}
xorTerm.setNormalize(true);
return xorTerm;
} else if (target instanceof AndCompositeAssertion) {
AndCompositeAssertion andTerm = new AndCompositeAssertion();
andTerm.addTerms(normalizedMe.getTerms());
andTerm.addTerms(target.getTerms());
andTerm.setNormalize(true);
return andTerm;
}
throw new IllegalArgumentException("error : merge is not defined for"
+ assertion.getClass().getName());
}
/**
* Returns an Assertion which is normalized using a specified
* policy registry.
*
* @param reg the policy registry used to resolve policy
* references
* @return an Assertion which is the normalized form of
* self
*/
public Assertion normalize(PolicyRegistry reg) {
AndCompositeAssertion resultantAndTerm = new AndCompositeAssertion();
XorCompositeAssertion resultantXorTerm = new XorCompositeAssertion();
ArrayList childAndTermList = new ArrayList();
ArrayList childXorTermList = new ArrayList();
Iterator myTerms = getTerms().iterator();
while (myTerms.hasNext()) {
Object term = myTerms.next();
if (term instanceof PolicyReference) {
if (reg == null) {
throw new RuntimeException("PolicyCache is not defined");
}
PolicyReference policyRef = (PolicyReference) term;
Policy policy = reg.lookup(policyRef.getPolicyURIString());
if (policy == null) {
throw new RuntimeException("PolicyReference<" + policyRef.getPolicyURIString() + "can not be resolved");
}
AndCompositeAssertion andTerm = new AndCompositeAssertion();
andTerm.addTerms(policy.getTerms());
Assertion normalizedPolicyRef = andTerm.normalize(reg);
if (normalizedPolicyRef instanceof AndCompositeAssertion) {
childAndTermList.add(normalizedPolicyRef);
} else {
childXorTermList.add(normalizedPolicyRef);
}
} else if (term instanceof PrimitiveAssertion) {
resultantAndTerm.addTerm((Assertion) term);
} else if (term instanceof CompositeAssertion) {
CompositeAssertion cterm = (CompositeAssertion) term;
cterm =((cterm.isNormalized()) ? cterm :(CompositeAssertion) cterm.normalize(reg));
if (cterm instanceof AndCompositeAssertion) {
childAndTermList.add(cterm);
} else {
childXorTermList.add(cterm);
}
}
}
// processing child-AndCompositeAssertions
if (! childAndTermList.isEmpty()) {
Iterator ANDterms = childAndTermList.iterator();
while (ANDterms.hasNext()) {
CompositeAssertion ANDterm = (CompositeAssertion) ANDterms.next();
resultantAndTerm.addTerms(ANDterm.getTerms());
}
}
// processing child-XORCompositeAssertions
if (childXorTermList.size() > 1) {
outer : for (int i = 0; i < childXorTermList.size(); i++) {
inner : for (int j = i; j < childXorTermList.size(); j++) {
if (i != j) {
XorCompositeAssertion xorTermA = (XorCompositeAssertion) childXorTermList.get(i);
XorCompositeAssertion xorTermB = (XorCompositeAssertion) childXorTermList.get(j);
/*
* if xorTermA or xorTermB is empty then the result should be an
* a policy with zero alternatives
*/
if (xorTermA.isEmpty() || xorTermB.isEmpty()) {
resultantXorTerm = new XorCompositeAssertion();
break outer;
}
Iterator interatorA = xorTermA.getTerms().iterator();
while (interatorA.hasNext()) {
CompositeAssertion andTermA = (CompositeAssertion) interatorA.next();
Iterator iteratorB = xorTermB.getTerms().iterator();
while (iteratorB.hasNext()) {
CompositeAssertion andTermB = (CompositeAssertion) iteratorB.next();
AndCompositeAssertion andTerm = new AndCompositeAssertion();
andTerm.addTerms(andTermA.getTerms());
andTerm.addTerms(andTermB.getTerms());
resultantXorTerm.addTerm(andTerm);
}
}
}
}
}
} else if (childXorTermList.size() == 1) {
CompositeAssertion XORterm = (CompositeAssertion) childXorTermList.get(0);
resultantXorTerm.addTerms(XORterm.getTerms());
}
if (childXorTermList.isEmpty()) {
resultantAndTerm.setNormalize(true);
return resultantAndTerm;
}
if (resultantXorTerm.isEmpty()) {
if (resultantAndTerm.isEmpty()) {
resultantAndTerm.setNormalize(true);
return resultantAndTerm;
}
resultantXorTerm.setNormalize(true);
return resultantXorTerm;
}
// get list of primitive assertions form result (AndCompositeAssertion)
List primTerms = resultantAndTerm.getTerms();
// these terms should be AndCompositeAssertions
Iterator andTerms = resultantXorTerm.getTerms().iterator();
while (andTerms.hasNext()) {
CompositeAssertion andTerm = (CompositeAssertion) andTerms.next();
andTerm.addTerms(primTerms);
}
resultantXorTerm.setNormalize(true);
return resultantXorTerm;
}
}