package org.societies.webapp.service;
/**
* 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.
*/
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.societies.api.identity.IIdentity;
import org.societies.api.internal.privacytrust.privacyprotection.model.privacyassessment.AssessmentResultBundle;
import org.societies.api.internal.privacytrust.privacyprotection.model.privacyassessment.AssessmentResultClassName;
import org.societies.api.internal.privacytrust.privacyprotection.model.privacyassessment.AssessmentResultIIdentity;
import org.societies.api.internal.privacytrust.privacyprotection.model.privacyassessment.IAssessment;
import org.societies.webapp.models.PrivacyAssessmentForm;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
@Service
@Scope("Session")
@SessionScoped
@ManagedBean
public class PrivacyAssessmentService implements Serializable {
private static final long serialVersionUID = -2466517020378971890L;
private static final Logger log = LoggerFactory.getLogger(PrivacyAssessmentService.class);
@ManagedProperty(value = "#{privacyAssessmentForm}")
private PrivacyAssessmentForm model;
private boolean imagesGenerated = false;
private int imageIndex;
private Map<Integer, byte[]> images;
public class PlotData {
private double[] data;
private String[] labels;
public PlotData(double[] data, Object[] labels) {
this.data = data;
this.labels = obj2str(labels);
}
private String[] obj2str(Object[] obj) {
Class<? extends Object> clazz;
if (obj.length == 0) {
return new String[0];
}
clazz = obj[0].getClass();
if (String.class.isAssignableFrom(clazz)) {
//return (String[]) obj;
String[] labelsStr = new String[obj.length];
for (int k = 0; k < obj.length; k++) {
log.debug("obj2str: obj[{}] = {}", k, obj[k]);
labelsStr[k] = (String) obj[k];
}
return labelsStr;
}
else if (IIdentity.class.isAssignableFrom(clazz)) {
String[] labelsStr = new String[obj.length];
for (int k = 0; k < obj.length; k++) {
log.debug("obj2str: obj[{}] = {}", k, obj[k]);
labelsStr[k] = obj[k] == null ? null : ((IIdentity) obj[k]).getJid();
}
return labelsStr;
}
else {
log.warn("Unsupported class: {}", clazz.getName());
return new String[0];
}
}
public double[] getData() {
// for (double d : data) {
// log.debug("getData(): {}", d);
// }
return data;
}
public String[] getLabels() {
for (String s : labels) {
log.debug("getLabels(): {}", s);
}
return labels;
}
}
public PrivacyAssessmentService() {
log.info("constructor");
images = new HashMap<Integer, byte[]>();
}
/**
* OSGI service get auto injected
*/
@ManagedProperty(value = "#{privacyAssessment}")
private IAssessment assessment;
public IAssessment getAssessment() {
return assessment;
}
public void setAssessment(IAssessment assessment) {
log.debug("setAssessment()");
this.assessment = assessment;
}
/**
* @return the model
*/
public PrivacyAssessmentForm getModel() {
return model;
}
/**
* @param model the model to set
*/
public void setModel(PrivacyAssessmentForm model) {
log.debug("Model set");
this.model = model;
}
public List<StreamedContent> getImages() {
log.debug("getImages()");
if (!imagesGenerated) {
generateImages();
imagesGenerated = true;
}
List<StreamedContent> result = new ArrayList<StreamedContent>();
for (byte[] img : images.values()) {
//log.debug("getImages(): adding image {}", img);
InputStream is = new ByteArrayInputStream(img);
//log.debug("getImages(): image input stream: {}", is);
DefaultStreamedContent dsc = new DefaultStreamedContent(is);
result.add(dsc);
//log.debug("getImages(): added image {}", dsc);
}
log.debug("getImages(): returning {} images", images.size());
return result;
}
public StreamedContent getImage() {
log.debug("getImage(): index = {}", imageIndex);
if (!imagesGenerated) {
generateImages();
imagesGenerated = true;
}
InputStream is = new ByteArrayInputStream(images.get(imageIndex));
return new DefaultStreamedContent(is);
}
public int getImageIndex() {
log.debug("getImageIndex(): {}", imageIndex);
return imageIndex;
}
public void setImageIndex(int imageIndex) {
log.debug("setImageIndex({})", imageIndex);
this.imageIndex = imageIndex;
}
public void previousImage() {
log.debug("previousImage(): imageIndex before = {}", imageIndex);
imageIndex = (imageIndex - 1 + images.size()) % images.size();
log.debug("previousImage(): imageIndex after = {}", imageIndex);
}
public void nextImage() {
imageIndex = (imageIndex + 1) % images.size();
log.debug("nextImage(): imageIndex = {}", imageIndex);
}
/**
* @param map Map<String, Integer> or Map<IIdentity, Integer>
* @return
*/
private PlotData mapToArrays(Map map) {
Object[] labels = new Object[map.keySet().size()];
double[] data = new double[map.keySet().size()];
int k;
k = 0;
for (Object key : map.keySet()) {
labels[k] = key;
data[k] = (Integer) map.get(key);
++k;
}
return new PlotData(data, labels);
}
private void createBarchart(String title, String categoryLabel, String valueLabel,
PlotData[] data, String[] dataLabels, int index) {
DefaultCategoryDataset dataSet = new DefaultCategoryDataset();
int maxDataLength = 0;
for (int i = 0; i < dataLabels.length; i++) {
for (int j = 0; j < data[i].getData().length; j++) {
dataSet.addValue(data[i].getData()[j], dataLabels[i], data[i].getLabels()[j]);
}
if (maxDataLength < data[i].getData().length) {
maxDataLength = data[i].getData().length;
}
}
JFreeChart chart = ChartFactory.createBarChart(
title,
categoryLabel,
valueLabel,
dataSet,
PlotOrientation.VERTICAL,
dataLabels.length > 1, // display legend
false,
false
);
CategoryPlot plot = (CategoryPlot)chart.getPlot();
CategoryAxis xAxis = (CategoryAxis)plot.getDomainAxis();
xAxis.setCategoryLabelPositions(CategoryLabelPositions.STANDARD);
xAxis.setMaximumCategoryLabelLines(6);
//chart.setBackgroundPaint(ChartColor.WHITE);
int width = 50 + maxDataLength * 170;
if (maxDataLength < 3) {
width += 170;
}
int height = 400;
try {
BufferedImage image = chart.createBufferedImage(width, height);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
ChartUtilities.writeBufferedImageAsPNG(outStream, image);
byte[] ba = outStream.toByteArray();
images.put(index, ba);
log.debug("Generated image {}", title);
} catch(IOException e) {
log.warn("createBarchart(): ", e);
}
}
public void generateImages() {
log.debug("generateImages()");
generateImageReceiverIds();
generateImageSenderIds();
generateImageSenderClass();
generateImageSenderBundle();
generateImageDataAccessClass();
generateImageDataAccessBundle();
generateImageDataAccessIds();
}
private void generateImageReceiverIds() {
String title = "Remote and local identities data has been sent to";
String xlabel = "Receiver identity";
String ylabel = "Number of data transmissions";
Map<IIdentity, Integer> identities;
identities = assessment.getNumDataTransmissionEventsForAllReceivers(
model.getStartDate(), model.getEndDate());
log.debug("Number of identities data has been transmitted to: {}", identities.size());
PlotData[] plotData = new PlotData[] {mapToArrays(identities)};
String[] plotDataLabels = new String[] {"data"};
createBarchart(title, xlabel, ylabel, plotData, plotDataLabels, 0);
}
private void generateImageSenderIds() {
String title = "Local identities which sent data and their correlation with data access";
String xlabel = "Sender identity";
String ylabel = "Correlation of data transmission and data access";
HashMap<IIdentity, AssessmentResultIIdentity> assResult;
assResult = assessment.getAssessmentAllIds(model.getStartDate(), model.getEndDate());
int size = assResult.size();
IIdentity[] labels = new IIdentity[size];
double[][] data = new double[2][size];
Iterator<IIdentity> iterator = assResult.keySet().iterator();
log.debug("privacyAssessment(): size = {}", size);
for (int k = 0; k < size; k++) {
labels[k] = iterator.next();
data[0][k] = assResult.get(labels[k]).getCorrWithDataAccessBySender();
data[1][k] = assResult.get(labels[k]).getCorrWithDataAccessByAll();
log.debug("privacyAssessment(): label[{}] = {}", k, labels[k]);
log.debug("privacyAssessment(): data[0][{}] = {}", k, data[0][k]);
log.debug("privacyAssessment(): data[1][{}] = {}", k, data[1][k]);
}
PlotData[] plotData = new PlotData[] {
new PlotData(data[0], labels),
new PlotData(data[1], labels)
};
String[] plotDataLabels = new String[] {
"Correlation with data access by the sender identity",
"Correlation with data access by any identity"
};
createBarchart(title, xlabel, ylabel, plotData, plotDataLabels, 1);
}
private void generateImageSenderClass() {
String title = "Local Java classes which sent data and their correlation with data access";
String xlabel = "Sender class";
String ylabel = "Correlation of data transmission and data access";
HashMap<String, AssessmentResultClassName> assResult;
assResult = assessment.getAssessmentAllClasses(model.isIncludePlatformBundles(), model.getStartDate(), model.getEndDate());
int size = assResult.size();
String[] labels = new String[size];
double[][] data = new double[2][size];
Iterator<String> iterator = assResult.keySet().iterator();
log.debug("privacyAssessment(): size = {}", size);
for (int k = 0; k < size; k++) {
labels[k] = iterator.next();
data[0][k] = assResult.get(labels[k]).getCorrWithDataAccessBySender();
data[1][k] = assResult.get(labels[k]).getCorrWithDataAccessByAll();
log.debug("privacyAssessment(): label[{}] = {}", k, labels[k]);
log.debug("privacyAssessment(): data[0][{}] = {}", k, data[0][k]);
log.debug("privacyAssessment(): data[1][{}] = {}", k, data[1][k]);
}
PlotData[] plotData = new PlotData[] {
new PlotData(data[0], labels),
new PlotData(data[1], labels)
};
String[] plotDataLabels = new String[] {
"Correlation with data access by the sender class",
"Correlation with data access by any class"
};
createBarchart(title, xlabel, ylabel, plotData, plotDataLabels, 2);
}
private void generateImageSenderBundle() {
String title = "Local bundles which sent data and their correlation with data access";
String xlabel = "Sender bundle";
String ylabel = "Correlation of data transmission and data access";
HashMap<String, AssessmentResultBundle> assResult;
assResult = assessment.getAssessmentAllBundles(model.isIncludePlatformBundles(), model.getStartDate(), model.getEndDate());
int size = assResult.size();
String[] labels = new String[size];
double[][] data = new double[2][size];
Iterator<String> iterator = assResult.keySet().iterator();
log.debug("privacyAssessment(): size = {}", size);
for (int k = 0; k < size; k++) {
labels[k] = iterator.next();
data[0][k] = assResult.get(labels[k]).getCorrWithDataAccessBySender();
data[1][k] = assResult.get(labels[k]).getCorrWithDataAccessByAll();
log.debug("privacyAssessment(): label[{}] = {}", k, labels[k]);
log.debug("privacyAssessment(): data[0][{}] = {}", k, data[0][k]);
log.debug("privacyAssessment(): data[1][{}] = {}", k, data[1][k]);
}
PlotData[] plotData = new PlotData[] {
new PlotData(data[0], labels),
new PlotData(data[1], labels)
};
String[] plotDataLabels = new String[] {
"Correlation with data access by the sender bundle",
"Correlation with data access by any bundle"
};
createBarchart(title, xlabel, ylabel, plotData, plotDataLabels, 3);
}
private void generateImageDataAccessClass() {
String title = "Java classes which accessed local data";
String xlabel = "Class";
String ylabel = "Number of accesses to local data";
Map<String, Integer> dataAccessClasses;
dataAccessClasses = assessment.getNumDataAccessEventsForAllClasses(model.isIncludePlatformBundles(), model.getStartDate(), model.getEndDate());
log.debug("Number of data access events (by class): {}", dataAccessClasses.size());
PlotData[] plotData = new PlotData[] {mapToArrays(dataAccessClasses)};
String[] plotDataLabels = new String[] {"data"};
createBarchart(title, xlabel, ylabel, plotData, plotDataLabels, 4);
}
private void generateImageDataAccessBundle() {
String title = "Bundles which accessed local data";
String xlabel = "Bundle";
String ylabel = "Number of accesses to local data";
Map<String, Integer> dataAccessBundles;
dataAccessBundles = assessment.getNumDataAccessEventsForAllBundles(model.isIncludePlatformBundles(), model.getStartDate(), model.getEndDate());
log.debug("Number of data access events (by bundle): {}", dataAccessBundles.size());
PlotData[] plotData = new PlotData[] {mapToArrays(dataAccessBundles)};
String[] plotDataLabels = new String[] {"data"};
createBarchart(title, xlabel, ylabel, plotData, plotDataLabels, 5);
}
private void generateImageDataAccessIds() {
String title = "Identities which accessed local data";
String xlabel = "Identity";
String ylabel = "Number of accesses to local data";
Map<IIdentity, Integer> identities;
identities = assessment.getNumDataAccessEventsForAllIdentities(model.getStartDate(), model.getEndDate());
log.debug("Number of data access events (by identity): {}", identities.size());
PlotData[] plotData = new PlotData[] {mapToArrays(identities)};
String[] plotDataLabels = new String[] {"data"};
createBarchart(title, xlabel, ylabel, plotData, plotDataLabels, 6);
}
}