Initial OpenECOMP policy/engine commit
[policy/engine.git] / ECOMP-PDP / src / test / java / org / openecomp / policy / pdp / test / conformance / ConformancePIPEngine.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ECOMP-PDP
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.policy.pdp.test.conformance;
22
23 import java.io.BufferedReader;
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileNotFoundException;
27 import java.io.IOException;
28 import java.io.InputStreamReader;
29 import java.text.ParseException;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Properties;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41 import org.openecomp.policy.common.logging.flexlogger.FlexLogger; 
42 import org.openecomp.policy.common.logging.flexlogger.Logger;
43
44 import com.att.research.xacml.api.Attribute;
45 import com.att.research.xacml.api.AttributeValue;
46 import com.att.research.xacml.api.DataType;
47 import com.att.research.xacml.api.DataTypeException;
48 import com.att.research.xacml.api.DataTypeFactory;
49 import com.att.research.xacml.api.Identifier;
50 import com.att.research.xacml.api.pip.PIPException;
51 import com.att.research.xacml.api.pip.PIPFinder;
52 import com.att.research.xacml.api.pip.PIPRequest;
53 import com.att.research.xacml.api.pip.PIPResponse;
54 import com.att.research.xacml.std.IdentifierImpl;
55 import com.att.research.xacml.std.StdMutableAttribute;
56 import com.att.research.xacml.std.pip.StdPIPResponse;
57 import com.att.research.xacml.std.pip.engines.ConfigurableEngine;
58 import com.att.research.xacml.util.FactoryException; 
59
60 /**
61  * ConformancePIPEngine implements the {@link com.att.research.xacml.api.pip.PIPFinder} interface to find attributes
62  * loaded from a text file containing the following fields:
63  *      category-id,attribute-id,datatype-id,issuer,value
64  * 
65  * @version $Revision: 1.1 $
66  */
67 public class ConformancePIPEngine implements ConfigurableEngine {
68         public static final String PROP_DESCRIPTION     = ".description";
69         public static final String PROP_FILE            = ".file";
70         
71         private static final Logger logger      = FlexLogger.getLogger(ConformancePIPEngine.class);
72         
73         private String name;
74         private String description;
75         private Map<String,PIPResponse> cache   = new HashMap<String,PIPResponse>();
76         private List<Attribute> listAttributes  = new ArrayList<Attribute>();
77         private DataTypeFactory dataTypeFactory;
78         
79         public ConformancePIPEngine() {
80                 
81         }
82         
83         protected DataTypeFactory getDataTypeFactory() throws FactoryException {
84                 if (this.dataTypeFactory == null) {
85                         this.dataTypeFactory    = DataTypeFactory.newInstance();
86                 }
87                 return this.dataTypeFactory;
88         }
89         
90         protected static String generateKey(PIPRequest pipRequest) {
91                 StringBuilder stringBuilder     = new StringBuilder(pipRequest.getCategory().toString());
92                 stringBuilder.append('+');
93                 stringBuilder.append(pipRequest.getAttributeId().toString());
94                 stringBuilder.append('+');
95                 stringBuilder.append(pipRequest.getDataTypeId().toString());
96                 String issuer   = pipRequest.getIssuer();
97                 if (issuer != null) {
98                         stringBuilder.append('+');
99                         stringBuilder.append(issuer);
100                 }
101                 return stringBuilder.toString();
102         }
103         
104         protected void store(String[] fields) throws FactoryException {
105                 DataTypeFactory thisDataTypeFactory     = this.getDataTypeFactory();
106                 Identifier identifierCategory           = new IdentifierImpl(fields[0]);
107                 Identifier identifierAttribute          = new IdentifierImpl(fields[1]);
108                 Identifier identifierDataType           = new IdentifierImpl(fields[2]);
109                 String issuer                                           = (fields.length == 5 ? fields[3] : null);
110                 String value                                            = fields[fields.length - 1];
111                 
112                 DataType<?> dataType                            = thisDataTypeFactory.getDataType(identifierDataType);
113                 if (dataType == null) {
114                         logger.error("Unknown data type " + identifierDataType.stringValue());
115                         return;
116                 }
117                 
118                 AttributeValue<?> attributeValue        = null;
119                 try {
120                         attributeValue  = dataType.createAttributeValue(value);
121                 } catch (DataTypeException ex) {
122                         throw new FactoryException("DataTypeException creating AttributeValue", ex);
123                 }
124                 Attribute attribute                                     = new StdMutableAttribute(identifierCategory, identifierAttribute, attributeValue, issuer, false);
125                 this.listAttributes.add(attribute);
126         }
127         
128         public void loadAttributes(File fileAttributes) throws IOException, ParseException, FactoryException {
129                 if (fileAttributes != null) {
130                         if (!fileAttributes.exists()) {
131                                 throw new FileNotFoundException("Attributes file " + fileAttributes.getAbsolutePath() + " not found.");
132                         } else if (!fileAttributes.canRead()) {
133                                 throw new IOException("Attributes file " + fileAttributes.getAbsolutePath() + " is not readable.");
134                         }
135                         
136                         BufferedReader bufferedReader   = null;
137                         try {
138                                 bufferedReader  = new BufferedReader(new InputStreamReader(new FileInputStream(fileAttributes)));
139                                 String line;
140                                 while ((line = bufferedReader.readLine()) != null) {
141                                         if (line.length() > 0) {
142                                                 String[] fields = line.split("[|]",-1);
143                                                 if (fields.length < 4) {
144                                                         logger.warn("Not enough fields in record \"" + line + "\"");
145                                                         continue;
146                                                 }
147                                                 this.store(fields);
148                                                 
149                                         }
150                                 }
151                         } finally {
152                                 if (bufferedReader != null) {
153                                         bufferedReader.close();
154                                 }
155                         }
156                 }
157         }
158         
159         protected Attribute findAttribute(PIPRequest pipRequest) {
160                 Attribute attributeResult                       = null;
161                 Iterator<Attribute> iterAttributes      = this.listAttributes.iterator();
162                 while ((attributeResult == null) && iterAttributes.hasNext()) {
163                         Attribute attributeTest = iterAttributes.next();
164                         if (pipRequest.getCategory().equals(attributeTest.getCategory()) &&
165                                 pipRequest.getAttributeId().equals(attributeTest.getAttributeId()) &&
166                                 (pipRequest.getIssuer() == null || pipRequest.getIssuer().equals(attributeTest.getIssuer()))) {
167                                 attributeResult = attributeTest;
168                         }
169                 }
170                 return attributeResult;
171         }
172
173         @Override
174         public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException {
175                 String pipRequestKey    = generateKey(pipRequest);
176                 PIPResponse pipResponse = this.cache.get(pipRequestKey);
177                 if (pipResponse != null) {
178                         return pipResponse;
179                 }
180                 Attribute attributeMatch        = this.findAttribute(pipRequest);
181                 if (attributeMatch == null) {
182                         return StdPIPResponse.PIP_RESPONSE_EMPTY;
183                 }
184                 /*
185                  * Iterate through the values and only return the ones that match the requested data type
186                  */
187                 List<AttributeValue<?>> matchingValues  = new ArrayList<AttributeValue<?>>();
188                 Iterator<AttributeValue<?>> iterAttributeValues = attributeMatch.getValues().iterator();
189                 while (iterAttributeValues.hasNext()) {
190                         AttributeValue<?> attributeValue        = iterAttributeValues.next();
191                         if (pipRequest.getDataTypeId().equals(attributeValue.getDataTypeId())) {
192                                 matchingValues.add(attributeValue);
193                         }
194                 }
195                 if (matchingValues.size() > 0) {
196                         Attribute attributeResponse     = new StdMutableAttribute(attributeMatch.getCategory(), attributeMatch.getAttributeId(), matchingValues, attributeMatch.getIssuer(), false);
197                         pipResponse                                     = new StdPIPResponse(attributeResponse);
198                         this.cache.put(pipRequestKey, pipResponse);
199                 }
200                 return pipResponse;
201         }
202
203         @Override
204         public String getName() {
205                 return this.name;
206         }
207
208         @Override
209         public String getDescription() {
210                 return this.description;
211         }
212
213         @Override
214         public void configure(String id, Properties properties) throws PIPException {
215                 this.name       = id;
216                 this.description        = properties.getProperty(id + PROP_DESCRIPTION);
217                 if (this.description == null) {
218                         this.description        = "PIPEngine for the Conformance tests that loads attributes from a CSV file";
219                 }
220                 String pipFile          = properties.getProperty(id + PROP_FILE);
221                 if (pipFile != null) {
222                         try {
223                                 this.loadAttributes(new File(pipFile));
224                         } catch (Exception ex) {
225                                 logger.error("Exception loading PIP file " + pipFile, ex);
226                                 throw new PIPException("Exception loading PIP file " + pipFile, ex);
227                         }
228                 }
229         }
230
231         @Override
232         public Collection<PIPRequest> attributesRequired() {
233                 return Collections.emptyList();
234         }
235
236         @Override
237         public Collection<PIPRequest> attributesProvided() {
238                 //
239                 // We could return everything in our list
240                 //
241                 return Collections.emptyList();
242         }
243
244 }