You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@clerezza.apache.org by re...@apache.org on 2015/03/23 18:03:45 UTC

[47/51] [partial] clerezza git commit: CLEREZZA-966: removed platform. prefix of folder names

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/ConceptsFinder.java
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/ConceptsFinder.java b/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/ConceptsFinder.java
new file mode 100644
index 0000000..f3ac14e
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/ConceptsFinder.java
@@ -0,0 +1,266 @@
+/*
+ * 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.clerezza.platform.concepts.core;
+
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.clerezza.platform.concepts.ontologies.QUERYRESULT;
+import org.apache.clerezza.platform.config.PlatformConfig;
+import org.apache.clerezza.platform.graphprovider.content.ContentGraphProvider;
+import org.apache.clerezza.platform.typerendering.RenderletManager;
+import org.apache.clerezza.platform.typerendering.scalaserverpages.ScalaServerPagesRenderlet;
+import org.apache.clerezza.rdf.core.BNode;
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.Literal;
+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.Resource;
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.access.TcManager;
+import org.apache.clerezza.rdf.core.impl.SimpleMGraph;
+import org.apache.clerezza.rdf.core.impl.TripleImpl;
+import org.apache.clerezza.rdf.ontologies.OWL;
+import org.apache.clerezza.rdf.ontologies.RDF;
+import org.apache.clerezza.rdf.ontologies.RDFS;
+import org.apache.clerezza.rdf.ontologies.SKOS;
+import org.apache.clerezza.rdf.utils.GraphNode;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * This JAX-RS resource can be used to search concepts accessible through
+ * registered {@link ConceptProvider}s. If no {@link LocalConceptProvider} is
+ * registered for {@link ConceptManipulator.FREE_CONCEPT_SCHEME}, then one is
+ * created to find free concepts in the content graph.
+ * Concept providers are prioritized.
+ * The URI, SKOS:prefLabel and RDFS:comment of a concept from a provider of a 
+ * higher priority will be used instead of those concepts having an OWL:sameAs
+ * relation with this concept, but from a provider of lower priority.
+ * Implicitly created {@link LocalConceptProvider} for free concepts has the
+ * lowest priority.
+ * 
+ * The URI path of this service is /concepts/find.
+ * 
+ * @author hasan
+ */
+@Component
+@Service(Object.class)
+@Property(name = "javax.ws.rs", boolValue = true)
+@Path("/concepts/find")
+public class ConceptsFinder {
+
+    @Reference
+    private RenderletManager renderletManager;
+
+    @Reference
+    protected ConceptProviderManager conceptProviderManager;
+
+    @Reference
+    private TcManager tcManager;
+
+    @Reference
+    private ContentGraphProvider cgProvider;
+
+    @Reference
+    private PlatformConfig platformConfig;
+
+    private LocalConceptProvider freeConceptProvider = null;
+
+    private UriRef freeConceptScheme = null;
+
+    protected void activate(ComponentContext context) throws URISyntaxException {
+        URL template = getClass().getResource("skos-collection-json.ssp");
+        renderletManager.registerRenderlet(ScalaServerPagesRenderlet.class.getName(),
+                new UriRef(template.toURI().toString()),
+                SKOS.Collection, null,
+                MediaType.APPLICATION_JSON_TYPE, true);
+
+        freeConceptScheme =
+                new UriRef(platformConfig.getDefaultBaseUri().getUnicodeString()
+                + ConceptManipulator.FREE_CONCEPT_SCHEME);
+        freeConceptProvider = new LocalConceptProvider(tcManager, cgProvider,
+                freeConceptScheme);
+    }
+
+    /**
+     * Searches concepts for a specified search term. The actual search task
+     * is delegated to each {@link ConceptProvider} instance. The results from
+     * each {@link ConceptProvider} are merged into a single result graph.
+     * However, concepts from providers of lower priority are only considered if
+     * they are not staying in an OWL:sameAs relation with concepts from
+     * providers of higher priority.
+     * 
+     * @param searchTerm
+     *            The search term in form of a String.
+     * @return
+     *        A GraphNode containing the search results.
+     */
+    @GET
+    @Produces("application/rdf+json")
+    public GraphNode findConcepts(@QueryParam(value="searchTerm")
+            String searchTerm) {
+
+        boolean freeConceptProviderFound = false;
+
+        List<ConceptProvider> conceptProviderList = conceptProviderManager
+                .getConceptProviders();
+
+        MGraph resultMGraph = new SimpleMGraph();
+        GraphNode resultNode = new GraphNode(new BNode(), resultMGraph);
+        boolean first = true;
+        for (ConceptProvider cp : conceptProviderList) {
+            if (!freeConceptProviderFound) {
+                if (cp instanceof LocalConceptProvider) {
+                    if (((LocalConceptProvider) cp).getSelectedScheme().equals(
+                            freeConceptScheme)) {
+                        freeConceptProviderFound = true;
+                    }
+                }
+            }
+            retrieveConcepts(cp, first, resultNode, searchTerm);
+            if (first) {
+                first = false;
+            }
+        }
+        if (!freeConceptProviderFound && freeConceptProvider != null) {
+            retrieveConcepts(freeConceptProvider, first, resultNode, searchTerm);
+        }
+        addCreationOfNewFreeConceptSuggested(resultNode, searchTerm);
+        resultNode.addProperty(RDF.type, QUERYRESULT.QueryResult);
+        return resultNode;
+    }
+
+    /**
+     * Adds a boolean value that answers whether the UI shall suggest to create
+     * a new free concept. A new free concept may not be added if the has the
+     * same base uri and search term. Therefore the consumer shall be suggested
+     * not to propose creation.
+     * 
+     * @param resultNode
+     *            the result node to add the property to
+     * @param searchTerm
+     *            the search term the data was searched for
+     */
+    private void addCreationOfNewFreeConceptSuggested(GraphNode resultNode,
+            String searchTerm) {
+        UriRef conceptUriRef = ConceptManipulator.getConceptUriRef(
+                platformConfig, searchTerm);
+        resultNode.addProperty(QUERYRESULT.creationOfNewFreeConceptSuggested,
+                LiteralFactory.getInstance().createTypedLiteral(
+                        !cgProvider.getContentGraph().contains(
+                                new TripleImpl(conceptUriRef, RDF.type,
+                                        SKOS.Concept))));
+    }
+
+    /**
+     * Retrieve concepts for the given search term.
+     * 
+     * @param conceptProvider
+     *            the provider delivers concepts
+     * @param first
+     *            is this the first execution
+     * @param resultNode
+     *            the node to attach the concepts to
+     * @param searchTerm
+     *            the search term that the concepts have to match against
+     */
+    private void retrieveConcepts(ConceptProvider conceptProvider,
+            boolean first, GraphNode resultNode, String searchTerm) {
+        MGraph resultMGraph = (MGraph) resultNode.getGraph();
+        Graph graph = conceptProvider.retrieveConcepts(searchTerm);
+        Iterator<Triple> concepts = graph.filter(null, RDF.type, SKOS.Concept);
+        if (first) {
+            while (concepts.hasNext()) {
+                resultNode.addProperty(QUERYRESULT.concept, concepts.next()
+                        .getSubject());
+            }
+            resultMGraph.addAll(graph);
+        } else {
+            while (concepts.hasNext()) {
+                NonLiteral concept = concepts.next().getSubject();
+                GraphNode conceptGraphNode = new GraphNode(concept, graph);
+                Iterator<Resource> sameAsConcepts = conceptGraphNode
+                        .getObjects(OWL.sameAs);
+                if (!(hasSameAs(resultMGraph, concept) || hasAnyConcept(
+                        resultMGraph, sameAsConcepts))) {
+                    resultNode.addProperty(QUERYRESULT.concept, concept);
+                    addConceptToResultMGraph(resultMGraph, conceptGraphNode);
+                }
+
+            }
+        }
+    }
+
+    private boolean hasSameAs(MGraph graph, NonLiteral sameAsConcept) {
+        Iterator<Triple> concepts = graph.filter(null, RDF.type, SKOS.Concept);
+        while (concepts.hasNext()) {
+            NonLiteral concept = concepts.next().getSubject();
+            if (graph.filter(concept, OWL.sameAs, sameAsConcept).hasNext()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean hasAnyConcept(MGraph graph, Iterator<Resource> concepts) {
+        while (concepts.hasNext()) {
+            NonLiteral concept = (NonLiteral) concepts.next();
+            if (graph.filter(concept, RDF.type, SKOS.Concept).hasNext()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void addConceptToResultMGraph(MGraph resultMGraph,
+            GraphNode graphNode) {
+        NonLiteral concept = (NonLiteral) graphNode.getNode();
+        resultMGraph.add(new TripleImpl(concept, RDF.type, SKOS.Concept));
+
+        Iterator<Literal> prefLabelStatements = graphNode.getLiterals(SKOS.prefLabel);
+        while (prefLabelStatements.hasNext()) {
+            resultMGraph.add(new TripleImpl(concept, SKOS.prefLabel,
+                    prefLabelStatements.next()));
+        }
+        Iterator<Literal> commentStatements = graphNode.getLiterals(RDFS.comment);
+        while (commentStatements.hasNext()) {
+            resultMGraph.add(new TripleImpl(concept, RDFS.comment,
+                    commentStatements.next()));
+        }
+        Iterator<UriRef> sameAsStatements = graphNode.getUriRefObjects(OWL.sameAs);
+        while (sameAsStatements.hasNext()) {
+            resultMGraph.add(new TripleImpl(concept, OWL.sameAs,
+                    sameAsStatements.next()));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/GenericResourcePage.java
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/GenericResourcePage.java b/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/GenericResourcePage.java
new file mode 100644
index 0000000..e96069e
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/GenericResourcePage.java
@@ -0,0 +1,111 @@
+/*
+ * 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.clerezza.platform.concepts.core;
+
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.clerezza.platform.concepts.ontologies.CONCEPTS;
+import org.apache.clerezza.platform.graphprovider.content.ContentGraphProvider;
+import org.apache.clerezza.platform.typerendering.RenderletManager;
+import org.apache.clerezza.platform.typerendering.scalaserverpages.ScalaServerPagesRenderlet;
+import org.apache.clerezza.rdf.core.BNode;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.impl.SimpleMGraph;
+import org.apache.clerezza.rdf.ontologies.PLATFORM;
+import org.apache.clerezza.rdf.ontologies.RDF;
+import org.apache.clerezza.rdf.utils.GraphNode;
+import org.apache.clerezza.rdf.utils.UnionMGraph;
+import org.apache.clerezza.utils.UriException;
+import org.apache.clerezza.web.fileserver.FileServer;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * This JAX-RS resource can be used to show selected concepts of a resource.
+ * The URI path of this service is /concepts/generic-resource.
+ * 
+ * @author tio
+ */
+@Component
+@Service(Object.class)
+@Property(name = "javax.ws.rs", boolValue = true)
+@Path("/concepts/generic-resource")
+public class GenericResourcePage extends FileServer {
+
+    @Reference
+    protected ContentGraphProvider cgProvider;
+    @Reference
+    private RenderletManager renderletManager;
+
+    private RemoteConceptsDescriptionManager remoteConceptsDescriptionManager = null;
+
+    protected void activate(ComponentContext context)
+            throws URISyntaxException {
+        
+        configure(context.getBundleContext());
+        
+        URL template = getClass().getResource("generic-resource-page.ssp");
+        renderletManager.registerRenderlet(ScalaServerPagesRenderlet.class.getName(),
+                new UriRef(template.toURI().toString()),
+                CONCEPTS.GenericResourcePage, "naked",
+                MediaType.APPLICATION_XHTML_XML_TYPE, true);
+
+        remoteConceptsDescriptionManager = new RemoteConceptsDescriptionManager();
+    }
+
+    /**
+     * Retrieves a resource and its associated concepts to be rendered with a template
+     * registered for CONCEPTS.GenericResourcePage.
+     * 
+     * @param uri specifies the uri of a resource
+     * 
+     * @return GraphNode
+     */
+    @GET
+    public GraphNode GenericResourcePage(@QueryParam("uri") UriRef uri,
+            @Context UriInfo uriInfo) {
+
+        GraphNode node = new GraphNode(new BNode(), new UnionMGraph(new SimpleMGraph(),
+                cgProvider.getContentGraph(),
+                remoteConceptsDescriptionManager.getRemoteConceptsDescriptionMGraph()));
+        node.addProperty(RDF.type, PLATFORM.HeadedPage);
+        node.addProperty(RDF.type, CONCEPTS.GenericResourcePage);
+        if (uri != null) {
+            node.addProperty(CONCEPTS.resource, uri);
+        } else {
+            throw new WebApplicationException(Response.status(Status.BAD_REQUEST)
+                    .entity("No resource uri defined.").build());
+        }
+        return node;
+    }
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/LocalConceptProvider.java
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/LocalConceptProvider.java b/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/LocalConceptProvider.java
new file mode 100644
index 0000000..4b96110
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/LocalConceptProvider.java
@@ -0,0 +1,90 @@
+/*
+ * 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.clerezza.platform.concepts.core;
+
+import org.apache.clerezza.platform.graphprovider.content.ContentGraphProvider;
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.access.TcManager;
+import org.apache.clerezza.rdf.core.sparql.ParseException;
+import org.apache.clerezza.rdf.core.sparql.QueryParser;
+import org.apache.clerezza.rdf.core.sparql.query.ConstructQuery;
+
+/**
+ * This {@link ConceptProvider} operates on concepts available in the localhost.
+ *
+ * @author tio, hasan
+ */
+public class LocalConceptProvider implements ConceptProvider {
+
+    private TcManager tcManager = null;
+    private ContentGraphProvider contentGraphProvider = null;
+    private UriRef selectedScheme = null;
+
+    /**
+     * Constructs a {@link LocalConceptProvider} with the specified parameters.
+     *
+     * @param tcManager
+     *        Reference to the {@link TcManager}
+     * @param contentGraphProvider
+     *        Reference to a {@link ContentGraphProvider}
+     * @param selectedScheme
+     *        The scheme in which concepts are to be searched.
+     */
+    public LocalConceptProvider(TcManager tcManager,
+            ContentGraphProvider contentGraphProvider, UriRef selectedScheme) {
+        this.tcManager = tcManager;
+        this.contentGraphProvider = contentGraphProvider;
+        this.selectedScheme = selectedScheme;
+    }
+
+    public UriRef getSelectedScheme() {
+        return this.selectedScheme;
+    }
+
+    @Override
+    public Graph retrieveConcepts(String searchTerm) {
+        QueryParser queryParser = QueryParser.getInstance();
+
+        String query = "PREFIX owl: <http://www.w3.org/2002/07/owl#> " +
+                "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> " +
+                "PREFIX skos: <http://www.w3.org/2008/05/skos#> " +
+                "CONSTRUCT {?concept a skos:Concept; skos:prefLabel ?prefLabel; " +
+                "rdfs:comment ?comment; owl:sameAs ?sameConcept .} " +
+                "WHERE {?concept skos:inScheme " + selectedScheme.toString() +
+                "; skos:prefLabel ?prefLabel . " +
+                "OPTIONAL { ?concept skos:altLabel ?altLabel .} " +
+                "OPTIONAL { ?concept rdfs:comment ?comment .} " +
+                "OPTIONAL { ?concept owl:sameAs ?sameConcept .} " +
+                "FILTER (REGEX(STR(?prefLabel), '" +
+                searchTerm + "', 'i') || REGEX(STR(?altLabel), '" +
+                searchTerm + "', 'i'))}";
+
+        ConstructQuery constructQuery;
+        try {
+            constructQuery = (ConstructQuery) queryParser.parse(query);
+        } catch (ParseException ex) {
+            throw new RuntimeException(ex);
+        }
+
+        MGraph defaultGraph = contentGraphProvider.getContentGraph();
+        return tcManager.executeSparqlQuery(constructQuery, defaultGraph);
+    }
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/RemoteConceptProvider.java
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/RemoteConceptProvider.java b/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/RemoteConceptProvider.java
new file mode 100644
index 0000000..f933a53
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/RemoteConceptProvider.java
@@ -0,0 +1,134 @@
+/*
+ * 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.clerezza.platform.concepts.core;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.ProtocolException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.Calendar;
+import java.util.Date;
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.serializedform.Parser;
+import org.apache.clerezza.rdf.core.serializedform.SupportedFormat;
+
+/**
+ * This implementation of {@link ConceptProvider} provides a functionality
+ * to query a SPARQL End Point for a given search term. The query is to be
+ * generated from a template by replacing the place holder for the search term
+ * with the specified search term.
+ *
+ * @author tio, hasan
+ */
+public class RemoteConceptProvider implements ConceptProvider {
+
+    private UriRef sparqlEndPoint = null;
+    private UriRef defaultGraph = null;
+    private String queryTemplate = null;
+    private ConceptCache conceptCache = null;
+    private RemoteConceptsDescriptionManager remoteConceptsDescriptionManager = null;
+
+    /**
+     * Constructs a {@link RemoteConceptProvider} with the specified parameters.
+     * 
+     * @param sparqlEndPoint
+     *        the SPARQL End Point to connect to
+     * @param defaultGraph
+     *        the Graph to query for concepts
+     * @param queryTemplate
+     *        the template for query containing place holders for the search term.
+     */
+    public RemoteConceptProvider(
+            UriRef sparqlEndPoint, UriRef defaultGraph, String queryTemplate) {
+        this.sparqlEndPoint = sparqlEndPoint;
+        this.defaultGraph = defaultGraph;
+        this.queryTemplate = queryTemplate;
+        this.conceptCache = new ConceptCache(sparqlEndPoint, defaultGraph);
+        this.remoteConceptsDescriptionManager = new RemoteConceptsDescriptionManager();
+    }
+
+    @Override
+    public Graph retrieveConcepts(String searchTerm) {
+
+        Calendar calendar = Calendar.getInstance();
+        calendar.add(Calendar.DAY_OF_MONTH, -30);
+        Date acceptableOldestCachingDate = calendar.getTime();
+        MGraph cachedConcepts = conceptCache.retrieve(searchTerm.toLowerCase(),
+                acceptableOldestCachingDate);
+        if (cachedConcepts != null) {
+            return cachedConcepts.getGraph();
+        } else {
+            final int connectionTimeout = 4000;
+            String query = queryTemplate.replace("${searchTerm}", searchTerm);
+            try {
+                String param = "query=" + URLEncoder.encode(query, "UTF-8");
+                if (defaultGraph != null) {
+                    param += "&default-graph-uri=" + defaultGraph.getUnicodeString();
+                }
+                final URL url = new URL(sparqlEndPoint.getUnicodeString());
+                final HttpURLConnection con =
+                        (HttpURLConnection) url.openConnection();
+                con.setRequestProperty("Accept", "application/rdf+xml");
+                con.setRequestMethod("POST");
+                con.setDoOutput(true);
+                con.setDoInput(true);
+                con.setUseCaches(false);
+                con.setConnectTimeout(connectionTimeout);
+
+                final OutputStream os = con.getOutputStream();
+                os.write(param.getBytes());
+                os.close();
+
+                if (con.getResponseCode() < 400) {
+                    final InputStream is = con.getInputStream();
+                    Graph parsedGraph = Parser.getInstance().parse(is,
+                            SupportedFormat.RDF_XML);
+                    is.close();
+                    conceptCache.cache(searchTerm.toLowerCase(), parsedGraph);
+                    remoteConceptsDescriptionManager.storeConceptsDescription(parsedGraph);
+                    return parsedGraph;
+                } else {
+                    final InputStream es = con.getErrorStream();
+                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    for (int ch = es.read(); ch != -1; ch = es.read()) {
+                        baos.write(ch);
+                    }
+                    es.close();
+                    throw new RuntimeException(baos.toString());
+                }
+            } catch (ProtocolException ex) {
+                throw new RuntimeException(ex);
+            } catch (MalformedURLException ex) {
+                throw new RuntimeException(ex);
+            } catch (UnsupportedEncodingException ex) {
+                throw new RuntimeException(ex);
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/RemoteConceptsDescriptionManager.java
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/RemoteConceptsDescriptionManager.java b/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/RemoteConceptsDescriptionManager.java
new file mode 100644
index 0000000..7932829
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/RemoteConceptsDescriptionManager.java
@@ -0,0 +1,102 @@
+/*
+ * 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.clerezza.platform.concepts.core;
+
+import java.util.Iterator;
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.Literal;
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.access.NoSuchEntityException;
+import org.apache.clerezza.rdf.core.access.TcManager;
+import org.apache.clerezza.rdf.ontologies.RDF;
+import org.apache.clerezza.rdf.ontologies.RDFS;
+import org.apache.clerezza.rdf.ontologies.SKOS;
+import org.apache.clerezza.rdf.utils.GraphNode;
+
+/**
+ * This class stores description of concepts resulted from searches
+ * performed by {@link RemoteConceptProvider}s.
+ *
+ * @author hasan
+ */
+public class RemoteConceptsDescriptionManager {
+
+    private UriRef REMOTE_CONCEPTS_DESCRIPTION_MGRAPH =
+            new UriRef("urn:x-localinstance:/remote.concepts.description");
+
+    /**
+     * Stores SKOS:prefLabel and RDFS.comment of concepts available in the
+     * specified Graph.
+     *
+     * @param graph
+     *        the Graph which contains concepts and their descriptions.
+     */
+    void storeConceptsDescription(Graph graph) {
+        MGraph remoteConceptsDescriptionMGraph =
+                getRemoteConceptsDescriptionMGraph();
+
+        Iterator<Triple> concepts = graph.filter(null, RDF.type, SKOS.Concept);
+        while (concepts.hasNext()) {
+            UriRef concept = (UriRef) concepts.next().getSubject();
+            copyConceptDescription(new GraphNode(concept, graph),
+                    new GraphNode(concept, remoteConceptsDescriptionMGraph));
+        }
+    }
+
+    /**
+     * This method creates an {@link MGraph} to store concepts' descriptions
+     * if this graph does not already exist.
+     *
+     * @return
+     *        an {@link MGraph}
+     */
+    public MGraph getRemoteConceptsDescriptionMGraph() {
+        MGraph remoteConceptsDescriptionMGraph = null;
+        TcManager tcManager = TcManager.getInstance();
+        try {
+            remoteConceptsDescriptionMGraph =
+                    tcManager.getMGraph(REMOTE_CONCEPTS_DESCRIPTION_MGRAPH);
+        } catch (NoSuchEntityException nsee) {
+            remoteConceptsDescriptionMGraph =
+                    tcManager.createMGraph(REMOTE_CONCEPTS_DESCRIPTION_MGRAPH);
+        }
+        return remoteConceptsDescriptionMGraph;
+    }
+
+    private void copyConceptDescription(GraphNode sourceGraphNode,
+            GraphNode destinationGraphNode) {
+
+        destinationGraphNode.deleteNodeContext();
+
+        Iterator<Literal> prefLabelStatements =
+                sourceGraphNode.getLiterals(SKOS.prefLabel);
+        if (prefLabelStatements.hasNext()) {
+            destinationGraphNode.addProperty(SKOS.prefLabel,
+                    prefLabelStatements.next());
+        }
+        Iterator<Literal> commentStatements =
+                sourceGraphNode.getLiterals(RDFS.comment);
+        while (commentStatements.hasNext()) {
+            destinationGraphNode.addProperty(RDFS.comment,
+                    commentStatements.next());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/ResourceTagger.java
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/ResourceTagger.java b/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/ResourceTagger.java
new file mode 100644
index 0000000..3bff348
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/ResourceTagger.java
@@ -0,0 +1,131 @@
+/*
+ * 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.clerezza.platform.concepts.core;
+
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.clerezza.jaxrs.utils.RedirectUtil;
+import org.apache.clerezza.platform.graphprovider.content.ContentGraphProvider;
+import org.apache.clerezza.platform.typerendering.scalaserverpages.ScalaServerPagesService;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.ontologies.DCTERMS;
+import org.apache.clerezza.rdf.ontologies.RDFS;
+import org.apache.clerezza.rdf.utils.GraphNode;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * This JAX-RS resource can be used for adding concepts to a resource.
+ *
+ * The URI path of this service is /concepts/tagger.
+ *
+ * @author tio
+ */
+@Component
+@Service(Object.class)
+@Property(name = "javax.ws.rs", boolValue = true)
+@Path("/concepts/tagger/")
+public class ResourceTagger {
+
+    @Reference
+    protected ContentGraphProvider cgProvider;
+    @Reference
+    private ScalaServerPagesService scalaServerPagesService;
+
+    protected void activate(ComponentContext context)
+            throws URISyntaxException {
+
+        BundleContext bundleContext = context.getBundleContext();
+        URL template = getClass().getResource("concept-existing-subjects.ssp");
+
+        scalaServerPagesService.registerScalaServerPage(
+                template,
+                RDFS.Resource, "concept-existing-subjects-naked",
+                MediaType.APPLICATION_XHTML_XML_TYPE, bundleContext);
+
+        template = getClass().getResource("concept-tagging.ssp");
+        scalaServerPagesService.registerScalaServerPage(
+                template,
+                RDFS.Resource, "concept-tagging-naked",
+                MediaType.APPLICATION_XHTML_XML_TYPE, bundleContext);
+
+        template = getClass().getResource("concept-find-create.ssp");
+        scalaServerPagesService.registerScalaServerPage(
+                template,
+                RDFS.Resource, "concept-find-create-naked",
+                MediaType.APPLICATION_XHTML_XML_TYPE, bundleContext);
+
+        template = getClass().getResource("selected-concepts.ssp");
+        scalaServerPagesService.registerScalaServerPage(
+                template,
+                RDFS.Resource, "selectedconcepts-naked",
+                MediaType.APPLICATION_XHTML_XML_TYPE, bundleContext);
+    }
+
+    /**
+     * Adds concepts to a resource. If parameters uri and
+     * concepts are not defined a response with code BAD_REQUEST is returned. If
+     * the relation is succefully added a redirect to /concepts/generic-resource with
+     * the UriRef of the resource as parameter.
+     *
+     * @param uri specifies the uri of a resource
+     * @param concepts specifies a list of concept uris.
+     *
+     * @return
+     *        A Response
+     */
+    @POST
+    @Path("set")
+    public Response updateConcepts(@FormParam("uri") UriRef uri,
+            @FormParam("concepts") List<String> concepts,
+            @Context UriInfo uriInfo) {
+
+        
+        if (uri != null) {
+            GraphNode node = new GraphNode(uri, cgProvider.getContentGraph());
+            node.deleteProperties(DCTERMS.subject);
+            if(concepts != null) {
+                for (String subject : concepts) {
+                    node.addProperty(DCTERMS.subject, new UriRef(subject));
+                }
+            }
+        } else {
+            throw new WebApplicationException(Response.status(
+                    Status.BAD_REQUEST).entity("No resource uri defined.").build());
+        }
+        return RedirectUtil.createSeeOtherResponse("/concepts/generic-resource?uri=" +
+                uri.getUnicodeString(), uriInfo);
+    }
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/SimpleConceptProviderManager.java
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/SimpleConceptProviderManager.java b/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/SimpleConceptProviderManager.java
new file mode 100644
index 0000000..98ee7cc
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/java/org/apache/clerezza/platform/concepts/core/SimpleConceptProviderManager.java
@@ -0,0 +1,319 @@
+/*
+ * 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.clerezza.platform.concepts.core;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+import org.apache.clerezza.jaxrs.utils.TrailingSlash;
+import org.apache.clerezza.platform.concepts.ontologies.CONCEPTS;
+import org.apache.clerezza.platform.globalmenu.GlobalMenuItem;
+import org.apache.clerezza.platform.globalmenu.GlobalMenuItemsProvider;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.clerezza.platform.graphprovider.content.ContentGraphProvider;
+import org.apache.clerezza.platform.typerendering.RenderletManager;
+import org.apache.clerezza.platform.typerendering.scalaserverpages.ScalaServerPagesRenderlet;
+import org.apache.clerezza.rdf.core.BNode;
+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.Triple;
+import org.apache.clerezza.rdf.core.TypedLiteral;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.access.TcManager;
+import org.apache.clerezza.rdf.core.access.security.TcPermission;
+import org.apache.clerezza.rdf.core.impl.SimpleMGraph;
+import org.apache.clerezza.rdf.core.impl.TripleImpl;
+import org.apache.clerezza.rdf.ontologies.PLATFORM;
+import org.apache.clerezza.rdf.ontologies.RDF;
+import org.apache.clerezza.rdf.utils.GraphNode;
+import org.apache.clerezza.rdf.utils.RdfList;
+import org.apache.clerezza.rdf.utils.UnionMGraph;
+import org.apache.felix.scr.annotations.Services;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * This service manages concept providers. Concept providers are prioritized.
+ *
+ * The URI path of this service is /concepts/provider-manager.
+ *
+ * @author hasan, tio
+ */
+@Component
+@Services({
+    @Service(Object.class),
+    @Service(ConceptProviderManager.class),
+    @Service(GlobalMenuItemsProvider.class)
+})
+@Property(name = "javax.ws.rs", boolValue = true)
+@Path("/concepts/provider-manager")
+public class SimpleConceptProviderManager implements ConceptProviderManager,
+        GlobalMenuItemsProvider {
+
+    @Reference
+    private TcManager tcManager;
+
+    @Reference
+    protected ContentGraphProvider cgProvider;
+
+    @Reference
+    private RenderletManager renderletManager;
+
+    private List<ConceptProvider> conceptProviderList =
+            new ArrayList<ConceptProvider>();
+
+    /**
+     * The activate method is called when SCR activates the component
+     * configuration. 
+     * 
+     * @param context
+     * @throws IOException
+     * @throws URISyntaxException
+     */
+    protected void activate(ComponentContext context)
+            throws IOException,
+            URISyntaxException {
+
+        URL template = getClass().getResource("manage-concept-providers-page.ssp");
+        renderletManager.registerRenderlet(ScalaServerPagesRenderlet.class.getName(),
+                new UriRef(template.toURI().toString()),
+                CONCEPTS.ManageConceptProvidersPage, "naked",
+                MediaType.APPLICATION_XHTML_XML_TYPE, true);
+
+        instantiateConceptProviders();
+    }
+
+    protected void deactivate(ComponentContext context) {
+        conceptProviderList.clear();
+    }
+
+    private void instantiateConceptProviders() {
+        conceptProviderList.clear();
+        MGraph contentGraph = cgProvider.getContentGraph();
+
+        NonLiteral cplNode = getConceptProviderListNode(contentGraph);
+        RdfList cpl = new RdfList(cplNode, contentGraph);
+        for (int i = 0; i < cpl.size(); i++) {
+            NonLiteral conceptProvider = (NonLiteral) cpl.get(i);
+            Iterator<Triple> conceptProviderTypes = contentGraph.filter(
+                    conceptProvider, RDF.type, null);
+            if (conceptProviderTypes.hasNext()) {
+                UriRef conceptProviderType = (UriRef) conceptProviderTypes.next().getObject();
+                if (conceptProviderType.equals(CONCEPTS.LocalConceptProvider)) {
+                    instantiateLocalConceptProvider(contentGraph, conceptProvider);
+                } else {
+                    instantiateRemoteConceptProvider(contentGraph, conceptProvider);
+                }
+            }
+        }
+    }
+
+    private NonLiteral getConceptProviderListNode(MGraph contentGraph) {
+        Iterator<Triple> triples = contentGraph.filter(null, RDF.type,
+                CONCEPTS.ConceptProviderList);
+        if (triples.hasNext()) {
+            return triples.next().getSubject();
+        }
+        NonLiteral cplNode = new BNode();
+        new RdfList(cplNode, contentGraph);
+        contentGraph.add(new TripleImpl(cplNode, RDF.type,
+                CONCEPTS.ConceptProviderList));
+        return cplNode;
+    }
+
+    private void instantiateLocalConceptProvider(MGraph contentGraph,
+            NonLiteral conceptProvider) {
+        Iterator<Triple> selectedSchemes = contentGraph.filter(
+                conceptProvider, CONCEPTS.selectedScheme, null);
+        if (selectedSchemes.hasNext()) {
+            UriRef selectedScheme = (UriRef) selectedSchemes.next().getObject();
+            conceptProviderList.add(new LocalConceptProvider(tcManager,
+                    cgProvider, selectedScheme));
+        }
+    }
+
+    private void instantiateRemoteConceptProvider(MGraph contentGraph,
+            NonLiteral conceptProvider) {
+        Iterator<Triple> endPoints = contentGraph.filter(
+                conceptProvider, CONCEPTS.sparqlEndPoint, null);
+        if (endPoints.hasNext()) {
+            UriRef sparqlEndPoint = (UriRef) endPoints.next().getObject();
+            Iterator<Triple> defaultGraphs = contentGraph.filter(
+                    conceptProvider, CONCEPTS.defaultGraph, null);
+            UriRef defaultGraph = null;
+            if (defaultGraphs.hasNext()) {
+                defaultGraph = (UriRef) defaultGraphs.next().getObject();
+            }
+            Iterator<Triple> queryTemplates = contentGraph.filter(
+                    conceptProvider, CONCEPTS.queryTemplate, null);
+            if (queryTemplates.hasNext()) {
+                TypedLiteral queryTemplate =
+                        (TypedLiteral) queryTemplates.next().getObject();
+                conceptProviderList.add(
+                        new RemoteConceptProvider(sparqlEndPoint,
+                        defaultGraph, queryTemplate.getLexicalForm()));
+            }
+        }
+    }
+
+    /**
+     * Returns a GraphNode containing a list of {@link ConceptProvider}s stored
+     * in the content graph to be managed. The order in the list represents
+     * the priority of the providers.
+     * This resource is accessible through a GET request on the URI sub-path
+     * "edit-concept-provider-list".
+     *
+     */
+    @GET
+    @Path("edit-concept-provider-list")
+    public GraphNode getProviderList(@Context UriInfo uriInfo) {
+        AccessController.checkPermission(
+                new ConceptProviderManagerAppPermission());
+        TrailingSlash.enforceNotPresent(uriInfo);
+        MGraph contentGraph = cgProvider.getContentGraph();
+        MGraph resultGraph = new SimpleMGraph();
+
+        NonLiteral cplNode = getConceptProviderListNode(contentGraph);
+        GraphNode resultNode = new GraphNode(cplNode, resultGraph);
+
+        resultNode.addProperty(RDF.type, CONCEPTS.ManageConceptProvidersPage);
+        resultNode.addProperty(RDF.type, PLATFORM.HeadedPage);
+        return new GraphNode(resultNode.getNode(),
+                new UnionMGraph(resultGraph, contentGraph));
+    }
+
+    /**
+     * Allows the list of {@link ConceptProvider}s stored in the content graph
+     * to be updated with the list POSTed via the URI sub-path
+     * "update-concept-provider-list".
+     * The order in the list represents the priority of the providers.
+     *
+     * @param types
+     *        specify the type of each ConceptProvider: either a
+     *        LocalConceptProvider or a RemoteConceptProvider.
+     * @param sparqlEndPoints
+     *        the SPARQL EndPoint to connect to in case of a RemoteConceptProvider.
+     * @param defaultGraphs
+     *        the Graph to be queried in case of a RemoteConceptProvider.
+     * @param queryTemplates
+     *        the template for the query to be used in case of a RemoteConceptProvider.
+     * @param conceptSchemes
+     *        the concept scheme within which concepts are to be searched,
+     *        in case of a LocalConceptProvider.
+     * @return
+     *        - a 200 (OK) response if everything is fine.
+     *        - a 400 (BAD REQUEST) response if types parameter is undefined.
+     */
+    @POST
+    @Path("update-concept-provider-list")
+    public Response updateConceptProviders(
+            @FormParam("types") List<String> types,
+            @FormParam("sparqlEndPoints") List<String> sparqlEndPoints,
+            @FormParam("defaultGraphs") List<String> defaultGraphs,
+            @FormParam("queryTemplates") List<String> queryTemplates,
+            @FormParam("conceptSchemes") List<String> conceptSchemes) {
+
+        if (types == null) {
+            //types is null when all provider have been removed, processing empty list
+            types = new ArrayList<String>();
+        }
+        MGraph contentGraph = cgProvider.getContentGraph();
+        NonLiteral cplNode = getConceptProviderListNode(contentGraph);
+        GraphNode cplGraphNode = new GraphNode(cplNode, contentGraph);
+        cplGraphNode.deleteNodeContext();
+
+        cplNode = getConceptProviderListNode(contentGraph);
+        RdfList cpl = new RdfList(cplNode, contentGraph);
+
+        int length = types.size();
+        for (int i=0; i<length; i++) {
+            UriRef conceptProviderType = new UriRef(types.get(i));
+            BNode conceptProvider = new BNode();
+            contentGraph.add(new TripleImpl(conceptProvider, RDF.type,
+                    conceptProviderType));
+            if (conceptProviderType.equals(CONCEPTS.LocalConceptProvider)) {
+                contentGraph.add(new TripleImpl(conceptProvider,
+                        CONCEPTS.selectedScheme,
+                        new UriRef(conceptSchemes.get(i))));
+            } else {
+                contentGraph.add(new TripleImpl(conceptProvider,
+                        CONCEPTS.sparqlEndPoint,
+                        new UriRef(sparqlEndPoints.get(i))));
+                String defaultGraph = defaultGraphs.get(i);
+                if (!defaultGraph.trim().isEmpty()) {
+                    contentGraph.add(new TripleImpl(conceptProvider,
+                            CONCEPTS.defaultGraph,
+                            new UriRef(defaultGraph)));
+                }
+                contentGraph.add(new TripleImpl(conceptProvider,
+                        CONCEPTS.queryTemplate,
+                        LiteralFactory.getInstance().createTypedLiteral(
+                        queryTemplates.get(i))));
+            }
+            cpl.add(i, conceptProvider);
+        }
+        instantiateConceptProviders();
+        return Response.status(Status.OK).build();
+    }
+
+    @Override
+    public List<ConceptProvider> getConceptProviders() {
+        return conceptProviderList;
+    }
+
+    @Override
+    public Set<GlobalMenuItem> getMenuItems() {
+        Set<GlobalMenuItem> items = new HashSet<GlobalMenuItem>();
+        try {
+            AccessController.checkPermission(
+                    new TcPermission("urn:x-localinstance:/content.graph",
+                    TcPermission.READWRITE));
+        } catch (AccessControlException e) {
+            return items;
+        }
+        try {
+            AccessController.checkPermission(
+                    new ConceptProviderManagerAppPermission());
+        } catch (AccessControlException e) {
+            return items;
+        }
+        items.add(new GlobalMenuItem("/concepts/provider-manager/edit-concept-provider-list",
+                "CPM", "Concept Providers", 5, "Administration"));
+        return items;
+    }
+}

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/scripts/concept-find-create.js
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/scripts/concept-find-create.js b/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/scripts/concept-find-create.js
new file mode 100644
index 0000000..67c4ee4
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/scripts/concept-find-create.js
@@ -0,0 +1,21 @@
+/*
+ *
+ * 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.
+ *
+*/
+

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/scripts/concept-provider-manipulation.js
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/scripts/concept-provider-manipulation.js b/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/scripts/concept-provider-manipulation.js
new file mode 100644
index 0000000..67c4ee4
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/scripts/concept-provider-manipulation.js
@@ -0,0 +1,21 @@
+/*
+ *
+ * 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.
+ *
+*/
+

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/scripts/selected-concepts.js
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/scripts/selected-concepts.js b/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/scripts/selected-concepts.js
new file mode 100644
index 0000000..67c4ee4
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/scripts/selected-concepts.js
@@ -0,0 +1,21 @@
+/*
+ *
+ * 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.
+ *
+*/
+

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/style/form.css
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/style/form.css b/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/style/form.css
new file mode 100644
index 0000000..67c4ee4
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/resources/META-INF/static-web/concepts/style/form.css
@@ -0,0 +1,21 @@
+/*
+ *
+ * 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.
+ *
+*/
+

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/concept-existing-subjects.ssp
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/concept-existing-subjects.ssp b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/concept-existing-subjects.ssp
new file mode 100644
index 0000000..823cb97
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/concept-existing-subjects.ssp
@@ -0,0 +1,29 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+def skos(s: Any) = new UriRef("http://www.w3.org/2008/05/skos#"+s)
+def dct(s: Any) = new UriRef("http://purl.org/dc/terms/"+s)
+def cpt(s: Any) = new UriRef("http://clerezza.org/2010/01/concepts#"+s);
+
+<form method="post" action="/concepts/tagger/set" id="selected-concepts-form">
+	<input type="hidden" name="uri" value={res/cpt("resource")*}></input>
+	{render(res/cpt("resource"), "selectedconcepts-naked")}
+</form>

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/concept-find-create.ssp
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/concept-find-create.ssp b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/concept-find-create.ssp
new file mode 100644
index 0000000..c0436d8
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/concept-find-create.ssp
@@ -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.
+ *
+*/
+
+resultDocModifier.addScriptReference("/jquery/jquery-1.3.2.min.js");
+resultDocModifier.addScriptReference("/scripts/ajax-options.js");
+//resultDocModifier.addScriptReference("/scripts/modification-status.js");
+resultDocModifier.addScriptReference("/scripts/status-message.js");
+
+resultDocModifier.addScriptReference("/concepts/generic-resource/scripts/concept-find-create.js");
+resultDocModifier.addScriptReference("/concepts/generic-resource/scripts/jquery.rdfquery.core-1.0.js");
+
+resultDocModifier.addScriptReference("/scripts/alert-message.js");
+resultDocModifier.addScriptReference("/yui/2/yahoo-dom-event/yahoo-dom-event.js");
+resultDocModifier.addScriptReference("/yui/2/element/element-min.js");
+resultDocModifier.addScriptReference("/yui/2/container/container-min.js");
+resultDocModifier.addStyleSheet("/yui/2/container/assets/container-core.css");
+
+
+<div>Add Concepts</div>
+<form onsubmit="return ConceptFinder.search()" id="search-form">
+	<br/>
+	<input type="text" value="" name="search-term"/>
+	<a href="#" id="go-button" class="tx-icon tx-icon-search">Go</a>
+	<br/>
+	<br/>
+	<div id="system-found-concepts-area">
+		<div id="label-for-search-results">
+			Found Concepts:
+		</div>
+		<br/>
+		<div id="system-found-concepts"></div>
+	</div>
+	<br/>
+	<div id="user-defined-concept-area">
+		<div id="add-button-label"></div>
+		<div>Description (optional):</div>
+		<textarea rows="8" id="concept-description" name="comment"/>
+		<input type="hidden" value="en" name="lang"/>
+		<div>
+			<a href="#" class="tx-icon tx-icon-plus" id="add-user-defined-concept">Add</a>
+		</div>
+	</div>
+</form>

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/concept-tagging.ssp
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/concept-tagging.ssp b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/concept-tagging.ssp
new file mode 100644
index 0000000..a81d5a2
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/concept-tagging.ssp
@@ -0,0 +1,23 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+<div class="concept-tagging">{render(res,"concept-existing-subjects-naked")}
+{render(res,"concept-find-create-naked")}</div>

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/generic-resource-page.ssp
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/generic-resource-page.ssp b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/generic-resource-page.ssp
new file mode 100644
index 0000000..e27759b
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/generic-resource-page.ssp
@@ -0,0 +1,43 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+def skos(s: Any) = new UriRef("http://www.w3.org/2008/05/skos#"+s)
+def dct(s: Any) = new UriRef("http://purl.org/dc/terms/"+s)
+def cpt(s: Any) = new UriRef("http://clerezza.org/2010/01/concepts#"+s);
+
+resultDocModifier.setTitle("Generic Resource Page");
+resultDocModifier.addNodes2Elem("tx-module", <h1>Generic Resource Page</h1>);
+resultDocModifier.addNodes2Elem("tx-module-tabs-ol", <li class="tx-active"><a href="#">Resource</a></li>);
+resultDocModifier.addNodes2Elem("tx-contextual-buttons-ol", <li><a id="addButton" class="tx-button tx-button-create" href="#">Save</a></li>);
+
+<div id="tx-content">
+	<script type="text/javascript">
+		$(document).ready(function() {{
+			$("#addButton").click(function() {{
+				$("#selected-concepts-form").submit();
+			}});
+		}});
+	</script>
+	<h4>About: {res/cpt("resource")*}</h4>
+	<div><object width="80%" data={res/cpt("resource")*}></object></div>
+	<br/>
+	{render(res,"concept-tagging-naked")}
+</div>

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/manage-concept-providers-page.ssp
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/manage-concept-providers-page.ssp b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/manage-concept-providers-page.ssp
new file mode 100644
index 0000000..e0ef754
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/manage-concept-providers-page.ssp
@@ -0,0 +1,128 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+def skos(s: Any) = new UriRef("http://www.w3.org/2008/05/skos#"+s)
+def cpt(s: Any) = new UriRef("http://clerezza.org/2010/01/concepts#"+s)
+def lingvoj(s: Any) = new UriRef("http://www.lingvoj.org/ontology#"+s)
+def rdfs(s: Any) = new UriRef("http://www.w3.org/2000/01/rdf-schema#"+s)
+def rdf(s: Any) = new UriRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#"+s)
+
+def createProvider(rdfType: String, selectedScheme: String, sparqlEndPoint: String, defaultGraph: String, query: String) =
+						<tr>
+							<td>
+								<input type="checkbox" value={rdfType}/>
+							</td>
+							<td>
+							<div>Provider:
+							</div>
+								{createSelection(!selectedScheme.equals(""))}
+							<br/>
+							<div>Concept Scheme:</div>
+							<input type="text" value={selectedScheme} name="conceptSchemes"/>
+							<div>SPARQL Endpoint:</div>
+							<input type="text" value={sparqlEndPoint} name="sparqlEndPoints"/>
+							<div>Default Graph:</div>
+							<input type="text" value={defaultGraph} name="defaultGraphs"/>
+							<div>Query Template:</div>
+							<textarea rows="8" name="queryTemplates">{query}</textarea>
+							<br/>
+							<br/>
+							</td>
+						</tr>
+
+
+def createSelection(isLocal: Boolean) = <select name="types">
+									{if(isLocal) {
+										<option value={cpt("LocalConceptProvider").getUnicodeString()} selected="selected">LocalConceptProvider</option>
+										<option value={cpt("RemoteConceptProvider").getUnicodeString()} >RemoteConceptProvider</option>
+									} else {
+										<option value={cpt("LocalConceptProvider").getUnicodeString()}>LocalConceptProvider</option>
+										<option value={cpt("RemoteConceptProvider").getUnicodeString()} selected="selected">RemoteConceptProvider</option>
+									}}
+						</select>
+
+resultDocModifier.addStyleSheet("/static/concepts/style/form.css");
+resultDocModifier.addScriptReference("/jquery/jquery.tooltip.pack.js");
+resultDocModifier.addScriptReference("/jquery/jquery.ajaxQueue.js");
+resultDocModifier.addScriptReference("/jquery/jquery.autocomplete.min.js");
+resultDocModifier.addScriptReference("/yui/2/yahoo-dom-event/yahoo-dom-event.js");
+/*resultDocModifier.addScriptReference("/yui/2/container/assets/container-core.css");*/
+resultDocModifier.addScriptReference("/yui/2/container/container-min.js");
+resultDocModifier.addScriptReference("/scripts/alert-message.js");
+resultDocModifier.addScriptReference("/scripts/ajax-options.js");
+resultDocModifier.addScriptReference("/concepts/generic-resource/scripts/concept-provider-manipulation.js");
+resultDocModifier.setTitle("Resource Tagging");
+resultDocModifier.addNodes2Elem("tx-module", <h1>Resource Tagging</h1>);
+
+resultDocModifier.addNodes2Elem("tx-module-tabs-ol", <li class="tx-active"><a href="">Concept Providers Manager</a></li>);
+
+resultDocModifier.addNodes2Elem("tx-contextual-buttons-ol", <li><a id="deleteButton" class="tx-button tx-button-remove" href="#">Remove</a></li>);
+resultDocModifier.addNodes2Elem("tx-contextual-buttons-ol", <li><a id="addButton" class="tx-button tx-button-create" href="#">Save</a></li>);
+
+<div id="tx-content">
+	<div  class="tx-tree">
+		<form action="" id="providers" method="post">
+			<fieldset>
+				<table>
+					<thead>
+						<tr>
+							<th><a href="#"></a></th>
+							<th style="width: 95%"><a href="#"></a>Concept Providers</th>
+						</tr>
+					</thead>
+					<tbody>
+						{	for (provider <- (res!!)) yield {
+								if((provider/rdf("type")*).indexOf("LocalConceptProvider") != -1) {
+									createProvider((provider/rdf("type")*), provider/cpt("selectedScheme")*, "", "", "")
+								} else {
+									createProvider((provider/rdf("type")*), "", provider/cpt("sparqlEndPoint")*, provider/cpt("defaultGraph")*, provider/cpt("queryTemplate")*)
+								}
+							}
+						}
+						<tr id="last">
+							<td></td>
+							<td>
+								<div>Add Concept Provider:</div>
+								<select id="type">
+									<option value={cpt("LocalConceptProvider").getUnicodeString()}>LocalConceptProvider</option>
+									<option value={cpt("RemoteConceptProvider").getUnicodeString()}>RemoteConceptProvider</option>
+								</select>
+								<div>Concept Scheme:</div>
+								<input type="text" name="conceptScheme" id="conceptScheme"/>
+								<div>SPARQL Endpoint</div>
+								<input type="text" name="sparqlEndPoint" id="sparqlEndPoint" />
+								<div>Default Graph:</div>
+								<input type="text" name="defaultGraph" id="defaultGraph"/>
+								<div>Query Template:</div>
+								<textarea rows="8" id="query"/>
+								<br/>
+								<br/>
+								<div>
+									<a href="#" class="tx-icon tx-icon-ok" id="addProvider">Add</a>
+								</div>
+							</td>
+						</tr>
+					</tbody>
+				</table>
+			</fieldset>
+		</form>
+	</div>
+</div>

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/selected-concepts.ssp
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/selected-concepts.ssp b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/selected-concepts.ssp
new file mode 100644
index 0000000..707c11a
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/selected-concepts.ssp
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+def skos(s: Any) = new UriRef("http://www.w3.org/2008/05/skos#"+s)
+def dct(s: Any) = new UriRef("http://purl.org/dc/terms/"+s)
+
+resultDocModifier.addScriptReference("/concepts/generic-resource/scripts/selected-concepts.js");
+
+<div>
+	<div id="selected-concepts">
+		{for (concept <- (res/dct("subject"))) yield {
+		<div>
+			<div>PrefLabel: {concept/skos("prefLabel")*}</div>
+			<div>Uri: {concept*}</div>
+			<input type="hidden" name="concepts" value={concept*}></input>
+			<a href="#" class="tx-icon tx-icon-delete" >Remove</a>
+			<br />
+			<br />
+		</div>
+		}
+		}
+	</div>
+</div>

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/skos-collection-json.ssp
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/skos-collection-json.ssp b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/skos-collection-json.ssp
new file mode 100644
index 0000000..5ee4663
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/skos-collection-json.ssp
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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 org.json.simple.JSONObject
+
+def skos(s: Any) = new UriRef("http://www.w3.org/2008/05/skos#"+s)
+
+"{\"concepts\":" +
+	(for (concept <- (res/skos("member"))) yield {
+		"{" +
+			"\"prefLabel\":\"" + JSONObject.escape(concept/skos("prefLabel")*) + "\"," +
+			"\"uri\":\"" + JSONObject.escape(concept*) + "\"" +
+		"}"
+	}).mkString("[", ",", "]") +
+"}";

http://git-wip-us.apache.org/repos/asf/clerezza/blob/70220239/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/staticweb/scripts/concept-find-create.js
----------------------------------------------------------------------
diff --git a/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/staticweb/scripts/concept-find-create.js b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/staticweb/scripts/concept-find-create.js
new file mode 100644
index 0000000..e31bd88
--- /dev/null
+++ b/platform/concepts/platform.concepts.core/src/main/resources/org/apache/clerezza/platform/concepts/core/staticweb/scripts/concept-find-create.js
@@ -0,0 +1,217 @@
+/*
+ * 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.
+ * 
+ * @author hasan, andre
+ */
+function ConceptFinder(){
+};
+
+ConceptFinder.callback;
+
+ConceptFinder.setAddConceptCallback = function(callback){
+	this.callback = callback;
+}
+
+/**
+ * Request the server concepts that match the search term in the input field "search-term"
+ */
+ConceptFinder.search = function(){
+	$("#system-found-concepts").empty();
+	var queryResult = null;
+	var searchTerm = $(":text[name=\"search-term\"]").val();
+	if (searchTerm.length > 0) {
+		var options = new AjaxOptions("find-concepts", "finding concepts", function(data){
+			var databank = $.rdf.databank();
+			var store = databank.load(data, {});
+			var query = $.rdf({
+				databank: store
+			});
+			query.prefix('rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
+			query.prefix('concepts', 'http://clerezza.org/2010/01/concepts#');
+			query.prefix('rdfs', 'http://www.w3.org/2000/01/rdf-schema#');
+			query.prefix('qr', 'http://clerezza.org/2010/04/queryresult#');
+			var resultSet = query.where('?subject rdf:type qr:QueryResult');
+			if (resultSet.size() != 1) {
+				AlertMessage.show(function(){
+				}, "The query results did not match what's expected: exactly 1 result");
+			}
+			var queryResult = query.node(resultSet.get(0).subject);
+			var conceptProperty = $.rdf.resource("<http://clerezza.org/2010/04/queryresult#concept>");
+			var conceptProperties = queryResult.get(conceptProperty);
+			if (conceptProperties) {
+				ConceptFinder.addFoundConcepts(conceptProperties);
+			}
+			$("#add-button-label").html("<div>Add '" + searchTerm + "' as new Free Concept</div>");
+			$("#system-found-concepts-area").show();
+			var newFreeConceptProperty = $.rdf.resource("<http://clerezza.org/2010/04/queryresult#creationOfNewFreeConceptSuggested>");
+			var creationOfNewFreeConceptSuggested = queryResult.get(newFreeConceptProperty)[0].value.toString() == "true";
+			if (creationOfNewFreeConceptSuggested) {
+				$("#user-defined-concept-area").show();
+			} else {
+				$("#user-defined-concept-area").hide();
+			}
+		});
+		options.url = "/concepts/find";
+		options.data = "searchTerm=" + encodeURIComponent(searchTerm) + "&xPropObj=http://clerezza.org/2010/04/queryresult%23concept";
+		options.dataType = "json";
+		options.beforeSend = function(req){
+			req.setRequestHeader("Accept", "application/rdf+json");
+		};
+		
+		$.ajax(options);
+	}
+	return false;
+}
+
+/**
+ * Adds the given (array of) concepts to the UI (that's currently being displayed). Displays them by a 
+ * +-button and labels (for each of them)
+ *
+ * @param Json array of concepts
+ */
+ConceptFinder.addFoundConcepts = function(concepts){
+	var selectedConceptsExists = false;
+	if (typeof(SelectedConcepts) != "undefined") {
+		selectedConceptsExists = true;
+	}
+	var added = false;
+	for (var i = 0; i < concepts.length; i++) {
+		var concept = concepts[i];
+		if (!selectedConceptsExists || !SelectedConcepts.exists(concept.value)) {
+			added = true;
+			var prefLabelProperty = $.rdf.resource("<http://www.w3.org/2008/05/skos#prefLabel>"); 
+			var prefLabel = concept.get(prefLabelProperty).value;
+			var uri = concept.value;
+			ConceptFinder.createSystemFoundConcept(prefLabel, uri);
+		}
+	}
+	if (added) {
+		$("#label-for-search-results").text("Concepts found:");
+	}
+	else {
+		$("#label-for-search-results").text("No additional concepts found.");
+	}
+}
+
+/**
+ * Creates the widget that show the user a concept that was found on the backend. Shows prefLabel, 
+ * uri and a button to add the concept to the backend
+ * 
+ * @param {Object} prefLabel
+ * @param {Object} uri
+ */
+ConceptFinder.createSystemFoundConcept = function(prefLabel, uri) {
+	var div = $("<div/>");
+	ConceptFinder.createConceptWidgets(prefLabel, uri).appendTo(div)
+	$("<a/>").addClass("tx-icon tx-icon-plus").attr({
+		href: "#"
+	}).text("Add").click(ConceptFinder.onAddClicked(prefLabel, uri)).appendTo(div);
+	$("<br/>").appendTo(div);
+	$("<br/>").appendTo(div);
+	div.appendTo("#system-found-concepts")
+}
+
+ConceptFinder.onAddClicked = function(prefLabel, uri){
+	return function(){
+		if (typeof(SelectedConcepts) != "undefined") {
+			SelectedConcepts.addConcept(prefLabel, uri);
+		}
+		if (typeof(ConceptFinder.callback) == "function") {
+			ConceptFinder.callback(prefLabel, uri);
+		}
+		$(this).parent().remove();
+	};
+}
+
+/**
+ * Creates html elements that show the given pref label and uri. Appends them to the given div.
+ * 
+ * @param {Object} prefLabel
+ * @param {Object} uri
+ * @param {Object} div
+ */
+ConceptFinder.createConceptWidgets = function(prefLabel, uri) {
+	var div = $("<div/>");
+	if (prefLabel.substr(0,1) == "\"") {
+		prefLabel = prefLabel.substring(1, prefLabel.length - 1);
+	}
+	$("<div/>").text("PrefLabel: " + prefLabel).appendTo(div);
+	$("<div/>").text("Uri: " + uri).appendTo(div);
+	$("<input/>").attr({
+		"type": "hidden",
+		"name": "concepts"
+	}).val(uri).appendTo(div);
+	return div;
+}
+
+/**
+ * Checks if a concept with the given uri already exists
+ * @param {Object} uri
+ */
+ConceptFinder.exists = function(uri){
+
+};
+
+function ConceptManipulator(){
+};
+
+ConceptManipulator.callback;
+
+ConceptManipulator.setAddConceptCallback = function(callback){
+	this.callback = callback;
+}
+
+/**
+ * sends a new concept to the backend for addition. Uses the search term entered by the user (in the same form).
+ */
+ConceptManipulator.addConcept = function(){
+	var searchTerm = $(":text[name='search-term']").val();
+	if (searchTerm.length > 0) {
+		var options = new AjaxOptions("add-concepts", "adding concepts", function(uri){
+			$("#concept-description").val("");
+			if (typeof(SelectedConcepts) != "undefined") {
+				SelectedConcepts.addConcept(searchTerm, uri);
+			}
+			if (typeof(this.callback) == "function") {
+				this.callback(searchTerm, uri);
+			}
+		});
+		options.type = "POST";
+		options.url = "/concepts/manipulator/add-concept";
+		options.data = {
+			"pref-label": searchTerm,
+			lang: $(":input[name='lang']").val(),
+			comment: $(":textarea[name='comment']").val()
+		}
+		
+		$.ajax(options);
+	}
+	return false;
+}
+
+$(document).ready(function(){
+	$("#go-button").click(function(){
+		ConceptFinder.search();
+	});
+	$("#add-user-defined-concept").click(function(){
+		ConceptManipulator.addConcept();
+		$("#user-defined-concept-area").hide();
+	});
+	$("#system-found-concepts-area").hide();
+	$("#user-defined-concept-area").hide();
+});