/**
* 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.topkw;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.openiot.cupus.artefact.Announcement;
import org.openiot.cupus.artefact.MemorizedPublication;
import org.openiot.cupus.artefact.MemorySubscription;
import org.openiot.cupus.artefact.Publication;
import org.openiot.cupus.artefact.Subscription;
import org.openiot.cupus.entity.broker.TopKWMatcher;
/**
* An implementation of a topKW processor.
*
* @author Krešimir Pripužić <kpripuzic at gmail.com>, Eugen & Maria
*/
public class SkybandProcessor implements TopKWProcessor {
private TopKWMatcher matcher;
private Set<MemorySubscription> subscriptions;
private ExpiringMemorizedPublications emp
;
public SkybandProcessor(TopKWMatcher matcher) {
this.matcher = matcher;
this.subscriptions = new HashSet<MemorySubscription>();
this.emp = new ExpiringMemorizedPublications();
}
@Override
public synchronized boolean add(MemorySubscription s) {
return this.subscriptions.add(s);
}
public synchronized List<MemorySubscription> getSubscriptions() {
return new LinkedList<>(this.subscriptions);
}
@Override
public synchronized boolean remove(MemorySubscription s) {
return this.subscriptions.remove(s);
}
public synchronized void deleteSubscriber (UUID subscriberID) {
Set<MemorySubscription> toDelete = new HashSet<>();
for (MemorySubscription ms : subscriptions) {
if (ms.getSubscriber().equals(subscriberID))
toDelete.add(ms);
}
for (MemorySubscription ms : toDelete) {
subscriptions.remove(ms);
}
}
public Set<Subscription> findMatchingSubscriptions (Announcement announcement) {
Set<Subscription> matched = new HashSet<>();
for (MemorySubscription ms : subscriptions) {
if (announcement.coversSubscription(ms.getSubscription())) {
matched.add(ms.getSubscription());
}
}
return matched;
}
/**
* It has to be synchronized in full otherwise the List could be changed
* while being iterated. So processing of a publication must be atomary (all
* subscriptions at once) not only because of subscription removal, but
* because of iteration.
*/
@Override
public synchronized void process(Publication publication, UUID publisher, long time) {
if (matcher.isTesting()) {
//System.out.println("Broker: topkw recieved publication " + publication.toString());
}
if (matcher.isLogWriting()) {
matcher.informBroker("Broker: topkw Processor recieved publication " + publication.toString(), false);
}
Iterator<MemorySubscription> iter = subscriptions.iterator();
while (iter.hasNext()) {
MemorySubscription s = iter.next();
if (s.getValidity() <= System.currentTimeMillis()) {
if (s.getValidity() != -1) {
iter.remove();
continue;
}
}
s.process(publication, publisher, emp, time);
}
}
@Override
public boolean unpublish(Publication publication) {
List<MemorizedPublication> pubsToUnpublish= emp.findMatchingPubs(publication);
boolean successful = false;
for (MemorizedPublication memPub : pubsToUnpublish) {
successful = emp.remove(memPub); //it is synchronized on the emp itself...
//TODO: dohvati i obavijesti o promjenama
memPub.getSubscription().remove(memPub); //it is synchronized on the SASubscription...
}
return successful;
}
@Override
public void checkExpired(long time) {
//TODO: dohvati i obavijesti o promjenama
emp.checkExpired(time);
}
@Override
public void run() {
while (true) {
//TODO: dohvati i obavijesti o promjenama
emp.checkExpired(System.currentTimeMillis());
}
}
}