
org.xacml4j.v30.BagOfAttributeExp Maven / Gradle / Ivy
The newest version!
package org.xacml4j.v30;
/*
* #%L
* Xacml4J Core Engine Implementation
* %%
* Copyright (C) 2009 - 2014 Xacml4J.org
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.io.Serializable;
import java.util.HashSet;
import java.util.NoSuchElementException;
import java.util.Set;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMultiset;
import com.google.common.collect.Multiset;
/**
* XACML defines implicit collections of its data-types.
* XACML refers to a collection of values that are of a single data-type as a bag.
* Bags of data-types are needed because selections of nodes from an XML resource
* or XACML request context may return more than one value.
*
* The values in a bag are not ordered, and some of the values may be duplicates.
* There SHALL be no notion of a bag containing bags, or a bag containing values
* of differing types. I.e. a bag in XACML SHALL contain only values that
* are of the same data-type.
*
* @author Giedrius Trumpickas
*/
public final class BagOfAttributeExp
implements ValueExpression, Serializable
{
private static final long serialVersionUID = -8197446176793438616L;
private final BagOfAttributeExpType type;
private final Multiset values;
private final int hashCode;
/**
* Constructs bag of attributes.
*
* @param type a bag attribute type
* @param attributes a collection of attributes
*/
BagOfAttributeExp(BagOfAttributeExpType type,
Iterable attributes){
for (AttributeExp attr : attributes) {
assertExpressionType(attr, type);
}
this.type = type;
this.values = ImmutableMultiset.copyOf(attributes);
this.hashCode = Objects.hashCode(type, values);
}
private BagOfAttributeExp(Builder b){
this.type = b.bagType;
this.values = b.valuesBuilder.build();
this.hashCode = Objects.hashCode(type, values);
}
@SuppressWarnings("unchecked")
public Iterable values() {
return (Iterable)values;
}
/**
* Gets bag value data type
*
* @return {@link AttributeExpType}
*/
public AttributeExpType getDataType(){
return type.getDataType();
}
@Override
public ValueType getEvaluatesTo() {
return type;
}
/**
* Gets first attribute value
* in this bag
*
* @return first {@link AttributeExp}
* instance in this bag
* @exception NoSuchElementException if bag is empty
*/
public T value(){
return this.values().iterator().next();
}
/**
* Gets number of {@link AttributeExp}
* instances in this bag
*
* @return number of attributes
* in this bag
*/
public int size() {
return values.size();
}
/**
* Tests if this bag is empty.
*
* @return {@code true} if bag is empty
*/
public boolean isEmpty(){
return values.isEmpty();
}
/**
* Tests if this bag contains given attribute.
*
* @param attr an attribute
* @return {@code true} if bag contains given attribute
*/
public boolean contains(AttributeExp attr){
return values.contains(attr);
}
/**
* Returns the number of elements in this bag equal
* to the specified attribute value.
*
* @param value an attribute value
* @return a number of elements equal to the
* specified value
*/
public int count(AttributeExp value){
return values.count(value);
}
/**
* Returns a bag of such that it contains all elements of
* all the argument bags all duplicate elements are removed
*
* @param bag an another bag
* @return union of this and given bag without duplicate
* elements
*/
public BagOfAttributeExp union(BagOfAttributeExp bag)
{
Preconditions.checkArgument(type.equals(bag.type));
Set union = new HashSet();
union.addAll(bag.values);
union.addAll(values);
return type.create(union);
}
/**
* Returns a bag of values such that it contains only
* elements that are common between this and given bag
*
* @param bag an another bag
* @return bag which contains common
* elements between this and given bag
*/
public BagOfAttributeExp intersection(BagOfAttributeExp bag)
{
Preconditions.checkArgument(type.equals(bag.type));
Set intersection = new HashSet();
for(AttributeExp attr : values){
if(bag.values.contains(attr)){
intersection.add(attr);
}
}
return type.create(intersection);
}
/**
* Tests if this bag contains at least on value
* from the given bag
*
* @param bag a bag
* @return {@code true} if this bag contains
* at least one value from the given bag
*/
public boolean containsAtLeastOneOf(BagOfAttributeExp bag)
{
for(AttributeExp v : bag.values){
if(values.contains(v)){
return true;
}
}
return false;
}
@Override
public BagOfAttributeExp evaluate(EvaluationContext context)
throws EvaluationException {
return this;
}
@Override
public ValueType getType() {
return type;
}
/**
* Tests if this bag is subset of given bag.
*
* @param bag a bag
* @return {@code true} if given bag
* is subset if this bag
*/
public boolean containsAll(BagOfAttributeExp bag){
Preconditions.checkArgument(type.equals(bag.type));
return values.containsAll(bag.values);
}
@Override
public boolean equals(Object o){
if(o == this){
return true;
}
if(!(o instanceof BagOfAttributeExp)){
return false;
}
BagOfAttributeExp bag = (BagOfAttributeExp)o;
return type.equals(bag.type) &&
values.equals(bag.values);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this).
add("DataType", type.getDataType()).
add("Values", values).toString();
}
@Override
public int hashCode(){
return hashCode;
}
/**
* A static helper method to retrieve a single
* value from a given bag
*
* @param attribute expression type
* @param v a bag of values
* @return a single value or {@code null}
* if a given bag is {@code null} or empty
*/
public static T value(BagOfAttributeExp v){
if(v == null ||
v.isEmpty()){
return null;
}
return v.value();
}
@Override
public void accept(ExpressionVisitor expv) {
BagOfAttributeVisitor v = (BagOfAttributeVisitor)expv;
v.visitEnter(this);
v.visitLeave(this);
}
public interface BagOfAttributeVisitor extends ExpressionVisitor
{
void visitEnter(BagOfAttributeExp v);
void visitLeave(BagOfAttributeExp v);
}
private static void assertExpressionType(AttributeExp value, BagOfAttributeExpType bagType) {
if (!value.getType().equals(bagType.getDataType())) {
throw new IllegalArgumentException(String.format(
"Given attribute value=\"%s\" " +
"can't be used as a value of bag=\"%s\"", value, bagType));
}
}
public static class Builder
{
private BagOfAttributeExpType bagType;
private ImmutableMultiset.Builder valuesBuilder = ImmutableMultiset.builder();
public Builder(AttributeExpType type){
this.bagType = new BagOfAttributeExpType(type);
}
public Builder attribute(AttributeExp ...values){
for(AttributeExp v : values){
assertExpressionType(v, bagType);
this.valuesBuilder.add(v);
}
return this;
}
public Builder value(Object ...values){
for(Object v : values){
this.valuesBuilder.add(bagType.getDataType().of(v));
}
return this;
}
public Builder values(Iterable
© 2015 - 2025 Weber Informatics LLC | Privacy Policy