/*
* Created on 01.11.2004
*
* COPYRIGHT NOTICE
*
* Copyright (C) 2005 DFKI GmbH, Germany
* Developed by Benedikt Fries, Matthias Klusch
*
* The code is free for non-commercial use only.
* You can redistribute it and/or modify it under the terms
* of the Mozilla Public License version 1.1 as
* published by the Mozilla Foundation at
* http://www.mozilla.org/MPL/MPL-1.1.txt
*/
package owlsmx;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import owlsmx.data.MatchedService;
import owlsmx.data.MatchingResult;
import owlsmx.exceptions.MatchingException;
import owlsmx.io.ErrorLog;
import owlsmx.similaritymeasures.SimilarityMeasure;
/**
* The matching engine handles the matchmaker and the registered services
*
* @author bEn
*
*/
public class SimilarityMatchingEngine implements MatchingEngine {
private Map advertisedServices = new HashMap();
private OWLSMXMatchmaker matcher = null;
private LinkedList newKeys;
public static final boolean debug = false;
public String printServiceRegistry() {
String result = "Lokal Services: \n";
SortedSet keys = new TreeSet(advertisedServices.keySet());
Iterator iter = keys.iterator();
Integer me;
while (iter.hasNext()) {
me = (Integer) iter.next();
result += " " + me + " - " + ((URI)advertisedServices.get(me)).toString() + "\n";
}
return result;
}
private void init() {
newKeys=new LinkedList();
for (int i = 1;i<6;i++ )
newKeys.addLast(new Integer(i));
}
/**
* Constructor
* Initializes Matatchmaker
*/
public SimilarityMatchingEngine() {
matcher=new OWLSMXMatchmaker();
init();
}
/**
* Constructor
* Initializes Matatchmaker with given SimilarityMeasure
*
* @param sim SimilarityMeasure to be used
*/
public SimilarityMatchingEngine(SimilarityMeasure sim) {
matcher=new OWLSMXMatchmaker(sim);
init();
}
/**
* Constructor
* Initializes Matatchmaker with given SimilarityMeasure
*
* @param sim SimilarityMeasure to be used
*/
public SimilarityMatchingEngine(short sim) throws MatchingException{
matcher=new OWLSMXMatchmaker(sim);
init();
}
/**
* @return new Integer key for a service
*/
private Integer getNewKey() {
Integer integer = (Integer) (newKeys.getFirst());
// int tmpint = integer.intValue();
newKeys.removeFirst();
newKeys.addLast(new Integer( ((Integer)newKeys.getLast()).intValue()+1));
return integer;
}
/**
* @param key removes a key from the list of new keys
*/
private void removeKey(Integer key) {
newKeys.addFirst(key);
}
/* (non-Javadoc)
* @see owlsmx.MatchingEngine#addService(java.net.URI)
*/
public void addService(URI profileURI) {
if (!advertisedServices.containsKey(profileURI)) {
try {
Integer ID=getNewKey();
advertisedServices.put(ID,profileURI);
// if (debug)
// System.out.println("Service ID " + ID + " " + profileURI.toString() );
matcher.addService(ID,profileURI);
} catch (Exception e) {
System.out.println("Service failed " + profileURI.toString());
e.printStackTrace();
}
}
}
/**
* Removes the service with the given ID from the advertisements
*
* @param ID
*/
private void removeService(Integer ID) {
if (advertisedServices.containsKey(ID)) {
//Service service = (Service) advertisedServices.get(ID);
advertisedServices.remove(ID);
removeKey(ID);
matcher.removeService(ID);
}
}
/* (non-Javadoc)
* @see owlsmx.MatchingEngine#removeService(java.net.URI)
*/
public void removeService(java.net.URI uri) {
Map.Entry me;
for (Iterator iter = advertisedServices.entrySet().iterator(); iter.hasNext();) {
me = (Map.Entry) iter.next();
if ( ((URI)me.getValue()).equals(uri)) {
removeService((Integer) me.getKey());
return;
}
}
}
/**
* Checks if the given service should really be used
*
* @param service service that is checked
* @param minimumDegreeOfMatch minimum degree used for this matching
* @param treshold syntactic similarity treshold to be used
* @return If the given service is not relevant
*/
private boolean shouldPruneService(MatchedService service,int minimumDegreeOfMatch, double treshold){
if ( (service.degreeOfMatch>minimumDegreeOfMatch) ) {
owlsmx.io.ErrorLog.instanceOf().report("Had to skip (" + service.serviceURI + "/" + service.degreeOfMatch + "/" + service.similarity + ") Degree of service " + service.degreeOfMatch + ">" + minimumDegreeOfMatch );
return true;
}
if ( (matcher.sim==null) || (matcher.sim.getSimilarityType()==SimilarityMeasure.SIMILARITY_NONE)) {
// owlsmx.io.ErrorLog.instanceOf().report("Had to skip (" + service.serviceURI + "/" + service.degreeOfMatch + "/" + service.similarity + ") Degree of service " + service.degreeOfMatch + " is not relevant for semantic matching" );
return (service.degreeOfMatch>=OWLSMXMatchmaker.NEAREST_NEIGHBOUR) ;
}
if ((service.degreeOfMatch==OWLSMXMatchmaker.NEAREST_NEIGHBOUR) && (service.similarity<treshold)) {
owlsmx.io.ErrorLog.instanceOf().report("Had to skip (" + service.serviceURI + "/" + service.degreeOfMatch + "/" + service.similarity + ") Sim of service " + service.similarity + "<" + treshold );
return true;
}
if ((service.degreeOfMatch==OWLSMXMatchmaker.SUBSUMED_BY) && (service.similarity<treshold)) {
owlsmx.io.ErrorLog.instanceOf().report("Had to skip (" + service.serviceURI + "/" + service.degreeOfMatch + "/" + service.similarity + ") Sim of service " + service.similarity + "<" + treshold );
return true;
}
return false;
}
/**
* Matches a service with the given URI against the local advertisements
* using given minimum degree of match and syntactic similarity treshold
*
* @param profileURI URI of the service
* @param minimumDegreeOfMatch minimum hybrid degree of match
* @param treshold syntactic similarity treshold
* @return SortedSet of MatchedService items
* @throws MatchingException Thrown if something goes wrong
*/
public SortedSet matchRequest(URI profileURI, int minimumDegreeOfMatch, double treshold) throws MatchingException {
double synTr = matcher.getSyntacticTreshold();
double tresh = treshold;
if ( (matcher.sim==null) ||(matcher.sim.getSimilarityType() == SimilarityMeasure.SIMILARITY_NONE)) {
ErrorLog.instanceOf().report("Reset treshold to 0.0 as syntactic matching is used");
tresh = 0.0;
}
matcher.setSyntacticTreshold(tresh);
SortedSet result = new TreeSet();
MatchedService entry;
SortedSet OWLSMXResult = matchRequest(profileURI);
//owlsmx.io.ErrorLog.instanceOf().debug("MXResult:\n " + OWLSMXResult.toString());
//matcher.print();
for (Iterator iter = OWLSMXResult.iterator();iter.hasNext();) {
entry = (MatchedService) iter.next();
//System.err.println(this.getClass().toString() + "(" + entry.degreeOfMatch + "/" + entry.similarity + ") <= (" + minimumDegreeOfMatch + "/" + treshold + ")");
if (!shouldPruneService(entry, minimumDegreeOfMatch, treshold))
result.add(entry);
}
matcher.setSyntacticTreshold(synTr);
return result;
}
/* (non-Javadoc)
* @see owlsmx.MatchingEngine#matchRequest(java.net.URI)
*/
public SortedSet matchRequest(URI profileURI) throws MatchingException{
try {
SortedSet Matchingresult = new TreeSet();
SortedSet result = matcher.matchRequest(profileURI);
Iterator iter = result.iterator();
MatchingResult entry;
URI uri;
while(iter.hasNext()) {
entry =(MatchingResult)iter.next();
if (advertisedServices.containsKey(new Integer(entry.serviceID))) {
uri=new URI(((URI)advertisedServices.get(new Integer(entry.serviceID))).toString());
// System.err.println(this.getClass().toString() + "matchRequest (" + entry.degreeOfMatch + "/" + entry.similarity + ")");
Matchingresult.add(new MatchedService(entry,uri));
}
}
return Matchingresult;
}
catch(Exception e) {
e.printStackTrace();
return new TreeSet();
}
}
/* (non-Javadoc)
* @see owlsmx.MatchingEngine#save()
*/
public boolean save() {
boolean result = save("");
return result;
}
/**
* Saves the matching engine to the given path
*
* @param targetpath Path where to save the engine
* @return if saving was successful
*/
public boolean save(String targetpath) {
try {
FileWriter writer = new FileWriter(targetpath + "Services.map",false);
Iterator iter = advertisedServices.entrySet().iterator();
Map.Entry me;
while (iter.hasNext()) {
me = (Map.Entry) iter.next();
writer.write("(" + me.getKey() + ";" + me.getValue() + ")\n");
}
writer.close();
return matcher.save();
} catch (Exception e) { return false; }
}
/* (non-Javadoc)
* @see owlsmx.MatchingEngine#load()
*/
public boolean load() {
boolean result = load("");
//this.matcher.load();
return result;
}
/**
* Loades the matching engine from the given path
*
* @param targetpath Path from where to load the engine
* @return if loading was successful
*/
private boolean load(String path) {
try {
advertisedServices.clear();
BufferedReader reader = new BufferedReader(new FileReader(path + "Services.map" ));
String line;
String[] tokens;
while ( (line = reader.readLine()) != null) {
line = line.trim();
line = line.substring(line.indexOf("(")+1,line.lastIndexOf(")"));
tokens = line.split(";");
if (tokens.length>=2)
advertisedServices.put(new Integer(tokens[0]),new URI(tokens[1]) );
}
reader.close();
return matcher.load();
} catch (NumberFormatException e) {
e.printStackTrace();
return false;
}
catch (IOException e) {
e.printStackTrace();
return false;
}
catch (URISyntaxException e) {
e.printStackTrace();
return false;
}
}
/**
* Sets the SimilarityMeasure to the stated measure
*
* @param sim SimilarityMeasure to be used
*/
public void setSimilarityMeasure(SimilarityMeasure sim) {
matcher.setSimilarityMeasure(sim);
}
/**
* Sets the SimilarityMeasure to the stated measure
*
* @param sim SimilarityMeasure to be used
*/
public void setSimilarityMeasure(short sim) {
matcher.setSimilarityMeasure(sim);
}
/* (non-Javadoc)
* @see owlsmx.MatchingEngine#clear()
*/
public void clear() {
matcher.clear();
}
public void print() {
System.out.println(this.getClass().toString());
this.printServiceRegistry();
matcher.print();
}
/**
* Enables support for profile hierarchies
*
* @param speedyButProblematic If the entire semantic check should be disabled (hence speedy but could cause problems)
*/
public void enableProfileHierarchies(boolean speedyButProblematic) {
matcher.enableProfileHierarchies(speedyButProblematic);
}
/**
* Disables the support for profile hierarchies
*/
public void disableProfileHierarchies() {
matcher.disableProfileHierarchies();
}
public String toString() {
return printServiceRegistry() + "\n" + matcher.toString();
}
}