/**
* Copyright (c) 2011, SOCIETIES Consortium (WATERFORD INSTITUTE OF TECHNOLOGY (TSSG), HERIOT-WATT UNIVERSITY (HWU), SOLUTA.NET
* (SN), GERMAN AEROSPACE CENTRE (Deutsches Zentrum fuer Luft- und Raumfahrt e.V.) (DLR), Zavod za varnostne tehnologije
* informacijske družbe in elektronsko poslovanje (SETCCE), INSTITUTE OF COMMUNICATION AND COMPUTER SYSTEMS (ICCS), LAKE
* COMMUNICATIONS (LAKE), INTEL PERFORMANCE LEARNING SOLUTIONS LTD (INTEL), PORTUGAL TELECOM INOVAÇÃO, SA (PTIN), IBM Corp.,
* INSTITUT TELECOM (ITSUD), AMITEC DIACHYTI EFYIA PLIROFORIKI KAI EPIKINONIES ETERIA PERIORISMENIS EFTHINIS (AMITEC), TELECOM
* ITALIA S.p.a.(TI), TRIALOG (TRIALOG), Stiftelsen SINTEF (SINTEF), NEC EUROPE LTD (NEC))
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.societies.privacytrust.privacyprotection.privacypreferencemanager.evaluation;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.societies.api.context.model.CtxIdentifier;
import org.societies.api.internal.privacytrust.trust.ITrustBroker;
import org.societies.api.privacytrust.privacy.model.PrivacyException;
import org.societies.api.privacytrust.trust.TrustException;
import org.societies.api.schema.privacytrust.privacy.model.privacypolicy.Condition;
import org.societies.api.schema.privacytrust.privacy.model.privacypolicy.RequestItem;
import org.societies.api.schema.privacytrust.privacy.model.privacypolicy.ResponseItem;
import org.societies.privacytrust.privacyprotection.api.model.privacypreference.ContextPreferenceCondition;
import org.societies.privacytrust.privacyprotection.api.model.privacypreference.IPrivacyOutcome;
import org.societies.privacytrust.privacyprotection.api.model.privacypreference.IPrivacyPreference;
import org.societies.privacytrust.privacyprotection.api.model.privacypreference.IPrivacyPreferenceCondition;
import org.societies.privacytrust.privacyprotection.api.model.privacypreference.PrivacyCondition;
import org.societies.privacytrust.privacyprotection.api.model.privacypreference.TrustPreferenceCondition;
import org.societies.privacytrust.privacyprotection.api.model.privacypreference.constants.OperatorConstants;
import org.societies.privacytrust.privacyprotection.api.model.privacypreference.ppn.PPNPOutcome;
import org.societies.privacytrust.privacyprotection.api.model.privacypreference.ppn.PPNPrivacyPreferenceTreeModel;
public class PreferenceEvaluator {
private PrivateContextCache contextCache;
private Logger logging = LoggerFactory.getLogger(this.getClass());
private ITrustBroker trustBroker;
private List<Condition> conditions;
public PreferenceEvaluator(PrivateContextCache cache, ITrustBroker broker){
this.contextCache = cache;
trustBroker = broker;
}
public Hashtable<IPrivacyOutcome,List<CtxIdentifier>> evaluatePreference(IPrivacyPreference ptn){
Hashtable<IPrivacyOutcome,List<CtxIdentifier>> temp = new Hashtable<IPrivacyOutcome,List<CtxIdentifier>>();
IPrivacyPreference p = this.evaluatePreferenceInternal(ptn);
if (p!=null){
ArrayList<CtxIdentifier> ctxIds = new ArrayList<CtxIdentifier>();
Object[] objs = p.getUserObjectPath();
for (Object obj : objs){
if (obj instanceof ContextPreferenceCondition){
ctxIds.add( ((ContextPreferenceCondition) obj).getCtxIdentifier());
}
}
/*IPreference[] prefs = (IPreference[]) p.getUserObjectPath();
for (int i = 0; i<prefs.length; i++){
if (null!=prefs[i].getUserObject()){
if (prefs[i].isBranch()){
IPreferenceCondition condition = prefs[i].getCondition();
ctxIds.add(condition.getCtxIdentifier());
}
}
}*/
temp.put(p.getOutcome(), ctxIds);
////JOptionPane.showMessageDiathis.logging.debug(null, "Evaluation: returning outcome: "+p.getOutcome().toString());
return temp;
}else{
return new Hashtable<IPrivacyOutcome,List<CtxIdentifier>>();
}
}
private IPrivacyPreference evaluatePreferenceInternal(IPrivacyPreference ptn){
this.logging.debug("evaluating preference");
//a non-context aware preference
if (ptn.isLeaf()){
this.logging.debug("preference is not context-dependent. returning IAction object"+ptn.getOutcome().toString());
//JOptionPane.showMessageDialog(null, "preference is not context-dependent. returning IAction object"+ptn.getOutcome().toString());
return ptn;
}
//if the root object is null then the tree is split so we have to evaluate more than one tree
if (ptn.getUserObject()==null){
this.logging.debug("preference tree is split. we might have a conflict");
//JOptionPane.showMessageDialog(null, "preference tree is split. we might have a conflict");
Enumeration<IPrivacyPreference> e = ptn.children();
ArrayList<IPrivacyPreference> prefList = new ArrayList<IPrivacyPreference>();
while (e.hasMoreElements()){
IPrivacyPreference p = e.nextElement();
IPrivacyPreference outcomePreference = this.evaluatePreferenceInternal(p);
if (outcomePreference!=null){
prefList.add(outcomePreference);
}
}
//if only one IOutcome is applicable with the current context return that
if (prefList.size()==1){
this.logging.debug("PrefEvaluator> Returning: "+ prefList.get(0).toString());
//JOptionPane.showMessageDialog(null, "split: PrefEvaluator> Returning: "+ prefList.get(0).toString());
return prefList.get(0);
}
//if no IOutcome is applicable, return a null object
else if (prefList.size()==0){
this.logging.debug("PrefEvaluator> No preference applicable");
//JOptionPane.showMessageDialog(null, "split: PrefEvaluator> No preference applicable");
return null;
}
//if more than one IOutcome objs is applicable, use conflict resolution and return the most applicable
else{
ConflictResolver cr = new ConflictResolver();
IPrivacyPreference io = cr.resolveConflicts(prefList);
//JOptionPane.showMessageDialog(null, "split PrefEvaluator> Returning: "+io.toString());
this.logging.debug("PrefEvaluator> Returning: "+io.toString());
return io;
}
}
//if the root node is not empty
else{
this.logging.debug("preference tree is not split. no conflicts here");
//JOptionPane.showMessageDialog(null, "preference tree is not split. no conflicts here");
//and it's a condition
if (ptn.isBranch()){
//evaluate the condition
IPrivacyPreferenceCondition con = ptn.getCondition();
try {
if (evaluatesToTrue(con)){
////JOptionPane.showMessageDiathis.logging.debug(null, con.toString()+" evaluated to true");
this.logging.debug(con.toString()+" is true - descending tree levels");
//JOptionPane.showMessageDialog(null, con.toString()+" is true - descending tree levels");
//traverse the tree in preorder traversal to evaluate all the conditions under this branch and find an Action
Enumeration<IPrivacyPreference> e = ptn.children();
while (e.hasMoreElements()){
IPrivacyPreference p = e.nextElement();
IPrivacyPreference outcomePreference = this.evaluatePreferenceInternal(p);
if(null != outcomePreference){
return outcomePreference;
}
}
}else{
////JOptionPane.showMessageDiathis.logging.debug(null, con.toString()+" evaluated to false");
this.logging.debug(con.toString()+" is false - returning");
//JOptionPane.showMessageDialog(null, con.toString()+" is false - returning");
}
} catch (PrivacyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//and it's not a condition but an Outcome (i.e. not a branch but a leaf)
else{
//JOptionPane.showMessageDialog(null, "PrefEvaluator> Returning: "+ptn.getOutcome());
this.logging.debug("PrefEvaluator> Returning: "+ptn.getOutcome());
return ptn;
}
}
return null;
}
public boolean evaluatesToTrue(IPrivacyPreferenceCondition cond)throws PrivacyException{
if (cond instanceof ContextPreferenceCondition){
ContextPreferenceCondition contextCond = (ContextPreferenceCondition) cond;
String currentContextValue = this.getValueFromContext(contextCond.getCtxIdentifier());
OperatorConstants operator = contextCond.getOperator();
this.logging.debug("evaluating cond: "+contextCond.toString()+" against current value: "+currentContextValue);
if (operator.equals(OperatorConstants.EQUALS)){
return currentContextValue.equalsIgnoreCase(contextCond.getValue());
}
else
return this.evaluateInt(parseString(contextCond.getValue()), parseString(currentContextValue), operator);
}else if (cond instanceof TrustPreferenceCondition){
TrustPreferenceCondition trustCond = (TrustPreferenceCondition) cond;
try {
Double trustValue = this.trustBroker.retrieveTrust(trustCond.getTrustId()).get();
if (trustValue.compareTo(trustCond.getTrustThreshold())>=0){
return true;
}else{
return false;
}
} catch (TrustException e) {
e.printStackTrace();
return false;
} catch (InterruptedException e) {
e.printStackTrace();
return false;
} catch (ExecutionException e) {
e.printStackTrace();
return false;
}
}else if (cond instanceof PrivacyCondition){
this.logging.debug("evaluating condition: "+cond.toString());
this.logging.debug("Conditions available from negotiation: "+conditions.size());
for (Condition condition : conditions){
if (((PrivacyCondition) cond).getCondition().getConditionConstant().equals(condition.getConditionConstant())){
this.logging.debug("Found same condition. "+cond.getType());
if (((PrivacyCondition) cond).getCondition().getValue().equals(condition.getValue())){
this.logging.debug("Conditions match. returning true");
return true;
}
}
}
return false;
}
else{
throw new PrivacyException("PM: Condition is not a Context condition");
}
}
public boolean evaluateInt(int valueInPreference, int valueInContext, OperatorConstants operator){
boolean result = false;
switch (operator){
case GREATER_OR_EQUAL_THAN:
result = valueInContext >= valueInPreference;
break;
case GREATER_THAN:
result = valueInContext > valueInPreference;
break;
case LESS_OR_EQUAL_THAN:
result = valueInContext <= valueInPreference;
break;
case LESS_THAN:
result = valueInContext < valueInPreference;
break;
default: this.logging.debug("Invalid Operator");
}
return result;
}
public String getValueFromContext(CtxIdentifier id){
if (id==null){
this.logging.debug("can't get context value from null id");
}
if (this.contextCache==null){
this.logging.debug("ContextCache is null. PrefEvaluator not initialised properly");
}
return this.contextCache.getContextValue(id);
}
public int parseString(String str){
try{
return Integer.parseInt(str);
}catch (NumberFormatException nbe){
this.logging.debug("Could not parse String to int");
return 0;
}
}
public HashMap<RequestItem, ResponseItem> evaluatePPNPreferences(
Hashtable<RequestItem, PPNPrivacyPreferenceTreeModel> modelsHashtable) {
Enumeration<RequestItem> items = modelsHashtable.keys();
HashMap<RequestItem, ResponseItem> toReturn = new HashMap<RequestItem, ResponseItem>();
//for every requestItem, a list of responseItems will be created
//for each action in the requestItem, there will be a ResponseItem
while(items.hasMoreElements()){
RequestItem item = items.nextElement();
//set the conditions from the request policy
this.conditions = item.getConditions();
//evaluate all the preferences for this request item
PPNPrivacyPreferenceTreeModel model = modelsHashtable.get(item);
Hashtable<IPrivacyOutcome, List<CtxIdentifier>> outList = this.evaluatePreference(model.getRootPreference());
//we actually don't care about the ctxIdentifiers in the case of ppn as there will be no proactive actions for these preferences
IPrivacyOutcome temp = outList.keys().nextElement(); //there's only one key
if (temp instanceof PPNPOutcome){
PPNPOutcome outcome = (PPNPOutcome) temp;
ResponseItem respItem = new ResponseItem();
respItem.setDecision(outcome.getDecision());
respItem.setRequestItem(item);
toReturn.put(item, respItem);
}
}
return toReturn;
}
public Hashtable<IPrivacyOutcome, List<CtxIdentifier>> evaluateAccessCtrlPreference(IPrivacyPreference pref, List<Condition> conditions) {
this.conditions = conditions;
return this.evaluatePreference(pref);
}
/* public static void main(String[] args){
ICtxBroker sbroker = new StubCtxBroker();
try {
ICtxEntity entity = sbroker.createEntity("Person");
if (entity==null){
this.logging.debug("entity is null");
}
ICtxEntityIdentifier entityID = entity.getCtxIdentifier();
ICtxAttribute symlocAttr = sbroker.createAttribute(entityID, CtxTypes.SYMBOLIC_LOCATION);
//ICtxEntityIdentifier entityID = new StubCtxEntityIdentifier("AliceSecret1234%5Bbe94bf83-1264-4f36-b339-53894b0a376f%5D,","ac3fdc679c58235326","person",1L);
//ICtxAttributeIdentifier symlocAttrID = new StubCtxAttributeIdentifier(entityID, CtxTypes.SYMBOLIC_LOCATION, 62L);
//ICtxAttribute symlocAttr = new StubCtxAttribute(symlocAttrID, entityID);
symlocAttr.setStringValue("home");
sbroker.update(symlocAttr);
IPreference condition1 = new PreferenceTreeNode(
new ContextPreferenceCondition(symlocAttr.getCtxIdentifier(), OperatorConstants.EQUALS, "home", CtxTypes.SYMBOLIC_LOCATION));
IPreference condition2 = new PreferenceTreeNode(
new ContextPreferenceCondition(symlocAttr.getCtxIdentifier(), OperatorConstants.EQUALS, "work", CtxTypes.SYMBOLIC_LOCATION));
//define outcomes
IPreference outcome1 = new PreferenceTreeNode(new PreferenceOutcome("volume", "100"));
IPreference outcome2 = new PreferenceTreeNode(new PreferenceOutcome("volume", "0"));
//build tree
IPreference preference = new PreferenceTreeNode();
preference.add(condition1); //branch 1
condition1.add(outcome1);
preference.add(condition2); //branch 2
condition2.add(outcome2);
PrivateContextCache cc = new PrivateContextCache(sbroker);
PreferenceEvaluator ev = new PreferenceEvaluator(cc);
Hashtable<IOutcome,List<CtxIdentifier>> result = ev.evaluatePreference(preference);
if (result!=null && (!result.isEmpty())){
this.logging.debug("got result. size: "+result.size());
Enumeration<IOutcome> outcomes = result.keys();
while (outcomes.hasMoreElements()){
IOutcome o = outcomes.nextElement();
this.logging.debug(o.toString());
}
}
} catch (ContextException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
}