package org.openiot.cupus.artefact;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import org.openiot.cupus.common.Triplet;
import org.openiot.cupus.common.enums.Operator;
/**
* An implementation of a TopKWSubscription that is based on a structured
* continuous query and notifies about maximum value of the requested parameter.
*
* @author Aleksandar
*
*/
public class MaxTopKWSubscription extends TopKWSubscription implements Serializable {
private static final long serialVersionUID = 1L;
private Set<Triplet> data;
public MaxTopKWSubscription(int K, long W, long validity, long startTime, String parameter, String area) {
super(K, W, validity, startTime);
data = new HashSet<Triplet>();
data.add(new Triplet(parameter, 0, Operator.GREATER_THAN));
data.add(new Triplet("Area", area, Operator.EQUAL));
}
/**
* Removes the given triplet from the data (conditions) of this subscription
*
* @return true if removed, false otherwise (wasn't present)
*/
public boolean removeTriplet(Triplet triplet) {
return data.remove(triplet);
}
public void clearTriplets() {
data.clear();
}
public boolean containsTriplet(Triplet triplet) {
return data.contains(triplet);
}
public boolean hasNoTriplets() {
return data.isEmpty();
}
public Set<Triplet> getData() {
return data;
}
@Override
public double calculateRelevance(Publication p) {
if (!(p instanceof HashtablePublication)) {
System.err.println("Cannot compare a structured subsciption (TripletTopKW) with a non structured publication (not a HashtablePublication)!");
return Double.NEGATIVE_INFINITY;
}
double ret_val = 0.0;
HashMap<String, Object> publication = ((HashtablePublication) p).getProperties();
// for every condition (triplet)...
for (Triplet t : data) {
//check if exists
Object pub_value = publication.get(t.getKey());
if (pub_value == null) {
return Double.NEGATIVE_INFINITY;
}
//if string...
if (t.getValue().getClass() == String.class) {
if (pub_value.getClass() != String.class) {
System.err.println("Same key (" + t.getKey() + ") different types: String != " + pub_value.getClass());
return Double.NEGATIVE_INFINITY;
}
String thisVal = ((String) t.getValue()).toLowerCase(Locale.ENGLISH);
String thatVal = ((String) pub_value).toLowerCase(Locale.ENGLISH);
//check every possible string operator (has to satisfy)
switch (t.getOperator()) {
case EQUAL:
if (!thatVal.equals(thisVal)) {
return Double.NEGATIVE_INFINITY;
}
break;
default:
System.err.println("Triplet with string value and numeric operator?!");
return Double.NEGATIVE_INFINITY;
}
} else { //if not strings then they have to be numbers of some kind
double thisVal, thatVal;
try {
thisVal = Double.parseDouble(t.getValue().toString());
thatVal = Double.parseDouble(pub_value.toString());
} catch (NumberFormatException e) {
System.err.println("Triplet with non-string, non-numeric value?!");
return Double.NEGATIVE_INFINITY;
}
//for every possible numerical operator
switch (t.getOperator()) {
case GREATER_THAN:
ret_val += (thatVal - thisVal);
break;
default:
System.err.println("Triplet with numerical value and string operator?!");
return Double.NEGATIVE_INFINITY;
}
}
}
return ret_val;
}
@Override
public boolean coversPublication(Publication pub) {
if (pub instanceof HashtablePublication) {
HashtablePublication hp = (HashtablePublication) pub;
for (Triplet t : data) {
if (hp.getProperties().containsKey(t.getKey())) {
return true;
}
}
}
return false;
}
@Override
public String toString() {
StringBuilder retVal = new StringBuilder("K=" + K + ",W=" + W + " ");
Iterator<Triplet> iterator = data.iterator();
retVal.append("(" + iterator.next().toString());
while (iterator.hasNext()) {
retVal.append("," + iterator.next().toString());
}
return retVal.append(")").toString();
}
}