//* Licensed Materials - Property of *
//* IBM *
//* Alexandra Instituttet A/S *
//* *
//* eu.abc4trust.pabce.1.34 *
//* *
//* (C) Copyright IBM Corp. 2014. All Rights Reserved. *
//* (C) Copyright Alexandra Instituttet A/S, Denmark. 2014. All *
//* Rights Reserved. *
//* US Government Users Restricted Rights - Use, duplication or *
//* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. *
//* *
//* This file is licensed under the Apache License, Version 2.0 (the *
//* "License"); you may not use this file except in compliance with *
//* the License. You may obtain a copy of the License at: *
//* http://www.apache.org/licenses/LICENSE-2.0 *
//* Unless required by applicable law or agreed to in writing, *
//* software distributed under the License is distributed on an *
//* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
//* KIND, either express or implied. See the License for the *
//* specific language governing permissions and limitations *
//* under the License. *
//*/**/****************************************************************
package eu.abc4trust.util;
import java.net.URI;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.datatype.XMLGregorianCalendar;
import eu.abc4trust.returnTypes.ui.RevealedAttributeValue;
import eu.abc4trust.returnTypes.ui.RevealedFact;
import eu.abc4trust.returnTypes.ui.RevealedFactsAndAttributeValues;
import eu.abc4trust.util.Constants.OperationType;
import eu.abc4trust.util.attributeTypes.MyAttributeValue;
import eu.abc4trust.util.attributeTypes.MyAttributeValueDate;
import eu.abc4trust.util.attributeTypes.MyAttributeValueDateTime;
import eu.abc4trust.xml.CredentialInToken;
import eu.abc4trust.xml.CredentialSpecification;
import eu.abc4trust.xml.FriendlyDescription;
import eu.abc4trust.xml.ObjectFactory;
import eu.abc4trust.xml.PresentationTokenDescription;
import eu.abc4trust.xml.IssuerParameters;
public class RevealedAttrsAndFactsdDescrGenerator {
public static RevealedFactsAndAttributeValues generateFriendlyDesciptions(PresentationTokenDescription ptd,
Map<URI,CredentialSpecification> credSpecs){
PolicyTranslator pt = new PolicyTranslator(ptd, getAliasCredSpecList(ptd,credSpecs));
RevealedFactsAndAttributeValues ret = composeFriendlyDescOfRevealedFactsAndAttributeValues(pt, null);
return ret;
}
public static RevealedFactsAndAttributeValues generateFriendlyDesciptions(PresentationTokenDescription ptd,
Map<URI,CredentialSpecification> credSpecs, Map<URI,IssuerParameters> isParams){
PolicyTranslator pt = new PolicyTranslator(ptd, getAliasCredSpecList(ptd,credSpecs));
RevealedFactsAndAttributeValues ret = composeFriendlyDescOfRevealedFactsAndAttributeValues(pt, getAliasIssParamsList(ptd, isParams));
return ret;
}
private static RevealedFactsAndAttributeValues composeFriendlyDescOfRevealedFactsAndAttributeValues(
PolicyTranslator policyTranslator, Map<String,IssuerParameters> isParams) {
//Compose the return value
RevealedFactsAndAttributeValues ret = new RevealedFactsAndAttributeValues();
//Get info that we need from the Policy translator
Map<MyAttributeReference,List<FriendlyDescription>> attrFriendlyDescr = policyTranslator.getAttrRefFriedlyDescrList();
Map<String,List<FriendlyDescription>> credFriendlyDescr = policyTranslator.getCredAliasFriedlyDescrList();
Map<MyAttributeReference,MyAttributeValue> allDisclosedAttrsAndValues = policyTranslator.getAllDisclosedAttributesAndValues();
//get mypredicates
List<MyPredicate> myPredicates = policyTranslator.getAllPredicates();
//Create revealed attribute values descriptions:
for (MyAttributeReference mar: allDisclosedAttrsAndValues.keySet()){
RevealedAttributeValue attValue = new RevealedAttributeValue();
//get friendly name of the credential
List<FriendlyDescription> credFriendly = credFriendlyDescr.get(mar.getCredentialAlias());
//get friendly name of the attribute
List<FriendlyDescription> attrFriendly = attrFriendlyDescr.get(mar);
//get the attribute value
MyAttributeValue atValue = allDisclosedAttrsAndValues.get(mar);
attValue.descriptions = composeFriendlyAttributeValue(credFriendly, attrFriendly, atValue);
//add to the return value
ret.revealedAttributeValues.add(attValue);
}
//Create revealed facts descriptions:
for (MyPredicate mp: myPredicates){
RevealedFact revFact = composeFriendlyFact(mp, credFriendlyDescr, attrFriendlyDescr, isParams);
if (revFact!=null) {
ret.revealedFacts.add(revFact);
}
}
return ret;
}
private static RevealedFact composeFriendlyFact(MyPredicate mp, Map<String,List<FriendlyDescription>> credFriendlyDescr, Map<MyAttributeReference,List<FriendlyDescription>> attrFriendlyDescr, Map<String,IssuerParameters> issParams){
ObjectFactory of = new ObjectFactory();
RevealedFact ret = new RevealedFact();
String constant = new String(""); //$NON-NLS-1$
MyAttributeReference attribute = null;
GregorianCalendar date = new GregorianCalendar();
Map<String,FriendlyDescription> attrLangDescMap = new HashMap<String,FriendlyDescription>();
Map<String,FriendlyDescription> credLangDescMap = new HashMap<String,FriendlyDescription>();
Map<String,FriendlyDescription> issLangDescMap = new HashMap<String,FriendlyDescription>();
if (!mp.getFunction().equals(OperationType.EQUALONEOF)){
if (mp.getLeftRef().isConstant()){
if (mp.getTypeOfArguments().equals(Constants.DATE_TYPE)){
date = getDateValue(mp.getLeftVal());
constant = getFriendlyDate(mp.getLeftVal());
} else if (mp.getTypeOfArguments().equalsIgnoreCase(Constants.DATETIME_TYPE)){
constant = getFriendlyDateTime(mp.getLeftVal());
date = getDateTimeValue(mp.getLeftVal());
} else {
constant = mp.getLeftVal().toString();
}
} else {
attribute = mp.getLeftRef();
}
if (mp.getRightRef().isConstant()){
if (mp.getTypeOfArguments().equals(Constants.DATE_TYPE)){
constant = getFriendlyDate(mp.getRightVal());
date = getDateValue(mp.getRightVal());
} else if (mp.getTypeOfArguments().equalsIgnoreCase(Constants.DATETIME_TYPE)){
constant = getFriendlyDateTime(mp.getRightVal());
date = getDateTimeValue(mp.getRightVal());
} else {
constant = mp.getRightVal().toString();
}
} else {
attribute = mp.getRightRef();
}
} else {
// treat ONE-OF
for (Map<MyAttributeReference,MyAttributeValue> atRefAndValue: mp.getArguments()){
for (MyAttributeReference mar: atRefAndValue.keySet()){
if (mar.isConstant()){
constant = constant+ atRefAndValue.get(mar).toString()+", "; //$NON-NLS-1$
} else {
attribute = mar;
}
}
}
//remove last ","
constant = constant.substring(0, constant.length() - 2);
}
if (attribute==null){
//this means that the attribute was disclosed either implicitly or through EQUAL/EQUAL-ONE-OF predicate -
// it will appear in revealed attributes
return null;
} else {
//get friendly name of the credential or create an empty one
List<FriendlyDescription> credFriendly = credFriendlyDescr.get(attribute.getCredentialAlias());
//if issuer params are not null - we will add them to the fact string
List<FriendlyDescription> issFriendly = new ArrayList<FriendlyDescription>();
if (issParams!=null){
issFriendly = issParams.get(attribute.getCredentialAlias()).getFriendlyIssuerDescription();
for (FriendlyDescription issFrDescription: issFriendly) {
issLangDescMap.put(issFrDescription.getLang(), issFrDescription);
}
}
if ((credFriendly == null)||(credFriendly.isEmpty())){
FriendlyDescription credFrDescription = createEmptyFriendlyDescription();
credLangDescMap.put(credFrDescription.getLang(), credFrDescription);
} else {
for (FriendlyDescription credFrDescription: credFriendly) {
credLangDescMap.put(credFrDescription.getLang(), credFrDescription);
}
}
//get friendly name of the attribute or create an empty one
List<FriendlyDescription> attrFriendly = attrFriendlyDescr.get(attribute);
if ((attrFriendly == null)||(attrFriendly.isEmpty())){
FriendlyDescription attrFrDescription = createEmptyFriendlyDescription();
attrLangDescMap.put(attrFrDescription.getLang(), attrFrDescription);
} else {
for (FriendlyDescription attrFrDescription: attrFriendly){
attrLangDescMap.put(attrFrDescription.getLang(), attrFrDescription);
}
}
for (String lang:attrLangDescMap.keySet()){
FriendlyDescription frednlyDescription = of.createFriendlyDescription();
//COMPOSE THE RETURN STRING:
StringBuilder sb = new StringBuilder();
//check for predefined predicates
sb = handlePredefinedPredicates(attribute, constant, date, mp, credLangDescMap, issLangDescMap, lang);
if (sb.toString().equals("")) {
sb.append(translateTheValueOfLang(lang) +" ");
sb.append(attrLangDescMap.get(lang).getValue()+ " ");
sb.append(translateFromToLang(lang)+" ");
if (credLangDescMap.get(lang)!=null){
sb.append(credLangDescMap.get(lang).getValue());
} else {
sb.append(Messages.getString(Messages.NO_FRIENDLY_DESCRIPTION,lang)); //$NON-NLS-1$
}
try {
sb.append(" "+getFriendlyFunction(mp.getFunction(), lang, mp.getTypeOfArguments())+" ");
} catch (Exception e) {
sb.append(Messages.NO_FRIENDLY_DESCRIPTION); //$NON-NLS-1$
}
sb.append(constant);
}
frednlyDescription.setLang(lang);
frednlyDescription.setValue(sb.toString());
ret.descriptions.add(frednlyDescription);
}
}
return ret;
}
private static StringBuilder handlePredefinedPredicates(MyAttributeReference attribute, String constant, GregorianCalendar date, MyPredicate mp, Map<String,FriendlyDescription> credLangDescMap, Map<String,FriendlyDescription> issLangDescMap, String lang)
{
StringBuilder sb = new StringBuilder();
if (attribute.getAttributeType().equals(Messages.BIRTHDATE)){
if (date!=null){
GregorianCalendar today = (GregorianCalendar) GregorianCalendar.getInstance();
long diff = (removeTime(today).getTime() - removeTime(date).getTime());
long inYears = 1000L * 60 * 60 * 24 * 365;
long age = diff/inYears;
sb.append(Messages.getString(Messages.YOU_ARE_OLDER, lang) + " "); //$NON-NLS-1$
sb.append(age + " ");
if (credLangDescMap.get(lang)!=null){
sb.append(Messages.getString(Messages.USING, lang) + " " + credLangDescMap.get(lang).getValue());
} else {
sb.append(Messages.getString(Messages.NO_FRIENDLY_DESCRIPTION,lang)); //$NON-NLS-1$
}
if (issLangDescMap.get(lang)!=null)
sb.append(" " + Messages.getString(Messages.FROM, lang) + " " + issLangDescMap.get(lang).getValue()); //$NON-NLS-1$
}
return sb;
} else
if (attribute.getAttributeType().equals(Messages.EXPIRESINMINUTES)){
// if (date!=null){
// GregorianCalendar today = (GregorianCalendar) GregorianCalendar.getInstance();
// long diff = removeMilliseconds(date).getTime() - removeMilliseconds(today).getTime();
// long inMinutes = 1000 * 60;
// long expInMinutes = diff/inMinutes;
if (credLangDescMap.get(lang)!=null)
sb.append(Messages.getString(Messages.YOUR, lang) + " " + credLangDescMap.get(lang).getValue());
else
sb.append(Messages.getString(Messages.YOUR, lang) + " " + credLangDescMap.get(lang).getValue());
if ((issLangDescMap!=null)&&(issLangDescMap.get(lang)!=null))
sb.append( " " + Messages.getString(Messages.FROM, lang) + " " + issLangDescMap.get(lang).getValue());
sb.append(" " + Messages.getString(Messages.IS_VALID, lang)); //$NON-NLS-1$
// }
return sb;
//} else if (attribute.getAttributeType().equals(Messages.EXPIRESINHOURS)){
// if (date!=null){
// GregorianCalendar today = (GregorianCalendar) GregorianCalendar.getInstance();
// long diff = removeMilliseconds(date).getTime() - removeMilliseconds(today).getTime();
// long inHours = 1000 * 60 * 60;
// long expInHours = diff/inHours;
// if (credLangDescMap.get(lang)!=null){
// sb.append(Messages.getString(Messages.YOUR, lang) + " " + credLangDescMap.get(lang).getValue() + " " + Messages.getString(Messages.EXPIRES, lang) + " " + expInHours + " " + Messages.getString(Messages.HOURS, lang));
// } else {
// sb.append(Messages.getString(Messages.YOUR, lang) + " " + Messages.getString(Messages.NO_FRIENDLY_DESCRIPTION,lang) + " " + Messages.getString(Messages.EXPIRES, lang) + " " + expInHours + " " + Messages.getString(Messages.HOURS, lang)); //$NON-NLS-1$
//
// }
// }
// return sb;
} else return sb; //TODO
}
private static List<FriendlyDescription> composeFriendlyAttributeValue(List<FriendlyDescription> credentialName, List<FriendlyDescription> attributeName, MyAttributeValue attributeValue){
ObjectFactory of = new ObjectFactory();
List<FriendlyDescription> ret = new ArrayList<FriendlyDescription>();
Map<String,FriendlyDescription> attrLangDescMap = new HashMap<String,FriendlyDescription>();
Map<String,FriendlyDescription> credLangDescMap = new HashMap<String,FriendlyDescription>();
for (FriendlyDescription atrFrDescription: attributeName) {
attrLangDescMap.put(atrFrDescription.getLang(), atrFrDescription);
}
for (FriendlyDescription credFrDescription: credentialName){
credLangDescMap.put(credFrDescription.getLang(), credFrDescription);
}
for (String lang:attrLangDescMap.keySet()){
StringBuilder sb = new StringBuilder();
//COMPOSE THE RETURN STRING:
sb.append(translateTheValueOfLang(lang)+" ");
sb.append(attrLangDescMap.get(lang).getValue()+" ");
sb.append(translateFromToLang(lang)+" ");
if (credLangDescMap.get(lang)!=null){
sb.append(credLangDescMap.get(lang).getValue());
} else {
sb.append(Messages.getString(Messages.NO_FRIENDLY_DESCRIPTION,lang)); //$NON-NLS-1$
}
sb.append(": "); //$NON-NLS-1$
sb.append(attributeValue.toString());
FriendlyDescription revealedFrDescr = of.createFriendlyDescription();
revealedFrDescr.setLang(lang);
revealedFrDescr.setValue(sb.toString());
ret.add(revealedFrDescr);
}
return ret;
}
private static String translateFromToLang(String language){
return Messages.getString(Messages.FROM, language); //$NON-NLS-1$
}
private static String translateTheValueOfLang(String language){
return Messages.getString(Messages.THE_VALUE_OF, language); //$NON-NLS-1$
}
private static FriendlyDescription createEmptyFriendlyDescription(){
ObjectFactory of = new ObjectFactory();
FriendlyDescription frednlyDescription = of.createFriendlyDescription();
frednlyDescription.setLang("en"); //$NON-NLS-1$
frednlyDescription.setValue("NO FRIENDLY DESCRIPTION"); //$NON-NLS-1$
return frednlyDescription;
}
private static String getFriendlyFunction(OperationType function, String lang, String argumentsType) throws Exception {
if (function == null)
throw new Exception("No function specified");
boolean dateFlag = argumentsType.equals(Constants.DATE_TYPE)||argumentsType.equals(Constants.DATETIME_TYPE);
switch (function) {
case EQUAL: return Messages.getString(Messages.EQUAL, lang);
case NOTEQUAL: return Messages.getString(Messages.NOTEQUAL, lang);
case GREATER:
if (dateFlag) {
return Messages.getString(Messages.GREATER_DATE, lang);
} else {
return Messages.getString(Messages.GREATER, lang);
}
case GREATEREQ:
if (dateFlag) {
return Messages.getString(Messages.GREATEREQ_DATE, lang);
} else {
return Messages.getString(Messages.GREATEREQ, lang);
}
case LESS:
if (dateFlag) {
return Messages.getString(Messages.LESS_DATE, lang);
} else {
return Messages.getString(Messages.LESS, lang);
}
case LESSEQ:
if (dateFlag) {
return Messages.getString(Messages.LESSEQ_DATE, lang);
} else {
return Messages.getString(Messages.LESSEQ, lang);
}
case EQUALONEOF: return Messages.getString(Messages.EQUALONEOF, lang);
default: throw new Exception("Unknown operator: " + function.toString());
}
}
private static String getFriendlyDate(MyAttributeValue av){
MyAttributeValueDate date = (MyAttributeValueDate) av;
if (date.getValueAsObject() instanceof XMLGregorianCalendar) {
XMLGregorianCalendar value = (XMLGregorianCalendar) date.getValueAsObject();
GregorianCalendar dateNormal = value.toGregorianCalendar();
DateFormat df = new SimpleDateFormat("dd.MM.yyyy");
return df.format(dateNormal.getTime());
} else return av.toString();
};
private static GregorianCalendar getDateValue(MyAttributeValue av) {
MyAttributeValueDate date = (MyAttributeValueDate) av;
if (date.getValueAsObject() instanceof XMLGregorianCalendar) {
XMLGregorianCalendar value = (XMLGregorianCalendar) date.getValueAsObject();
GregorianCalendar dateNormal = value.toGregorianCalendar();
return dateNormal;
} else return null;
};
private static GregorianCalendar getDateTimeValue(MyAttributeValue av) {
MyAttributeValueDateTime dateTime = (MyAttributeValueDateTime) av;
if (dateTime.getValueAsObject() instanceof XMLGregorianCalendar) {
XMLGregorianCalendar value = (XMLGregorianCalendar) dateTime.getValueAsObject();
GregorianCalendar dateNormal = value.toGregorianCalendar();
return dateNormal;
} else return null;
};
private static String getFriendlyDateTime(MyAttributeValue av){
MyAttributeValueDateTime date = (MyAttributeValueDateTime) av;
if (date.getValueAsObject() instanceof XMLGregorianCalendar) {
XMLGregorianCalendar value = (XMLGregorianCalendar) date.getValueAsObject();
GregorianCalendar dateNormal = value.toGregorianCalendar();
DateFormat df = new SimpleDateFormat("dd.MM.yyyy HH:mm");
return df.format(dateNormal.getTime());
} else return av.toString();
};
private static Map<String, CredentialSpecification> getAliasCredSpecList(PresentationTokenDescription ptd, Map<URI,CredentialSpecification> credSpecs){
Map<String, CredentialSpecification> aliasCredSpecs = new HashMap<String, CredentialSpecification>();
int credIndex = 0;
for (CredentialInToken cit: ptd.getCredential()) {
URI credentialAlias = cit.getAlias();
if (credentialAlias == null) {
credentialAlias = URI.create("abc4trust.eu/credential/"+ credIndex); //$NON-NLS-1$
}
credIndex ++;
CredentialSpecification credSpec = credSpecs.get(cit.getCredentialSpecUID());
if (credSpec==null) {
throw new RuntimeException("There is no correct credential specification stored"); //$NON-NLS-1$
}
aliasCredSpecs.put(credentialAlias.toString(), credSpec);
}
return aliasCredSpecs;
}
private static Map<String, IssuerParameters> getAliasIssParamsList(PresentationTokenDescription ptd, Map<URI,IssuerParameters> issParams){
Map<String, IssuerParameters> aliasIssParams = new HashMap<String, IssuerParameters>();
int credIndex = 0;
for (CredentialInToken cit: ptd.getCredential()) {
URI credentialAlias = cit.getAlias();
if (credentialAlias == null) {
credentialAlias = URI.create("abc4trust.eu/credential/"+ credIndex); //$NON-NLS-1$
}
credIndex ++;
IssuerParameters issParam = issParams.get(cit.getIssuerParametersUID());
if (issParam==null) {
throw new RuntimeException("There is no correct issuer parameters stored"); //$NON-NLS-1$
}
aliasIssParams.put(credentialAlias.toString(), issParam);
}
return aliasIssParams;
}
private static Date removeTime(GregorianCalendar today) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(today.getTimeInMillis());
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
private static Date removeMilliseconds(GregorianCalendar today) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(today.getTimeInMillis());
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
}