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

com.att.research.xacml.std.pip.engines.csv.ConfigurableCSVResolver Maven / Gradle / Ivy

/*
 *                        AT&T - PROPRIETARY
 *          THIS FILE CONTAINS PROPRIETARY INFORMATION OF
 *        AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN
 *             ACCORDANCE WITH APPLICABLE AGREEMENTS.
 *
 *          Copyright (c) 2014 AT&T Knowledge Ventures
 *              Unpublished and Not for Publication
 *                     All Rights Reserved
 */
package com.att.research.xacml.std.pip.engines.csv;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.att.research.xacml.api.Attribute;
import com.att.research.xacml.api.AttributeValue;
import com.att.research.xacml.api.DataType;
import com.att.research.xacml.api.DataTypeException;
import com.att.research.xacml.api.DataTypeFactory;
import com.att.research.xacml.api.pip.PIPEngine;
import com.att.research.xacml.api.pip.PIPException;
import com.att.research.xacml.api.pip.PIPFinder;
import com.att.research.xacml.api.pip.PIPRequest;
import com.att.research.xacml.api.pip.PIPResponse;
import com.att.research.xacml.std.StdMutableAttribute;
import com.att.research.xacml.std.pip.StdPIPRequest;
import com.att.research.xacml.std.pip.StdPIPResponse;
import com.att.research.xacml.std.pip.engines.Configurables;
import com.att.research.xacml.util.FactoryException;
import com.google.common.base.Splitter;

public class ConfigurableCSVResolver implements CSVResolver {

	public static final String PROP_PARAMETERS		= "parameters";
	
	public static final String PROP_ID				= "id";
	public static final String PROP_DATATYPE		= "datatype";
	public static final String PROP_CATEGORY		= "category";
	public static final String PROP_ISSUER			= "issuer";

	public static final String PROP_COLUMN			= "column";

	private static DataTypeFactory dataTypeFactory		= null;
	
	static {
		try {
			dataTypeFactory	= DataTypeFactory.newInstance();
		}
		catch (FactoryException fx) {
			throw new RuntimeException(fx);
		}
	}
	
	protected Log logger	= LogFactory.getLog(this.getClass());

	private String id;
	private String defaultIssuer;
	
	private Map	parameterMap = new HashMap();
	private Map	fieldMap = new HashMap();	

	public ConfigurableCSVResolver() {

	}

	/**
	 * Helper to load the "parameters" that define the search criteria for the rows to find in the CSV file.
	 * 
	 * @param id
	 * @param properties
	 * @throws PIPException
	 */
	private void readSearchParameters(String id, Properties properties) throws PIPException {
		String parameterNamesString = properties.getProperty(id + "." + PROP_PARAMETERS);
		if (parameterNamesString == null || parameterNamesString.length() == 0) {
			String message = id + ".parameters must not be empty";
			logger.error(message);
			throw new PIPException(message);
		}
		for (String parameterName : Splitter.on(',').omitEmptyStrings().trimResults().split(parameterNamesString)) {
			String parameterIdPrefix = id + ".parameter." + parameterName;
			String tmpString = properties.getProperty(parameterIdPrefix + "." + PROP_COLUMN);
			if (tmpString == null || tmpString.length() == 0) {
				String message = id + ": parameter " + parameterName + " missing number for '.column'";
				logger.error(message);
				throw new PIPException(message);
			}
			int column;
			try {
				column = Integer.parseInt(tmpString);
			} catch (NumberFormatException e) {
				String message = id + ": parameter " + parameterName + ".column is not a number in '" + tmpString + "'";
				logger.error(message);
				throw new PIPException(message);
			}
			
			PIPRequest request = Configurables.getPIPRequest(parameterIdPrefix, properties, null);
			if (request != null) {
				this.parameterMap.put(column, request);
			} else {
				String message = id + ": attribute not defined";
				this.logger.error(message);
				throw new PIPException(message);
			}
		}
	}

	/**
	 * Helper - read the definitions of the fields that can be returned from this PIP
	 * 
	 * @param id
	 * @param properties
	 * @throws PIPException
	 */
	private void readPIPRequestFieldDefinitions(String id, Properties properties) throws PIPException {
		String fieldNamesString = properties.getProperty(id + ".fields");
		if (fieldNamesString == null || fieldNamesString.length() == 0) {
			String message = id + ".fields must not be empty";
			logger.error(message);
			throw new PIPException(message);
		}
		for (String fieldName : Splitter.on(',').trimResults().omitEmptyStrings().split(fieldNamesString)) {
			String fieldIdPrefix = id + ".field." + fieldName;
			String tmpString = properties.getProperty(fieldIdPrefix + "." + "column");
			if (tmpString == null || tmpString.length() == 0) {
				String message = id + ": field " + fieldName + " missing number for '.column'";
				logger.error(message);
				throw new PIPException(message);
			}
			int column;
			try {
				column = Integer.parseInt(tmpString);
			} catch (NumberFormatException e) {
				String message = id + ": field " + fieldName + ".column is not a number in '" + tmpString + "'";
				logger.error(message);
				throw new PIPException(message);
			}
		
			PIPRequest pipRequest = Configurables.getPIPRequest(fieldIdPrefix, properties, this.defaultIssuer);
			if (pipRequest != null) {
				this.fieldMap.put(column, pipRequest);
			} else {
				String message = id + ": attribute not defined column " + column;
				this.logger.error(message);
				throw new PIPException(message);
			}
		}
	}

