You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stanbol.apache.org by si...@apache.org on 2012/05/04 15:38:17 UTC

svn commit: r1333955 [1/2] - in /incubator/stanbol/trunk/contenthub/web: ./ src/main/java/org/apache/stanbol/contenthub/web/fragment/ src/main/java/org/apache/stanbol/contenthub/web/resources/ src/main/resources/org/apache/stanbol/contenthub/web/static...

Author: sinaci
Date: Fri May  4 13:38:16 2012
New Revision: 1333955

URL: http://svn.apache.org/viewvc?rev=1333955&view=rev
Log:
* Removed dependency to enhancer.jersey: contenthub.web was using ContentItemResource from enhancer.jersey. Now, it has its own implementation.
* RESTAPI documentation completed for all REST services of Contenthub.

Added:
    incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/resources/ContentItemResource.java
    incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/static/images/copy_icon_16.png   (with props)
    incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/contentitem.ftl
    incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/ldpathrestapi.ftl
    incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/searchrestapi.ftl
    incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/storerestapi.ftl
    incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/org/apache/stanbol/contenthub/web/resources/ContentItemResource/
    incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/org/apache/stanbol/contenthub/web/resources/ContentItemResource/index.ftl
Modified:
    incubator/stanbol/trunk/contenthub/web/pom.xml
    incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/fragment/ContenthubWebFragment.java
    incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/resources/StoreResource.java
    incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/static/style/contenthub.css
    incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/relatedKeywordMacro.ftl
    incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/org/apache/stanbol/contenthub/web/resources/FeaturedSearchResource/index.ftl
    incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/org/apache/stanbol/contenthub/web/resources/SemanticIndexManagerResource/index.ftl
    incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/org/apache/stanbol/contenthub/web/resources/StoreResource/index.ftl

Modified: incubator/stanbol/trunk/contenthub/web/pom.xml
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/web/pom.xml?rev=1333955&r1=1333954&r2=1333955&view=diff
==============================================================================
--- incubator/stanbol/trunk/contenthub/web/pom.xml (original)
+++ incubator/stanbol/trunk/contenthub/web/pom.xml Fri May  4 13:38:16 2012
@@ -104,8 +104,8 @@
 
     <!-- needed for the ContentItem resource -->
     <dependency>
-      <groupId>org.apache.stanbol</groupId>
-      <artifactId>org.apache.stanbol.enhancer.jersey</artifactId>
+      <groupId>org.apache.clerezza</groupId>
+      <artifactId>jaxrs.rdf.providers</artifactId>
     </dependency>
 
     <!-- dependencies on other Stanbol modules -->

Modified: incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/fragment/ContenthubWebFragment.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/fragment/ContenthubWebFragment.java?rev=1333955&r1=1333954&r2=1333955&view=diff
==============================================================================
--- incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/fragment/ContenthubWebFragment.java (original)
+++ incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/fragment/ContenthubWebFragment.java Fri May  4 13:38:16 2012
@@ -31,6 +31,7 @@ import org.apache.stanbol.commons.web.ba
 import org.apache.stanbol.commons.web.base.ScriptResource;
 import org.apache.stanbol.commons.web.base.WebFragment;
 import org.apache.stanbol.contenthub.web.resources.FeaturedSearchResource;
+import org.apache.stanbol.contenthub.web.resources.RelatedKeywordResource;
 import org.apache.stanbol.contenthub.web.resources.RootResource;
 import org.apache.stanbol.contenthub.web.resources.SemanticIndexManagerResource;
 import org.apache.stanbol.contenthub.web.resources.StoreResource;
@@ -74,6 +75,7 @@ public class ContenthubWebFragment imple
 		classes.add(StoreResource.class);
 		classes.add(FeaturedSearchResource.class);
 		classes.add(SemanticIndexManagerResource.class);
+		classes.add(RelatedKeywordResource.class);
 
 		classes.add(LDProgramCollectionWriter.class);
 		classes.add(SearchResultWriter.class);

Added: incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/resources/ContentItemResource.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/resources/ContentItemResource.java?rev=1333955&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/resources/ContentItemResource.java (added)
+++ incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/resources/ContentItemResource.java Fri May  4 13:38:16 2012
@@ -0,0 +1,585 @@
+/*
+ * 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.contenthub.web.resources;
+
+import static javax.ws.rs.core.MediaType.TEXT_HTML;
+import static org.apache.stanbol.commons.web.base.CorsHelper.addCORSOrigin;
+import static org.apache.stanbol.enhancer.servicesapi.helper.EnhancementEngineHelper.getReference;
+import static org.apache.stanbol.enhancer.servicesapi.helper.EnhancementEngineHelper.getReferences;
+import static org.apache.stanbol.enhancer.servicesapi.helper.EnhancementEngineHelper.getString;
+import static org.apache.stanbol.enhancer.servicesapi.rdf.OntologicalClasses.DBPEDIA_ORGANISATION;
+import static org.apache.stanbol.enhancer.servicesapi.rdf.OntologicalClasses.DBPEDIA_PERSON;
+import static org.apache.stanbol.enhancer.servicesapi.rdf.OntologicalClasses.DBPEDIA_PLACE;
+import static org.apache.stanbol.enhancer.servicesapi.rdf.OntologicalClasses.SKOS_CONCEPT;
+import static org.apache.stanbol.enhancer.servicesapi.rdf.Properties.DC_RELATION;
+import static org.apache.stanbol.enhancer.servicesapi.rdf.Properties.DC_TYPE;
+import static org.apache.stanbol.enhancer.servicesapi.rdf.Properties.ENHANCER_CONFIDENCE;
+import static org.apache.stanbol.enhancer.servicesapi.rdf.Properties.ENHANCER_ENTITY_LABEL;
+import static org.apache.stanbol.enhancer.servicesapi.rdf.Properties.ENHANCER_ENTITY_REFERENCE;
+import static org.apache.stanbol.enhancer.servicesapi.rdf.Properties.GEO_LAT;
+import static org.apache.stanbol.enhancer.servicesapi.rdf.Properties.GEO_LONG;
+import static org.apache.stanbol.enhancer.servicesapi.rdf.TechnicalClasses.ENHANCER_ENTITYANNOTATION;
+import static org.apache.stanbol.enhancer.servicesapi.rdf.TechnicalClasses.ENHANCER_TEXTANNOTATION;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+
+import javax.servlet.ServletContext;
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.clerezza.rdf.core.Language;
+import org.apache.clerezza.rdf.core.LiteralFactory;
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.NonLiteral;
+import org.apache.clerezza.rdf.core.PlainLiteral;
+import org.apache.clerezza.rdf.core.Resource;
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.clerezza.rdf.core.TripleCollection;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.access.TcManager;
+import org.apache.clerezza.rdf.core.impl.TripleImpl;
+import org.apache.clerezza.rdf.core.serializedform.Serializer;
+import org.apache.clerezza.rdf.core.serializedform.SupportedFormat;
+import org.apache.clerezza.rdf.core.sparql.ParseException;
+import org.apache.clerezza.rdf.ontologies.RDF;
+import org.apache.stanbol.commons.indexedgraph.IndexedMGraph;
+import org.apache.stanbol.commons.web.base.resource.BaseStanbolResource;
+import org.apache.stanbol.enhancer.servicesapi.Blob;
+import org.apache.stanbol.enhancer.servicesapi.ContentItem;
+import org.apache.stanbol.enhancer.servicesapi.helper.ContentItemHelper;
+import org.apache.stanbol.enhancer.servicesapi.helper.EnhancementEngineHelper;
+import org.apache.stanbol.enhancer.servicesapi.rdf.Properties;
+
+import com.sun.jersey.api.view.Viewable;
+
+public class ContentItemResource extends BaseStanbolResource {
+
+    // TODO make this configurable trough a property
+    public static final UriRef SUMMARY = new UriRef("http://www.w3.org/2000/01/rdf-schema#comment");
+
+    // TODO make this configurable trough a property
+    public static final UriRef THUMBNAIL = new UriRef("http://dbpedia.org/ontology/thumbnail");
+    public static final UriRef DEPICTION = new UriRef("http://xmlns.com/foaf/0.1/depiction");
+
+    public final Map<UriRef,String> defaultThumbnails = new HashMap<UriRef,String>();
+
+    protected ContentItem contentItem;
+
+    protected String localId;
+
+    protected String textContent;
+
+    protected URI imageSrc;
+
+    protected URI downloadHref;
+
+    protected URI metadataHref;
+
+    protected final TcManager tcManager;
+
+    protected final Serializer serializer;
+
+    protected String serializationFormat = SupportedFormat.RDF_XML;
+
+    /**
+     * Map holding the extraction mapped by {@link Properties#DC_TYPE} and the
+     * {@link Properties#ENHANCER_SELECTED_TEXT}. This map is initialised by {@link #initOccurrences()}.
+     */
+    protected Map<UriRef,Map<String,EntityExtractionSummary>> extractionsByTypeMap = new HashMap<UriRef,Map<String,EntityExtractionSummary>>();
+
+    public ContentItemResource(String localId,
+                               ContentItem ci,
+                               UriInfo uriInfo,
+                               String storePath,
+                               TcManager tcManager,
+                               Serializer serializer,
+                               ServletContext servletContext) throws IOException {
+        this.contentItem = ci;
+        this.localId = localId;
+        this.uriInfo = uriInfo;
+        this.tcManager = tcManager;
+        this.serializer = serializer;
+        this.servletContext = servletContext;
+
+        if (localId != null) {
+            URI rawURI = uriInfo.getBaseUriBuilder().path(storePath).path("raw").path(localId).build();
+            Entry<UriRef,Blob> plainTextContentPart = ContentItemHelper.getBlob(contentItem,
+                Collections.singleton("text/plain"));
+            if (plainTextContentPart != null) {
+                this.textContent = ContentItemHelper.getText(plainTextContentPart.getValue());
+            }
+            if (ci.getMimeType().startsWith("image/")) {
+                this.imageSrc = rawURI;
+            }
+            this.downloadHref = rawURI;
+            this.metadataHref = uriInfo.getBaseUriBuilder().path(storePath).path("metadata").path(localId)
+                    .build();
+        }
+        defaultThumbnails.put(DBPEDIA_PERSON, getStaticRootUrl() + "/home/images/user_48.png");
+        defaultThumbnails.put(DBPEDIA_ORGANISATION, getStaticRootUrl() + "/home/images/organization_48.png");
+        defaultThumbnails.put(DBPEDIA_PLACE, getStaticRootUrl() + "/home/images/compass_48.png");
+        defaultThumbnails.put(SKOS_CONCEPT, getStaticRootUrl() + "/home/images/black_gear_48.png");
+        defaultThumbnails.put(null, getStaticRootUrl() + "/home/images/unknown_48.png");
+        initOccurrences();
+    }
+
+    public String getRdfMetadata(String mediatype) throws UnsupportedEncodingException {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        serializer.serialize(out, contentItem.getMetadata(), mediatype);
+        return out.toString("utf-8");
+    }
+
+    public String getRdfMetadata() throws UnsupportedEncodingException {
+        return getRdfMetadata(serializationFormat);
+    }
+
+    public ContentItem getContentItem() {
+        return contentItem;
+    }
+
+    public String getLocalId() {
+        return localId;
+    }
+
+    public String getTextContent() {
+        return textContent;
+    }
+
+    public URI getImageSrc() {
+        return imageSrc;
+    }
+
+    public URI getDownloadHref() {
+        return downloadHref;
+    }
+
+    public URI getMetadataHref() {
+        return metadataHref;
+    }
+
+    /**
+     * Checks if there are Occurrences
+     */
+    public boolean hasOccurrences() {
+        for (Map<String,EntityExtractionSummary> occ : extractionsByTypeMap.values()) {
+            if (!occ.isEmpty()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Used to print occurrences with other types than the natively supported
+     */
+    public Collection<UriRef> getOtherOccurrencyTypes() {
+        Set<UriRef> types = new HashSet<UriRef>(extractionsByTypeMap.keySet());
+        types.remove(DBPEDIA_PERSON);
+        types.remove(DBPEDIA_ORGANISATION);
+        types.remove(DBPEDIA_PLACE);
+        types.remove(SKOS_CONCEPT);
+        types.remove(null); // other
+        return types;
+    }
+
+    public Collection<EntityExtractionSummary> getOccurrences(UriRef type) {
+        Map<String,EntityExtractionSummary> typeMap = extractionsByTypeMap.get(type);
+        Collection<EntityExtractionSummary> typeOccurrences;
+        if (typeMap != null) {
+            typeOccurrences = typeMap.values();
+        } else {
+            typeOccurrences = Collections.emptyList();
+        }
+        return typeOccurrences;
+    }
+
+    public Collection<EntityExtractionSummary> getPersonOccurrences() throws ParseException {
+        return getOccurrences(DBPEDIA_PERSON);
+    }
+
+    public Collection<EntityExtractionSummary> getOtherOccurrences() throws ParseException {
+        return getOccurrences(null);
+    }
+
+    public Collection<EntityExtractionSummary> getOrganizationOccurrences() throws ParseException {
+        return getOccurrences(DBPEDIA_ORGANISATION);
+    }
+
+    public Collection<EntityExtractionSummary> getPlaceOccurrences() throws ParseException {
+        return getOccurrences(DBPEDIA_PLACE);
+    }
+
+    public Collection<EntityExtractionSummary> getConceptOccurrences() throws ParseException {
+        return getOccurrences(SKOS_CONCEPT);
+    }
+
+    enum EAProps {
+        label,
+        entity,
+        confidence
+    }
+
+    private void initOccurrences() {
+        MGraph graph = contentItem.getMetadata();
+        LiteralFactory lf = LiteralFactory.getInstance();
+        Map<UriRef,Collection<NonLiteral>> suggestionMap = new HashMap<UriRef,Collection<NonLiteral>>();
+        // 1) get Entity Annotations
+        Map<NonLiteral,Map<EAProps,Object>> entitySuggestionMap = new HashMap<NonLiteral,Map<EAProps,Object>>();
+        Iterator<Triple> entityAnnotations = graph.filter(null, RDF.type, ENHANCER_ENTITYANNOTATION);
+        while (entityAnnotations.hasNext()) {
+            NonLiteral entityAnnotation = entityAnnotations.next().getSubject();
+            // to avoid multiple lookups (e.g. if one entityAnnotation links to+
+            // several TextAnnotations) we cache the data in an intermediate Map
+            Map<EAProps,Object> eaData = new EnumMap<EAProps,Object>(EAProps.class);
+            eaData.put(EAProps.entity, getReference(graph, entityAnnotation, ENHANCER_ENTITY_REFERENCE));
+            eaData.put(EAProps.label, getString(graph, entityAnnotation, ENHANCER_ENTITY_LABEL));
+            eaData.put(EAProps.confidence,
+                EnhancementEngineHelper.get(graph, entityAnnotation, ENHANCER_CONFIDENCE, Double.class, lf));
+            entitySuggestionMap.put(entityAnnotation, eaData);
+            Iterator<UriRef> textAnnotations = getReferences(graph, entityAnnotation, DC_RELATION);
+            while (textAnnotations.hasNext()) {
+                UriRef textAnnotation = textAnnotations.next();
+                Collection<NonLiteral> suggestions = suggestionMap.get(textAnnotation);
+                if (suggestions == null) {
+                    suggestions = new ArrayList<NonLiteral>();
+                    suggestionMap.put(textAnnotation, suggestions);
+                }
+                suggestions.add(entityAnnotation);
+            }
+        }
+        // 2) get the TextAnnotations
+        Iterator<Triple> textAnnotations = graph.filter(null, RDF.type, ENHANCER_TEXTANNOTATION);
+        while (textAnnotations.hasNext()) {
+            NonLiteral textAnnotation = textAnnotations.next().getSubject();
+            if (graph.filter(textAnnotation, DC_RELATION, null).hasNext()) {
+                // this is not the most specific occurrence of this name: skip
+                continue;
+            }
+            String text = getString(graph, textAnnotation, Properties.ENHANCER_SELECTED_TEXT);
+            if (text == null) {
+                // ignore text annotations without text
+                continue;
+            }
+            Iterator<UriRef> types = getReferences(graph, textAnnotation, DC_TYPE);
+            if (!types.hasNext()) { // create an iterator over null in case no types are present
+                types = Collections.singleton((UriRef) null).iterator();
+            }
+            while (types.hasNext()) {
+                UriRef type = types.next();
+                Map<String,EntityExtractionSummary> occurrenceMap = extractionsByTypeMap.get(type);
+                if (occurrenceMap == null) {
+                    occurrenceMap = new TreeMap<String,EntityExtractionSummary>(String.CASE_INSENSITIVE_ORDER);
+                    extractionsByTypeMap.put(type, occurrenceMap);
+                }
+                EntityExtractionSummary entity = occurrenceMap.get(text);
+                if (entity == null) {
+                    entity = new EntityExtractionSummary(text, type, defaultThumbnails);
+                    occurrenceMap.put(text, entity);
+                }
+                Collection<NonLiteral> suggestions = suggestionMap.get(textAnnotation);
+                if (suggestions != null) {
+                    for (NonLiteral entityAnnotation : suggestions) {
+                        Map<EAProps,Object> eaData = entitySuggestionMap.get(entityAnnotation);
+                        entity.addSuggestion((UriRef) eaData.get(EAProps.entity),
+                            (String) eaData.get(EAProps.label), (Double) eaData.get(EAProps.confidence),
+                            graph);
+                    }
+                }
+            }
+        }
+    }
+
+    public static class EntityExtractionSummary implements Comparable<EntityExtractionSummary> {
+
+        protected final String name;
+
+        protected final UriRef type;
+
+        protected List<EntitySuggestion> suggestions = new ArrayList<EntitySuggestion>();
+
+        protected List<String> mentions = new ArrayList<String>();
+
+        public final Map<UriRef,String> defaultThumbnails;
+
+        public EntityExtractionSummary(String name, UriRef type, Map<UriRef,String> defaultThumbnails) {
+            this.name = name;
+            this.type = type;
+            mentions.add(name);
+            this.defaultThumbnails = defaultThumbnails;
+        }
+
+        public void addSuggestion(UriRef uri, String label, Double confidence, TripleCollection properties) {
+            EntitySuggestion suggestion = new EntitySuggestion(uri, type, label, confidence, properties,
+                    defaultThumbnails);
+            if (!suggestions.contains(suggestion)) {
+                suggestions.add(suggestion);
+                Collections.sort(suggestions);
+            }
+        }
+
+        public String getName() {
+            EntitySuggestion bestGuess = getBestGuess();
+            if (bestGuess != null) {
+                return bestGuess.getLabel();
+            }
+            return name;
+        }
+
+        public String getUri() {
+            EntitySuggestion bestGuess = getBestGuess();
+            if (bestGuess != null) {
+                return bestGuess.getUri();
+            }
+            return null;
+        }
+
+        public String getSummary() {
+            if (suggestions.isEmpty()) {
+                return "";
+            }
+            return suggestions.get(0).getSummary();
+        }
+
+        public String getThumbnailSrc() {
+            if (suggestions.isEmpty()) {
+                return getMissingThumbnailSrc();
+            }
+            return suggestions.get(0).getThumbnailSrc();
+        }
+
+        public String getMissingThumbnailSrc() {
+            String source = defaultThumbnails.get(type);
+            if (source == null) {
+                source = defaultThumbnails.get(null);// default
+            }
+            return source;
+        }
+
+        public EntitySuggestion getBestGuess() {
+            if (suggestions.isEmpty()) {
+                return null;
+            }
+            return suggestions.get(0);
+        }
+
+        public List<EntitySuggestion> getSuggestions() {
+            return suggestions;
+        }
+
+        public List<String> getMentions() {
+            return mentions;
+        }
+
+        @Override
+        public int compareTo(EntityExtractionSummary o) {
+            return getName().compareTo(o.getName());
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            EntityExtractionSummary that = (EntityExtractionSummary) o;
+
+            return !(name != null ? !name.equals(that.name) : that.name != null);
+        }
+
+        @Override
+        public int hashCode() {
+            return name != null ? name.hashCode() : 0;
+        }
+    }
+
+    public static class EntitySuggestion implements Comparable<EntitySuggestion> {
+
+        protected final UriRef uri;
+
+        protected final UriRef type;
+
+        protected final String label;
+
+        protected final Double confidence;
+
+        protected TripleCollection entityProperties;
+
+        protected final Map<UriRef,String> defaultThumbnails;
+
+        public EntitySuggestion(UriRef uri,
+                                UriRef type,
+                                String label,
+                                Double confidence,
+                                TripleCollection entityProperties,
+                                Map<UriRef,String> defaultThumbnails) {
+            this.uri = uri;
+            this.label = label;
+            this.type = type;
+            this.confidence = confidence != null ? confidence : 0.0;
+            this.entityProperties = entityProperties;
+            this.defaultThumbnails = defaultThumbnails;
+        }
+
+        @Override
+        public int compareTo(EntitySuggestion o) {
+            // order suggestions by decreasing confidence
+            return -confidence.compareTo(o.confidence);
+        }
+
+        public String getUri() {
+            return uri.getUnicodeString();
+        }
+
+        public Double getConfidence() {
+            return confidence;
+        }
+
+        public String getLabel() {
+            return label;
+        }
+
+        public String getThumbnailSrc() {
+            Iterator<Triple> thumbnails = entityProperties.filter(uri, THUMBNAIL, null);
+            while (thumbnails.hasNext()) {
+                Resource object = thumbnails.next().getObject();
+                if (object instanceof UriRef) {
+                    return ((UriRef) object).getUnicodeString();
+                }
+            }
+            // if no dbpedia ontology thumbnail was found. try the same with foaf:depiction
+            thumbnails = entityProperties.filter(uri, DEPICTION, null);
+            while (thumbnails.hasNext()) {
+                Resource object = thumbnails.next().getObject();
+                if (object instanceof UriRef) {
+                    return ((UriRef) object).getUnicodeString();
+                }
+            }
+            return getMissingThumbnailSrc();
+        }
+
+        public String getMissingThumbnailSrc() {
+            String source = defaultThumbnails.get(type);
+            if (source == null) {
+                source = defaultThumbnails.get(null);
+            }
+            return source;
+        }
+
+        public String getSummary() {
+            Iterator<Triple> abstracts = entityProperties.filter(uri, SUMMARY, null);
+            while (abstracts.hasNext()) {
+                Resource object = abstracts.next().getObject();
+                if (object instanceof PlainLiteral) {
+                    PlainLiteral abstract_ = (PlainLiteral) object;
+                    if (new Language("en").equals(abstract_.getLanguage())) {
+                        return abstract_.getLexicalForm();
+                    }
+                }
+            }
+            return "";
+        }
+
+        // consider entities with same URI as equal even if we have alternate
+        // label values
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((uri == null) ? 0 : uri.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) return true;
+            if (obj == null) return false;
+            if (getClass() != obj.getClass()) return false;
+            EntitySuggestion other = (EntitySuggestion) obj;
+            if (uri == null) {
+                if (other.uri != null) return false;
+            } else if (!uri.equals(other.uri)) return false;
+            return true;
+        }
+
+    }
+
+    public void setRdfSerializationFormat(String format) {
+        serializationFormat = format;
+    }
+
+    /**
+     * @return an RDF/JSON descriptions of places for the word map widget
+     */
+    public String getPlacesAsJSON() throws ParseException, UnsupportedEncodingException {
+        MGraph g = new IndexedMGraph();
+        LiteralFactory lf = LiteralFactory.getInstance();
+        MGraph metadata = contentItem.getMetadata();
+        for (EntityExtractionSummary p : getPlaceOccurrences()) {
+            EntitySuggestion bestGuess = p.getBestGuess();
+            if (bestGuess == null) {
+                continue;
+            }
+            UriRef uri = new UriRef(bestGuess.getUri());
+            Iterator<Triple> latitudes = metadata.filter(uri, GEO_LAT, null);
+            if (latitudes.hasNext()) {
+                g.add(latitudes.next());
+            }
+            Iterator<Triple> longitutes = metadata.filter(uri, GEO_LONG, null);
+            if (longitutes.hasNext()) {
+                g.add(longitutes.next());
+                g.add(new TripleImpl(uri, Properties.RDFS_LABEL, lf.createTypedLiteral(bestGuess.getLabel())));
+            }
+        }
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        serializer.serialize(out, g, SupportedFormat.RDF_JSON);
+
+        String rdfString = out.toString("utf-8");
+        return rdfString;
+    }
+
+    @GET
+    @Produces(TEXT_HTML)
+    public Response get(@Context HttpHeaders headers) {
+        ResponseBuilder rb = Response.ok(new Viewable("index", this));
+        rb.header(HttpHeaders.CONTENT_TYPE, TEXT_HTML + "; charset=utf-8");
+        addCORSOrigin(servletContext, rb, headers);
+        return rb.build();
+    }
+}

Modified: incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/resources/StoreResource.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/resources/StoreResource.java?rev=1333955&r1=1333954&r2=1333955&view=diff
==============================================================================
--- incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/resources/StoreResource.java (original)
+++ incubator/stanbol/trunk/contenthub/web/src/main/java/org/apache/stanbol/contenthub/web/resources/StoreResource.java Fri May  4 13:38:16 2012
@@ -93,7 +93,6 @@ import org.apache.stanbol.contenthub.ser
 import org.apache.stanbol.contenthub.servicesapi.store.solr.SolrStore;
 import org.apache.stanbol.contenthub.servicesapi.store.vocabulary.SolrVocabulary.SolrFieldName;
 import org.apache.stanbol.contenthub.web.util.JSONUtils;
-import org.apache.stanbol.enhancer.jersey.resource.ContentItemResource;
 import org.apache.stanbol.enhancer.servicesapi.ContentItem;
 import org.apache.stanbol.enhancer.servicesapi.EngineException;
 import org.apache.stanbol.enhancer.servicesapi.helper.ContentItemHelper;
@@ -299,6 +298,8 @@ public class StoreResource extends BaseS
      *            content item will be prepared for download.
      * @param contentURI
      *            URI of the resource in the Stanbol Contenthub store
+     * @param format
+     *            Rdf serialization format of metadata
      * @return Raw content item or metadata of the content item.
      * @throws IOException
      * @throws StoreException
@@ -307,6 +308,7 @@ public class StoreResource extends BaseS
     @Path("/download/{type}/{uri:.+}")
     public Response downloadContentItem(@PathParam(value = "type") String type,
                                         @PathParam(value = "uri") String contentURI,
+                                        @QueryParam(value = "format") String format,
                                         @Context HttpHeaders headers) throws IOException, StoreException {
 
         ContentItem ci = solrStore.get(contentURI, indexName);
@@ -314,7 +316,7 @@ public class StoreResource extends BaseS
             throw new WebApplicationException(404);
         }
         if (type.equals("metadata")) {
-            String fileName = contentURI + "-metadata";
+            String fileName = URLEncoder.encode(contentURI, "utf-8") + "-metadata";
             File file = new File(fileName);
             if (file.exists()) {
                 file.delete();
@@ -322,7 +324,7 @@ public class StoreResource extends BaseS
             boolean success = file.createNewFile();
             if (success) {
                 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
-                serializer.serialize(bos, ci.getMetadata(), SupportedFormat.RDF_XML);
+                serializer.serialize(bos, ci.getMetadata(), format);
                 bos.close();
             } else {
                 log.error("Failed to create file: {}", fileName);

Added: incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/static/images/copy_icon_16.png
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/static/images/copy_icon_16.png?rev=1333955&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/static/images/copy_icon_16.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/static/style/contenthub.css
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/static/style/contenthub.css?rev=1333955&r1=1333954&r2=1333955&view=diff
==============================================================================
--- incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/static/style/contenthub.css (original)
+++ incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/static/style/contenthub.css Fri May  4 13:38:16 2012
@@ -84,4 +84,18 @@ H3.ui-accordion-header{
 	width: 72px;
 	font-size: 12px;
 	color: #C43187;
+}
+
+.preParent{
+  position:relative;
+}
+
+.copyImg{
+  position: absolute;
+  right: 5px;
+  top: 5px;
+}
+
+.curlLine{
+  display: none;
 }
\ No newline at end of file

Added: incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/contentitem.ftl
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/contentitem.ftl?rev=1333955&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/contentitem.ftl (added)
+++ incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/contentitem.ftl Fri May  4 13:38:16 2012
@@ -0,0 +1,166 @@
+<#--
+  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.
+-->
+<#import "/imports/entities.ftl" as entities>
+<#macro view>
+
+<div class="entitylistings">
+<#if it.hasOccurrences()>
+<h3>Extracted entities</h3>
+</#if>
+<#-- First print the predefined types -->
+<div class="entitylisting">
+<#if it.personOccurrences?size != 0>
+<h3>People</h3>
+<@entities.listing entities=it.personOccurrences /> 
+</#if>
+</div>
+
+<div class="entitylisting">
+<#if it.organizationOccurrences?size != 0>
+<h3>Organizations</h3>
+<@entities.listing entities=it.organizationOccurrences /> 
+</#if>
+</div>
+
+<div class="entitylisting">
+<#if it.placeOccurrences?size != 0>
+<h3>Places</h3>
+<@entities.listing entities=it.placeOccurrences /> 
+</#if>
+</div>
+
+<div class="entitylisting">
+<#if it.conceptOccurrences?size != 0>
+<h3>Concepts</h3>
+<@entities.listing entities=it.conceptOccurrences /> 
+</#if>
+</div>
+
+<#-- add Occurrences with other types -->
+<#list it.otherOccurrencyTypes as type>
+  <div class="entitylisting">
+  <h3>${it.extractLabel(type)}</h3>
+  <@entities.listing entities=it.getOccurrences(type) />
+  </div>
+</#list>
+
+<#-- add Occurrences with no type -->
+<div class="entitylisting">
+<#if it.otherOccurrences?size != 0>
+<h3>Others</h3>
+<@entities.listing entities=it.otherOccurrences /> 
+</#if>
+</div>
+
+</div>
+<div style="clear: both"></div>
+
+<script>
+$("th").click(function () {
+  $(this).parents("table").toggleClass("collapsed");
+});
+</script>
+
+<#if it.placeOccurrences?size != 0>
+<div class="mapContainer">
+  <div id="map" class="olMap"
+   style="border: 1px solid #ccc; height: 400px; width: 800px;"></div> 
+<script>
+$(document).ready(function() {
+  var extent = new OpenLayers.Bounds(-180, -90, 180, 90);
+
+  var map = new OpenLayers.Map('map',
+    {controls: [
+      new OpenLayers.Control.Navigation({documentDrag: true}),
+      new OpenLayers.Control.PanZoom(),
+      new OpenLayers.Control.ArgParser(),
+      new OpenLayers.Control.Attribution()
+     ],
+     restrictedExtent: extent});
+
+  var options = {
+    numZoomLevels: 2,
+  };
+  var graphic = new OpenLayers.Layer.Image(
+    'Default World Map',
+    '${it.staticRootUrl}/home/images/world_map_1024_512.png',
+    extent,
+    new OpenLayers.Size(1024, 512),
+    options
+  );
+  map.addLayer(graphic);
+
+  map.setCenter(new OpenLayers.LonLat(0, 20), 0);
+  map.addControl(new OpenLayers.Control.LayerSwitcher());
+  map.zoomToMaxExtent();
+
+
+  var markers = new OpenLayers.Layer.Markers("Markers");
+  map.addLayer(markers);
+
+  var entities = ${it.placesAsJSON};
+  
+  var id = 0;
+  for (var entity_id in entities) {
+    id += 1;
+    var entity = entities[entity_id];
+    var label = entity['http://www.w3.org/2000/01/rdf-schema#label'][0]['value'];
+    var lat;
+    var long;
+    var georsspoint = entity['http://www.georss.org/georss/point'];
+    if (georsspoint != undefined) {
+      var parts = georsspoint[0]['value'].split(' ');
+      lat = parseFloat(parts[0]);
+      long = parseFloat(parts[1]);
+    }
+  var latitutes = entity['http://www.w3.org/2003/01/geo/wgs84_pos#lat'];
+    var longitutes = entity['http://www.w3.org/2003/01/geo/wgs84_pos#long'];
+    if (latitutes != undefined && longitutes != undefined) {
+      lat = parseFloat(latitutes[0]['value']);
+      long = parseFloat(longitutes[0]['value']);
+    }
+    
+    if (lat == undefined || long == undefined) {
+      continue;
+    }
+    
+    (function(lat, long) {
+      /* closure leak isolation for the popup instance scoped in the event handle */
+      var position = new OpenLayers.LonLat(long, lat);
+    var iconSize = new OpenLayers.Size(32, 32);
+      var offset = new OpenLayers.Pixel(-(iconSize.w/2), -iconSize.h);
+      var markerIcon = new OpenLayers.Icon('${it.staticRootUrl}/home/images/pin_map_32.png', iconSize, offset);
+    var popupSize = new OpenLayers.Size(200, 20);
+      var marker = new OpenLayers.Marker(position, markerIcon);
+      var popup = new OpenLayers.Popup.Anchored("popup-" + id, position, popupSize, label, markerIcon, false);
+      map.addPopup(popup);
+      popup.hide();
+      marker.events.register('mouseover', marker,
+        function(evt) { popup.show(); OpenLayers.Event.stop(evt); });
+      marker.events.register('mouseout', marker,
+        function(evt) { popup.hide(); OpenLayers.Event.stop(evt); });
+      markers.addMarker(marker);
+    })(lat, long);
+  }
+
+});
+</script>
+
+</div>
+</#if>
+
+</#macro>
\ No newline at end of file

Added: incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/ldpathrestapi.ftl
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/ldpathrestapi.ftl?rev=1333955&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/ldpathrestapi.ftl (added)
+++ incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/ldpathrestapi.ftl Fri May  4 13:38:16 2012
@@ -0,0 +1,172 @@
+<h3>The RESTful API of the Contenthub LDPath</h3>
+
+<h4>Retrieve All Programs</h4>
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP GET method which returns all LDPath programs residing in Contenthub. LDPath programs are uniquely dentified by their names. Returning JSON string presents each LDPath program in string format aligned with its name.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>GET /contenthub/ldpath</td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>JSON string of <code>name:program</code> pairs.</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<pre>curl -i http://localhost:8080/contenthub/ldpath</pre>
+
+<hr>
+
+
+<h4>Submit Program</h4>
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP POST method which saves an LDPath program into the persistent store of Contenthub.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>POST /contenthub/ldpath/program</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td>
+      <b>programName:</b> Unique name to identify the LDPath program<br>
+      <b>program:</b> The LDPath program.
+    </td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>HTTP OK(200) or BAD REQUEST(400)</td>
+  </tr>
+  <tr>
+    <th>Throws</th>
+    <td>LDPathException</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<div class="preParent">
+  <img onClick="javascript:getLine(this.parentNode);" class="copyImg" src="${it.staticRootUrl}/contenthub/images/copy_icon_16.png" title="Get command in a single line" />
+<pre>
+<div id="curl1" class="curlLine">curl -i -X POST -d "name=universities&program= @prefix dbp-ont : <http://dbpedia.org/ontology/>; city = dbp-ont:city / rdfs:label :: xsd:string; country = dbp-ont:country / rdfs:label :: xsd:string; president = dbp-ont:president / rdfs:label :: xsd:string; numberOfStudent = dbp-ont:numberOfStudents :: xsd:int;" "http://localhost:8080/contenthub/ldpath/program"<hr/></div>curl -i -X POST -d "name=universities&program= \
+                    @prefix dbp-ont : <http://dbpedia.org/ontology/>; \
+                    city = dbp-ont:city / rdfs:label :: xsd:string; \
+                    country = dbp-ont:country / rdfs:label :: xsd:string; \
+                    president = dbp-ont:president / rdfs:label :: xsd:string; \
+                    numberOfStudent = dbp-ont:numberOfStudents :: xsd:int;" \
+                    "http://localhost:8080/contenthub/ldpath/program"
+</pre>
+</div>
+<hr>
+
+
+<h4>Get Program By Name</h4>
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP GET method to retrieve an LDPath program, given its name.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>GET /contenthub/ldpath/program</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td><b>name:</b> The name of the LDPath program to be retrieved.</td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>LDPath program in String format or HTTP NOT FOUND(404)</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<pre>curl -i "http://localhost:8080/contenthub/ldpath/program?name=universities"</pre>
+
+<hr>
+
+
+<h4>Delete Program</h4>
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP DELETE method to delete an LDPath program.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>DELETE /contenthub/ldpath/program/{name}</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td><b>name:</b> The name of the LDPath program.</td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>HTTP OK(200)</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<pre>curl -i -X DELETE http://localhost:8080/contenthub/ldpath/program/universities</pre>
+
+<hr>
+
+
+<h4>Check existance of LdPath Program</h4>
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP GET method to check whether an LDPath program exists in Contenthub or not.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>GET /contenthub/ldpath/exists</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td><b>name:</b> The name of the LDPath program.</td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>HTTP OK(200) or HTTP NOT FOUND(404)</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<pre>curl -i http://localhost:8080/contenthub/ldpath/exists?name=universities</pre>
+
+<hr>
+
+<script>
+function selectText(element) {
+    var doc = document;
+    var text = doc.getElementById(element);    
+    if (doc.body.createTextRange) { // ms
+        var range = doc.body.createTextRange();
+        range.moveToElementText(text);
+        range.select();
+    } else if (window.getSelection) {
+        var selection = window.getSelection();
+        var range = doc.createRange();
+        range.selectNodeContents(text);
+        selection.removeAllRanges();
+        selection.addRange(range);
+        
+    }
+}
+
+  function getLine(div){
+    $(div).children('pre').children('.curlLine').toggle();
+    selectText($(div).children('pre').children('.curlLine').attr('id'));
+  }
+</script>
\ No newline at end of file

Modified: incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/relatedKeywordMacro.ftl
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/relatedKeywordMacro.ftl?rev=1333955&r1=1333954&r2=1333955&view=diff
==============================================================================
--- incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/relatedKeywordMacro.ftl (original)
+++ incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/relatedKeywordMacro.ftl Fri May  4 13:38:16 2012
@@ -40,11 +40,11 @@
               if(document.getElementById("${relatedKeywordId}${normalizedSourceName}button").innerHTML == "more") {
                   var a="<#list relatedKeywordList as related><#assign relatedName = related.keyword?replace(' ','_')><li><a href=javascript:getResults(null,'${relatedName}','explore')>${relatedName?replace('_', ' ')}</a></li></#list>";
                   document.getElementById("${relatedKeywordId}${normalizedSourceName}list").innerHTML=a;
-                  $(this).attr({ 'innerHTML': 'less' });
+                  $(this).html("less");
               } else{
                   var a="<#assign x=0><#list relatedKeywordList as related><#assign relatedName = related.keyword?replace('_',' ')><#if x == limit><#break/></#if><li><a href=javascript:getResults(null,'${relatedName}','explore')>${relatedName?replace('_', ' ')}</a></li><#assign x=x+1 /></#list>";
                   document.getElementById("${relatedKeywordId}${normalizedSourceName}list").innerHTML=a;
-                  $(this).attr({ 'innerHTML': 'more' });       
+                  $(this).html("more");       
               }    
           });
        }     

Added: incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/searchrestapi.ftl
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/searchrestapi.ftl?rev=1333955&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/searchrestapi.ftl (added)
+++ incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/searchrestapi.ftl Fri May  4 13:38:16 2012
@@ -0,0 +1,213 @@
+<h3>The RESTful API of the Contenthub Search</h3>
+
+There are two endpoints you can reach from search
+<li>Featured Search</li>
+<li>Related Search</li>
+
+<h3>Featured Search</h3>  
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP GET method to make a featured search over Contenthub.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>GET /contenthub/{indexName}/search/featured</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td>
+        <b>queryTerm:</b> A keyword a statement or a set of keywords which can be regarded as the query term.<br>
+        <b>solrQuery:</b> Solr query string. This is the string format which is accepted by a Solr server. For example, <code> q="john doe"&fl=score</code> is a valid value for this parameter. If this parameter exists, search is performed based on this solrQuery and any queryTerms are neglected.<br>
+        <b>constraints:</b> Solr query string. This is the string format which is accepted by a Solr server. For example, <code> q="john doe"&fl=score</code> is a valid value for this parameter. If this parameter exists, search is performed based on this solrQuery and any queryTerms are neglected.<br>
+        <b>ontologyURI:</b> URI of the ontology in which related keywords will be searched by RelatedKeywordSearchManager#getRelatedKeywordsFromOntology(String, String)<br>
+        <b>offset:</b> The offset of the document from which the resultant documents will start as the search result.<br>
+        <b>limit:</b> Maximum number of resultant documents to be returned as the search result. offset and limit parameters can be used to make a pagination mechanism for search results.<br>
+        <b>fromStore:</b> Special parameter for HTML view only.
+    </td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>HTML view or JSON representation of the search results or HTTP BAD REQUEST(400)</td>
+  </tr>
+  <tr>
+    <th>Throws</th>
+    <td>
+      IllegalArgumentException<br>
+      SearchException<br>
+      InstantiationException<br>
+      IllegalAccessException<br>
+      SolrServerException<br>
+      IOException
+    </td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<pre>curl -i "http://localhost:8080/contenthub/contenthub/search/featured?queryTerm=paris&limit=3"</pre>
+
+<hr>
+
+
+<h3>Related Search</h3>
+
+Related Search provide three sub-endpoints
+
+<h4>/related endpoint</h4>
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP GET method to retrieve related keywords from all resources defined within Contenthub.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>GET /contenthub/search/related</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td>
+        <b>keyword:</b> The keyword whose related keywords will be retrieved.<br>
+        <b>graphURI:</b> URI of the ontology to be used during the step in which related keywords are searched in ontology resources. If this parameter is <code> null</code>, then no related keywords are returned from ontology resources.
+    </td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>JSON string which is constructed by SearchResultWriter. SearchResult returned by RelatedKeywordSearchManager#getRelatedKeywordsFromAllSources(String, String) only contains related keywords (no resultant documents or facet fields are returned within the SearchResult).</td>
+  </tr>
+  <tr>
+    <th>Throws</th>
+    <td>SearchException</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<pre>curl -i -X GET http://localhost:8080/contenthub/search/related?keyword=Paris -H "Accept:application/json"</pre>
+<hr>
+
+
+<h4>related/wordnet sub-endpoint</h4>  
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP GET method to retrieve related keywords from Wordnet. If a Wordnet database is not installed into Contenthub, this method cannot find any related keywords.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>GET /contenthub/search/related/wordnet</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td><b>keyword:</b> The keyword whose related keywords will be retrieved from Wordnet.</td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>JSON string which is constructed by SearchResultWriter. SearchResult returned by RelatedKeywordSearchManager#getRelatedKeywordsFromWordnet(String) contains only related keywords from Wordnet. (No resultant documents or facet fields are returned within the SearchResult).</td>
+  </tr>
+  <tr>
+    <th>Throws</th>
+    <td>SearchException</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<pre>curl -i -X GET http://localhost:8080/contenthub/search/related/wordnet?keyword=Paris -H "Accept:application/json"</pre>
+
+<hr>
+
+
+<h4>related/ontology sub-endpoint</h4>
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP GET method to retrieve related keywords from ontology resources. Given the ontology URI, this method looks for subsumption/hierarchy relations among the concepts to come up with related keywords.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>GET /contenthub/search/related/ontology</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td>
+      <b>keyword:</b> The keyword whose related keywords will be retrieved from ontology resources.<br>
+      <b>graphURI:</b> URI of the ontology in which related keywords will be searched. The ontology should be available in the Contenthub system.
+    </td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>JSON string which is constructed by SearchResultWriter. SearchResult returned by RelatedKeywordSearchManager#getRelatedKeywordsFromOntology(String, String) contains only related keywords from ontology resources. (No resultant documents or facet fields are returned within the SearchResult).</td>
+  </tr>
+  <tr>
+    <th>Throws</th>
+    <td>SearchException</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<div class="preParent">
+  <img onClick="javascript:getLine(this.parentNode);" class="copyImg" src="${it.staticRootUrl}/contenthub/images/copy_icon_16.png" title="Get command in a single line" />
+<pre>
+<div id="curl1" class="curlLine">curl -i -X GET http://localhost:8080/contenthub/search/related/ontology?keyword=Paris&graphURI=testOntology -H "Accept:application/json"<hr/></div>curl -i -X GET http://localhost:8080/contenthub/search/related/ontology?keyword=Paris&graphURI=testOntology \
+     -H "Accept:application/json"
+</pre>
+</div>
+
+<hr>
+
+
+<h4>related/referencedsite sub-endpoint</h4>
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP GET method to retrieve related keywords from the referenced sites.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>GET /contenthub/search/related/referencedsite</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td><b>keyword:</b> The keyword whose related keywords will be retrieved from referenced sites.</td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>JSON string which is constructed by SearchResultWriter. SearchResult returned by RelatedKeywordSearchManager#getRelatedKeywordsFromReferencedSites(String) contains only related keywords from referenced sites. (No resultant documents or facet fields are returned within the SearchResult).</td>
+  </tr>
+  <tr>
+    <th>Throws</th>
+    <td>SearchException</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<pre>curl -i -X GET http://localhost:8080/contenthub/search/related/referencedsite?keyword=Paris -H "Accept:application/json"</pre>
+
+<hr>
+
+<script>
+function selectText(element) {
+    var doc = document;
+    var text = doc.getElementById(element);    
+    if (doc.body.createTextRange) { // ms
+        var range = doc.body.createTextRange();
+        range.moveToElementText(text);
+        range.select();
+    } else if (window.getSelection) {
+        var selection = window.getSelection();
+        var range = doc.createRange();
+        range.selectNodeContents(text);
+        selection.removeAllRanges();
+        selection.addRange(range);
+        
+    }
+}
+
+  function getLine(div){
+    $(div).children('pre').children('.curlLine').toggle();
+    selectText($(div).children('pre').children('.curlLine').attr('id'));
+  }
+</script>
\ No newline at end of file

Added: incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/storerestapi.ftl
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/storerestapi.ftl?rev=1333955&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/storerestapi.ftl (added)
+++ incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/imports/storerestapi.ftl Fri May  4 13:38:16 2012
@@ -0,0 +1,578 @@
+  <h3>Uploading new content to the Contenthub</h3>
+
+  <p>Contenthub lives at the endpoint starting with "contenthub":</p>
+  <code>${it.publicBaseUri}contenthub/</code>
+  <p>This endpoint automatically forwards to:</p>
+  <code>${it.publicBaseUri}contenthub/${it.indexName}/store/</code>
+  <p>The endpoint to which Contenthub automatically forwards includes the name of the default index,
+  whose name is "contenthub". That is the reason for two consecutive "contenthub"s in the endpoint.
+  Lastly, "store" page provides the storage related functionalities of Contenthub such as document submission.</p>
+
+  <p>You can upload content to the Contenthub for analysis with or without providing the content
+   id at your option:</p>
+  <ul>
+    <li><code>POST</code> content to <code>${it.publicBaseUri}contenthub/${it.indexName}/store/<strong>content-id</strong></code>
+     with <code>Content-Type: text/plain</code>.</li>
+    <li><code>GET</code> content with its enhancements from the same URL.</li>
+  </ul>
+  
+  <p><code><strong>content-id</strong></code> can be any valid URI and
+   will be used to fetch your item back later. <code><strong>content-id</strong></code>s are unique within Contenthub.</p>
+
+  <p>On a unix-ish box you can use run the following command from
+   the top-level source directory to populate the Stanbol Contenthub service with
+   sample content items:</p>
+
+<pre>
+for file in enhancer/data/text-examples/*.txt;
+do
+  curl -i -X POST -H "Content-Type:text/plain" -T $file ${it.publicBaseUri}contenthub/${it.indexName}/store/$(basename $file);
+done
+</pre> 
+
+  Alternatively you can let the Stanbol Contenthub automatically build an id base on the SHA1
+  hash of the content by posting it at the root of the Contenthub.
+  <ul>
+    <li><code>POST</code> content to <code>${it.publicBaseUri}contenthub/${it.indexName}/store</code>
+     with <code>Content-Type: text/plain</code>.</li>
+  </ul>
+  
+  <p>For instance:</p>
+<pre>
+curl -i -X POST -H "Content-Type:text/plain" \
+     --data "The Stanbol enhancer can detect famous cities such as Paris." \
+     ${it.publicBaseUri}contenthub/${it.indexName}/store
+    
+HTTP/1.1 201 Created
+Location: ${it.publicBaseUri}contenthub/${it.indexName}/store/content/{<code><strong>content-id</strong><code>}
+Content-Length: 0
+Server: Jetty(6.1.x)
+</pre>
+
+<h3>Fetching back the original content item and the related enhancements from the Contenthub</h3>
+
+<p>Once the content is created in the Contenthub, you can fetch back either the original content, a HTML summary view or
+the extracted RDF metadata by dereferencing the URL:</p>
+
+<pre>
+curl -i <strong>-H "Accept: text/plain"</strong> ${it.publicBaseUri}contenthub/${it.indexName}/store/content/{<code><strong>content-id</strong><code>}
+
+HTTP/1.1 307 TEMPORARY_REDIRECT
+Location: ${it.publicBaseUri}contenthub/${it.indexName}/store/raw/{<code><strong>content-id</strong><code>}
+Content-Length: 0
+Server: Jetty(6.1.x)
+</pre>
+
+<p>
+Tutorials on Stanbol Contenthub can be found in the following links:<br/>
+<a href="http://incubator.apache.org/stanbol/docs/trunk/contenthub/">Contenhub - One Minute Tutorial</a><br/>
+<a href="http://incubator.apache.org/stanbol/docs/trunk/contenthub/contenthub5min">Contenthub - Five Minutes Tutorial</a>
+</p>
+
+<br>
+<h3>The RESTful API of the Contenthub Store</h3>
+
+<h3>Create a Content Item</h3>
+
+<h4>Create with raw content</h4>  
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP POST method to create a content item in Contenthub. This is the very basic method to create the content item. The payload of the POST method should include the raw data of the content item to be created. This method stores the content in the default Solr index ("contenthub").</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>POST /contenthub/{indexName}/store</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td><b>data:</b> Raw data of the content item</td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>Redirects to "contenthub/{indexName}/store/content/uri" which shows the content item in the HTML view</td>
+  </tr>
+  <tr>
+    <th>Throws</th>
+    <td>
+      URISyntaxException<br>
+      EngineException<br>
+      StoreException
+    </td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<div class="preParent">
+  <img onClick="javascript:getLine(this.parentNode);" class="copyImg" src="${it.staticRootUrl}/contenthub/images/copy_icon_16.png" title="Get command in a single line" />
+<pre>
+<div id="curl1" class="curlLine">curl -i -X POST -H "Content-Type:text/plain" --data @/home/user/Documents/test.txt http://localhost:8080/contenthub/contenthub/store<hr/></div>curl -i -X POST -H "Content-Type:text/plain" \
+     --data @/home/user/Documents/test.txt \
+     http://localhost:8080/contenthub/contenthub/store
+</pre>
+</div>
+
+<div class="preParent">
+  <img onClick="javascript:getLine(this.parentNode);" class="copyImg" src="${it.staticRootUrl}/contenthub/images/copy_icon_16.png" title="Get command in a single line" />
+<pre>
+<div id="curl2" class="curlLine">curl -i -X POST -H "Content-Type:text/plain" --data "I live in Paris." http://localhost:8080/contenthub/contenthub/store<hr/></div>curl -i -X POST -H "Content-Type:text/plain" \ 
+     --data "I live in Paris." \
+     http://localhost:8080/contenthub/contenthub/store
+</pre>
+</div>
+
+<hr>
+
+<h4>Create with raw content and user specified uri</h4>
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP POST method to create a content item in Contenthub. This is the very basic method to create the content item. The payload of the POST method should include the raw data of the content item to be created. This method stores the content in the default Solr index ("contenthub").</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>POST /contenthub/{indexName}/store/{uri}</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td>
+      <b>data:</b> Raw data of the content item<br>
+      <b>uri:</b>  URI for the content item. If not supplied, Contenthub automatically assigns a unique ID (uri) to the content item.
+    </td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>Redirects to "contenthub/{indexName}/store/content/uri" which shows the content item in the HTML view.</td>
+  </tr>
+  <tr>
+    <th>Throws</th>
+    <td>
+      URISyntaxException<br>
+      EngineException<br>
+      StoreException
+    </td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<div class="preParent">
+  <img onClick="javascript:getLine(this.parentNode);" class="copyImg" src="${it.staticRootUrl}/contenthub/images/copy_icon_16.png" title="Get command in a single line" />
+<pre>
+<div id="curl3" class="curlLine">curl -i -X POST -H "Content-Type:text/plain" --data @/home/user/Documents/test.txt http://localhost:8080/contenthub/contenthub/store/example1234<hr/></div>curl -i -X POST -H "Content-Type:text/plain" \
+     --data @/home/user/Documents/test.txt \
+     http://localhost:8080/contenthub/contenthub/store/example1234
+</pre>
+</div>
+
+<div class="preParent">
+  <img onClick="javascript:getLine(this.parentNode);" class="copyImg" src="${it.staticRootUrl}/contenthub/images/copy_icon_16.png" title="Get command in a single line" />
+<pre>
+<div id="curl4" class="curlLine">curl -i -X POST -H "Content-Type:text/plain" --data "I live in Paris." http://localhost:8080/contenthub/contenthub/store/example1234<hr/></div>curl -i -X POST -H "Content-Type:text/plain" \
+     --data "I live in Paris." \
+     http://localhost:8080/contenthub/contenthub/store/example1234
+</pre>
+</div>
+
+<hr>
+
+
+<h4>Create with form elements</h4>
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>Creates a content item in Contenthub. This method requires the content to be text-based</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>POST /contenthub/{indexName}/store</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td>
+      <b>content:</b> Actual content in text format. If this parameter is supplied, url is ommitted.<br>
+      <b>url:</b> URL where the actual content resides. If this parameter is supplied (and content is <code>null</code>, then the content is retrieved from this url.<br>
+      <b>constraints:</b> Constraints in JSON format. Constraints are used to add supplementary metadata to the content item. For example, author of the content item may be supplied as {author: "John Doe"}. Then, this constraint is added to the Solr and will be indexed if the corresponding Solr schema includes the author field. Solr indexed can be created/adjusted through LDPath programs.<br>
+      <b>title:</b> The title for the content item. Titles can be used to present summary of the actual content. For example, search results are presented by showing the titles of resultant content items.<br>
+    </td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>Redirects to "contenthub/{indexName}/store/content/{uri}" which shows the content item in the HTML view.</td>
+  </tr>
+  <tr>
+    <th>Throws</th>
+    <td>
+      URISyntaxException<br>
+      EngineException<br>
+      MalformedURLException<br>
+      IOException<br>
+      StoreException
+    </td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+
+<div class="preParent">
+  <img onClick="javascript:getLine(this.parentNode);" class="copyImg" src="${it.staticRootUrl}/contenthub/images/copy_icon_16.png" title="Get command in a single line" />
+<pre>
+<div id="curl5" class="curlLine">curl -i -X POST --data "content=Paris is the capital of France&constraints={type:city}&title=Paris" http://localhost:8080/contenthub/contenthub/store<hr/></div>curl -i -X POST --data \
+     "content=Paris is the capital of France&constraints={type:city}&title=Paris" \
+     http://localhost:8080/contenthub/contenthub/store
+</pre>
+</div>
+
+<hr>
+
+
+<h4>Create with file</h4>  
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP POST method to create a content item from file. File is read and loaded as the actual content.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>POST /contenthub/{indexName}/store</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td>
+      <b>file:</b> File which contains the content for the content item.<br>
+      <b>disposition:</b> Additional information about the file parameter<br>
+      <b>jsonCons:</b> Constraints in JSON format. Constraints are used to add supplementary metadata to the content item. For example, author of the content item may be supplied as {author: "John Doe"}. Then, this constraint is added to the Solr and will be indexed if the corresponding Solr schema includes the author field. Solr indexed can be created/adjusted through LDPath programs.<br>
+      <b>title:</b> The title for the content item. Titles can be used to present summary of the actual content. For example, search results are presented by showing the titles of resultant content items.<br>
+    </td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>Redirects to "contenthub/{indexName}/store/content/{uri}" which shows the content item in the HTML view.</td>
+  </tr>
+  <tr>
+    <th>Throws</th>
+    <td>
+      URISyntaxException<br>
+      EngineException<br>
+      MalformedURLException<br>
+      IOException<br>
+      StoreException
+    </td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<div class="preParent">
+  <img onClick="javascript:getLine(this.parentNode);" class="copyImg" src="${it.staticRootUrl}/contenthub/images/copy_icon_16.png" title="Get command in a single line" />
+<pre>
+<div id="curl6" class="curlLine">curl -i POST -F "file=@/home/mrc/Desktop/test.txt" -F "constraints={type:city}" -F "title=Paris" http://localhost:8080/contenthub/contenthub/store<hr/></div>curl -i POST -F "file=@/home/mrc/Desktop/test.txt" \
+             -F "constraints={type:city}" \ 
+             -F "title=Paris" \
+     http://localhost:8080/contenthub/contenthub/store
+</pre>
+</div>
+
+<hr>
+
+
+<h3>Update a Content Item</h3>
+
+<h4>Update with form elements</h4>
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP POST method to update an existing content item.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>POST /contenthub/{indexName}/store/update</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td>
+      <b>uri:</b> URI of the content item to be updated.<br>
+      <b>content:</b> Actual content in text format. If this parameter is supplied, url is ommitted.<br>
+      <b>url:</b> URL where the actual content resides. If this parameter is supplied (and content is <code>null</code>, then the content is retrieved from this url.<br>
+      <b>jsonCons:</b> Constraints in JSON format. Constraints are used to add supplementary metadata to the content item. For example, author of the content item may be supplied as {author: "John Doe"}. Then, this constraint is added to the Solr and will be indexed if the corresponding Solr schema includes the author field. Solr indexed can be created/adjusted through LDPath programs.<br>
+      <b>title:</b> The title for the content item. Titles can be used to present summary of the actual content. For example, search results are presented by showing the titles of resultant content items.<br>
+    </td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>Redirects to "contenthub/{indexName}/store/content/{uri}" which shows the content item in the HTML view.</td>
+  </tr>
+  <tr>
+    <th>Throws</th>
+    <td>
+      URISyntaxException<br>
+      EngineException<br>
+      MalformedURLException<br>
+      IOException<br>
+      StoreException
+    </td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<div class="preParent">
+  <img onClick="javascript:getLine(this.parentNode);" class="copyImg" src="${it.staticRootUrl}/contenthub/images/copy_icon_16.png" title="Get command in a single line" />
+<pre>
+<div id="curl7" class="curlLine">curl -i -X POST --data "uri=example1234&content=Paris is the capital of France&constraints={type:city}&title=France" http://localhost:8080/contenthub/contenthub/store/update<hr/></div>curl -i -X POST --data \
+     "uri=example1234&content=Paris is the capital of France&constraints={type:city}&title=France" \
+     http://localhost:8080/contenthub/contenthub/store/update
+</pre>
+</div>
+
+<hr>
+
+
+<h4>Update with file</h4>  
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP POST method to update an existing content item.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>POST /contenthub/{indexName}/store/update</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td>
+      <b>uri:</b> URI of the content item to be updated.<br>
+      <b>file:</b> File which contains the content for the content item.<br>
+      <b>disposition:</b> Additional information about the file parameter<br>
+      <b>jsonCons:</b> Constraints in JSON format. Constraints are used to add supplementary metadata to the content item. For example, author of the content item may be supplied as {author: "John Doe"}. Then, this constraint is added to the Solr and will be indexed if the corresponding Solr schema includes the author field. Solr indexed can be created/adjusted through LDPath programs.<br>
+      <b>title:</b> The title for the content item. Titles can be used to present summary of the actual content. For example, search results are presented by showing the titles of resultant content items.<br>
+    </td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>Redirects to "contenthub/{indexName}/store/content/{uri}" which shows the content item in the HTML view.</td>
+  </tr>
+  <tr>
+    <th>Throws</th>
+    <td>
+      URISyntaxException<br>
+      EngineException<br>
+      MalformedURLException<br>
+      IOException<br>
+      StoreException
+    </td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<div class="preParent">
+  <img onClick="javascript:getLine(this.parentNode);" class="copyImg" src="${it.staticRootUrl}/contenthub/images/copy_icon_16.png" title="Get command in a single line" />
+<pre>
+<div id="curl8" class="curlLine">curl -i POST -F "file=@/home/mrc/Desktop/test.txt" -F "constraints={type:city}" -F "title=Paris" -F "uri=example1234" http://localhost:8080/contenthub/contenthub/store/update<hr/></div>curl -i POST -F "file=@/home/mrc/Desktop/test.txt" \
+             -F "constraints={type:city}" \
+             -F "title=Paris" \
+             -F "uri=example1234" \
+     http://localhost:8080/contenthub/contenthub/store/update
+</pre>
+</div>
+
+<hr>
+
+
+<h3>Delete a Content Item</h3>  
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>HTTP DELETE method to delete a content item from Contenhub.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>DELETE /contenthub/{indexName}/store/{uri}</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td><b>uri:</b> URI of the content item to be deleted.</td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>HTTP OK</td>
+  </tr>
+  <tr>
+    <th>Throws</th>
+    <td>StoreException</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<pre>curl -i -X DELETE http://localhost:8080/contenthub/contenthub/store/example-uri-1234</pre>
+
+<hr>
+
+
+<h3>Subresources</h3>
+
+<h4>Subresource /content</h4>  
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>A redirection to either a browser view, the RDF metadata or the raw binary content</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>GET /contenthub/{indexName}/store/content/{uri}</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td><b>uri:</b> The URI of the resource in the Stanbol Contenthub store</td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>Depending on requested media type, it can produce HTML, RDF or raw binary content</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<pre>curl http://localhost:8080/contenthub/contenthub/store/content/uri-234231</pre>
+
+<hr>
+
+
+<h4>Subresource /download</h4>
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>Raw data or metadata of the content item can be downloaded.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>GET /contenthub/{indexName}/store/download/{type}/{uri}</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td>
+      <b>type: </b>It can be <code> "metadata"</code> or <code> "raw"</code>. Based on the type, related parts of the content item will be prepared for download.<br>
+      <b>uri: </b>URI of the resource in the Stanbol Contenthub store.<br>
+      <b>format: </b>Rdf serialization format of metadata.
+    </td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>200 with a file containing metadata or raw data of the content item</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<pre>curl http://localhost:8080/contenthub/contenthub/store/download/metadata/5d85e7c63cc48c0985?format=application%2Fjson</pre>
+<pre>curl http://localhost:8080/contenthub/contenthub/store/download/raw/5d85e7c63cc48c01b8d4?format=application%2Frdf%2Bxml</pre>
+
+<hr>
+
+
+<h4>Subresource /metadata</h4>  
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>Retrieves the metadata of the content item. Generally, metadata contains the enhancements of the content item.</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>GET /contenthub/{indexName}/store/metadata/{uri}</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td><b>uri:</b> The URI of the resource in the Stanbol Contenthub store</td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>200 with RDF representation of the metadata of the content item.</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<pre>curl http://localhost:8080/contenthub/contenthub/store/metadata/sha1-5d85e7c63cc48c01</pre>
+<hr>
+
+
+<h4>Subresource /raw</h4>
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>Retrieve the raw content item</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>GET /contenthub/{indexName}/store/raw/{uri}</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td><b>uri:</b> The URI of the resource in the Stanbol Contenthub store</td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>200 with the raw data of the content item</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<pre>curl http://localhost:8080/contenthub/contenthub/store/raw/testuri2343124</pre>
+
+<hr>
+
+
+<h4>Subresource /edit</h4>  
+<table>
+<tbody>
+  <tr>
+    <th>Description</th>
+    <td>Creates the JSON string of a content item (to be edited) to display it in the HTML view</td>
+  </tr>
+  <tr>
+    <th>Request</th>
+    <td>GET /contenthub/{indexName}/store/edit/{uri}</td>
+  </tr>
+  <tr>
+    <th>Parameter</th>
+    <td><b>uri:</b> The URI of the resource in the Stanbol Contenthub store</td>
+  </tr>
+  <tr>
+    <th>Produces</th>
+    <td>200 with an JSON representation of the content item</td>
+  </tr>
+</tbody>
+</table>
+<h4>Example</h4>
+<pre>curl http://localhost:8080/contenthub/contenthub/store/edit/sha1-5d85e7c63cc48c01</pre>
+
+<hr>
+
+<script>
+function selectText(element) {
+    var doc = document;
+    var text = doc.getElementById(element);    
+    if (doc.body.createTextRange) { // ms
+        var range = doc.body.createTextRange();
+        range.moveToElementText(text);
+        range.select();
+    } else if (window.getSelection) {
+        var selection = window.getSelection();
+        var range = doc.createRange();
+        range.selectNodeContents(text);
+        selection.removeAllRanges();
+        selection.addRange(range);
+        
+    }
+}
+
+  function getLine(div){
+    $(div).children('pre').children('.curlLine').toggle();
+    selectText($(div).children('pre').children('.curlLine').attr('id'));
+  }
+</script>
\ No newline at end of file

Added: incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/org/apache/stanbol/contenthub/web/resources/ContentItemResource/index.ftl
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/org/apache/stanbol/contenthub/web/resources/ContentItemResource/index.ftl?rev=1333955&view=auto
==============================================================================
--- incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/org/apache/stanbol/contenthub/web/resources/ContentItemResource/index.ftl (added)
+++ incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/org/apache/stanbol/contenthub/web/resources/ContentItemResource/index.ftl Fri May  4 13:38:16 2012
@@ -0,0 +1,64 @@
+<#--
+  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.
+-->
+<#import "/imports/common.ftl" as common>
+<#import "/imports/contentitem.ftl" as contentitem>
+<#escape x as x?html>
+<@common.page title="Content Item: ${it.localId} (${it.contentItem.mimeType})" hasrestapi=false> 
+
+<h3>Public URI of this resource</h3>
+<pre>${it.contentItem.uri.unicodeString}</pre>
+
+<h3>Content preview</h3>
+<div class="contentItemPreview">
+<#if it.textContent?exists>
+<pre>${it.textContent}</pre>
+</#if>
+<#if it.imageSrc?exists>
+<img class="preview" src="${it.imageSrc}" alt="Image content of ${it.localId}" />
+</#if>
+</div>
+
+<ul class="downloadLinks">
+<#if it.downloadHref?exists>
+<li><a href="${it.downloadHref}" class="download">Download the original Content Item</a></li>
+</#if>
+<#if it.metadataHref?exists>
+<li>
+  Output format:
+  <select onChange="javascript:setFormat();" id="selectFormat">
+    <option value="application/json">JSON-LD</option>
+    <option value="application/rdf+xml">RDF/XML</option>
+    <option value="application/rdf+json">RDF/JSON</option>
+    <option value="text/turtle">Turtle</option>
+    <option value="text/rdf+nt">N-TRIPLES</option>
+  </select>
+  <a id="downloadRDF" href="${it.metadataHref}?format=application%2Fjson" class="downloadRDF">Download the related RDF enhancements</a>
+</li>
+</#if>
+</ul>
+
+<@contentitem.view />
+
+</...@common.page>
+</#escape>
+
+<script>
+ function setFormat(){
+   var format = encodeURIComponent($("#selectFormat").val());
+   $("#downloadRDF").attr("href", "${it.metadataHref}?format="+format);
+ }
+</script>

Modified: incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/org/apache/stanbol/contenthub/web/resources/FeaturedSearchResource/index.ftl
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/org/apache/stanbol/contenthub/web/resources/FeaturedSearchResource/index.ftl?rev=1333955&r1=1333954&r2=1333955&view=diff
==============================================================================
--- incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/org/apache/stanbol/contenthub/web/resources/FeaturedSearchResource/index.ftl (original)
+++ incubator/stanbol/trunk/contenthub/web/src/main/resources/org/apache/stanbol/contenthub/web/templates/org/apache/stanbol/contenthub/web/resources/FeaturedSearchResource/index.ftl Fri May  4 13:38:16 2012
@@ -16,46 +16,52 @@
 -->
 <#import "/imports/common.ftl" as common>
 <#escape x as x?html>
-<@common.page title="Search" hasrestapi=false>
-  <div id="search">
-  <#-- this feildset was normally in a form, ajax is used to do the post, dont need to use fom -->
-    <fieldset>
-      <legend>Keyword Based Search</legend>
-      
-      <p>
-        Select an index: <div id="indexDiv"><#--this div will be populated by ajax--></div>
-      </p>
-      <p>
-        Keywords: <input id="keywordIn" class="autoCompleteText" <#-- onkeyup="javascript:completePattern();" --> name="topic" type="text" onkeydown="if (event.keyCode == 13) document.getElementById('submitIn').click()"/><br/>
-      </p>
-      <p>
-        <!-- Ontology selection combobox-->
-        <#if it.ontologies?exists && it.ontologies?size != 0>
-          Graph: 
-          <select  id="graphIn" name="max" type="text" value="5">
-            <option value="choose_ontology">Choose an ontology</option>
-            <#list it.ontologies as ont>
-              <option value="${ont}">${ont}</option>
-            </#list>
-          </select>
-        <#else>
-          <p><i>No graphs to search.<i><p> 
-        </#if>
-      </p>
-      <p>
-        <input id="submitIn" type="button" value="Search" onclick="getResults(null,null,'first');"></input>
-      </p>
-      <img id="busyIcon" class="invisible centerImage" src="${it.staticRootUrl}/contenthub/images/ajax-loader.gif"/>
-    </fieldset>
-  </div>  
-  
-  <div id="resultContainer" class="invisible">
-    <div class="invisible" id="previousSuggestionButton"></div>
-    <div>
-      <!-- To be populated with ajax without xml :)-->
+<@common.page title="Search" hasrestapi=true>
+  <div class="panel" id="webview">
+    <div id="search">
+    <#-- this feildset was normally in a form, ajax is used to do the post, dont need to use fom -->
+      <fieldset>
+        <legend>Keyword Based Search</legend>
+        
+        <p>
+          Select an index: <div id="indexDiv"><#--this div will be populated by ajax--></div>
+        </p>
+        <p>
+          Keywords: <input id="keywordIn" class="autoCompleteText" <#-- onkeyup="javascript:completePattern();" --> name="topic" type="text" onkeydown="if (event.keyCode == 13) document.getElementById('submitIn').click()"/><br/>
+        </p>
+        <p>
+          <!-- Ontology selection combobox-->
+          <#if it.ontologies?exists && it.ontologies?size != 0>
+            Graph: 
+            <select  id="graphIn" name="max" type="text" value="5">
+              <option value="choose_ontology">Choose an ontology</option>
+              <#list it.ontologies as ont>
+                <option value="${ont}">${ont}</option>
+              </#list>
+            </select>
+          <#else>
+            <p><i>No graphs to search.<i><p> 
+          </#if>
+        </p>
+        <p>
+          <input id="submitIn" type="button" value="Search" onclick="getResults(null,null,'first');"></input>
+        </p>
+        <img id="busyIcon" class="invisible centerImage" src="${it.staticRootUrl}/contenthub/images/ajax-loader.gif"/>
+      </fieldset>
+    </div>  
+    
+    <div id="resultContainer" class="invisible">
+      <div class="invisible" id="previousSuggestionButton"></div>
+      <div>
+        <!-- To be populated with ajax without xml :)-->
+      </div>
     </div>
   </div>
   
+  <div class="panel" id="restapi" style="display: none;">
+    <#include "/imports/searchrestapi.ftl">
+  </div>
+
   <!-- to be populated by the list of suggested keywords to be able to get back in search -->
   <input type="hidden" id="suggestedKeywordList" value=""/>  
   <!-- FIXME put a textarea so jQuery-ui tabs does not expand through footer -->
@@ -111,7 +117,17 @@
       }
 
       function getResults(facetName,facetValue,operation,voffset,vpageSize) {
-        
+
+          if($("#keywordIn").val() == null || $.trim($("#keywordIn").val()).length == 0) {
+              alert("You should enter keyword(s) for search");
+              return;
+          }
+          
+          $("#keywordIn").val($.trim($("#keywordIn").val()));          
+          if($("#keywordIn").val() == "*" || $("#keywordIn").val() == "?"){
+              $("#keywordIn").val("*:*");
+          }
+          
           //clears the content of div because it'll be filled by explorer posts
           var keywordToSearch = $("#keywordIn").val();
           
@@ -225,7 +241,7 @@
           //show busy icon
           $("#busyIcon").removeClass("invisible");
 
-		  var urlStr = "${it.publicBaseUri}contenthub/${it.indexName}/search/featured?queryTerm=" + $("#keywordIn").val();
+          var urlStr = "${it.publicBaseUri}contenthub/${it.indexName}/search/featured?queryTerm=" + $("#keywordIn").val();
 
           var graph_selected = "";
           var graphInCombo = document.getElementById('graphIn');
@@ -237,7 +253,7 @@
               }
           }
       
-      	    
+            
           $.ajax({
               url : urlStr,
               type : "GET",