/** * Copyright 2010 JBoss Inc * * Licensed 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.drools.simulation.impl; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.PriorityQueue; import java.util.Set; import java.util.concurrent.TimeUnit; import org.drools.StatefulSession; import org.drools.command.Command; import org.drools.command.Context; import org.drools.command.ContextManager; import org.drools.command.KnowledgeContextResolveFromContextCommand; import org.drools.command.NewStatefulKnowledgeSessionCommand; import org.drools.command.builder.KnowledgeBuilderAddCommand; import org.drools.command.impl.ContextImpl; import org.drools.command.impl.GenericCommand; import org.drools.impl.StatefulKnowledgeSessionImpl; import org.drools.reteoo.ReteooStatefulSession; import org.drools.reteoo.ReteooWorkingMemory; import org.drools.runtime.StatefulKnowledgeSession; import org.drools.simulation.Path; import org.drools.simulation.Simulation; import org.drools.simulation.Step; import org.drools.time.SessionPseudoClock; public class Simulator implements ContextManager { private PriorityQueue<Step> queue; private SimulationImpl simulation; // private SessionPseudoClock clock; private long startTime; private Context root; private Map<String, Context> contexts; private String ROOT = "ROOT"; private Set<StatefulKnowledgeSession> ksessions; private CommandExecutionHandler executionHandler = new DefaultCommandExecutionHandler(); public Simulator(Simulation simulation, //SessionPseudoClock clock, long startTime) { // this.clock = clock; this.ksessions = new HashSet<StatefulKnowledgeSession>(); this.startTime = startTime; this.simulation = (SimulationImpl) simulation; this.root = new ContextImpl( ROOT, this ); this.contexts = new HashMap<String, Context>(); this.contexts.put( ROOT, this.root ); Map<String, Path> paths = this.simulation.getPaths(); // calculate capacity int capacity = 0; for ( Path path : paths.values() ) { this.contexts.put( path.getName(), new ContextImpl( path.getName(), this, root ) ); capacity += path.getSteps().size(); } if ( capacity == 0 ) { return; } this.queue = new PriorityQueue( capacity, new Comparator<Step>() { public int compare(Step s1, Step s2) { return (int) (s1.getTemporalDistance() - s2.getTemporalDistance()); } } ); for ( Path path : paths.values() ) { for ( Step step : path.getSteps() ) this.queue.add( step ); } } public void run() { Step step; while ( (step = executeNextStep()) != null ) { } } public Step executeNextStep() { if ( this.queue.isEmpty() ) { return null; } StepImpl step = (StepImpl) this.queue.remove(); PathImpl path = (PathImpl) step.getPath(); Context pathContext = this.contexts.get( path.getName() ); // increment the clock for all the registered ksessions for ( StatefulKnowledgeSession ksession : this.ksessions ) { SessionPseudoClock clock = (SessionPseudoClock) ksession.getSessionClock(); long newTime = this.startTime + step.getTemporalDistance(); long currentTime = clock.getCurrentTime(); clock.advanceTime( (currentTime + (newTime - currentTime)), TimeUnit.MICROSECONDS ); } for ( Command cmd : step.getCommands() ) { if ( cmd instanceof KnowledgeContextResolveFromContextCommand) { if ( ((KnowledgeContextResolveFromContextCommand)cmd).getCommand() instanceof NewStatefulKnowledgeSessionCommand ) { // instantiate the ksession, set it's clock and register it StatefulKnowledgeSession ksession = ( StatefulKnowledgeSession ) executionHandler.execute( (GenericCommand) cmd, pathContext ); if ( ksession != null ) { SessionPseudoClock clock = (SessionPseudoClock) ksession.getSessionClock(); if ( clock.getCurrentTime() == 0 ) { clock.advanceTime( startTime, TimeUnit.MILLISECONDS ); } this.ksessions.add( ksession ); } } else if ( cmd instanceof GenericCommand) { executionHandler.execute( (GenericCommand) cmd, pathContext ); } } else if ( cmd instanceof GenericCommand) { executionHandler.execute( (GenericCommand) cmd, pathContext ); } } return step; } public void setCommandExecutionHandler(CommandExecutionHandler executionHandler) { this.executionHandler = executionHandler; } public Context getContext(String identifier) { return this.contexts.get( identifier ); } public Context getDefaultContext() { return this.root; } public Simulation getSimulation() { return this.simulation; } public static interface CommandExecutionHandler { public Object execute(GenericCommand command, Context context); } public static class DefaultCommandExecutionHandler implements CommandExecutionHandler { public Object execute(GenericCommand command, Context context) { return command.execute( context ); } } // public static interface CommandExecutorService<T> { // T execute(Command command); // } // // public static class SimulatorCommandExecutorService<T> implements CommandExecutorService { // Map map = new HashMap() { // { // put( KnowledgeBuilderAddCommand.class, null); // } // }; // // public T execute(Command command) { // return null; // } // } // // public static interface CommandContextAdapter { // Context getContext(); // } // // public static class KnowledgeBuilderCommandContextAdapter implements CommandContextAdapter { // // public Context getContext() { // return new KnowledgeBuilderCommandContext(); // } // // } // public void runUntil(Step step) { // // } // // public void runForTemporalDistance(long distance) { // // } }