All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xacml4j.v30.Entity Maven / Gradle / Ivy

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.util.Collection;
import java.util.LinkedList;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import org.xacml4j.util.DOMUtil;
import org.xacml4j.v30.pdp.XPathEvaluationException;
import org.xacml4j.v30.spi.xpath.XPathProvider;
import org.xacml4j.v30.types.TypeToString;
import org.xacml4j.v30.types.XPathExp;
import org.xacml4j.v30.types.XacmlTypes;

import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;

/**
 * An entity represents a collection of related attributes
 *
 * @author Giedrius Trumpickas
 */
public final class Entity extends AttributeContainer
{
	private final static String CONTENT_SELECTOR = "urn:oasis:names:tc:xacml:3.0:content-selector";

	private final static Logger log = LoggerFactory.getLogger(Entity.class);

	private final Document content;

	private Entity(Builder b) {
		super(b);
		this.content = DOMUtil.copyNode(b.content);
	}

	public static Builder builder(){
		return new Builder();
	}

	/**
	 * Gets entity with all include
	 * in result attributes
	 * @return {@link Entity} with all include in result attributes
	 */
	public Entity getIncludeInResult(){
		return Entity
		.builder()
		.copyOf(this, new Predicate() {
			public boolean apply(Attribute a){
				return a.isIncludeInResult();
			}
		}).build();
	}

	/**
	 * Gets content as {@link Node}
	 * instance
	 *
	 * @return a {@link Node} instance or {@code null}
	 */
	public Node getContent(){
		return content;
	}

	/**
	 * Tests if this entity has content
	 *
	 * @return {@code true} if entity has content; returns {@code false} otherwise
	 */
	public boolean hasContent(){
		return content != null;
	}

	public BagOfAttributeExp getAttributeValues(
			String xpath,
			XPathProvider xpathProvider,
			AttributeExpType type,
			String contextSelectorId)
					throws XPathEvaluationException
	{
		try
		{
			Node contextNode = content;
			Collection v = getAttributeValues(
						(contextSelectorId == null?CONTENT_SELECTOR:contextSelectorId),
								XacmlTypes.XPATH);
			if(v.size() > 1){
				throw new XPathEvaluationException(xpath,
						Status.syntaxError().build(),
						"Found more than one value of=\"%s\"",
						contextSelectorId);
			}
			if(v.size() == 1){
				XPathExp xpathAttr = (XPathExp)v.iterator().next();
				if(log.isDebugEnabled()){
					log.debug("Evaluating " +
							"contextSelector xpath=\"{}\"", xpathAttr.getValue());
				}
				contextNode = xpathProvider.evaluateToNode(xpathAttr.getPath(), content);
			}
			NodeList nodeSet = xpathProvider.evaluateToNodeSet(xpath, contextNode);
			if(nodeSet == null ||
					nodeSet.getLength() == 0){
				return type.bagType().createEmpty();
			}
			if(log.isDebugEnabled()){
				log.debug("Found=\"{}\" nodes via xpath=\"{}\"",
						new Object[]{nodeSet.getLength(), xpath});
			}
			return toBag(xpath, type, nodeSet);
		}
		catch(EvaluationException e){
			if(log.isDebugEnabled()){
				log.debug(e.getMessage(), e);
			}
			throw e;
		}
		catch(Exception e){
			if(log.isDebugEnabled()){
				log.debug(e.getMessage(), e);
			}
			throw new XPathEvaluationException(xpath, e, e.getMessage());
		}
	}

	/**
	 * Converts a given node list to the {@link BagOfAttributeExp}
	 *
	 * @param xpath XPath for nodes
	 * @param type attribute type
	 * @param nodeSet a node set
	 * @return {@link BagOfAttributeExp}
	 * @throws EvaluationException
	 */
	private BagOfAttributeExp toBag(String xpath,
			AttributeExpType type, NodeList nodeSet)
		throws XPathEvaluationException
	{
		Collection values = new LinkedList();
		for(int i = 0; i< nodeSet.getLength(); i++)
		{
			Node n = nodeSet.item(i);
			String v = null;
			switch(n.getNodeType()){
				case Node.TEXT_NODE:
					v = ((Text)n).getData();
					break;
				case Node.PROCESSING_INSTRUCTION_NODE:
					v = ((ProcessingInstruction)n).getData();
					break;
				case Node.ATTRIBUTE_NODE:
					v = ((Attr)n).getValue();
					break;
				case Node.COMMENT_NODE:
					v = ((Comment)n).getData();
					break;
				default:
					throw new XPathEvaluationException(
							xpath,
							Status.syntaxError().build(),
							"Unsupported DOM node type=\"%d\"",
							n.getNodeType());
			}
			try
			{
				Optional toString = TypeToString.Types.getIndex().get(type);
				if(!toString.isPresent()){
					throw new XPathEvaluationException(
							xpath,
							Status.syntaxError().build(),
							"Unsupported XACML type=\"%d\"",
							type.getDataTypeId());
				}
				AttributeExp value = toString.get().fromString(v);
				if(log.isDebugEnabled()){
					log.debug("Node of type=\"{}\" converted attribute=\"{}\"",
							n.getNodeType(), value);
				}
				values.add(value);
			}catch(EvaluationException e){
				throw e;
			}catch(Exception e){
				throw new XPathEvaluationException(xpath,
						Status.processingError().build(),
						e, e.getMessage());
			}
		}
	  	return type.bagType().create(values);
	}



	public BagOfAttributeExp getAttributeValues(String attributeId, AttributeExpType type, String issuer){
		Collection values = getAttributeValues(attributeId, issuer, type);
		return type.bagOf(values);
	}

	@Override
	public String toString(){
		return Objects.toStringHelper(this)
		.add("attributes", attributes)
		.add("content", (content != null)?DOMUtil.toString(content.getDocumentElement()):content)
		.toString();
	}

	@Override
	public int hashCode(){
		return Objects.hashCode(attributes, content);
	}

	@Override
	public boolean equals(Object o) {
		if (o == this) {
			return true;
		}
		if (!(o instanceof Entity)) {
			return false;
		}
		Entity a = (Entity) o;
		return Objects.equal(attributes, a.attributes) &&
				DOMUtil.isEqual(content, a.content);
	}

	public static class Builder
		extends AttributeContainer.Builder
	{
		private Node content;

		public Builder content(Node node) {
			this.content = DOMUtil.copyNode(node);
			return this;
		}

		public Builder copyOf(Entity a){
			return copyOf(a, Predicates.alwaysTrue());
		}

		public Builder copyOf(Entity a,
				Predicate f){
			Preconditions.checkNotNull(a);
			content(a.getContent());
			attributes(Collections2.filter(a.getAttributes(), f));
			return this;
		}

		@Override
		protected Builder getThis() {
			return this;
		}

		public Entity build(){
			return new Entity(this);
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy