You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stanbol.apache.org by rw...@apache.org on 2012/05/03 14:47:20 UTC

svn commit: r1333433 [1/2] - in /incubator/stanbol/trunk: commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/utils/ entityhub/generic/core/src/main/java/org/apache/stanbol/entityhub/core/mapping/ entityhub/generic/servicesapi/src/main/j...

Author: rwesten
Date: Thu May  3 12:47:18 2012
New Revision: 1333433

URL: http://svn.apache.org/viewvc?rev=1333433&view=rev
Log:
STANBOL-594: First working version of the Stanbol Entityhub based implementation for the Google Refine Reconciliation API

* supports Entityhub, ReferencedSiteManager and ReferencedSites
* URI: {serviceendpoint}/reconcile (e.g. http://localhost:8080/entityhub/site/dbpedia/reconcile)
* supports reconciliation based on name, types and properties

fixes STANBOL-595: ReferenceConstraints and ValueConstraints do now support multiple values

* Adapted interfaces (incompatible API change): decided against keeping the old Object getValue() method
* Added support for JSON serialisation/parsing
* Implementation for SPARQL and Solr (SolrYard)

Added:
    incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/grefine/
    incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/grefine/ReconcileQuery.java   (with props)
    incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/grefine/Utils.java   (with props)
    incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/
    incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/BaseGoogleRefineReconcileResource.java   (with props)
    incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/EntityhubReconcileResource.java   (with props)
    incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/ReferencedSiteReconcileResource.java   (with props)
    incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/SiteManagerReconcileResource.java   (with props)
    incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/static/images/
    incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/static/images/google_refine_reconciliation-add_service.png   (with props)
    incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/static/images/google_refine_reconciliation-open_dialog.png   (with props)
    incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/static/images/google_refine_reconciliation-use_service.png   (with props)
    incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/reconcile/
    incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/reconcile/BaseGoogleRefineReconcileResource/
Modified:
    incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/utils/MediaTypeUtil.java
    incubator/stanbol/trunk/entityhub/generic/core/src/main/java/org/apache/stanbol/entityhub/core/mapping/DefaultFieldMapperImpl.java
    incubator/stanbol/trunk/entityhub/generic/servicesapi/src/main/java/org/apache/stanbol/entityhub/servicesapi/query/ReferenceConstraint.java
    incubator/stanbol/trunk/entityhub/generic/servicesapi/src/main/java/org/apache/stanbol/entityhub/servicesapi/query/ValueConstraint.java
    incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/fragment/EntityhubWebFragment.java
    incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/parsers/FieldQueryReader.java
    incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/writers/FieldQueryToJSON.java
    incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/EntityhubRootResource/index.ftl
    incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/ReferencedSiteRootResource/index.ftl
    incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/SiteManagerRootResource/index.ftl
    incubator/stanbol/trunk/entityhub/query/clerezza/src/main/java/org/apache/stanbol/entityhub/query/clerezza/SparqlQueryUtils.java
    incubator/stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrQueryFactory.java
    incubator/stanbol/trunk/integration-tests/src/test/java/org/apache/stanbol/entityhub/it/query/DbpediaQueryTest.java

Modified: incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/utils/MediaTypeUtil.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/utils/MediaTypeUtil.java?rev=1333433&r1=1333432&r2=1333433&view=diff
==============================================================================
--- incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/utils/MediaTypeUtil.java (original)
+++ incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/utils/MediaTypeUtil.java Thu May  3 12:47:18 2012
@@ -99,7 +99,29 @@ public final class MediaTypeUtil {
         }
         return acceptedMediaType;
     }
-    
+    /**
+     * Checks if the parse mediaType is compatible with one of the Accept headers.
+     * Fully supports wildcard for both parsed Accept headers AND the parsed
+     * {@link MediaType}
+     * @param headers
+     * @param mediaType
+     * @return
+     */
+    public static boolean isAcceptableMediaType(HttpHeaders headers, MediaType mediaType){
+        if (!headers.getAcceptableMediaTypes().isEmpty()) {
+            for (MediaType accepted : headers.getAcceptableMediaTypes()) {
+                //if one of the types is wildcard or types are equals AND
+                // one of the subtypes is wildcard or subtypes are equals
+                if ((accepted.isWildcardType() || mediaType.isWildcardType() || 
+                        accepted.getType().equals(mediaType.getType())) &&
+                        (accepted.isWildcardSubtype() || mediaType.isWildcardSubtype() || 
+                                accepted.getSubtype().equals(mediaType.getSubtype()))){
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
     public static boolean isAcceptableMediaType(MediaType mediaType, Collection<String> supported){
         if(supported == null || mediaType == null){
             return true;

Modified: incubator/stanbol/trunk/entityhub/generic/core/src/main/java/org/apache/stanbol/entityhub/core/mapping/DefaultFieldMapperImpl.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/generic/core/src/main/java/org/apache/stanbol/entityhub/core/mapping/DefaultFieldMapperImpl.java?rev=1333433&r1=1333432&r2=1333433&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/generic/core/src/main/java/org/apache/stanbol/entityhub/core/mapping/DefaultFieldMapperImpl.java (original)
+++ incubator/stanbol/trunk/entityhub/generic/core/src/main/java/org/apache/stanbol/entityhub/core/mapping/DefaultFieldMapperImpl.java Thu May  3 12:47:18 2012
@@ -397,7 +397,7 @@ public class DefaultFieldMapperImpl impl
      * @return
      */
     private Collection<Object> processFilter(ValueConstraint valueConstraint, Collection<Object> values,ValueFactory valueFactory) {
-        if(valueConstraint.getValue() != null){
+        if(valueConstraint.getValues() != null){
             log.warn("Filtering based on values is not yet implemented");
         }
         //1) collect all active dataTypes

Modified: incubator/stanbol/trunk/entityhub/generic/servicesapi/src/main/java/org/apache/stanbol/entityhub/servicesapi/query/ReferenceConstraint.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/generic/servicesapi/src/main/java/org/apache/stanbol/entityhub/servicesapi/query/ReferenceConstraint.java?rev=1333433&r1=1333432&r2=1333433&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/generic/servicesapi/src/main/java/org/apache/stanbol/entityhub/servicesapi/query/ReferenceConstraint.java (original)
+++ incubator/stanbol/trunk/entityhub/generic/servicesapi/src/main/java/org/apache/stanbol/entityhub/servicesapi/query/ReferenceConstraint.java Thu May  3 12:47:18 2012
@@ -17,26 +17,52 @@
 package org.apache.stanbol.entityhub.servicesapi.query;
 
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
 
 import org.apache.stanbol.entityhub.servicesapi.defaults.DataTypeEnum;
 
 
 public class ReferenceConstraint extends ValueConstraint {
 
-
+    /**
+     * The references. Same as returned by {@link ValueConstraint#getValues()}
+     * but in a Set of generic type string
+     */
+    private Set<String> references;
+    
     public ReferenceConstraint(String reference) {
-        super(reference,Arrays.asList(DataTypeEnum.Reference.getUri()));
-        if(reference == null){
-            throw new IllegalArgumentException("Parsed Reference MUST NOT be NULL");
+        this(reference != null ? Collections.singleton(reference) : null);
+    }
+    public ReferenceConstraint(Collection<String> references) {
+        super(references,Arrays.asList(DataTypeEnum.Reference.getUri()));
+        if(references == null){
+            throw new IllegalArgumentException("Parsed Reference(s) MUST NOT be NULL");
+        }
+        //we need to copy the values over, because in Java one can not cast
+        //Set<Object> to Set<String>
+        Set<String> r = new LinkedHashSet<String>(getValues().size());
+        for(Object value : getValues()){
+            r.add((String)value);
         }
+        this.references = Collections.unmodifiableSet(r);
     }
 
+//    /**
+//     * Getter for the first parsed Reference
+//     * @return the reference
+//     */
+//    public String getReference() {
+//        return (String)getValue();
+//    }
     /**
      * Getter for the Reference
      * @return the reference
      */
-    public String getReference() {
-        return (String)getValue();
+    public Set<String> getReferences() {
+        return references;
     }
 
 

Modified: incubator/stanbol/trunk/entityhub/generic/servicesapi/src/main/java/org/apache/stanbol/entityhub/servicesapi/query/ValueConstraint.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/generic/servicesapi/src/main/java/org/apache/stanbol/entityhub/servicesapi/query/ValueConstraint.java?rev=1333433&r1=1333432&r2=1333433&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/generic/servicesapi/src/main/java/org/apache/stanbol/entityhub/servicesapi/query/ValueConstraint.java (original)
+++ incubator/stanbol/trunk/entityhub/generic/servicesapi/src/main/java/org/apache/stanbol/entityhub/servicesapi/query/ValueConstraint.java Thu May  3 12:47:18 2012
@@ -17,7 +17,10 @@
 package org.apache.stanbol.entityhub.servicesapi.query;
 
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.LinkedHashSet;
+import java.util.Set;
 
 /**
  * A constraint the filters/selects based on the value and/or the parsed
@@ -32,7 +35,7 @@ import java.util.LinkedHashSet;
 public class ValueConstraint extends Constraint {
 
 
-    private final Object value;
+    private final Set<Object> values;
     private final Collection<String> dataTypeUris;
 
     public ValueConstraint(Object value) {
@@ -40,7 +43,25 @@ public class ValueConstraint extends Con
     }
     public ValueConstraint(Object value,Iterable<String> dataTypes) {
         super(ConstraintType.value);
-        this.value = value;
+        if(value == null){
+            this.values = null;
+        } else if(value instanceof Iterable<?>){
+            Set<Object> v = new LinkedHashSet<Object>();
+            @SuppressWarnings("unchecked")
+            Iterable<Object> values = (Iterable<Object>)value;
+            for(Object val : values){
+                if(val != null){
+                    v.add(val);
+                }
+            }
+            if(v.isEmpty()){
+                throw new IllegalArgumentException("The values MUST BE NULL or " +
+                		"contain at least a single NOT NULL value MUST BE parsed!");
+            }
+            this.values = Collections.unmodifiableSet(v);
+        } else { //single value
+            this.values = Collections.singleton(value);
+        }
         /*
          * Implementation NOTE:
          *   We need to use a LinkedHashSet here to
@@ -53,16 +74,21 @@ public class ValueConstraint extends Con
          *   that values that need to be converted are preferable converted to
          *   the datatype specified as first)
          */
-        this.dataTypeUris = new LinkedHashSet<String>();
         if(dataTypes != null){
+            Set<String> dataTypeUris = new LinkedHashSet<String>();
             for(String dataType : dataTypes){
                 if(dataType != null && !dataType.isEmpty()){
                     dataTypeUris.add(dataType);
                 }
             }
-        }
-        if(value == null && dataTypeUris.isEmpty()){
-            throw new IllegalArgumentException("A value constraint MUST define at least a value or a valid - NOT NULL, NOT empty - data type uri!");
+            if(dataTypeUris.isEmpty()){
+                throw new IllegalArgumentException("At least a single NOT NULL and " +
+                        "not empty data type uri MUST BE parsed (NULL will trigger " +
+                        "detection of the data type based on the parsed value(s))!");
+            }
+            this.dataTypeUris = Collections.unmodifiableSet(dataTypeUris);
+        } else {
+            this.dataTypeUris = null;
         }
         //it's questionable if we should do that at this position, because
         //components that process that constraint might have better ways to
@@ -75,11 +101,18 @@ public class ValueConstraint extends Con
 //        }
     }
     /**
+     * Getter for the first parsed value
+     * @return the value or <code>null</code> if the value is not constraint
+     */
+//    public final Object getValue() {
+//        return values.iterator().next();
+//    }
+    /**
      * Getter for the value
      * @return the value or <code>null</code> if the value is not constraint
      */
-    public final Object getValue() {
-        return value;
+    public final Set<Object> getValues() {
+        return values;
     }
     /**
      * Getter for the list of the parsed data types URIs
@@ -90,6 +123,6 @@ public class ValueConstraint extends Con
     }
     @Override
     public String toString() {
-        return String.format("ValueConstraint[value=%s|types:%s]",value,dataTypeUris);
+        return String.format("ValueConstraint[values=%s|types:%s]",values,dataTypeUris);
     }
 }

Modified: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/fragment/EntityhubWebFragment.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/fragment/EntityhubWebFragment.java?rev=1333433&r1=1333432&r2=1333433&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/fragment/EntityhubWebFragment.java (original)
+++ incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/fragment/EntityhubWebFragment.java Thu May  3 12:47:18 2012
@@ -34,6 +34,9 @@ import org.apache.stanbol.entityhub.jers
 import org.apache.stanbol.entityhub.jersey.resource.EntityhubRootResource;
 import org.apache.stanbol.entityhub.jersey.resource.ReferencedSiteRootResource;
 import org.apache.stanbol.entityhub.jersey.resource.SiteManagerRootResource;
+import org.apache.stanbol.entityhub.jersey.resource.reconcile.EntityhubReconcileResource;
+import org.apache.stanbol.entityhub.jersey.resource.reconcile.ReferencedSiteReconcileResource;
+import org.apache.stanbol.entityhub.jersey.resource.reconcile.SiteManagerReconcileResource;
 import org.apache.stanbol.entityhub.jersey.writers.JettisonWriter;
 import org.apache.stanbol.entityhub.jersey.writers.QueryResultListWriter;
 import org.apache.stanbol.entityhub.jersey.writers.RepresentationWriter;
@@ -74,6 +77,10 @@ public class EntityhubWebFragment implem
         //classes.add(EntityMappingResource.class);
         classes.add(ReferencedSiteRootResource.class);
         classes.add(SiteManagerRootResource.class);
+        //Google Refine Reconciliation API support
+        classes.add(ReferencedSiteReconcileResource.class);
+        classes.add(EntityhubReconcileResource.class);
+        classes.add(SiteManagerReconcileResource.class);
         //classes.add(SymbolResource.class);
         // message body readers and writers
         classes.add(FieldQueryReader.class);

Added: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/grefine/ReconcileQuery.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/grefine/ReconcileQuery.java?rev=1333433&view=auto
==============================================================================
--- incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/grefine/ReconcileQuery.java (added)
+++ incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/grefine/ReconcileQuery.java Thu May  3 12:47:18 2012
@@ -0,0 +1,409 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.stanbol.entityhub.jersey.grefine;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
+import org.apache.stanbol.entityhub.core.model.InMemoryValueFactory;
+import org.apache.stanbol.entityhub.servicesapi.defaults.NamespaceEnum;
+import org.apache.stanbol.entityhub.servicesapi.model.ValueFactory;
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Java Representation for <a href="http://code.google.com/p/google-refine/wiki/ReconciliationServiceApi#Query_Request">
+ * Google Refine Reconciliation queries</a>.<p>
+ * {@link #getTypes()} and {@link Value#getId()} do support 'prefix:localname'
+ * syntax for prefixes defined in the {@link NamespaceEnum}.
+ * Also defines methods for parsing single and multiple request strings.
+ * 
+ * @author Rupert Westenthaler
+ *
+ */
+public class ReconcileQuery {
+
+    private static final Logger log = LoggerFactory.getLogger(ReconcileQuery.class);
+    
+    public static final Integer DEFAULT_LIMIT = 5;
+    
+    public static final TYPE_STRICT DEFAULT_TYPE_STRICT = TYPE_STRICT.any;
+    
+    private final String query;
+    
+    private final Set<String> types;
+    
+    private Integer limit;
+    
+    private final Map<String,Collection<Value>> properties = new HashMap<String,Collection<Value>>();
+    
+    private TYPE_STRICT typeStrict;
+    
+    protected static final ValueFactory vf = InMemoryValueFactory.getInstance();
+    
+    /**
+     * @return the limit
+     */
+    public final Integer getLimit() {
+        return limit;
+    }
+
+    /**
+     * @param limit the limit to set
+     */
+    public final void setLimit(Integer limit) {
+        this.limit = limit;
+    }
+
+    /**
+     * @return the typeStrict
+     */
+    public final TYPE_STRICT getTypeStrict() {
+        return typeStrict;
+    }
+
+    /**
+     * @param typeStrict the typeStrict to set
+     */
+    public final void setTypeStrict(TYPE_STRICT typeStrict) {
+        this.typeStrict = typeStrict;
+    }
+
+    /**
+     * @return the query
+     */
+    public final String getQuery() {
+        return query;
+    }
+
+    /**
+     * @return the types
+     */
+    public final Set<String> getTypes() {
+        return types;
+    }
+
+
+    public static enum TYPE_STRICT {any,all,should};
+
+
+    public ReconcileQuery(String query,Collection<String> types) {
+        if(query == null || query.isEmpty()){
+            throw new IllegalArgumentException("The parsed query string MUST NOT be NULL nor empty!");
+        }
+        this.query = query;
+        if(types == null || types.isEmpty()){
+            this.types = Collections.emptySet();
+        } else {
+            Set<String> t = new HashSet<String>(types.size());
+            for(String type : types){
+                if(type != null && !type.isEmpty()){
+                    t.add(type);
+                }
+            }
+            this.types = Collections.unmodifiableSet(t);
+        }
+    }
+    
+    public Collection<Value> putProperty(String field, Collection<Value> values){
+        if(field == null || field.isEmpty()){
+            throw new IllegalArgumentException("The field for an property MUST NOT be NULL!");
+        }
+        if(values == null || values.isEmpty()){
+            return properties.remove(values);
+        } else {
+            return properties.put(field, values);
+        }
+    }
+    public Collection<Value> removeProperty(String field){
+        return properties.remove(field);
+    }
+    public Collection<Value> getProperty(String field){
+        return properties.get(field);
+    }
+    public Iterable<Entry<String,Collection<Value>>> getProperties(){
+        return properties.entrySet();
+    }
+    /**
+     * Values can be simple JSON values or JSON objects with an 'id' and a
+     * 'name'. This is mapped to {@link Value} objects with an optional 
+     * {@link #getId()} and a required {@link #getValue()}.<p>
+     * The 'id' supports prefix:localname syntax for prefixes defined within the
+     * {@link NamespaceEnum}
+     * @author Rupert Westenthaler
+     *
+     */
+    public static class Value {
+        private final String id;
+        private final Object value;
+
+        private Value(Object value){
+            this(null,value);
+        }
+        private Value(String id, Object value){
+            this.id = id == null ? null : NamespaceEnum.getFullName(id);
+            if(value == null){
+                throw new IllegalArgumentException("The parsed value MUST NOT be NULL!");
+            }
+            this.value = value;
+        }
+
+        /**
+         * The getter for the value of the 'id' property of the 'v' object
+         * if present. This represents the value of fields that are already
+         * successfully linked (reconciled) with some entity.
+         * @return the id
+         */
+        public String getId() {
+            return id;
+        }
+
+        /**
+         * @return the value
+         */
+        public Object getValue() {
+            return value;
+        }
+        /**
+         * Calls the {@link #toString()} method of the {@link #getValue()}
+         */
+        @Override
+        public String toString() {
+            return value.toString();
+        }
+        @Override
+        public int hashCode() {
+            return id != null ? id.hashCode() : value.hashCode();
+        }
+        @Override
+        public boolean equals(Object o) {
+            return o instanceof Value && ( //other is value
+                    (id != null && id.equals(((Value) o).id)) || //ids are equals or 
+                        (id == null && ((Value)o).id == null //ids are null and
+                        && value.equals(((Value)o).value))); //values are equals
+            
+        }
+    }
+    
+    public static Map<String,ReconcileQuery> parseQueries(String queriesString) throws WebApplicationException {
+        JSONObject jQueries;
+        try {
+            jQueries = new JSONObject(queriesString);
+        }catch (JSONException e) {
+            throw new WebApplicationException(
+                Response.status(Response.Status.BAD_REQUEST).entity(
+                    "The parsed query is illegal formatted! \n query: \n"+queriesString+"\n").build());
+        }
+        @SuppressWarnings("unchecked")
+        Iterator<String> keys = jQueries.keys();
+        Map<String,ReconcileQuery> queries = new HashMap<String,ReconcileQuery>();
+        while(keys.hasNext()){
+            String key = keys.next();
+            try {
+                ReconcileQuery query = parseQuery(jQueries.getJSONObject(key));
+                queries.put(key, query);
+            } catch (JSONException e) {
+                throw new WebApplicationException(
+                    Response.status(Response.Status.BAD_REQUEST).entity(
+                        "The query of key '"+key+"is illegal formatted! \n query: \n"
+                                + queriesString+"\n").build());
+            }
+        }
+        return queries;
+    }
+    /**
+     * Parses a Google Refine Reconcile Query from the parsed String.
+     * @param queryString the string representation of the reconcile query
+     * @return the parsed {@link ReconcileQuery} object
+     * @throws WebApplicationException {@link Response.Status#BAD_REQUEST} in
+     * case of the parsed string is not a well formated query. Unsupported
+     * Properties are silently ignored (warnings are still logged).
+     */
+    public static ReconcileQuery parseQuery(String queryString) throws WebApplicationException {
+        JSONObject jQuery;
+        try {
+            if(queryString.charAt(0) == '{') {
+                jQuery = new JSONObject(queryString);
+            } else {
+                jQuery = new JSONObject();
+                jQuery.put("query", queryString);
+                //simple string query
+            }
+        }catch (JSONException e) {
+            throw new WebApplicationException(
+                Response.status(Response.Status.BAD_REQUEST).entity(
+                    "The parsed query is illegal formatted! \n query: \n"+queryString+"\n").build());
+        }
+        return parseQuery(jQuery);
+    }
+    
+    private static ReconcileQuery parseQuery(JSONObject jQuery) throws WebApplicationException {
+        //query (string)
+        //limit (integer), optional
+        //type (string| [string]), optional
+        //type_strict ("any","all","should"), optional
+        //properties ([Property]), optional
+        //    Property:
+        //        p (string)  -> ignore
+        //        pid (string) -> uri
+        //        v (string/Value, [string/Value]), required
+        //    Value
+        //        id (uri)
+        String value = jQuery.optString("query");
+        if(value == null || value.isEmpty()){
+            throw new WebApplicationException(
+                Response.status(Response.Status.BAD_REQUEST).entity(
+                    "The parsed query is illegal formatted! \n query: \n"+jQuery.toString()+"\n").build());
+        }
+        JSONArray jTypes = null;
+        Collection<String> types;
+        if(!jQuery.has("type")){
+            types = Collections.emptySet();
+        } else if((jTypes = jQuery.optJSONArray("type")) != null){
+            types = new HashSet<String>(jTypes.length());
+            for(int i=0;i<jTypes.length();i++){
+                String type = NamespaceEnum.getFullName(jTypes.optString(i));
+                if(type != null && !type.isEmpty()){
+                    types.add(type);
+                }
+            }
+        } else {
+            String type = jQuery.optString("type");
+            if(type != null && !type.isEmpty()){
+                types = Collections.singleton(type);
+            } else {
+                types = Collections.emptySet();
+            }
+        }
+        ReconcileQuery reconcileQuery = new ReconcileQuery(value,types);
+        //TYPE_STRICT typeStrict = null;
+        String jTypeStrict = jQuery.optString("type_strict");
+        if(jTypeStrict != null){
+            try {
+                reconcileQuery.setTypeStrict(TYPE_STRICT.valueOf(jTypeStrict));
+            } catch (RuntimeException e) {
+                log.warn("Unknown \"type_strict\" value in Google Refine Reconcile" +
+                        " Request (use default '{}')\n {}",DEFAULT_TYPE_STRICT,jQuery.toString());
+                reconcileQuery.setTypeStrict(DEFAULT_TYPE_STRICT);
+            }
+        } else {
+            reconcileQuery.setTypeStrict(DEFAULT_TYPE_STRICT);
+        }
+        reconcileQuery.setLimit(jQuery.optInt("limit", DEFAULT_LIMIT));
+        JSONArray jProperties = jQuery.optJSONArray("properties");
+        if(jProperties != null){
+            for(int i=0;i<jProperties.length();i++){
+                parseProperty(reconcileQuery, jProperties.optJSONObject(i));
+            }
+        }
+        return reconcileQuery;
+    }
+
+
+    /**
+     * Internally used to parse a Property of a Google Refine Reconcile Query
+     * @param reconcileQuery the query to add the property
+     * @param jProperty the JSON formatted property
+     */
+    private static void parseProperty(ReconcileQuery reconcileQuery,JSONObject jProperty) {
+        if(jProperty != null){
+            //parse property
+            String property = NamespaceEnum.getFullName(jProperty.optString("pid"));
+            if(property == null){
+                log.warn("Ignore Property because of missing 'pid'! \n{}",jProperty.toString());
+            } else {
+                //property keys may appear multiple times in queries
+                //so we need to initialise the property values with already
+                //existing values
+                Collection<Value> values = reconcileQuery.getProperty(property);
+                if(values == null){ //if not create a new Set
+                    //maybe the order is important (e.g. for similarity alg) 
+                    //   ... so try to keep it
+                    values = new LinkedHashSet<Value>();
+                }
+                //parse the value
+                Object jValue = jProperty.opt("v");
+                if(jValue == null){
+                    log.warn("Ignore Property '{}' because it has no value! \n {}",property,jProperty.toString());
+                } else if(jValue instanceof JSONObject){
+                    //Reconciliation data available!
+                    Value value = parseValueFromV(jValue);
+                    if(value != null){
+                        values.add(value);
+                    } else {
+                        log.warn("ignore value for property {} because no name is present (value: {})!",
+                            property,jValue.toString());
+                    }
+                } else if(jValue instanceof JSONArray){
+                    //parse value list
+                    JSONArray jValueArray = (JSONArray)jValue;
+                    for(int j=0;j<jValueArray.length();j++){
+                        jValue = jValueArray.opt(j);
+                        if(jValue instanceof JSONObject){
+                            //Reconciliation data available!
+                            Value value = parseValueFromV(jValue);
+                            if(value != null){
+                                values.add(value);
+                            } else {
+                                log.warn("ignore value for property {} because no name is present (value: {})!",
+                                    property,jValue.toString());
+                            }
+                        } else if(jValue != null){
+                            values.add(new Value(jValue));
+                        }
+                    }
+                    if(values.isEmpty()){
+                        log.warn("Ignore Property '{}' because it does not define a valid value! \n {}",
+                            property,jProperty.toString());
+                    }
+                } else { //number or String
+                    values.add(new Value(jValue)); //directly use the value
+                }
+                
+                if(!values.isEmpty()){
+                    reconcileQuery.putProperty(property, values);
+                }
+            }
+        }
+    }
+
+    /**
+     * Parses a Value from a JSON Object by reading the 'id' and 'name' keys
+     * @param jValue
+     * @return The value or <code>null</code> if the parsed json object does not
+     * contain the required information.
+     */
+    private static Value parseValueFromV(Object jValue) {
+        String id = ((JSONObject)jValue).optString("id");
+        String value = ((JSONObject)jValue).optString("name");
+        return value != null ? new Value(id,value) : null;
+    }
+    
+}

Propchange: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/grefine/ReconcileQuery.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/grefine/Utils.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/grefine/Utils.java?rev=1333433&view=auto
==============================================================================
--- incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/grefine/Utils.java (added)
+++ incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/grefine/Utils.java Thu May  3 12:47:18 2012
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.stanbol.entityhub.jersey.grefine;
+
+import static org.apache.commons.lang.StringUtils.getLevenshteinDistance;
+
+import org.apache.commons.lang.StringUtils;
+
+public class Utils {
+
+    
+    /**
+     * Compares two strings (after {@link StringUtils#trim(String) trimming} 
+     * by using the Levenshtein's Edit Distance of the two
+     * strings. Does not return the {@link Integer} number of changes but
+     * <code>1-(changes/maxStringSizeAfterTrim)</code><p>
+     * @param s1 the first string
+     * @param s2 the second string
+     * @return the distance
+     * @throws IllegalArgumentException if any of the two parsed strings is NULL
+     */
+    public static double levenshtein(String s1, String s2) {
+        if(s1 == null || s2 == null){
+            throw new IllegalArgumentException("NONE of the parsed String MUST BE NULL!");
+        }
+        s1 = StringUtils.trim(s1);
+        s2 = StringUtils.trim(s2);
+        return s1.isEmpty() || s2.isEmpty() ? 0 :
+            1.0 - (((double)getLevenshteinDistance(s1, s2)) / ((double)(Math.max(s1.length(), s2.length()))));
+    }
+}

Propchange: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/grefine/Utils.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/parsers/FieldQueryReader.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/parsers/FieldQueryReader.java?rev=1333433&r1=1333432&r2=1333433&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/parsers/FieldQueryReader.java (original)
+++ incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/parsers/FieldQueryReader.java Thu May  3 12:47:18 2012
@@ -497,7 +497,36 @@ public class FieldQueryReader implements
         Constraint constraint;
         Collection<String> dataTypes = parseDatatypeProperty(jConstraint);
         if(jConstraint.has("value") && !jConstraint.isNull("value")){
-            constraint = new ValueConstraint(jConstraint.get("value"), dataTypes);
+            Object value = jConstraint.get("value");
+            final List<Object> valueList;
+            if(value instanceof JSONArray){
+                valueList = new ArrayList<Object>(((JSONArray)value).length());
+                for(int i=0;i<((JSONArray)value).length();i++){
+                    Object v = ((JSONArray)value).get(i);
+                    if(v == null || v instanceof JSONArray || v instanceof JSONObject){
+                        log.warn("Parsed ValueConstraint does define illegal values (values={})!",value);
+                        StringBuilder message = new StringBuilder();
+                        message.append("Parsed ValueConstraint does define illegal values for field 'value'" +
+                        		"(value MUST NOT contain NULL, JSONObject nor JSONArray values)!\n");
+                        message.append("Parsed Constraint: \n");
+                        message.append(jConstraint.toString(4));
+                        throw new IllegalArgumentException(message.toString());
+                    }
+                    valueList.add(v);
+                }
+            } else if(value instanceof JSONObject){
+                log.warn("Parsed ValueConstraint does define illegal values (values={})!",value);
+                StringBuilder message = new StringBuilder();
+                message.append("Parsed ValueConstraint does define illegal value for field 'value'" +
+                        "(value MUST NOT be an JSON object. Only values and JSONArray to parse" +
+                        "multiple values are allowed)!\n");
+                message.append("Parsed Constraint: \n");
+                message.append(jConstraint.toString(4));
+                throw new IllegalArgumentException(message.toString());
+            } else {
+                valueList = Collections.singletonList(jConstraint.get("value"));
+            }
+            constraint = new ValueConstraint(valueList,dataTypes);
         } else {
             log.warn("Parsed ValueConstraint does not define the required field \"value\"!");
             StringBuilder message = new StringBuilder();
@@ -559,7 +588,26 @@ public class FieldQueryReader implements
     private static Constraint parseReferenceConstraint(JSONObject jConstraint) throws JSONException {
         Constraint constraint;
         if(jConstraint.has("value") && !jConstraint.isNull("value")){
-            constraint = new ReferenceConstraint(jConstraint.getString("value"));
+            Object value = jConstraint.get("value");
+            final List<String> refList;
+            if(value instanceof JSONArray){
+                refList = new ArrayList<String>(((JSONArray)value).length());
+                for(int i=0;i<((JSONArray)value).length();i++){
+                    refList.add(NamespaceEnum.getFullName(((JSONArray)value).getString(i)));
+                }
+            } else if(value instanceof JSONObject){
+                log.warn("Parsed ValueConstraint does define illegal values (values={})!",value);
+                StringBuilder message = new StringBuilder();
+                message.append("Parsed ValueConstraint does define illegal value for field 'value'" +
+                        "(value MUST NOT be an JSON object. Only values and JSONArray to parse" +
+                        "multiple values are allowed)!\n");
+                message.append("Parsed Constraint: \n");
+                message.append(jConstraint.toString(4));
+                throw new IllegalArgumentException(message.toString());
+            } else {
+                refList = Collections.singletonList(NamespaceEnum.getFullName(jConstraint.getString("value")));
+            }
+            constraint = new ReferenceConstraint(refList);
         } else {
             log.warn("Parsed ReferenceConstraint does not define the required field \"value\"!");
             StringBuilder message = new StringBuilder();

Added: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/BaseGoogleRefineReconcileResource.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/BaseGoogleRefineReconcileResource.java?rev=1333433&view=auto
==============================================================================
--- incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/BaseGoogleRefineReconcileResource.java (added)
+++ incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/BaseGoogleRefineReconcileResource.java Thu May  3 12:47:18 2012
@@ -0,0 +1,374 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.stanbol.entityhub.jersey.resource.reconcile;
+
+import static javax.ws.rs.core.MediaType.TEXT_HTML;
+import static org.apache.stanbol.commons.web.base.CorsHelper.addCORSOrigin;
+import static org.apache.stanbol.commons.web.base.CorsHelper.enableCORS;
+import static org.apache.stanbol.entityhub.servicesapi.model.rdf.RdfResourceEnum.resultScore;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.POST;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import org.apache.stanbol.commons.web.base.CorsHelper;
+import org.apache.stanbol.commons.web.base.resource.BaseStanbolResource;
+import org.apache.stanbol.commons.web.base.utils.MediaTypeUtil;
+import org.apache.stanbol.entityhub.jersey.grefine.ReconcileQuery;
+import org.apache.stanbol.entityhub.jersey.grefine.Utils;
+import org.apache.stanbol.entityhub.jersey.grefine.ReconcileQuery.Value;
+import org.apache.stanbol.entityhub.servicesapi.EntityhubException;
+import org.apache.stanbol.entityhub.servicesapi.defaults.NamespaceEnum;
+import org.apache.stanbol.entityhub.servicesapi.model.Reference;
+import org.apache.stanbol.entityhub.servicesapi.model.Representation;
+import org.apache.stanbol.entityhub.servicesapi.model.Text;
+import org.apache.stanbol.entityhub.servicesapi.query.FieldQuery;
+import org.apache.stanbol.entityhub.servicesapi.query.QueryResultList;
+import org.apache.stanbol.entityhub.servicesapi.query.ReferenceConstraint;
+import org.apache.stanbol.entityhub.servicesapi.query.TextConstraint;
+import org.apache.stanbol.entityhub.servicesapi.query.ValueConstraint;
+import org.apache.stanbol.entityhub.servicesapi.site.ReferencedSiteException;
+import org.apache.stanbol.entityhub.servicesapi.util.ModelUtils;
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.jersey.api.view.Viewable;
+
+/**
+ * Implementation of the <a href="http://code.google.com/p/google-refine/wiki/ReconciliationServiceApi">
+ * Google Refine Reconciliation API</a>
+ * This base class is used to support this API for the Entityhub, ReferencedSites
+ * and the ReferencedSiteManager.
+ * 
+ * @author Rupert Westenthaler
+ *
+ */
+public abstract class BaseGoogleRefineReconcileResource extends BaseStanbolResource {
+
+    private final Logger log = LoggerFactory.getLogger(BaseGoogleRefineReconcileResource.class);
+
+    private static final String NAME_FIELD = NamespaceEnum.rdfs+"label";
+    private static final String TYPE_FIELD = NamespaceEnum.rdf+"type";
+    private static final Collection<String> SELECTED_FIELDS = Collections.unmodifiableList(
+        Arrays.asList(NAME_FIELD,TYPE_FIELD));
+
+
+    protected BaseGoogleRefineReconcileResource(){
+        super();
+    }
+    
+    @OPTIONS
+    public final Response handleCorsPreflight(@Context HttpHeaders headers){
+        ResponseBuilder res = Response.ok();
+        enableCORS(servletContext, res, headers);
+        return res.build();
+    }
+    
+    @POST
+    public final Response queryPOST(@FormParam(value="query") String query, 
+                          @FormParam(value="queries")String queries,
+                          @FormParam(value="callback")String callback,
+                          @Context HttpHeaders header) throws WebApplicationException {
+        return query(query,queries,callback,header);
+    }
+    @GET
+    public final Response query(@QueryParam(value="query") String query, 
+                          @QueryParam(value="queries")String queries,
+                          @QueryParam(value="callback")String callback,
+                          @Context HttpHeaders header) throws WebApplicationException {
+        if(callback != null){
+            log.info("callback: {}",callback);
+            try {
+                return sendMetadata(callback,header);
+            } catch (JSONException e) {
+                throw new WebApplicationException(e);
+            }
+        }
+        JSONObject jResult;
+        if(query != null){
+            log.debug("query: {}",query);
+            try {
+                jResult = reconcile(ReconcileQuery.parseQuery(query));
+            } catch (JSONException e) {
+                throw new WebApplicationException(
+                    Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
+                        String.format("Error while writing Reconcilation results (%s: %s)",
+                            JSONException.class.getSimpleName(),e.getMessage())).build());
+            } catch (EntityhubException e) {
+                throw new WebApplicationException(
+                    Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
+                        String.format("Error while searching on %s (%s: %s)",
+                            getSiteName(),ReferencedSiteException.class.getSimpleName(),e.getMessage())).build());
+            }
+        } else if(queries != null){
+            log.debug("multi-query: {}",queries);
+            try {
+                jResult = reoncile(ReconcileQuery.parseQueries(queries));
+            } catch (JSONException e) {
+                throw new WebApplicationException(
+                    Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
+                        String.format("Error while writing Reconcilation results (%s: %s)",
+                            JSONException.class.getSimpleName(),e.getMessage())).build());
+            } catch (EntityhubException e) {
+                throw new WebApplicationException(
+                    Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
+                        String.format("Error while searching on %s (%s: %s)",
+                            getSiteName(),ReferencedSiteException.class.getSimpleName(),e.getMessage())).build());
+            }
+        } else {
+            if(MediaTypeUtil.isAcceptableMediaType(header,MediaType.TEXT_HTML_TYPE)){
+                ResponseBuilder rb = Response.ok(new Viewable("index", this));
+                rb.header(HttpHeaders.CONTENT_TYPE, TEXT_HTML+"; charset=utf-8");
+                addCORSOrigin(servletContext, rb, header);
+                return rb.build();
+            }
+            throw new WebApplicationException(
+                Response.status(Response.Status.BAD_REQUEST).entity(
+                    "One of the 'query' or 'querues' or 'callback=jsonp' parameter MUST BE present!").build());
+        }
+        //return the results and enable Cors
+        ResponseBuilder rb = Response.ok(jResult.toString()).type(MediaType.APPLICATION_JSON_TYPE);
+        CorsHelper.addCORSOrigin(servletContext, rb, header);
+        return rb.build();
+
+    }
+
+
+    private JSONObject reoncile(Map<String,ReconcileQuery> parsedQueries) throws JSONException, EntityhubException {
+        JSONObject container = new JSONObject();
+        for(Entry<String,ReconcileQuery> query : parsedQueries.entrySet()){
+            container.put(query.getKey(), reconcile(query.getValue()));
+        }
+        return container;
+    }
+
+    private JSONObject reconcile(ReconcileQuery rQuery) throws JSONException, EntityhubException {
+        FieldQuery query = createFieldQuery();
+        query.addSelectedFields(SELECTED_FIELDS);
+        addNameConstraint(rQuery, query);
+        addTypeConstraint(rQuery, query);
+        addPropertyConstraints(rQuery, query);
+        query.setLimit(query.getLimit());
+        QueryResultList<Representation> results = performQuery(query);
+        JSONArray jResultList = new JSONArray();
+        //we need to know the highest score to normalise between [0..1]
+        double maxQueryScore = -1;
+        if(!results.isEmpty()){
+            for(Representation r : results){
+                if(maxQueryScore < 0){
+                    maxQueryScore = r.getFirst(resultScore.getUri(),Number.class).doubleValue();
+                }
+                JSONObject jResult = new JSONObject();
+                jResult.put("id", r.getId());
+                double similarity = 0.0;
+                String name = null; //the name returned for the entity
+                for(Iterator<Text> labels = r.getText(NAME_FIELD);labels.hasNext();){
+                    Text label = labels.next();
+                    if(label.getText().equalsIgnoreCase(rQuery.getQuery())){
+                        name = label.getText();
+                        similarity = 1.0;
+                        break;
+                    }
+                    double curSimilarity = Utils.levenshtein(rQuery.getQuery(), label.getText());
+                    if(similarity < curSimilarity){
+                        name = label.getText();
+                        similarity = curSimilarity;
+                    }
+                }
+                //set the selected name
+                jResult.put("name", name);
+                Iterator<Reference> types = r.getReferences(TYPE_FIELD);
+                if(types != null && types.hasNext()) {
+                    jResult.put("type", new JSONArray(ModelUtils.asCollection(types)));
+                }
+                double normalisedScore = r.getFirst(resultScore.getUri(),Number.class).doubleValue();
+                normalisedScore = normalisedScore*similarity/maxQueryScore;
+                jResult.put("score", normalisedScore);
+                jResult.put("match", similarity >= 0);
+                jResultList.put(jResult);
+            }
+        } //else no results ... nothing todo
+        JSONObject jResultContainer = new JSONObject();
+        jResultContainer.put("result", jResultList);
+        return jResultContainer;
+    }
+    /**
+     * @param query
+     * @return
+     * @throws ReferencedSiteException
+     */
+    protected abstract QueryResultList<Representation> performQuery(FieldQuery query) throws EntityhubException;
+    
+    /**
+     * Getter for the name of the Site as used for logging
+     * @return
+     */
+    protected abstract String getSiteName();
+    
+    /**
+     * Creates a new FieldQuery
+     * @return
+     */
+    protected abstract FieldQuery createFieldQuery();
+    
+    /**
+     * @param rQuery
+     * @param query
+     */
+    private void addPropertyConstraints(ReconcileQuery rQuery, FieldQuery query) {
+        Collection<String> ids = new HashSet<String>();
+        List<String> texts = new ArrayList<String>(); // keep order for texts
+        Collection<Object> values = new HashSet<Object>();
+        for (Entry<String,Collection<Value>> property : rQuery.getProperties()) {
+            // collect the properties
+            for (Value value : property.getValue()) {
+                if (value.getId() != null) {
+                    ids.add(value.getId());
+                }
+                if (value.getValue() instanceof String) {
+                    texts.add((String) value.getValue());
+                } else {
+                    values.add(value.getValue());
+                }
+            }
+            // add the Constraint to the FieldQuery
+            // TODO: how to deal with values of different types
+            //  * currently References > Text > Datatype. First present value
+            //    is used
+            //  * non Reference | Text | Datatype values are ignored
+            if (!ids.isEmpty()) {
+                // only references -> create reference constraint
+                query.setConstraint(property.getKey(), new ReferenceConstraint(ids));
+                if (ids.size() != property.getValue().size()) {
+                    log.info("Only some of the parsed values of the field {} contain"
+                             + "references -> will ignore values with missing references");
+                }
+            } else if (!texts.isEmpty()) {
+                // NOTE: This will use OR over all texts. To enforce AND one
+                // would need to parse a single string with all values e.g. by
+                // using StringUtils.join(texts," ")
+                query.setConstraint(property.getKey(), new TextConstraint(texts));
+                if (ids.size() != property.getValue().size()) {
+                    log.info("Only some of the parsed values of the field {} are"
+                             + "of type String -> will ignore non-string values");
+                }
+            } else if(!values.isEmpty()){
+                query.setConstraint(property.getKey(), new ValueConstraint(values));
+            } //else no values ... ignore property
+            //clean up
+            ids.clear();
+            texts.clear();
+            values.clear();
+        }
+    }
+    /**
+     * @param rQuery
+     * @param query
+     */
+    private void addTypeConstraint(ReconcileQuery rQuery, FieldQuery query) {
+        //maybe an other column was also mapped to the TYPE_FIELD property
+        Collection<Value> additionalTypes = rQuery.removeProperty(TYPE_FIELD);
+        Set<String> queryTypes = rQuery.getTypes();
+        Set<String> types = null;
+        if(additionalTypes == null){
+            if(queryTypes != null){
+                types = queryTypes;
+            }
+        } else {
+            types = new HashSet<String>();
+            if(queryTypes != null){
+                types.add(rQuery.getQuery());
+            }
+            for(Value value : additionalTypes){
+                if(value != null){
+                    if(value.getId() != null){
+                        types.add(value.getId());
+                    } else if (value.getValue() instanceof String){
+                        //TODO: check if the assumption that String values are
+                        //good for types is valid
+                        types.add((String)value.getValue());
+                    }
+                } //else null -> ignore
+            }
+        }
+        if (!types.isEmpty()) {
+            query.setConstraint(TYPE_FIELD, new ReferenceConstraint(types));
+        }
+    }
+    /**
+     * @param rQuery
+     * @param query
+     */
+    private void addNameConstraint(ReconcileQuery rQuery, FieldQuery query) {
+        //maybe an other column was also mapped to the NAME_FIELD property
+        Collection<Value> additionalValues = rQuery.removeProperty(NAME_FIELD);
+        List<String> values;
+        if(additionalValues == null){
+            values = Collections.singletonList(rQuery.getQuery());
+        } else {
+            values = new ArrayList<String>(additionalValues.size()+1);
+            values.add(rQuery.getQuery());
+            for(Value value : additionalValues){
+                if(value != null && value.getValue() instanceof String){
+                    values.add((String)value.getValue());
+                }
+            }
+        }
+        query.setConstraint(NAME_FIELD, new TextConstraint(values));
+    }
+    /**
+     * Called on requests for the Metadata for the Reconciliation service
+     * @param callback
+     * @param header
+     * @return
+     * @throws JSONException
+     */
+    protected Response sendMetadata(String callback, HttpHeaders header) throws JSONException {
+        //TODO: implement!!
+        JSONObject jMetadata = new JSONObject();
+        jMetadata.put("name", "Stanbol Entityhub: "+getSiteName());
+        StringBuilder callbackString = new StringBuilder(callback);
+        callbackString.append('(');
+        callbackString.append(jMetadata.toString());
+        callbackString.append(')');
+        ResponseBuilder rb = Response.ok(callbackString.toString()).type(MediaType.APPLICATION_JSON_TYPE);
+        CorsHelper.addCORSOrigin(servletContext, rb, header);
+        return rb.build();
+    }
+}

Propchange: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/BaseGoogleRefineReconcileResource.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/EntityhubReconcileResource.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/EntityhubReconcileResource.java?rev=1333433&view=auto
==============================================================================
--- incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/EntityhubReconcileResource.java (added)
+++ incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/EntityhubReconcileResource.java Thu May  3 12:47:18 2012
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.stanbol.entityhub.jersey.resource.reconcile;
+
+import javax.ws.rs.Path;
+
+import org.apache.stanbol.commons.web.base.ContextHelper;
+import org.apache.stanbol.entityhub.servicesapi.Entityhub;
+import org.apache.stanbol.entityhub.servicesapi.EntityhubException;
+import org.apache.stanbol.entityhub.servicesapi.model.Representation;
+import org.apache.stanbol.entityhub.servicesapi.query.FieldQuery;
+import org.apache.stanbol.entityhub.servicesapi.query.QueryResultList;
+
+@Path("/entityhub/reconcile")
+public class EntityhubReconcileResource extends BaseGoogleRefineReconcileResource {
+
+    private Entityhub _entityhub;
+    
+    public EntityhubReconcileResource() {
+        super();
+    }
+    private Entityhub getEntityhub(){
+        if(_entityhub == null){
+            _entityhub = ContextHelper.getServiceFromContext(Entityhub.class, servletContext);
+            if(_entityhub == null){
+                throw new IllegalArgumentException("The Entityhub service is currently not available!");
+            }
+        }
+        return _entityhub;
+    }
+    
+    @Override
+    protected QueryResultList<Representation> performQuery(FieldQuery query) throws EntityhubException {
+        return getEntityhub().find(query);
+    }
+
+    @Override
+    protected String getSiteName() {
+        return "Entityhub (local managed Entities)";
+    }
+
+    @Override
+    protected FieldQuery createFieldQuery() {
+        return getEntityhub().getQueryFactory().createFieldQuery();
+    }
+
+}

Propchange: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/EntityhubReconcileResource.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/ReferencedSiteReconcileResource.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/ReferencedSiteReconcileResource.java?rev=1333433&view=auto
==============================================================================
--- incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/ReferencedSiteReconcileResource.java (added)
+++ incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/ReferencedSiteReconcileResource.java Thu May  3 12:47:18 2012
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.stanbol.entityhub.jersey.resource.reconcile;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.stanbol.commons.web.base.ContextHelper;
+import org.apache.stanbol.entityhub.servicesapi.model.Representation;
+import org.apache.stanbol.entityhub.servicesapi.query.FieldQuery;
+import org.apache.stanbol.entityhub.servicesapi.query.QueryResultList;
+import org.apache.stanbol.entityhub.servicesapi.site.ReferencedSite;
+import org.apache.stanbol.entityhub.servicesapi.site.ReferencedSiteException;
+import org.apache.stanbol.entityhub.servicesapi.site.ReferencedSiteManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Path("/entityhub/site/{site}/reconcile")
+public class ReferencedSiteReconcileResource extends BaseGoogleRefineReconcileResource {
+    
+    private final Logger log = LoggerFactory.getLogger(ReferencedSiteReconcileResource.class);
+    private ReferencedSiteManager _siteManager;
+    private final String siteId;
+    
+    
+    
+    public ReferencedSiteReconcileResource(@PathParam(value = "site") String siteId) {
+       super();
+       if (siteId == null || siteId.isEmpty()) {
+           log.error("Missing path parameter site={}", siteId);
+           throw new WebApplicationException(Response.Status.NOT_FOUND);
+       }
+       this.siteId = siteId;
+    }
+    private ReferencedSite getSite() throws WebApplicationException {
+        if(_siteManager == null){
+            _siteManager = ContextHelper.getServiceFromContext(
+                ReferencedSiteManager.class, servletContext);
+            if(_siteManager == null){
+                throw new IllegalStateException("Unable to lookup ReferencedSite '"
+                        +siteId+"' because ReferencedSiteManager service is unavailable!");
+            }
+        }
+        ReferencedSite site = _siteManager.getReferencedSite(siteId);
+        if (site == null) {
+            String message = String.format("ReferencedSite '%s' not acitve!",siteId);
+            log.error(message);
+            throw new WebApplicationException(
+                Response.status(Status.NOT_FOUND).entity(message).build());
+        }
+        return site;
+    }
+    /**
+     * @param query
+     * @return
+     * @throws ReferencedSiteException
+     */
+    protected QueryResultList<Representation> performQuery(FieldQuery query) throws ReferencedSiteException {
+        return getSite().find(query);
+    }
+    @Override
+    protected String getSiteName() {
+        return getSite().getId() + "Referenced Site";
+    }
+    @Override
+    protected FieldQuery createFieldQuery() {
+        return getSite().getQueryFactory().createFieldQuery();
+    }
+    
+}

Propchange: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/ReferencedSiteReconcileResource.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/SiteManagerReconcileResource.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/SiteManagerReconcileResource.java?rev=1333433&view=auto
==============================================================================
--- incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/SiteManagerReconcileResource.java (added)
+++ incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/SiteManagerReconcileResource.java Thu May  3 12:47:18 2012
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.stanbol.entityhub.jersey.resource.reconcile;
+
+import javax.ws.rs.Path;
+
+import org.apache.stanbol.commons.web.base.ContextHelper;
+import org.apache.stanbol.entityhub.core.query.DefaultQueryFactory;
+import org.apache.stanbol.entityhub.servicesapi.model.Representation;
+import org.apache.stanbol.entityhub.servicesapi.query.FieldQuery;
+import org.apache.stanbol.entityhub.servicesapi.query.QueryResultList;
+import org.apache.stanbol.entityhub.servicesapi.site.ReferencedSiteException;
+import org.apache.stanbol.entityhub.servicesapi.site.ReferencedSiteManager;
+
+@Path("/entityhub/sites/reconcile")
+public class SiteManagerReconcileResource extends BaseGoogleRefineReconcileResource {
+
+    ReferencedSiteManager _siteManager;
+    
+    public SiteManagerReconcileResource() {
+        super();
+    }
+
+    private ReferencedSiteManager getSiteManager(){
+        if(_siteManager == null){
+            _siteManager = ContextHelper.getServiceFromContext(
+                ReferencedSiteManager.class, servletContext);
+            if(_siteManager == null){
+                throw new IllegalStateException("ReferencedSiteManager service is unavailable!");
+            }
+        }
+        return _siteManager;
+    }
+    @Override
+    protected QueryResultList<Representation> performQuery(FieldQuery query) throws ReferencedSiteException {
+        return getSiteManager().find(query);
+    }
+
+    @Override
+    protected String getSiteName() {
+        return "Referenced Site Manager (all sites)";
+    }
+
+    @Override
+    protected FieldQuery createFieldQuery() {
+        return DefaultQueryFactory.getInstance().createFieldQuery();
+    }
+
+}

Propchange: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/resource/reconcile/SiteManagerReconcileResource.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/writers/FieldQueryToJSON.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/writers/FieldQueryToJSON.java?rev=1333433&r1=1333432&r2=1333433&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/writers/FieldQueryToJSON.java (original)
+++ incubator/stanbol/trunk/entityhub/jersey/src/main/java/org/apache/stanbol/entityhub/jersey/writers/FieldQueryToJSON.java Thu May  3 12:47:18 2012
@@ -88,8 +88,12 @@ final class FieldQueryToJSON {
         switch (constraint.getType()) {
             case value: //both ValueConstraint and ReferenceConstraint
                 ValueConstraint valueConstraint = ((ValueConstraint) constraint);
-                if (valueConstraint.getValue() != null) {
-                    jConstraint.put("value", valueConstraint.getValue());
+                if (valueConstraint.getValues() != null) {
+                    if(valueConstraint.getValues().size() == 1){
+                        jConstraint.put("value", valueConstraint.getValues().iterator().next());
+                    } else {
+                        jConstraint.put("value", new JSONArray(valueConstraint.getValues()));
+                    }
                 }
                 if(constraint instanceof ReferenceConstraint){
                     //the type "reference" is not present in the ConstraintType

Added: incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/static/images/google_refine_reconciliation-add_service.png
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/static/images/google_refine_reconciliation-add_service.png?rev=1333433&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/static/images/google_refine_reconciliation-add_service.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/static/images/google_refine_reconciliation-open_dialog.png
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/static/images/google_refine_reconciliation-open_dialog.png?rev=1333433&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/static/images/google_refine_reconciliation-open_dialog.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/static/images/google_refine_reconciliation-use_service.png
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/static/images/google_refine_reconciliation-use_service.png?rev=1333433&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/static/images/google_refine_reconciliation-use_service.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/EntityhubRootResource/index.ftl
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/EntityhubRootResource/index.ftl?rev=1333433&r1=1333432&r2=1333433&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/EntityhubRootResource/index.ftl (original)
+++ incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/EntityhubRootResource/index.ftl Thu May  3 12:47:18 2012
@@ -79,6 +79,10 @@
     <li>LDPath @<a href="${it.publicBaseUri}entityhub/ldpath">/entityhub/ldpath</a>:
        Allows to execute LDPath programs on locally managed Entities.
     </li>
+    <li>Reconciliation @<a href="${it.publicBaseUri}entityhub/reconcile">/entityhub/reconcile</a>:
+       Implements the <a href="http://code.google.com/p/google-refine/">
+       Google Refine</a> Reconciliation API
+    </li>
   </ul>
   <hr>
   <#include "inc_entity.ftl">

Modified: incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/ReferencedSiteRootResource/index.ftl
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/ReferencedSiteRootResource/index.ftl?rev=1333433&r1=1333432&r2=1333433&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/ReferencedSiteRootResource/index.ftl (original)
+++ incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/ReferencedSiteRootResource/index.ftl Thu May  3 12:47:18 2012
@@ -24,6 +24,11 @@
 	<li><a href="find">/entityhub/site/{siteId}/find</a></li>
 	<li><a href="query">/entityhub/site/{siteId}/query</a></li>
     <li><a href="ldpath">/entityhub/site/{siteId}/ldpath</a></li>
+    <li><a href="reconcile">/entityhub/site/{siteId}/reconcile</a>:
+       Implements the <a href="http://code.google.com/p/google-refine/">
+       Google Refine</a> Reconciliation API
+    </li>
+    
 </ul>
 <hr>
 <#include "inc_metadata.ftl">

Modified: incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/SiteManagerRootResource/index.ftl
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/SiteManagerRootResource/index.ftl?rev=1333433&r1=1333432&r2=1333433&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/SiteManagerRootResource/index.ftl (original)
+++ incubator/stanbol/trunk/entityhub/jersey/src/main/resources/org/apache/stanbol/entityhub/jersey/templates/org/apache/stanbol/entityhub/jersey/resource/SiteManagerRootResource/index.ftl Thu May  3 12:47:18 2012
@@ -25,6 +25,10 @@
 	<li><a href="${it.publicBaseUri}entityhub/sites/find">/entityhub/sites/find</a></li>
 	<li><a href="${it.publicBaseUri}entityhub/sites/query">/entityhub/sites/query</a></li>
     <li><a href="${it.publicBaseUri}entityhub/sites/ldpath">/entityhub/sites/ldpath</a></li>
+    <li><a href="reconcile">/entityhub/sites/reconcile</a>:
+       Implements the <a href="http://code.google.com/p/google-refine/">
+       Google Refine</a> Reconciliation API over all referenced sites.
+    </li>
 </ul>
 
 <hr>

Modified: incubator/stanbol/trunk/entityhub/query/clerezza/src/main/java/org/apache/stanbol/entityhub/query/clerezza/SparqlQueryUtils.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/query/clerezza/src/main/java/org/apache/stanbol/entityhub/query/clerezza/SparqlQueryUtils.java?rev=1333433&r1=1333432&r2=1333433&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/query/clerezza/src/main/java/org/apache/stanbol/entityhub/query/clerezza/SparqlQueryUtils.java (original)
+++ incubator/stanbol/trunk/entityhub/query/clerezza/src/main/java/org/apache/stanbol/entityhub/query/clerezza/SparqlQueryUtils.java Thu May  3 12:47:18 2012
@@ -40,6 +40,7 @@ import org.apache.stanbol.entityhub.serv
 import org.apache.stanbol.entityhub.servicesapi.model.rdf.RdfResourceEnum;
 import org.apache.stanbol.entityhub.servicesapi.query.Constraint;
 import org.apache.stanbol.entityhub.servicesapi.query.RangeConstraint;
+import org.apache.stanbol.entityhub.servicesapi.query.ReferenceConstraint;
 import org.apache.stanbol.entityhub.servicesapi.query.TextConstraint;
 import org.apache.stanbol.entityhub.servicesapi.query.ValueConstraint;
 import org.apache.stanbol.entityhub.servicesapi.query.TextConstraint.PatternType;
@@ -500,22 +501,22 @@ public final class SparqlQueryUtils {
             //see http://www.w3.org/TR/rdf-sparql-query/#QSynLiterals
             dataTypes = Collections.emptySet();
         }
-        if(constraint.getValue() != null){
+        if(constraint.getValues() != null){
             if(dataTypes.size()<=1){
                 addDataTypeValueConstraint(queryString, rootVarName, field,
                         dataTypes.isEmpty()?null:dataTypes.iterator().next(),
-                                constraint.getValue(),intend);
+                                constraint.getValues(),intend);
             } else { //we have multiple dataTypes -> ned to use union!
                 boolean first = true;
                 for(Iterator<String> it = dataTypes.iterator();it.hasNext();){
                     String dataType = it.next();
                     if(first){
-                        queryString.append(intend);
+                        //queryString.append(intend);
                         first = false;
                     } else {
-                        queryString.append(" UNION \n  ").append(intend);
+                        queryString.append(" UNION \n");
                     }
-                    addDataTypeValueConstraint(queryString, rootVarName, field, dataType, constraint.getValue(),"");
+                    addDataTypeValueConstraint(queryString, rootVarName, field, dataType, constraint.getValues(),intend);
                 }
                 //queryString.append('}');
             }
@@ -564,15 +565,33 @@ public final class SparqlQueryUtils {
      * @param dataType the dataType constraint or <code>null</code> if none
      * @param value the value. MUST NOT be <code>null</code>.
      */
-    private static void addDataTypeValueConstraint(StringBuilder queryString, String rootVarName, String field, String dataType, Object value, String intend) {
-        if(DataTypeEnum.Reference.getUri().equals(dataType) ||
-                value instanceof Reference){
-            queryString.append(String.format("%s?%s <%s> <%s>", 
-                intend,rootVarName,field,value));
-        } else {
-            queryString.append(String.format("%s?%s <%s> \"%s\"%s",
-                    intend, rootVarName,field,value,
-                    dataType!=null?String.format("^^<%s>",dataType):""));
+    private static void addDataTypeValueConstraint(StringBuilder queryString, String rootVarName, String field, String dataType, Collection<Object> values, String intend) {
+        String addIntend = intend;
+        queryString.append(intend);
+        if(values.size() > 1){
+            queryString.append("{ ");
+            addIntend = intend+"  ";
+        }
+        boolean first = true;
+        for(Object value : values){
+            if(first){
+                //queryString.append(intend);
+                first = false;
+            } else {
+                queryString.append(" UNION\n").append(addIntend);
+            }
+            if(DataTypeEnum.Reference.getUri().equals(dataType) ||
+                    value instanceof Reference){
+                queryString.append(String.format("?%s <%s> <%s>", 
+                    rootVarName,field,value));
+            } else {
+                queryString.append(String.format("?%s <%s> \"%s\"%s",
+                        rootVarName,field,value,
+                        dataType!=null?String.format("^^<%s>",dataType):""));
+            }
+        }
+        if(values.size() > 1){
+            queryString.append(" }");
         }
     }
     /**
@@ -857,19 +876,26 @@ public final class SparqlQueryUtils {
     public static void main(String[] args) {
         SparqlFieldQuery query = SparqlFieldQueryFactory.getInstance().createFieldQuery();
 //        query.setConstraint("urn:field1", new ReferenceConstraint("urn:testReference"));
+        query.setConstraint("urn:field1", new ReferenceConstraint(
+            Arrays.asList("urn:testReference","urn:testReference1","urn:testReference3")));
 //        query.setConstraint("urn:field1a", new ValueConstraint(null, Arrays.asList(
 //                DataTypeEnum.Float.getUri())));
 //        query.addSelectedField("urn:field1a");
+        
 //        query.setConstraint("urn:field1b", new ValueConstraint(9, Arrays.asList(
 //                DataTypeEnum.Float.getUri())));
+//        query.setConstraint("urn:field1b", new ValueConstraint(Arrays.asList(9,10,11), Arrays.asList(
+//                DataTypeEnum.Float.getUri())));
 //        query.setConstraint("urn:field1c", new ValueConstraint(null, Arrays.asList(
 //                DataTypeEnum.Float.getUri(),DataTypeEnum.Double.getUri(),DataTypeEnum.Decimal.getUri())));
 //        query.addSelectedField("urn:field1c");
 //        query.setConstraint("urn:field1d", new ValueConstraint(9, Arrays.asList(
 //                DataTypeEnum.Float.getUri(),DataTypeEnum.Double.getUri(),DataTypeEnum.Decimal.getUri())));
+//        query.setConstraint("urn:field1d", new ValueConstraint(Arrays.asList(9,10,11), Arrays.asList(
+//                DataTypeEnum.Float.getUri(),DataTypeEnum.Double.getUri(),DataTypeEnum.Decimal.getUri())));
 //        query.setConstraint("urn:field2", new TextConstraint("test value"));
-        query.setConstraint("urn:field3", new TextConstraint(Arrays.asList(
-            "text value","anothertest","some more values"),true));
+//        query.setConstraint("urn:field3", new TextConstraint(Arrays.asList(
+//            "text value","anothertest","some more values"),true));
 //        query.setConstraint("urn:field2a", new TextConstraint(":-]")); //tests escaping of REGEX
 //        query.setConstraint("urn:field3", new TextConstraint("language text","en"));
 //        query.setConstraint("urn:field4", new TextConstraint("multi language text","en","de",null));