/**
* Copyright (c) 2011-2014, OpenIoT
*
* This file is part of OpenIoT.
*
* OpenIoT is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* OpenIoT is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with OpenIoT. If not, see <http://www.gnu.org/licenses/>.
*
* Contact: OpenIoT mailto: info@openiot.eu
*/
package org.openiot.cupus.subForest;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.openiot.cupus.artefact.ActiveSubscription;
import org.openiot.cupus.artefact.Announcement;
import org.openiot.cupus.artefact.Publication;
import org.openiot.cupus.artefact.Subscription;
import org.openiot.cupus.common.SubscriptionDataStructure;
/**
*
* @author Aleksandar, Eugen
*/
public class ActiveSubscriptionForest implements SubscriptionDataStructure {
private List<ActSubTree> trees = new ArrayList<ActSubTree>();
public List<ActSubTree> getTrees() {
return trees;
}
public HashSet<UUID> findMatchingSubscribers(Publication publication){
HashSet<UUID> subscribers = null;
for (ActSubTree tree : trees){
if (subscribers==null)
subscribers = tree.findMatchingSubscribers(publication);
else
subscribers.addAll(tree.findMatchingSubscribers(publication));
}
return subscribers;
}
public HashSet<Subscription> findMatchingSubscriptions(Announcement announcement){
HashSet<Subscription> subscriptions = null;
for (ActSubTree tree : trees){
if (subscriptions==null)
subscriptions = tree.findMatchingSubscriptions(announcement);
else
subscriptions.addAll(tree.findMatchingSubscriptions(announcement));
}
return subscriptions;
}
public int getMaxTreeDepth() {
int temp, retVal = 0;
for (ActSubTree e : this.trees) {
temp = e.getTreeDepth(e.getRootElement());
if (temp > retVal) {
retVal = temp;
}
}
return retVal;
}
public int addSubscription(ActiveSubscription subscription) {
ActSubNode newNode = new ActSubNode(subscription);
if (trees.isEmpty()) {
trees.add(new ActSubTree(newNode));
return NEW_TREE_CREATED;
}
List<ActSubTree> toBeRemoved = new ArrayList<ActSubTree>();
for (ActSubTree e : this.trees) {
switch(e.addNode(newNode, e.getRootElement())){ //try to add the node to each of the trees...
case (NEW_TREE_ROOT):
toBeRemoved.add(e); //try others to see if common root to more trees...
break;
case (SUB_NOT_ADDED):
break; //try the next tree...
case (SUB_ALREADY_IN_FOREST):
return SUB_ALREADY_IN_FOREST;
case (SUB_ADDED):
return SUB_ADDED;
case (NEW_TREE_CREATED):
System.err.println("ActiveSubscriptionForest: new tree created?!?!");
return ERROR_ADDING_SUB;
case (ERROR_ADDING_SUB):
default:
System.err.println("ActiveSubscriptionForest: WTF?!?");
return ERROR_ADDING_SUB;
}
}
if (toBeRemoved.size()==0){ //the subscription wasn't added anywhere
trees.add(new ActSubTree(newNode));
return NEW_TREE_CREATED;
} else {
for (int i=1; i<toBeRemoved.size(); i++) { //remove all but the first (because all of them have the same node as root)
toBeRemoved.get(0).addAllSubscribers(toBeRemoved.get(i), true);
this.trees.remove(toBeRemoved.get(i));
}
return NEW_TREE_ROOT;
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (ActSubTree e : this.trees) {
sb.append(e.toString()).append("\n\n-----------------------------------------\n");
}
return sb.toString();
}
public int removeSubscription(ActiveSubscription subscription) {
for (ActSubTree e : trees) {
if (e.getRootElement().getData().equals(subscription)) {
for (ActSubNode f : e.getRootElement().getChildren()) {
trees.add(new ActSubTree(f));
}
trees.remove(e);
return 1;//new root node
} else {
if (e.getRootElement().getData().coversActiveSubscription(subscription)) {
e.removeNode(subscription, e.getRootElement());
}
}
}
return 2;
}
public int deleteSubscriber(UUID subscriberID) {
int retVal = 2;
for (ActSubTree tree : new ArrayList<ActSubTree>(this.trees)) {
if (tree.getRootElement().getData().getSubscriberID().equals(subscriberID)) {
retVal = 1;
}
for (ActSubNode e : new ArrayList<ActSubNode>(tree.toList())) {
if (e.getData().getSubscriberID().equals(subscriberID)) {
this.removeSubscription(e.getData());
}
}
tree.activeSubscribersSet.remove(subscriberID);
tree.activeSubscribersCounter.remove(subscriberID);
}
return retVal;
}
public List<ActiveSubscription> getRootSubs() {
List<ActiveSubscription> retVal = new ArrayList<ActiveSubscription>();
for (ActSubTree e : trees) {
retVal.add(e.getRootElement().getData());
}
return retVal;
}
public boolean contains(Subscription sub) {
for (ActSubTree e : trees) {
if (e.contains(sub, e.getRootElement())) {
return true;
}
}
return false;
}
public float percentCovered() {
float retVal = 100 * (1 - ((float) this.trees.size()) / (float) this.toList().size());
return retVal;
}
public List<ActSubNode> toList() {
List<ActSubNode> retVal = new ArrayList<ActSubNode>();
for (ActSubTree e : this.trees) {
retVal.addAll(e.toList());
}
return retVal;
}
public void removeExpiredSubscriptions() {
List<ActSubNode> retVal = toList();
for (ActSubNode e : retVal) {
if (!((e.getData().getSubscription().getValidity() >= java.lang.System.currentTimeMillis()) || (e.getData().getSubscription().getValidity() == -1))) {
removeSubscription(e.getData());
}
}
}
}