/* * JaamSim Discrete Event Simulation * Copyright (C) 2002-2011 Ausenco Engineering Canada 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 com.jaamsim.basicsim; import java.util.ArrayList; import com.jaamsim.events.EventManager; import com.jaamsim.events.ProcessTarget; import com.jaamsim.input.FileInput; import com.jaamsim.input.InputAgent; import com.jaamsim.input.Keyword; import com.jaamsim.input.ValueInput; import com.jaamsim.units.TimeUnit; public class ScriptEntity extends Entity { @Keyword(description = "The name of the script file for the script entity.", example = "ScriptEntity Script { test.scr }") private final FileInput scriptFileName; @Keyword(description = "The Time keyword appears inside the script file. The value represents the simulation " + "time at which the next set of commands in the script are implemented.", example = "ScriptEntity Time { 24.0 h }") private final ValueInput scriptTime; // the time that has been read in the script private ArrayList<ArrayList<String>> tokens; private int lastTokenIdx; { scriptFileName = new FileInput( "Script", "Key Inputs", null ); scriptFileName.setRequired(true); this.addInput( scriptFileName ); scriptTime = new ValueInput("Time", "Key Inputs", 0.0d); scriptTime.setUnitType(TimeUnit.class); scriptTime.setValidRange(0.0d, Double.POSITIVE_INFINITY); this.addInput(scriptTime); } public ScriptEntity() { tokens = new ArrayList<>(); } @Override public void earlyInit() { super.earlyInit(); tokens.clear(); lastTokenIdx = -1; // Open the script file tokens = FileInput.getTokensFromURI(scriptFileName.getValue()); boolean record = InputAgent.recordEdits(); InputAgent.setRecordEdits(false); // Read records until a Time record is read // Restarts will work for simple scripts with a record at Time 0 // Restarts should work for all scripts provided the script has initial inputs before the first Time record for (lastTokenIdx++; lastTokenIdx < tokens.size(); lastTokenIdx++) { InputAgent.processKeywordRecord(tokens.get(lastTokenIdx), null); if( tokens.get(lastTokenIdx).get( 0 ).equals( this.getName() ) ) { if( tokens.get( lastTokenIdx ).get( 1 ).equals( "Time" ) ) { lastTokenIdx--; InputAgent.setRecordEdits(record); return; } } } } private static class ScriptTarget extends ProcessTarget { final ScriptEntity script; ScriptTarget(ScriptEntity script) { this.script = script; } @Override public String getDescription() { return script.getName() + ".doScript"; } @Override public void process() { script.doScript(); } } private final ProcessTarget targ = new ScriptTarget(this); @Override public void startUp() { doScript(); } /** * Read the script */ public void doScript() { boolean record = InputAgent.recordEdits(); InputAgent.setRecordEdits(false); for (lastTokenIdx++; lastTokenIdx < tokens.size(); lastTokenIdx++) { InputAgent.processKeywordRecord(tokens.get(lastTokenIdx), null); // If a "Time" record was read, then wait until the time long delayTicks = EventManager.current().secondsToNearestTick(scriptTime.getValue()) - getSimTicks(); if (delayTicks > 0) { scheduleProcessTicks(delayTicks, 0, targ); break; } } InputAgent.setRecordEdits(record); } }