/** * 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 * @return the execution plan * @deprecated use {@link #calculateExecutionPlan(String, List, Set, Set, Map)} * with <code>null</code> as last argument instead */ @Deprecated public static ImmutableGraph calculateExecutionPlan(String chainName, List<EnhancementEngine> availableEngines, Set<String> optional, Set<String> missing) { return calculateExecutionPlan(chainName, availableEngines, optional, missing, null); } /**
/** * Creates an ExecutionPlan for the parsed chainName in the parsed ImmutableGraph * @param graph the graph * @param chainName the chain name * @return the node representing the ex:ExecutionPlan * @deprecated use {@link #createExecutionPlan(Graph, String, Map)} with * parsing <code>null</code> as last parameter */ @Deprecated public static BlankNodeOrIRI createExecutionPlan(Graph graph,String chainName){ return createExecutionPlan(graph, chainName, null); }
public ExecutionNode(Graph executionPlan, BlankNodeOrIRI node) { this.node = node; this.ep = executionPlan; this.optional = ExecutionPlanHelper.isOptional(ep, node); this.engineName = ExecutionPlanHelper.getEngine(ep, node); } /**
/** * 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"; Graph graph = new IndexedGraph(); writeExecutionNode(graph, createExecutionPlan(graph, name, null), engine.getName(), false, null, enhProps); executionPlan = graph.getImmutableGraph(); }
String engine = getEngine(executionPlan, executionNode); boolean optional = isOptional(executionPlan, executionNode); Set<BlankNodeOrIRI> dependsOn = getDependend(executionPlan, executionNode); log.trace("++ w: {}: {}","setRunning",ExecutionPlanHelper.getEngine(executionPlan, executionNode)); writeLock.lock(); try { log.trace(">> w: {}: {}","setRunning",ExecutionPlanHelper.getEngine(executionPlan, executionNode)); if (completed.contains(executionNode)) { String message = "Unable to set state of ExectionNode '" + executionNode + "'(chain '" log.trace("<< w: {}: {}","setRunning",ExecutionPlanHelper.getEngine(executionPlan, executionNode)); writeLock.unlock();
ExecutionPlanHelper.getExecutable(executionPlan, completed); Collection<String> engines = new ArrayList<String>(executeableNodes.size()); for(BlankNodeOrIRI node : executeableNodes){ engines.add(getEngine(executionPlan, node));
executionPlanNode = ExecutionPlanHelper.getExecutionPlan(ep, chainName); if(executionPlanNode == null){ throw new IllegalArgumentException("The parsed ExectuonPlan graph does not contain an" + Set<BlankNodeOrIRI> executionNodes = getExecutionNodes(ep, executionPlanNode); Set<BlankNodeOrIRI> executions = getExecutions(em, chainExecutionNode); for(BlankNodeOrIRI en : executionNodes) { if(!executions.contains(execution)){ throw new IllegalStateException("Execution '"+execution + "' for ExecutionNode '"+en+"' (engine: '"+getEngine(ep, en) + "') is not part of ChainExecution '" + chainExecutionNode +"' (chain: '"+chainName+")!"); + chainExecutionNode +"' (chain: '"+chainName+") contains" + "Execution '"+e+"' for ExecutionNode '" + en + "' (engine: '"+ExecutionPlanHelper.getEngine(ep, en) + "') that is not part of the pased ExecutionPlan '" + executionPlanNode +"'(chain; '"+chainName+"')!");
/** * Sets the state of the parsed executionNode to completed. This also validates if the new state * confirms to the ExectionPlan (e.g. if all nodes the parsed node depends on are also marked as * completed). * * @param execution * the exection to be marked as running * @throws IllegalArgumentException * if <code>null</code> is parsed as execution node * @throws IllegalStateException * if the parsed execution node can not be marked as completed because some of its * depended nodes are not yet marked as completed. */ public void setCompleted(BlankNodeOrIRI execution) { if(execution == null) { throw new IllegalArgumentException("The parsed em:Execution instance MUST NOT be NULL!"); } writeLock.lock(); BlankNodeOrIRI executionNode = getExecutionNode(execution); log.trace("++ w: {}: {}","setCompleted",getEngine(executionPlan, executionNode)); try { log.trace(">> w: {}: {}","setCompleted",getEngine(executionPlan, executionNode)); setNodeCompleted(executionNode); setExecutionCompleted(executionMetadata, execution, null); } finally { log.trace("<< w: {}: {}","setCompleted",getEngine(executionPlan, executionNode)); writeLock.unlock(); } } /**
/** * Calculates a sorted list of active EnhancementEngines form the given * ExecutinPlan * @param engineManager The engine manager (OSGI service or {@link EnginesTracker}) * @param ep the execution plan * @return */ public static List<EnhancementEngine> getActiveEngines(EnhancementEngineManager engineManager, Graph ep) { List<EnhancementEngine> engines = new ArrayList<EnhancementEngine>(); Set<BlankNodeOrIRI> visited = new HashSet<BlankNodeOrIRI>(); Set<BlankNodeOrIRI> executeable; do { executeable = getExecutable(ep, visited); for(BlankNodeOrIRI node : executeable){ String engineName = getString(ep, node, ENGINE); EnhancementEngine engine = engineManager.getEngine(engineName); if(engine != null){ engines.add(engine); } visited.add(node); } } while(!executeable.isEmpty()); return engines; }
/** * Writes all triples for an ep:ExecutionNode to the parsed {@link Graph}. * An {@link BlankNode} is use for representing the execution node resource. * @param graph the graph to write the triples. MUST NOT be empty * @param epNode the BlankNodeOrIRI 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(Graph, BlankNodeOrIRI, String, boolean, Set, Map)} * with <code>null</code> as last parameter */ @Deprecated public static BlankNodeOrIRI writeExecutionNode(Graph graph,BlankNodeOrIRI epNode, String engineName, boolean optional, Set<BlankNodeOrIRI> dependsOn){ return writeExecutionNode(graph,epNode,engineName,optional,dependsOn, null); } /**
public static Set<BlankNodeOrIRI> getDependend(Graph executionPlan, BlankNodeOrIRI executionNode){ Set<BlankNodeOrIRI> dependend = new HashSet<BlankNodeOrIRI>(); addDependend(dependend, executionPlan, executionNode); return dependend; } public static void addDependend(Collection<BlankNodeOrIRI> collection, Graph executionPlan, BlankNodeOrIRI executionNode){
@Override public List<EnhancementEngine> getActiveEngines() { //This implementation return the list of active engined for the default //Chain in the order they would be executed Chain defaultChain = chainManager.getDefault(); if(defaultChain == null){ throw new IllegalStateException("Currently no enhancement chain is " + "active. Please configure a Chain or enable the default chain"); } ImmutableGraph ep; try { ep = defaultChain.getExecutionPlan(); } catch (ChainException e) { throw new IllegalStateException("Unable to get Execution Plan for " + "default enhancement chain (name: '"+defaultChain.getName()+ "'| class: '"+defaultChain.getClass()+"')!",e); } return ExecutionPlanHelper.getActiveEngines(engineManager,ep); }
/** * 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"; Graph graph = new IndexedGraph(); writeExecutionNode(graph, createExecutionPlan(graph, name, null), engine.getName(), false, null, enhProps); executionPlan = graph.getImmutableGraph(); }
String engine = getEngine(executionPlan, executionNode); boolean optional = isOptional(executionPlan, executionNode); Set<BlankNodeOrIRI> dependsOn = getDependend(executionPlan, executionNode); if (completed.contains(executionNode)) { log.warn("Execution of Engine '{}' for ContentItem {} already "
executionPlanNode = ExecutionPlanHelper.getExecutionPlan(ep, chainName); if(executionPlanNode == null){ throw new IllegalArgumentException("The parsed ExectuonPlan graph does not contain an" + Set<BlankNodeOrIRI> executionNodes = getExecutionNodes(ep, executionPlanNode); Set<BlankNodeOrIRI> executions = getExecutions(em, chainExecutionNode); for(BlankNodeOrIRI en : executionNodes) { if(!executions.contains(execution)){ throw new IllegalStateException("Execution '"+execution + "' for ExecutionNode '"+en+"' (engine: '"+getEngine(ep, en) + "') is not part of ChainExecution '" + chainExecutionNode +"' (chain: '"+chainName+")!"); + chainExecutionNode +"' (chain: '"+chainName+") contains" + "Execution '"+e+"' for ExecutionNode '" + en + "' (engine: '"+ExecutionPlanHelper.getEngine(ep, en) + "') that is not part of the pased ExecutionPlan '" + executionPlanNode +"'(chain; '"+chainName+"')!");
/** * triggers the execution of the next nodes or if * {@link EnhancementJob#isFinished()} notifies the one who registered * the {@link EnhancementJob} with this component. * @param job the enhancement job to process * @return if an Execution event was sent */ protected boolean executeNextNodes(EnhancementJob job) { //getExecutable returns an snapshot so we do not need to lock boolean startedExecution = false; for(BlankNodeOrIRI executable : job.getExecutable()){ if(log.isTraceEnabled()){ log.trace("PREPARE execution of Engine {}", getEngine(job.getExecutionPlan(), job.getExecutionNode(executable))); } Dictionary<String,Object> properties = new Hashtable<String,Object>(); properties.put(PROPERTY_JOB_MANAGER, job); properties.put(PROPERTY_EXECUTION, executable); job.setRunning(executable); if(log.isTraceEnabled()){ log.trace("SHEDULE execution of Engine {}", getEngine(job.getExecutionPlan(), job.getExecutionNode(executable))); } eventAdmin.postEvent(new Event(TOPIC_JOB_MANAGER,properties)); startedExecution = true; } return startedExecution; } /**
/** * Getter for the executionNodes * * @return */ public Set<ExecutionNode> getExecutionNodes() { if (_executionNodes == null) { ImmutableGraph ep; try { ep = chain.getExecutionPlan(); } catch (ChainException e) { ep = null; } if (ep != null) { _executionNodes = new LinkedHashSet<ExecutionNode>(); Set<BlankNodeOrIRI> processed = new HashSet<BlankNodeOrIRI>(); Set<BlankNodeOrIRI> next; do { next = ExecutionPlanHelper.getExecutable(ep, processed); for (BlankNodeOrIRI node : next) { _executionNodes.add(new ExecutionNode(ep, node)); } processed.addAll(next); } while (!next.isEmpty()); } } return _executionNodes; }
/** * Writes all triples for an ep:ExecutionNode to the parsed {@link Graph}. * An {@link BlankNode} is use for representing the execution node resource. * @param graph the graph to write the triples. MUST NOT be empty * @param epNode the BlankNodeOrIRI 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(Graph, BlankNodeOrIRI, String, boolean, Set, Map)} * with <code>null</code> as last parameter */ @Deprecated public static BlankNodeOrIRI writeExecutionNode(Graph graph,BlankNodeOrIRI epNode, String engineName, boolean optional, Set<BlankNodeOrIRI> dependsOn){ return writeExecutionNode(graph,epNode,engineName,optional,dependsOn, null); } /**
public static Set<BlankNodeOrIRI> getDependend(Graph executionPlan, BlankNodeOrIRI executionNode){ Set<BlankNodeOrIRI> dependend = new HashSet<BlankNodeOrIRI>(); addDependend(dependend, executionPlan, executionNode); return dependend; } public static void addDependend(Collection<BlankNodeOrIRI> collection, Graph executionPlan, BlankNodeOrIRI executionNode){
BlankNodeOrIRI epNode = createExecutionPlan(ep, chainName, enhProps != null ? enhProps.get(null) : null); Integer prevOrder = null; for(String name : missing){ boolean optionalMissing = optional.contains(name); BlankNodeOrIRI node = writeExecutionNode(ep, epNode, name, optionalMissing, null, enhProps == null ? null : enhProps.get(name)); if(!optionalMissing){ BlankNodeOrIRI executionNode = writeExecutionNode(ep, epNode, name, optional.contains(name), prev, enhProps == null ? null : enhProps.get(name));