	@Override
	public void configure(String id, Properties properties, String defaultIssuer) throws PIPException {
		//
		// Save our ID (i.e. name)
		//
		this.id = id;
		this.defaultIssuer = defaultIssuer;
		//
		// Get the "parameters", i.e. the fields to use for uniquely identifying a single row, from the properties
		//
		readSearchParameters(id, properties);
		//
		// Get the list of fields that the caller may ask for from a given row
		//
		readPIPRequestFieldDefinitions(id, properties);
	}

	@Override
	public void attributesRequired(Collection parameters) {
		for (Integer key : this.parameterMap.keySet()) {
			parameters.add(new StdPIPRequest(this.parameterMap.get(key)));
		}
	}

	@Override
	public void attributesProvided(Collection attributes) {
		for (Integer key : this.fieldMap.keySet()) {
			attributes.add(new StdPIPRequest(this.fieldMap.get(key)));
		}
	}

	@Override
	public boolean supportRequest(PIPRequest pipRequest) {
		for (Integer key : this.fieldMap.keySet()) {
			PIPRequest request = this.fieldMap.get(key);
			if (pipRequest == null) {
				return false;
			}
			if (request.equals(pipRequest)) {
				if (this.logger.isDebugEnabled()) {
					this.logger.debug(this.id + " supports " + pipRequest);
				}
				return true;
			}
		}
		if (this.logger.isDebugEnabled()) {
			this.logger.debug(this.id + " does NOT support " + pipRequest);
		}
		return false;
	}

	@Override
	public Map>>	getColumnParameterValues(PIPEngine engine, PIPRequest request, PIPFinder finder) throws PIPException {
		Map>> map = new HashMap>>();
		for (Integer column : this.parameterMap.keySet()) {
			PIPRequest requestParameter = this.parameterMap.get(column);
			//
			// Get the parameter attributes
			//
			PIPResponse pipResponse = finder.getMatchingAttributes(requestParameter, null);
			if (pipResponse == null || ! pipResponse.getStatus().isOk() || pipResponse == StdPIPResponse.PIP_RESPONSE_EMPTY) {
				//
				// We must have at least one attribute value. If none exist, then return null
				//
				return null;
			}
			//
			// Accumulate the values
			//
			List> values = new ArrayList>();
			for (Attribute attr : pipResponse.getAttributes()) {
				values.addAll(attr.getValues());
			}
			//
			// Add it to our map
			//
			map.put(column, values);
		}
		return map;
	}

	@Override
	public List decodeResult(String[] line) throws PIPException {
		//
		// Return all the fields
		//
		List attributeList = new ArrayList();
		for (Integer column : this.fieldMap.keySet()) {
			//
			// Sanity check, we should have the required number of columns
			//
			if (column >= line.length) {
				return null;
			}
			//
			// Does it have a value?
			//
			String value = line[column];
			if (value.length() == 0) {
				if (this.logger.isDebugEnabled()) {
					this.logger.debug("Column " + column + " does not have a value.");
				}
				continue;
			}
			//
			// Convert it to appropriate data type
			//
			PIPRequest request = this.fieldMap.get(column);
			//
			// Does the attribute already exist?
			//
			StdMutableAttribute attribute = null;
			for (Attribute a : attributeList) {
				if (a.getCategory() == request.getCategory() && a.getAttributeId() == request.getAttributeId()) {
					attribute = (StdMutableAttribute) a;
				}
			}
			if (attribute == null) {
				attribute = new StdMutableAttribute();
				attribute.setCategory(request.getCategory());
				attribute.setAttributeId(request.getAttributeId());
				attribute.setIssuer(request.getIssuer());
				attributeList.add(attribute);
			}
			//
			// Add it in
			//
			DataType dt = dataTypeFactory.getDataType(request.getDataTypeId());
			try {
				attribute.addValue(dt.createAttributeValue(value));
			} catch (DataTypeException e) {
				String message = this.id + ": " + e.getLocalizedMessage();
				this.logger.error(message);
				return null;
			}
		}
		return attributeList;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy