You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stanbol.apache.org by rw...@apache.org on 2014/05/09 07:08:22 UTC

svn commit: r1593490 [1/2] - in /stanbol/branches/release-0.12/enhancer: chain/graph/ chain/graph/src/main/java/org/apache/stanbol/enhancer/chain/graph/impl/ chain/graph/src/main/resources/OSGI-INF/metatype/ chain/list/ chain/list/src/main/java/org/apa...

Author: rwesten
Date: Fri May  9 05:08:21 2014
New Revision: 1593490

URL: http://svn.apache.org/r1593490
Log:
STANBOL-488: implemetnation of chain scoped enhancement properties for 0.12.1; Chain scoped Enhancement Properties are stored as RDF within the execution paln. Added Helper Methods for doing so to the ExecutionPlanHelper. EnhancementProperties do now consider chain scoped properties. Adapted the helper methods in the EnhancementEngineHelper accodringly. Added enhancement properties support to the list, weighted and graph chain.

Added:
    stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/DictionaryAdapter.java
    stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/test/java/org/apache/stanbol/enhancer/serviceapi/helper/EnhancementPropertyTest.java
    stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/test/resources/log4j.properties
Modified:
    stanbol/branches/release-0.12/enhancer/chain/graph/pom.xml
    stanbol/branches/release-0.12/enhancer/chain/graph/src/main/java/org/apache/stanbol/enhancer/chain/graph/impl/GraphChain.java
    stanbol/branches/release-0.12/enhancer/chain/graph/src/main/resources/OSGI-INF/metatype/metatype.properties
    stanbol/branches/release-0.12/enhancer/chain/list/pom.xml
    stanbol/branches/release-0.12/enhancer/chain/list/src/main/java/org/apache/stanbol/enhancer/chain/list/impl/ListChain.java
    stanbol/branches/release-0.12/enhancer/chain/list/src/main/resources/OSGI-INF/metatype/metatype.properties
    stanbol/branches/release-0.12/enhancer/chain/weighted/pom.xml
    stanbol/branches/release-0.12/enhancer/chain/weighted/src/main/java/org/apache/stanbol/enhancer/chain/weighted/impl/WeightedChain.java
    stanbol/branches/release-0.12/enhancer/chain/weighted/src/main/resources/OSGI-INF/metatype/metatype.properties
    stanbol/branches/release-0.12/enhancer/generic/servicesapi/pom.xml
    stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/InvalidContentException.java
    stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ConfigUtils.java
    stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/EnhancementEngineHelper.java
    stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ExecutionMetadataHelper.java
    stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ExecutionPlanHelper.java
    stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/impl/AbstractChain.java
    stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/impl/SingleEngineChain.java
    stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/rdf/NamespaceEnum.java

Modified: stanbol/branches/release-0.12/enhancer/chain/graph/pom.xml
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/chain/graph/pom.xml?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/chain/graph/pom.xml (original)
+++ stanbol/branches/release-0.12/enhancer/chain/graph/pom.xml Fri May  9 05:08:21 2014
@@ -84,7 +84,7 @@
     <dependency>
       <groupId>org.apache.stanbol</groupId>
       <artifactId>org.apache.stanbol.enhancer.servicesapi</artifactId>
-      <version>0.10.0</version>
+      <version>0.12.1-SNAPSHOT</version>
     </dependency>
     
     <dependency>

Modified: stanbol/branches/release-0.12/enhancer/chain/graph/src/main/java/org/apache/stanbol/enhancer/chain/graph/impl/GraphChain.java
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/chain/graph/src/main/java/org/apache/stanbol/enhancer/chain/graph/impl/GraphChain.java?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/chain/graph/src/main/java/org/apache/stanbol/enhancer/chain/graph/impl/GraphChain.java (original)
+++ stanbol/branches/release-0.12/enhancer/chain/graph/src/main/java/org/apache/stanbol/enhancer/chain/graph/impl/GraphChain.java Fri May  9 05:08:21 2014
@@ -17,6 +17,7 @@
 package org.apache.stanbol.enhancer.chain.graph.impl;
 
 import static org.apache.commons.io.FilenameUtils.getExtension;
+import static org.apache.stanbol.enhancer.servicesapi.helper.ConfigUtils.getEnhancementProperties;
 import static org.apache.stanbol.enhancer.servicesapi.helper.ConfigUtils.getParameters;
 import static org.apache.stanbol.enhancer.servicesapi.helper.ConfigUtils.getState;
 import static org.apache.stanbol.enhancer.servicesapi.helper.ConfigUtils.getValue;
@@ -84,12 +85,12 @@ import org.slf4j.LoggerFactory;
  * empty. Otherwise the {@link #PROPERTY_CHAIN_LIST} will be ignored regardless
  * if the graph resource is available or not.
  * </ol>
- * TODO: Maybe split this up into two chains - one for each configuration
- * possibility.
+ * <i>NOTE:</i> Since <code>0.12.1</code> this supports EnhancementProperties
+ * as described by <a href="https://issues.apache.org/jira/browse/STANBOL-488"></a>
  * 
  * @author Rupert Westenthaler
  */
-@Component(inherit=true,configurationFactory=true,metatype=true,
+@Component(configurationFactory=true,metatype=true,
     policy=ConfigurationPolicy.REQUIRE)
 @Service
 @Properties(value={
@@ -234,7 +235,7 @@ public class GraphChain extends Abstract
                     "The configured execution plan MUST at least contain a single " +
                     "valid execution node!");
             }
-            internalChain = new ListConfigExecutionPlan(config);
+            internalChain = new ListConfigExecutionPlan(config,getChainProperties());
             mode = MODE.LIST;
         } else { //both PROPERTY_CHAIN_LIST and PROPERTY_GRAPH_RESOURCE are null
             throw new ConfigurationException(PROPERTY_GRAPH_RESOURCE, 
@@ -431,7 +432,8 @@ public class GraphChain extends Abstract
          * Parses the execution plan form the configuration.
          * @param config
          */
-        private ListConfigExecutionPlan(Map<String,Map<String,List<String>>> config){
+        private ListConfigExecutionPlan(Map<String,Map<String,List<String>>> config,
+                Map<String,Object> chainProperties){
             if(config == null || config.isEmpty()){
                 throw new IllegalArgumentException("The parsed execution plan " +
                 		"confiuguration MUST NOT be NULL nor empty");
@@ -443,7 +445,7 @@ public class GraphChain extends Abstract
             }
             engines = Collections.unmodifiableSet(new HashSet<String>(config.keySet()));
             MGraph graph = new SimpleMGraph();
-            NonLiteral epNode = createExecutionPlan(graph, getName());
+            NonLiteral epNode = createExecutionPlan(graph, getName(), chainProperties);
             //caches the String name -> {NonLiteral node, List<Stirng> dependsOn} mappings
             Map<String,Object[]> name2nodes = new HashMap<String,Object[]>();
             //1. write the nodes (without dependencies)
@@ -454,7 +456,8 @@ public class GraphChain extends Abstract
                         writeExecutionNode(graph, epNode, 
                             node.getKey(), 
                             getState(node.getValue(), "optional"),
-                            null),
+                            null,
+                            getEnhancementProperties(node.getValue())),
                         node.getValue().get("dependsOn")}); //dependsOn
             }
             //2. write the dependencies

Modified: stanbol/branches/release-0.12/enhancer/chain/graph/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/chain/graph/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/chain/graph/src/main/resources/OSGI-INF/metatype/metatype.properties (original)
+++ stanbol/branches/release-0.12/enhancer/chain/graph/src/main/resources/OSGI-INF/metatype/metatype.properties Fri May  9 05:08:21 2014
@@ -42,3 +42,7 @@ stanbol.enhancer.chain.graph.chainlist.d
 of the execution plan with the syntax "<engineName>;[optional];[dependsOn=<engineName1>,<engineName2>]". \
 For details and examples please see the documentation. If a Graph Resource is \
 configured this property is ignored.
+
+stanbol.enhancer.chain.chainproperties.name=Chain Properties
+stanbol.enhancer.chain.chainproperties.description=Enhancement Properties parsed \
+to all engines of the chain. Syntax: '{property}={value-1},{value-2},..,{value-n}'
\ No newline at end of file

Modified: stanbol/branches/release-0.12/enhancer/chain/list/pom.xml
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/chain/list/pom.xml?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/chain/list/pom.xml (original)
+++ stanbol/branches/release-0.12/enhancer/chain/list/pom.xml Fri May  9 05:08:21 2014
@@ -84,7 +84,7 @@
     <dependency>
       <groupId>org.apache.stanbol</groupId>
       <artifactId>org.apache.stanbol.enhancer.servicesapi</artifactId>
-      <version>0.10.0</version>
+      <version>0.12.1-SNAPSHOT</version>
     </dependency>
     
     <dependency>

Modified: stanbol/branches/release-0.12/enhancer/chain/list/src/main/java/org/apache/stanbol/enhancer/chain/list/impl/ListChain.java
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/chain/list/src/main/java/org/apache/stanbol/enhancer/chain/list/impl/ListChain.java?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/chain/list/src/main/java/org/apache/stanbol/enhancer/chain/list/impl/ListChain.java (original)
+++ stanbol/branches/release-0.12/enhancer/chain/list/src/main/java/org/apache/stanbol/enhancer/chain/list/impl/ListChain.java Fri May  9 05:08:21 2014
@@ -16,6 +16,7 @@
 */
 package org.apache.stanbol.enhancer.chain.list.impl;
 
+import static org.apache.stanbol.enhancer.servicesapi.helper.ConfigUtils.getEnhancementProperties;
 import static org.apache.stanbol.enhancer.servicesapi.helper.ConfigUtils.getState;
 import static org.apache.stanbol.enhancer.servicesapi.helper.ExecutionPlanHelper.createExecutionPlan;
 import static org.apache.stanbol.enhancer.servicesapi.helper.ExecutionPlanHelper.writeExecutionNode;
@@ -75,14 +76,17 @@ import org.slf4j.LoggerFactory;
  * engine is not required.
  * </ul>
  * 
+ * <i>NOTE:</i> Since <code>0.12.1</code> this supports EnhancementProperties
+ * as described by <a href="https://issues.apache.org/jira/browse/STANBOL-488"></a>
+ * 
  * @author Rupert Westenthaler
  *
  */
-@Component(inherit=true,configurationFactory=true,metatype=true,
-policy=ConfigurationPolicy.REQUIRE)
+@Component(configurationFactory=true,metatype=true, policy=ConfigurationPolicy.REQUIRE)
 @Properties(value={
     @Property(name=Chain.PROPERTY_NAME),
     @Property(name=ListChain.PROPERTY_ENGINE_LIST, cardinality=1000),
+    @Property(name=AbstractChain.PROPERTY_CHAIN_PROPERTIES,cardinality=1000),
     @Property(name=Constants.SERVICE_RANKING, intValue=0)
 })
 @Service(value=Chain.class)
@@ -94,7 +98,7 @@ public class ListChain extends AbstractC
      * The list of Enhancement Engine names used to build the Execution Plan
      */
     public static final String PROPERTY_ENGINE_LIST = "stanbol.enhancer.chain.list.enginelist";
-    
+
     private Set<String> engineNames;
     
     private Graph executionPlan;
@@ -122,7 +126,7 @@ public class ListChain extends AbstractC
         Set<String> engineNames = new HashSet<String>(configuredChain.size());
         NonLiteral last = null;
         MGraph ep = new SimpleMGraph();
-        NonLiteral epNode = createExecutionPlan(ep, getName());
+        NonLiteral epNode = createExecutionPlan(ep, getName(), getChainProperties());
         log.debug("Parse ListChain config:");
         for(String line : configuredChain){
             try {
@@ -135,7 +139,8 @@ public class ListChain extends AbstractC
                 boolean optional = getState(parsed.getValue(), "optional");
                 log.debug(" > Engine: {} ({})",parsed.getKey(),optional? "optional" : "required");
                 last = writeExecutionNode(ep, epNode, parsed.getKey(), optional, 
-                    last == null ? null : Collections.singleton(last));
+                    last == null ? null : Collections.singleton(last),
+                    getEnhancementProperties(parsed.getValue()));
             } catch (IllegalArgumentException e) {
                 throw new ConfigurationException(PROPERTY_ENGINE_LIST, "Unable to parse Chain Configuraiton (message: '"+
                         e.getMessage()+"')!",e);

Modified: stanbol/branches/release-0.12/enhancer/chain/list/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/chain/list/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/chain/list/src/main/resources/OSGI-INF/metatype/metatype.properties (original)
+++ stanbol/branches/release-0.12/enhancer/chain/list/src/main/resources/OSGI-INF/metatype/metatype.properties Fri May  9 05:08:21 2014
@@ -33,4 +33,8 @@ This Chain implementation does not suppo
 
 stanbol.enhancer.chain.list.enginelist.name=Engines
 stanbol.enhancer.chain.list.enginelist.description=Defines the Engines in the oder \
-as executed by this Chain. Use "<engineName>;optional" if you want an engine to be optional.
\ No newline at end of file
+as executed by this Chain. Use "<engineName>;optional" if you want an engine to be optional.
+
+stanbol.enhancer.chain.chainproperties.name=Chain Properties
+stanbol.enhancer.chain.chainproperties.description=Enhancement Properties parsed \
+to all engines of the chain. Syntax: '{property}={value-1},{value-2},..,{value-n}'
\ No newline at end of file

Modified: stanbol/branches/release-0.12/enhancer/chain/weighted/pom.xml
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/chain/weighted/pom.xml?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/chain/weighted/pom.xml (original)
+++ stanbol/branches/release-0.12/enhancer/chain/weighted/pom.xml Fri May  9 05:08:21 2014
@@ -85,7 +85,7 @@
     <dependency>
       <groupId>org.apache.stanbol</groupId>
       <artifactId>org.apache.stanbol.enhancer.servicesapi</artifactId>
-      <version>0.10.0</version>
+      <version>0.12.1-SNAPSHOT</version>
     </dependency>
     
     <dependency>

Modified: stanbol/branches/release-0.12/enhancer/chain/weighted/src/main/java/org/apache/stanbol/enhancer/chain/weighted/impl/WeightedChain.java
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/chain/weighted/src/main/java/org/apache/stanbol/enhancer/chain/weighted/impl/WeightedChain.java?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/chain/weighted/src/main/java/org/apache/stanbol/enhancer/chain/weighted/impl/WeightedChain.java (original)
+++ stanbol/branches/release-0.12/enhancer/chain/weighted/src/main/java/org/apache/stanbol/enhancer/chain/weighted/impl/WeightedChain.java Fri May  9 05:08:21 2014
@@ -24,6 +24,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -39,6 +40,7 @@ import org.apache.felix.scr.annotations.
 import org.apache.stanbol.enhancer.servicesapi.Chain;
 import org.apache.stanbol.enhancer.servicesapi.ChainException;
 import org.apache.stanbol.enhancer.servicesapi.EnhancementEngine;
+import org.apache.stanbol.enhancer.servicesapi.helper.ConfigUtils;
 import org.apache.stanbol.enhancer.servicesapi.impl.AbstractChain;
 import org.apache.stanbol.enhancer.servicesapi.impl.EnginesTracker;
 import org.osgi.framework.Constants;
@@ -76,10 +78,13 @@ import org.slf4j.LoggerFactory;
  * engine is not required.
  * </ul>
  * 
+ * <i>NOTE:</i> Since <code>0.12.1</code> this supports EnhancementProperties
+ * as described by <a href="https://issues.apache.org/jira/browse/STANBOL-488"></a>
+ * 
  * @author Rupert Westenthaler
  *
  */
-@Component(inherit=true,configurationFactory=true,metatype=true,
+@Component(configurationFactory=true,metatype=true,
 policy=ConfigurationPolicy.REQUIRE)
 @Properties(value={
     @Property(name=Chain.PROPERTY_NAME),
@@ -96,9 +101,17 @@ public class WeightedChain extends Abstr
      * based on there weights. 
      */
     public static final String PROPERTY_CHAIN = "stanbol.enhancer.chain.weighted.chain";
-    
+    /**
+     * the Chain configuration as parsed in the {@link #activate(ComponentContext)} method
+     */
     private Map<String,Map<String,List<String>>> chain;
-    
+    /**
+     * Do hold chain scope EnhancementProperties of the configured chain.
+     */
+    private Map<String,Map<String,Object>> chainScopedEnhProps;
+    /**
+     * Tracks the engines defined in the {@link #chain}
+     */
     private EnginesTracker tracker;
     
     /**
@@ -138,6 +151,17 @@ public class WeightedChain extends Abstr
             throw new ConfigurationException(PROPERTY_CHAIN, 
                 "The configured chain MUST at least contain a single valid entry!");
         }
+        //init the chain scoped enhancement properties
+        chainScopedEnhProps = new HashMap<String,Map<String,Object>>();
+        if(getChainProperties() != null){
+            chainScopedEnhProps.put(null, getChainProperties());
+        }
+        for(Entry<String,Map<String,List<String>>> entry : chain.entrySet()){
+            Map<String,Object> enhProp = ConfigUtils.getEnhancementProperties(entry.getValue());
+            if(enhProp != null){
+                chainScopedEnhProps.put(entry.getKey(), enhProp);
+            }
+        }
         //start tracking the engines of the configured chain
         tracker = new EnginesTracker(ctx.getBundleContext(), chain.keySet(),this);
         tracker.open();
@@ -147,6 +171,7 @@ public class WeightedChain extends Abstr
     protected void deactivate(ComponentContext ctx) {
         tracker.close();
         tracker = null;
+        chainScopedEnhProps = null;
         chain = null;
         super.deactivate(ctx);
     }
@@ -174,6 +199,10 @@ public class WeightedChain extends Abstr
      * configured {@link #chain} is not active.
      */
     private Graph createExecutionPlan() throws ChainException {
+        Map<String,Map<String,Object>> chainScopedEnhancementProperties = new HashMap<String,Map<String,Object>>();
+        if(getChainProperties() != null){
+            chainScopedEnhancementProperties.put(null, getChainProperties());
+        }
         List<EnhancementEngine> availableEngines = new ArrayList<EnhancementEngine>(chain.size());
         Set<String> optionalEngines = new HashSet<String>();
         Set<String> missingEngines = new HashSet<String>();
@@ -193,7 +222,8 @@ public class WeightedChain extends Abstr
 //            throw new ChainException("This Chain is missing the following " +
 //            		"required Engines "+missingEngines);
 //        }
-        return calculateExecutionPlan(getName(),availableEngines,optionalEngines, missingEngines);
+        return calculateExecutionPlan(getName(),availableEngines,optionalEngines, 
+            missingEngines,chainScopedEnhancementProperties);
     }
 
     @Override

Modified: stanbol/branches/release-0.12/enhancer/chain/weighted/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/chain/weighted/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/chain/weighted/src/main/resources/OSGI-INF/metatype/metatype.properties (original)
+++ stanbol/branches/release-0.12/enhancer/chain/weighted/src/main/resources/OSGI-INF/metatype/metatype.properties Fri May  9 05:08:21 2014
@@ -33,4 +33,8 @@ calculated by using ordering information
 
 stanbol.enhancer.chain.weighted.chain.name=Engines
 stanbol.enhancer.chain.weighted.chain.description=Defines the Engines used by this Chain. \
-One engine name per line. Use "<engineName>;optional" if you want an engine to be optional.
\ No newline at end of file
+One engine name per line. Use "<engineName>;optional" if you want an engine to be optional.
+
+stanbol.enhancer.chain.chainproperties.name=Chain Properties
+stanbol.enhancer.chain.chainproperties.description=Enhancement Properties parsed \
+to all engines of the chain. Syntax: '{property}={value-1},{value-2},..,{value-n}'
\ No newline at end of file

Modified: stanbol/branches/release-0.12/enhancer/generic/servicesapi/pom.xml
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/generic/servicesapi/pom.xml?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/generic/servicesapi/pom.xml (original)
+++ stanbol/branches/release-0.12/enhancer/generic/servicesapi/pom.xml Fri May  9 05:08:21 2014
@@ -111,9 +111,10 @@
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
     </dependency>
-    <dependency>
+    <dependency>  <!-- used for debug level logging during tests -->
       <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-simple</artifactId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>test</scope>
     </dependency>
   </dependencies>
 

Modified: stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/InvalidContentException.java
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/InvalidContentException.java?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/InvalidContentException.java (original)
+++ stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/InvalidContentException.java Fri May  9 05:08:21 2014
@@ -25,20 +25,51 @@ package org.apache.stanbol.enhancer.serv
 public class InvalidContentException extends EngineException {
 
     private static final long serialVersionUID = 1L;
-
+    
+    /**
+     * 
+     * @param message
+     * @deprecated All EngineExceptions should parse the Engine and the 
+     * ContentItem
+     */
+    @Deprecated
     public InvalidContentException(String message) {
         super(message);
     }
-
+    /**
+     * 
+     * @param message
+     * @param cause
+     * @deprecated All EngineExceptions should parse the Engine and the 
+     * ContentItem
+     */
+    @Deprecated
     public InvalidContentException(String message, Throwable cause) {
         super(message, cause);
     }
 
+    /**
+     * A EngineException caused by an invalid ContentItem
+     * @param ee the enhancement engine
+     * @param ci the content item
+     * @param cause the root cause
+     */
     public InvalidContentException(EnhancementEngine ee, ContentItem ci,
             Throwable cause) {
-        super(String.format("'%s' failed to process invalid content item '%s'"
-                + " with type '%s': %s", ee.getClass().getSimpleName(),
-                ci.getUri().getUnicodeString(), ci.getMimeType(), cause.getMessage()), cause);
+        this(ee,ci, null,cause);
+    }
+    /**
+     * 
+     * @param ee the enhancement engine
+     * @param ci the content item
+     * @param message a custom message why the parsed content item was invalid
+     * @param cause the root cause
+     * @since 0.12.1
+     */
+    public InvalidContentException(EnhancementEngine ee, ContentItem ci,
+            String message, Throwable cause) {
+        super(ee,ci, message == null ? "Invalid ContentItem" : message,
+            cause);
     }
 
 }

Modified: stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ConfigUtils.java
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ConfigUtils.java?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ConfigUtils.java (original)
+++ stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ConfigUtils.java Fri May  9 05:08:21 2014
@@ -17,6 +17,7 @@
 package org.apache.stanbol.enhancer.servicesapi.helper;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -153,6 +154,51 @@ public final class ConfigUtils {
     }
     
     /**
+     * Utility that extracts enhancement properties from the parsed parameter maps.
+     * This will only consider keys starting with '<code>enhancer.</code>' as
+     * defined by <a href="https://issues.apache.org/jira/browse/STANBOL-488">STANBOL-488</a>
+     * @param parameters the paraemters (e.g. as returned as values by
+     * {@link #parseConfig(Iterator)})
+     * @return The enhancement properties extracted from the parsed parameters
+     * @since 0.12.1
+     */
+    public static Map<String,Object> getEnhancementProperties(Map<String, List<String>> parameters){
+        Map<String,Object> props = new HashMap<String,Object>();
+        for(Entry<String,List<String>> entry : parameters.entrySet()){
+            if(entry.getKey().startsWith("enhancer.")){
+                Object value;
+                if(entry.getValue().size() == 1){
+                    value = entry.getValue().get(0);
+                } else {
+                    value = entry.getValue();
+                }
+                if(value != null){
+                    props.put(entry.getKey(), value);
+                }
+            }
+        }
+        return props;
+    }
+    /**
+     * Utility that extracts enhancement properties from a configuration line
+     * using the syntax
+     * <pre>
+     *     {prop}={value-1},{value-2},..,{value-n}
+     * </pre>
+     * @param line the configuration of a single enhancement property
+     * @return The enhancement properties extracted from the parsed parameters
+     * @since 0.12.1
+     */
+    public static Map<String,Object> getEnhancementProperties(Collection<String> lines){
+        if(lines == null || lines.isEmpty()){
+            return null;
+        } else {
+            return getEnhancementProperties(getParameters(
+                lines.toArray(new String[lines.size()]), 0));
+        }
+    }
+    
+    /**
      * Internally used to parse single lines of an parsed {@link Iterable} or
      * {@link Iterator}
      * @param config the map used to write the parsed values

Added: stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/DictionaryAdapter.java
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/DictionaryAdapter.java?rev=1593490&view=auto
==============================================================================
--- stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/DictionaryAdapter.java (added)
+++ stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/DictionaryAdapter.java Fri May  9 05:08:21 2014
@@ -0,0 +1,134 @@
+package org.apache.stanbol.enhancer.servicesapi.helper;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Adapter for {@link Map} to {@link Dictionary}. Primarily implemented for the use in 
+ * {@link EnhancementEngineHelper#getEnhancementPropertyDict(org.apache.stanbol.enhancer.servicesapi.EnhancementEngine, org.apache.stanbol.enhancer.servicesapi.ContentItem)}.
+ * <p>
+ * This Adapter will hide {@link Entry Entries} in the {@link Map} that do use
+ * <code>null</code> as key or value. It also throws {@link NullPointerException}
+ * in case <code>null</code> is parsed to {@link #put(Object, Object)},
+ * {@link #get(Object)} or {@link #remove(Object)}.
+ * 
+ * @author Rupert Westenthaler
+ *
+ * @param <K>
+ * @param <V>
+ */
+public class DictionaryAdapter<K,V> extends Dictionary<K,V> {
+    
+    private final Map<K,V> map;
+
+    DictionaryAdapter(Map<K,V> map){
+        this.map = map;
+    }
+    
+    @Override
+    public int size() {
+        return map.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return map.isEmpty();
+    }
+
+    @Override
+    public Enumeration<K> keys() {
+        final Iterator<Entry<K,V>> it = map.entrySet().iterator();
+        return new Enumeration<K>(){
+
+            K next;
+            
+            @Override
+            public boolean hasMoreElements() {
+                return retrieveNext();
+            }
+
+            private boolean retrieveNext(){
+                if(next != null){
+                    return true;
+                } else {
+                    while(next == null && it.hasNext()){
+                        Entry<K,V> e = it.next();
+                        if(e.getKey() != null && e.getValue() != null){
+                            next = e.getKey();
+                        } //we need to ignore NULL key or NULL value mappings
+                    }
+                    return next != null;
+                }
+            }        
+            
+            @Override
+            public K nextElement() {
+                K cur = next;
+                next = null;
+                return cur;
+            }
+            
+        };
+    }
+
+    @Override
+    public Enumeration<V> elements() {
+        final Iterator<V> it = map.values().iterator();
+        return new Enumeration<V>(){
+
+            V next = null;
+            
+            @Override
+            public boolean hasMoreElements() {
+                return retrieveNext();
+            }
+            
+            private boolean retrieveNext(){
+                if(next != null){
+                    return true;
+                } else {
+                    while(next == null && it.hasNext()){
+                        next = it.next();
+                    }
+                    return next != null;
+                }
+            }
+
+            @Override
+            public V nextElement() {
+                V cur = next;
+                next = null;
+                return cur;
+            }
+            
+        };
+    }
+
+    @Override
+    public V get(Object key) {
+        if(key == null){
+            throw new NullPointerException("The key MUST NOT be NULL!");
+        }
+        return map.get(key);
+    }
+
+    @Override
+    public V put(K key, V value) {
+        if(key == null || value == null){
+            throw new NullPointerException("Key '"+key+"' and Value '"+value+"' MUST NOT be NULL!");
+        }
+        return map.put(key, value);
+    }
+
+    @Override
+    public V remove(Object key) {
+        if(key == null){
+            throw new NullPointerException("The key MUST NOT be NULL!");
+        }
+        return map.remove(key);
+    }
+
+}

Modified: stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/EnhancementEngineHelper.java
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/EnhancementEngineHelper.java?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/EnhancementEngineHelper.java (original)
+++ stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/EnhancementEngineHelper.java Fri May  9 05:08:21 2014
@@ -25,16 +25,16 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
+import java.util.Dictionary;
 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.Random;
-import java.util.Set;
 import java.util.UUID;
 
+import org.apache.clerezza.rdf.core.BNode;
 import org.apache.clerezza.rdf.core.Language;
 import org.apache.clerezza.rdf.core.Literal;
 import org.apache.clerezza.rdf.core.LiteralFactory;
@@ -51,6 +51,8 @@ import org.apache.stanbol.enhancer.servi
 import org.apache.stanbol.enhancer.servicesapi.ContentItem;
 import org.apache.stanbol.enhancer.servicesapi.EnhancementEngine;
 import org.apache.stanbol.enhancer.servicesapi.ServiceProperties;
+import org.apache.stanbol.enhancer.servicesapi.rdf.ExecutionPlan;
+import org.apache.stanbol.enhancer.servicesapi.rdf.NamespaceEnum;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -778,23 +780,55 @@ public final class EnhancementEngineHelp
      * NOTE: in 1.0.0 those are obsolete as EnhancementProperties will be parsed
      * as additional parameter to the computeEnhancement method.
      */
+    private static final String EHPROP_NS = NamespaceEnum.ehprop.getNamespace();
+    private static final int EHPROP_NS_LENGTH = EHPROP_NS.length();
+
     /**
      * Retrieves the Enhancement Properties for the parsed Engine from the ContentItem.
      * <p>
-     * The returned map will contain: <ul>
-     * <li> all properties with a key that does NOT include a '<code>:</code>'
-     * <li> all properties with a key starting with '<code>{engine-name}:</code>'
+     * The returned map will contain: <ol>
+     * <li> Request scoped properties defined for the parsed enhancement engines
+     * <li> Request scoped properties defined for chain
+     * <li> Chain scoped properties defined for the parsed enhancement engine
+     * <li> Chain scoped properties defined for the chain.
+     * </ol>
+     * NOTES: <ul>
+     * <li> The specification (see <a href="https://issues.apache.org/jira/browse/STANBOL-488">STANBOL-488</a>)
+     * required properties to start with '<code>enhancer.</code>'. While this
+     * implementation does not enforce this requirement non compliant properties
+     * will most likely get filtered earlier and not be part of the returned map.
+     * <li> Properties of an higher priority do override those with an lower one.
      * </ul>
-     * NOTE: that only properties containing '<code>enhancer.</code>' will get 
-     * parsed from Enhancement Requests.<p>
-     * See <a href="https://issues.apache.org/jira/browse/STANBOL-488">STANBOL-488</a> 
-     * for the specification of Enhancement Properties and 
-     * <a href="https://issues.apache.org/jira/browse/STANBOL-1280">STANBOL-1280</a> 
-     * for the list of features supported inStanbol version <code>0.12.1+</code>
      * @param engine the enhancement engine requesting the properties
      * @param ci the content item (representing the enhancement request).
      * @return The enhancement properties. This is a read/write copy of the
-     * read-only content part.
+     * read-only configuration.
+     * @see #getEnhancementPropertyDict(EnhancementEngine, ContentItem)
+     */
+    public static Dictionary<String,Object> getEnhancementPropertyDict(EnhancementEngine engine, ContentItem ci){
+        return new DictionaryAdapter<String,Object>(getEnhancementProperties(engine, ci));
+    }
+    /**
+     * Retrieves the Enhancement Properties for the parsed Engine from the ContentItem.
+     * <p>
+     * The returned map will contain: <ol>
+     * <li> Request scoped properties defined for the parsed enhancement engines
+     * <li> Request scoped properties defined for chain
+     * <li> Chain scoped properties defined for the parsed enhancement engine
+     * <li> Chain scoped properties defined for the chain.
+     * </ol>
+     * NOTES: <ul>
+     * <li> The specification (see <a href="https://issues.apache.org/jira/browse/STANBOL-488">STANBOL-488</a>)
+     * required properties to start with '<code>enhancer.</code>'. While this
+     * implementation does not enforce this requirement non compliant properties
+     * will most likely get filtered earlier and not be part of the returned map.
+     * <li> Properties of an higher priority do override those with an lower one.
+     * </ul>
+     * @param engine the enhancement engine requesting the properties
+     * @param ci the content item (representing the enhancement request).
+     * @return The enhancement properties. This is a read/write copy of the
+     * read-only configuration.
+     * @see #getEnhancementPropertyDict(EnhancementEngine, ContentItem)
      */
     public static Map<String,Object> getEnhancementProperties(EnhancementEngine engine, ContentItem ci){
         if(engine == null){
@@ -803,41 +837,137 @@ public final class EnhancementEngineHelp
         if(ci == null){
             throw new IllegalArgumentException("The parsed ContentItem MUST NOT be NULL");
         }
+        //(1) retrieve Chain scope Enhancement Properties
+        Map<String,Object> chainExProps = new HashMap<String,Object>();
+        Map<String,Object> engineExProps = new HashMap<String,Object>();
+        ci.getLock().readLock().lock();
+        try{
+            MGraph em = ExecutionMetadataHelper.getExecutionMetadata(ci);
+            //(1.a) retrieve EnhancementProperties from the ep:ExecutionPlan
+            log.debug("> extract EnhancementProperties form the ExecutionPlan");
+            NonLiteral executionPlanNode = ExecutionMetadataHelper.getExecutionPlanNode(em, 
+                ExecutionMetadataHelper.getChainExecution(em, ci.getUri()));
+            extractEnhancementProperties(chainExProps, em, executionPlanNode, "Chain Execution");
+            //(1.b) retrieve Enhancement Properties from the ep:ExectutionNode
+            //      for the parsed EnhancementEngine
+            log.debug("> extract EnhancementProperties form the ExecutionNode of Engine {}",
+                engine.getName());
+            Iterator<Triple> engineExecutions = em.filter(null, ExecutionPlan.ENGINE, new PlainLiteralImpl(engine.getName()));
+            //NOTE: we expect only a single execution node for an engine, but if
+            //      there are multiple we will merge the properties of those
+            while(engineExecutions.hasNext()){
+                NonLiteral engineExecution = engineExecutions.next().getSubject();
+                if(em.contains(new TripleImpl(executionPlanNode, ExecutionPlan.HAS_EXECUTION_NODE, engineExecution))){
+                    extractEnhancementProperties(engineExProps,em, engineExecution, "Engine Execution");
+                } //else engine execution of a different execution plan
+            }
+        } finally {
+            ci.getLock().readLock().unlock();
+        }
+        //(2) retrieve Request specific EnhancementProperties
+        //TODO: in future Stanbol version request specific EnhancementProperties
+        //      will get stored in the ExecutionMetadata. Chain level properties
+        //      with the `em:ChainExecution` node and engine specific properties
+        //      with the `em:EngineExecution` node.
+        //      So this code will need to be refactored similar to the above one
         Map<String,Object> epContentPart = ContentItemHelper.getEnhancementPropertiesContentPart(ci);
-        if(epContentPart == null){
-            log.debug("no EnhancementProperties for ContentItem",ci.getUri());
-            return Collections.emptyMap();
-        }
-        String prefix = new StringBuilder(engine.getName()).append(':').toString();
-        Map<String,Object> properties = new HashMap<String,Object>();
-        log.debug("Retrieve EnhancementProperties for Engine {} and ContentItem {}", 
-            engine.getName(), ci.getUri());
-        Set<String> engineKeys = new HashSet<String>();
-        for(Entry<String,Object> entry : epContentPart.entrySet()){
-            String key = entry.getKey();
-            int sepIndex = key.indexOf(':');
-            if(sepIndex < 0){
-                if(!engineKeys.contains(key)){
-                    log.debug(" - include chain property '{}'",key);
-                    properties.put(key, entry.getValue());
-                } else {
-                    log.debug(" - exclude chain property '{}' because property is "
-                        + "present in engine level.", key);
-                }
-            } else if(key.startsWith(prefix) && key.length() > prefix.length()){
-                key = key.substring(prefix.length(),key.length());
-                log.debug(" - include engine property '{}'",key);
-                engineKeys.add(key);
-                Object value = properties.put(key, entry.getValue());
-                if(value != null && log.isDebugEnabled()){
-                    log.debug("    ... overrides Chain level value: {}",value);
-                }
-            } else {
-                log.debug(" - exclude engine property '{}'",key);
+        Map<String,Object> chainProperties = new HashMap<String,Object>();
+        Map<String,Object> engineProperties = new HashMap<String,Object>();
+        if(epContentPart != null){
+            String enginePrefix = new StringBuilder(engine.getName()).append(':').toString();
+            log.debug("Retrieve EnhancementProperties for Engine {} and ContentItem {}", 
+                engine.getName(), ci.getUri());
+            //Set<String> engineKeys = new HashSet<String>();
+            for(Entry<String,Object> entry : epContentPart.entrySet()){
+                String key = entry.getKey();
+                int sepIndex = key.indexOf(':');
+                if(sepIndex < 0){
+                    log.debug(" ... add chain request level property {}='{}'", key,entry.getValue());
+                    chainProperties.put(key, entry.getValue());
+                } else if(key.startsWith(enginePrefix) && key.length() > enginePrefix.length()){
+                    key = key.substring(enginePrefix.length(),key.length());
+                    log.debug(" ... add engine request level property {}='{}'", key,entry.getValue());
+                    engineProperties.put(key, entry.getValue());
+                } // else not a enhancement property for the current engine.
             }
+        } else {
+            log.debug(" - no Request scope EnhancementProperties for ContentItem",ci.getUri());
         }
+        //Now we need to merge the properties based on the Enhancement Properties Precedence
+        //defined by STANBOL-488
+        // engineProp > engineEx > chainProp > chainExProp
+        Map<String,Object> properties = new HashMap<String,Object>(chainExProps);
+        properties.putAll(engineExProps);
+        properties.putAll(chainProperties);
+        properties.putAll(engineProperties);
         return properties;
     }
+
+    /**
+     * Extracts all EnhancementProperties from the parsed Node and adds them to
+     * the parsed map
+     * @param properties The Map to add the extracted properties. extracted values
+     * are appended to existing values.
+     * @param graph the RDF graph containing the data
+     * @param node the node to extract the properties from
+     * @param level the name of the level (only used for logging)
+     */
+    private static void extractEnhancementProperties(Map<String,Object> properties, TripleCollection graph,
+            NonLiteral node, String level) {
+        log.debug(" - extract {} properties from {}", level, node);
+        Iterator<Triple> props = graph.filter(node, null, null);
+        while(props.hasNext()){
+            Triple t = props.next();
+            String propUri =  t.getPredicate().getUnicodeString();
+            if(propUri.startsWith(EHPROP_NS)){
+                String prop = propUri.substring(EHPROP_NS_LENGTH);
+                Resource resource = t.getObject();
+                Object value = extractEnhancementPropertyValue(resource);
+                if(value != null && !prop.isEmpty()){
+                    Object current = properties.get(prop);
+                    if(log.isDebugEnabled()){
+                        if(current != null){
+                            log.debug(" ... append {} property '{}' to {}='{}'", 
+                                new Object[]{level, value, prop,current});
+                        } else {
+                            log.debug(" ... add {} property {}='{}'", 
+                                new Object[]{level, prop, value});
+                        }
+                    }
+                    if(current instanceof Collection<?>){
+                        ((Collection) current).add(value);
+                    } else if(current != null){
+                        Collection<Object> col = new ArrayList<Object>(4);
+                        col.add(current);
+                        col.add(value);
+                        properties.put(prop, col);
+                    } else {
+                        properties.put(prop, value);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Extracts the EnhancementProperty value from the parsed Resource.<p>
+     * Currently this will return {@link UriRef#getUnicodeString()} or
+     * {@link Literal#getLexicalForm()}. For {@link BNode}s <code>null</code> 
+     * is returned.
+     * @param r the resource to parse the value form
+     * @return the parsed value
+     */
+    private static Object extractEnhancementPropertyValue(Resource r) {
+        Object value;
+        if(r instanceof UriRef){
+            value = ((UriRef)r).getUnicodeString();
+        } else if(r instanceof Literal){
+            value = ((Literal) r).getLexicalForm();
+        } else {
+            value = null;
+        }
+        return value;
+    }
     
     
 }

Modified: stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ExecutionMetadataHelper.java
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ExecutionMetadataHelper.java?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ExecutionMetadataHelper.java (original)
+++ stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ExecutionMetadataHelper.java Fri May  9 05:08:21 2014
@@ -243,6 +243,25 @@ public final class ExecutionMetadataHelp
             return null;
         }
     }
+    /**
+     * Getter for the execution metadata content part.
+     * @param contentItem the content item
+     * @return the content part
+     * @throws NoSuchPartException if no execution metadata are present in the
+     * content part
+     * @since 0.12.1
+     */
+    public static MGraph getExecutionMetadata(ContentItem contentItem) {
+        if(contentItem == null) {
+            throw new IllegalArgumentException("The parsed ContentItme MUST NOT be NULL!");
+        }
+        contentItem.getLock().readLock().lock();
+        try{
+            return contentItem.getPart(CHAIN_EXECUTION, MGraph.class);
+        }finally{
+            contentItem.getLock().readLock().unlock();
+        }
+    }
     
     /**
      * Getter/Initialiser for the execution metadata content part of the parsed

Modified: stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ExecutionPlanHelper.java
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ExecutionPlanHelper.java?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ExecutionPlanHelper.java (original)
+++ stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/helper/ExecutionPlanHelper.java Fri May  9 05:08:21 2014
@@ -30,6 +30,7 @@ import static org.apache.stanbol.enhance
 import static org.apache.stanbol.enhancer.servicesapi.rdf.Properties.RDF_TYPE;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -42,12 +43,16 @@ import java.util.Set;
 
 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.NoConvertorException;
 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.TripleCollection;
+import org.apache.clerezza.rdf.core.TypedLiteral;
+import org.apache.clerezza.rdf.core.UriRef;
 import org.apache.clerezza.rdf.core.impl.PlainLiteralImpl;
 import org.apache.clerezza.rdf.core.impl.TripleImpl;
 import org.apache.stanbol.commons.indexedgraph.IndexedMGraph;
@@ -57,6 +62,7 @@ import org.apache.stanbol.enhancer.servi
 import org.apache.stanbol.enhancer.servicesapi.ServiceProperties;
 import org.apache.stanbol.enhancer.servicesapi.impl.EnginesTracker;
 import org.apache.stanbol.enhancer.servicesapi.rdf.ExecutionPlan;
+import org.apache.stanbol.enhancer.servicesapi.rdf.NamespaceEnum;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -67,6 +73,25 @@ public final class ExecutionPlanHelper {
     private static LiteralFactory lf = LiteralFactory.getInstance();
     
     private ExecutionPlanHelper(){/* Do not allow instances of utility classes*/}
+
+    /**
+     * Writes all triples for an ep:ExecutionNode to the parsed {@link MGraph}.
+     * An {@link BNode} is use for representing the execution node resource.
+     * @param graph the graph to write the triples. MUST NOT be empty
+     * @param epNode the NonLiteral representing the ep:ExecutionPlan
+     * @param engineName the name of the engine. MUST NOT be <code>null</code> nor empty
+     * @param optional if the execution of this node is optional or required
+     * @param dependsOn other nodes that MUST BE executed before this one. Parse 
+     * <code>null</code> or an empty set if none.
+     * @return the resource representing the added ep:ExecutionNode.
+     * @deprecated use {@link #writeExecutionNode(MGraph, NonLiteral, String, boolean, Set, Map)}
+     * with <code>null</code> as last parameter
+     */
+    @Deprecated
+    public static NonLiteral writeExecutionNode(MGraph graph,NonLiteral epNode, 
+            String engineName, boolean optional, Set<NonLiteral> dependsOn){
+        return writeExecutionNode(graph,epNode,engineName,optional,dependsOn, null);
+    }
     /**
      * Writes all triples for an ep:ExecutionNode to the parsed {@link MGraph}.
      * An {@link BNode} is use for representing the execution node resource.
@@ -76,9 +101,14 @@ public final class ExecutionPlanHelper {
      * @param optional if the execution of this node is optional or required
      * @param dependsOn other nodes that MUST BE executed before this one. Parse 
      * <code>null</code> or an empty set if none.
+     * @param enhProps the EnhancementProperties for this ExecutionNode or
+     * <code>null</code> if none
      * @return the resource representing the added ep:ExecutionNode.
+     * @since 0.12.1
      */
-    public static NonLiteral writeExecutionNode(MGraph graph,NonLiteral epNode, String engineName, boolean optional, Set<NonLiteral> dependsOn){
+    public static NonLiteral writeExecutionNode(MGraph graph,NonLiteral epNode, 
+            String engineName, boolean optional, Set<NonLiteral> dependsOn, 
+            Map<String,Object> enhProps){
         if(graph == null){
             throw new IllegalArgumentException("The parsed MGraph MUST NOT be NULL!");
         }
@@ -100,6 +130,7 @@ public final class ExecutionPlanHelper {
             }
         }
         graph.add(new TripleImpl(node, OPTIONAL, lf.createTypedLiteral(optional)));
+        writeEnhancementProperties(graph, node, engineName, enhProps);
         return node;
     }
     /**
@@ -107,8 +138,24 @@ public final class ExecutionPlanHelper {
      * @param graph the graph
      * @param chainName the chain name
      * @return the node representing the ex:ExecutionPlan
+     * @deprecated use {@link #createExecutionPlan(MGraph, String, Map)} with
+     * parsing <code>null</code> as last parameter
      */
+    @Deprecated
     public static NonLiteral createExecutionPlan(MGraph graph,String chainName){
+        return createExecutionPlan(graph, chainName, null);
+    }
+    
+    /**
+     * Creates an ExecutionPlan for the parsed chainName in the parsed Graph
+     * @param graph the graph
+     * @param chainName the chain name
+     * @param enhProps the map with the enhancement properties defined for the
+     * chain or <code>null</code> if none
+     * @return the node representing the ex:ExecutionPlan
+     * @since 0.12.1
+     */
+    public static NonLiteral createExecutionPlan(MGraph graph,String chainName, Map<String,Object> enhProps){
         if(graph == null){
             throw new IllegalArgumentException("The parsed MGraph MUST NOT be NULL!");
         }
@@ -118,6 +165,7 @@ public final class ExecutionPlanHelper {
         NonLiteral node = new BNode();
         graph.add(new TripleImpl(node, RDF_TYPE, EXECUTION_PLAN));
         graph.add(new TripleImpl(node, CHAIN,new PlainLiteralImpl(chainName)));
+        writeEnhancementProperties(graph, node, null, enhProps);
         return node;
     }
     
@@ -151,17 +199,49 @@ public final class ExecutionPlanHelper {
     /**
      * Creates an execution plan based on the 
      * {@link ServiceProperties#ENHANCEMENT_ENGINE_ORDERING} of the parsed
-     * EnhancementEngines. NOTE that the parsed list is modified as it is sroted by
+     * EnhancementEngines. NOTE that the parsed list is modified as it is sorted by
      * using the {@link EnhancementEngineHelper#EXECUTION_ORDER_COMPARATOR}.<p>
      * A second parameter with the set of optional engines can be used to define
      * what {@link ExecutionPlan#EXECUTION_NODE} in the execution plan should be 
      * marked as {@link ExecutionPlan#OPTIONAL}.
      * @param chainName the name of the Chain to build the execution plan for
      * @param availableEngines the list of engines
-     * @param the names of optional engines.
+     * @param optional the names of optional engines.
+     * @param missing the names of missing engines
      * @return the execution plan
+     * @deprecated use {@link #calculateExecutionPlan(String, List, Set, Set, Map)}
+     * with <code>null</code> as last argument instead
      */
-    public static Graph calculateExecutionPlan(String chainName, List<EnhancementEngine> availableEngines, Set<String> optional, Set<String> missing) {
+    @Deprecated
+    public static Graph calculateExecutionPlan(String chainName, List<EnhancementEngine> availableEngines, 
+            Set<String> optional, Set<String> missing) {
+        return calculateExecutionPlan(chainName, availableEngines, optional, missing, null);
+    }
+    /**
+     * Creates an execution plan based on the 
+     * {@link ServiceProperties#ENHANCEMENT_ENGINE_ORDERING} of the parsed
+     * EnhancementEngines. NOTE that the parsed list is modified as it is sorted by
+     * using the {@link EnhancementEngineHelper#EXECUTION_ORDER_COMPARATOR}.<p>
+     * A second parameter with the set of optional engines can be used to define
+     * what {@link ExecutionPlan#EXECUTION_NODE} in the execution plan should be 
+     * marked as {@link ExecutionPlan#OPTIONAL}.
+     * @param chainName the name of the Chain to build the execution plan for
+     * @param availableEngines the list of engines
+     * @param optional the names of optional engines.
+     * @param missing the names of missing engines
+     * @param enhProps chain scoped enhancement properties. The key of the outer
+     * map are the name of the engine or <code>null</code> for the chain. The
+     * inner map uses the property as key and the value(s) as value. Multiple
+     * values can be parsed as {@link Collection}. Single values will be
+     * converted to RDF {@link TypedLiteral}s by using the {@link LiteralFactory}.
+     * For types not supported by the LiteralFactory the <code>toString()</code>
+     * method will be used. <code>null</code> can be parsed if no enhancement
+     * properties are present.
+     * @return the execution plan
+     * @since 0.12.1
+     */
+    public static Graph calculateExecutionPlan(String chainName, List<EnhancementEngine> availableEngines, 
+            Set<String> optional, Set<String> missing, Map<String,Map<String,Object>> enhProps) {
         if(chainName == null || chainName.isEmpty()){
             throw new IllegalArgumentException("The parsed ChainName MUST NOT be empty!");
         }
@@ -169,13 +249,15 @@ public final class ExecutionPlanHelper {
         //now we have all required and possible also optional engines
         //  -> build the execution plan
         MGraph ep = new IndexedMGraph();
-        NonLiteral epNode = createExecutionPlan(ep, chainName);
+        NonLiteral epNode = createExecutionPlan(ep, chainName,
+            enhProps != null ? enhProps.get(null) : null);
         Integer prevOrder = null;
         Set<NonLiteral> prev = null;
         Set<NonLiteral> current = new HashSet<NonLiteral>();
         for(String name : missing){
             boolean optionalMissing = optional.contains(name);
-            NonLiteral node = writeExecutionNode(ep, epNode, name, optionalMissing, null);
+            NonLiteral node = writeExecutionNode(ep, epNode, name, optionalMissing, null,
+                enhProps == null ? null : enhProps.get(name));
             if(!optionalMissing){
                 current.add(node);
             } // else add missing optional engines without any dependsOn restrictions
@@ -189,7 +271,10 @@ public final class ExecutionPlanHelper {
                 prevOrder = order;
             }
             try {
-                current.add(writeExecutionNode(ep, epNode, name, optional.contains(name), prev));
+                NonLiteral executionNode = writeExecutionNode(ep, epNode, name, 
+                    optional.contains(name), prev, 
+                    enhProps == null ? null : enhProps.get(name));
+                current.add(executionNode);
             } catch (RuntimeException e){
                 //add the engine and class to ease debugging in such cases
                 log.error("Exception while writing ExecutionNode for Enhancement Eninge: "
@@ -200,6 +285,76 @@ public final class ExecutionPlanHelper {
         return ep.getGraph();
     }
     /**
+     * Writes the enhancementProperties for an engine/chain to the parsed 
+     * ExecutionNode
+     * @param ep The RDF graph holding the execution plan
+     * @param node the execution node of the engine (or chain) to add the
+     * enhancement properties
+     * @param engineName the name of the engine or <code>null</code> in case
+     * of the chain
+     * @param enhProps the chain scoped enhancement properties or <code>null</code>
+     * if none
+     * @since 0.12.1
+     */
+    private static void writeEnhancementProperties(MGraph ep, NonLiteral node, String engineName,
+            Map<String,Object> enhProps) {
+        if(enhProps == null){ //no enhancement properties for this engine
+            return;
+        }
+        for(Entry<String,Object> enhprop : enhProps.entrySet()){
+            if(enhprop.getKey() == null || enhprop.getValue() == null){
+                log.warn("Invalid Enhancement Property {} for {} {}", new Object[]{
+                        enhprop, engineName == null ? "Chain" : "engine",
+                        engineName == null ? "" : engineName});
+            } else {
+                writeEnhancementProperty(ep, node,
+                    new UriRef(NamespaceEnum.ehprop + enhprop.getKey()),
+                    enhprop.getValue());
+            }
+        }
+    }
+    
+    /**
+     * Writes enhancement property value(s) for the parsed node, property to the
+     * execution plan graph.
+     * @param ep the RDF graph holding the execution plan
+     * @param epNode the execution node
+     * @param property the property
+     * @param value the value(s). {@link Collection} and <code>Object[]</code> are
+     * supported for multiple values.
+     * @throws NullPointerException if any of the parsed parameter is <code>null</code>
+     */
+    @SuppressWarnings("unchecked")
+    private static void writeEnhancementProperty(MGraph ep, NonLiteral epNode, 
+            UriRef property, Object value) {
+        Collection<Object> values;
+        if(value instanceof Collection<?>){
+            values = (Collection<Object>)value;
+        } else if(value instanceof Object[]){
+            values = Arrays.asList((Object[])value);
+        } else {
+            values = Collections.singleton(value);
+        }
+        for(Object v : values){
+            if(v != null){
+                Literal literal;
+                if(v instanceof String){
+                    literal = new PlainLiteralImpl((String)v);
+                } else {
+                    try {
+                        literal = lf.createTypedLiteral(v);
+                    } catch (NoConvertorException e){
+                        log.warn("Use toString() value '{}' for EnhancementProperty "
+                            + "'{}' as no TypedLiteral converter is registered for "
+                            + "class {}", new Object[]{ v, property, v.getClass().getName()});
+                        literal = new PlainLiteralImpl(v.toString());
+                    }
+                }
+                ep.add(new TripleImpl(epNode, property, literal));
+            }
+        }
+    }
+    /**
      * Utility that checks if the parsed graph contains a valid execution
      * plan. This method is intended to be used by components that need to
      * ensure that an parsed graph contains a valid execution plan.<p>

Modified: stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/impl/AbstractChain.java
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/impl/AbstractChain.java?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/impl/AbstractChain.java (original)
+++ stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/impl/AbstractChain.java Fri May  9 05:08:21 2014
@@ -16,11 +16,18 @@
 */
 package org.apache.stanbol.enhancer.servicesapi.impl;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Properties;
 import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.stanbol.enhancer.servicesapi.Chain;
+import org.apache.stanbol.enhancer.servicesapi.helper.ConfigUtils;
 import org.osgi.framework.Constants;
 import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.component.ComponentContext;
@@ -48,12 +55,22 @@ import org.osgi.service.component.Compon
 @Service
 public abstract class AbstractChain implements Chain {
     
+    /**
+     * Property used to configure chain scoped enhancement properties as described
+     * by <a herf="https://issues.apache.org/jira/browse/STANBOL-488">STANBOL-488</a></p>
+     * Properties defined by this will get parsed to all enhancement engines in the
+     * chain.
+     */
+    public static final String PROPERTY_CHAIN_PROPERTIES = "stanbol.enhancer.chain.chainproperties";
+
     private String name;
     /**
      * The {@link ComponentContext} set in the {@link #activate(ComponentContext)}
      * and reset in the {@link #deactivate(ComponentContext)} method.
      */
     protected ComponentContext context;
+
+    private Map<String,Object> chainProperties;
     
     protected void activate(ComponentContext ctx) throws ConfigurationException {
         this.context = ctx;
@@ -71,6 +88,28 @@ public abstract class AbstractChain impl
                     "The name of a Chain MUST be an non empty String " +
                     "(type: "+value.getClass()+" value: "+value+")");
         }
+        value = ctx.getProperties().get(PROPERTY_CHAIN_PROPERTIES);
+        Collection<String> chainPropsConfig;
+        if(value instanceof String[]){
+            chainPropsConfig = Arrays.asList((String[])value);
+        } else if(value instanceof Collection<?>){
+            chainPropsConfig = new ArrayList<String>(((Collection<?>)value).size());
+            for(Object o : (Collection<?>)value){
+                if(o != null){
+                    chainPropsConfig.add(o.toString());
+                }
+            }
+        } else if(value instanceof String){
+            chainPropsConfig = Collections.singleton((String)value);
+        } else if (value != null){
+            throw new ConfigurationException(PROPERTY_CHAIN_PROPERTIES, 
+                "Chain level EnhancementProperties can be parsed as String[],"
+                + "Collection<String> or String (single value). The actually "
+                + "parsed type was "+value.getClass().getName());
+        } else {
+            chainPropsConfig = Collections.emptyList();
+        }
+        chainProperties = ConfigUtils.getEnhancementProperties(chainPropsConfig);
     }
     protected void deactivate(ComponentContext ctx){
         this.context = null;
@@ -81,5 +120,9 @@ public abstract class AbstractChain impl
     public final String getName(){
         return name;
     }
+    
+    protected Map<String,Object> getChainProperties(){
+        return chainProperties;
+    }
 
 }

Modified: stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/impl/SingleEngineChain.java
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/impl/SingleEngineChain.java?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/impl/SingleEngineChain.java (original)
+++ stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/impl/SingleEngineChain.java Fri May  9 05:08:21 2014
@@ -20,6 +20,7 @@ import static org.apache.stanbol.enhance
 import static org.apache.stanbol.enhancer.servicesapi.helper.ExecutionPlanHelper.writeExecutionNode;
 
 import java.util.Collections;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.clerezza.rdf.core.Graph;
@@ -49,15 +50,30 @@ public class SingleEngineChain implement
     private final EnhancementEngine engine;
     private final String name;
     
+    /**
+     * Creates a {@link Chain} for a single {@link EnhancementEngine}
+     * @param engine the engine
+     */
     public SingleEngineChain(EnhancementEngine engine){
+        this(engine,null);
+    }
+    /**
+     * Creates a {@link Chain} for a single {@link EnhancementEngine} including
+     * optional chain scoped enhancement properties
+     * @param engine the engine
+     * @param enhProps chain scoped enhancement properties or <code>null</code>
+     * if none.
+     * @since 0.12.1
+     */
+    public SingleEngineChain(EnhancementEngine engine, Map<String,Object> enhProps){
         if(engine == null){
             throw new IllegalArgumentException("The parsed EnhancementEngine MUST NOT be NULL!");
         }
         this.engine = engine;
         this.name = engine.getName()+"Chain";
         MGraph graph = new IndexedMGraph();
-        writeExecutionNode(graph, createExecutionPlan(graph, name),
-            engine.getName(), false, null);
+        writeExecutionNode(graph, createExecutionPlan(graph, name, null),
+            engine.getName(), false, null, enhProps);
         executionPlan = graph.getGraph();
     }
     

Modified: stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/rdf/NamespaceEnum.java
URL: http://svn.apache.org/viewvc/stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/rdf/NamespaceEnum.java?rev=1593490&r1=1593489&r2=1593490&view=diff
==============================================================================
--- stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/rdf/NamespaceEnum.java (original)
+++ stanbol/branches/release-0.12/enhancer/generic/servicesapi/src/main/java/org/apache/stanbol/enhancer/servicesapi/rdf/NamespaceEnum.java Fri May  9 05:08:21 2014
@@ -97,7 +97,12 @@ public enum NamespaceEnum {
      * Namespace for Disambiguation related properties and classes (added with
      * STANBOL-1053)
      */
-    dis("http://stanbol.apache.org/ontology/disambiguation/disambiguation#")
+    dis("http://stanbol.apache.org/ontology/disambiguation/disambiguation#"), 
+    /**
+     * Namespace used for EnhancementProperties
+     * @since 0.12.1
+     */
+    ehprop("http://stanbol.apache.org/ontology/enhancementproperties#")
     ;
     
     String ns;