connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/internal/ServiceTester.java
/**
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package com.nokia.carbide.remoteconnections.internal;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import com.nokia.carbide.remoteconnections.interfaces.AbstractConnectedService2;
import com.nokia.carbide.remoteconnections.interfaces.AbstractSynchronizedConnection;
import com.nokia.carbide.remoteconnections.interfaces.AbstractConnectedService2.Status;
import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatus;
public class ServiceTester {
public class TestRunner extends Thread {
private final Collection<Set<AbstractConnectedService2>> connectedServicesSets;
public TestRunner(Collection<Set<AbstractConnectedService2>> connectedServicesSets) {
this.connectedServicesSets = connectedServicesSets;
}
@Override
public void run() {
for (Set<AbstractConnectedService2> connectedServices : connectedServicesSets) {
// test first in the set and set status and properties for others
Iterator<AbstractConnectedService2> iterator = connectedServices.iterator();
AbstractConnectedService2 toTest = iterator.next();
toTest.testStatus();
IStatus status = toTest.getStatus();
while (iterator.hasNext()) {
AbstractConnectedService2 next = iterator.next();
next.setStatus((Status) status);
next.getProperties().putAll(toTest.getProperties());
}
}
unregisterThread(this);
}
@Override
public synchronized void start() {
registerThread(this);
super.start();
}
public boolean contains(AbstractConnectedService2 connectedService) {
for (Set<AbstractConnectedService2> csSet : connectedServicesSets) {
if (csSet.contains(connectedService))
return true;
}
return false;
}
}
public interface IEquivalence {
Object getRelation(AbstractConnectedService2 cs);
}
private static ServiceTester instance;
private Set<AbstractConnectedService2> registry;
private Set<TestRunner> runningThreads;
public static ServiceTester getInstance() {
if (instance == null)
instance = new ServiceTester();
return instance;
}
private ServiceTester() {
registry = Collections.synchronizedSet(new HashSet<AbstractConnectedService2>());
runningThreads = new HashSet<TestRunner>();
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
Collection<Set<AbstractConnectedService2>> csSetsByResource;
synchronized (registry) {
csSetsByResource = createConnectedServiceSetsByResource(new HashSet<AbstractConnectedService2>(registry));
}
for (Set<AbstractConnectedService2> set : csSetsByResource) {
Collection<Set<AbstractConnectedService2>> csSetsByService =
createConnectedServiceSetsByService(set);
runTests(csSetsByService);
}
try {
Thread.sleep(AbstractConnectedService2.TIMEOUT);
} catch (InterruptedException e) {
}
}
}
});
t.start();
}
private void runTests(Collection<Set<AbstractConnectedService2>> csSetsByResource) {
if (isRunningTest(csSetsByResource))
return;
if (csSetsByResource.isEmpty())
return;
TestRunner runner = new TestRunner(csSetsByResource);
runner.start();
}
private Collection<Set<AbstractConnectedService2>> partition(
Set<AbstractConnectedService2> connectedServices, IEquivalence equivalence) {
Map<Object, Set<AbstractConnectedService2>> collatedConnectedServiceSetMap =
new HashMap<Object, Set<AbstractConnectedService2>>();
for (AbstractConnectedService2 cs : connectedServices) {
Object object = equivalence.getRelation(cs);
if (object == null)
continue;
if (!collatedConnectedServiceSetMap.containsKey(object))
collatedConnectedServiceSetMap.put(object, new HashSet<AbstractConnectedService2>());
collatedConnectedServiceSetMap.get(object).add(cs);
}
return collatedConnectedServiceSetMap.values();
}
private Collection<Set<AbstractConnectedService2>> createConnectedServiceSetsByResource(Set<AbstractConnectedService2> connectedServices) {
return partition(connectedServices, new IEquivalence() {
public Object getRelation(AbstractConnectedService2 cs) {
AbstractSynchronizedConnection connection = (AbstractSynchronizedConnection) cs.getConnection();
if (connection != null)
return connection.getCurrentResource();
return null;
}
});
}
protected Collection<Set<AbstractConnectedService2>> createConnectedServiceSetsByService(Set<AbstractConnectedService2> connectedServices) {
return partition(connectedServices, new IEquivalence() {
public Object getRelation(AbstractConnectedService2 cs) {
return cs.getService();
}
});
}
public void register(AbstractConnectedService2 connectedService) {
registry.add(connectedService);
}
public boolean isRegistered(AbstractConnectedService2 connectedService) {
return registry.contains(connectedService);
}
public void unregister(AbstractConnectedService2 connectedService) {
registry.remove(connectedService);
}
public synchronized void registerThread(TestRunner testRunner) {
runningThreads.add(testRunner);
}
public synchronized void unregisterThread(TestRunner testRunner) {
runningThreads.remove(testRunner);
}
public synchronized boolean isRunningTest(Collection<Set<AbstractConnectedService2>> csSetsByResource) {
for (Set<AbstractConnectedService2> set : csSetsByResource) {
for (AbstractConnectedService2 cs : set) {
if (isRunningTest(cs))
return true;
}
}
return false;
}
private boolean isRunningTest(AbstractConnectedService2 cs) {
for (TestRunner runner : runningThreads) {
if (runner.contains(cs))
return true;
}
return false;
}
}