/*
* JaamSim Discrete Event Simulation
* Copyright (C) 2014 Ausenco Engineering Canada Inc.
* Copyright (C) 2016 JaamSim Software 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.ProcessFlow;
import java.util.ArrayList;
import com.jaamsim.Graphics.DisplayEntity;
import com.jaamsim.Samples.SampleInput;
import com.jaamsim.Samples.SampleProvider;
import com.jaamsim.basicsim.Entity;
import com.jaamsim.input.EntityInput;
import com.jaamsim.input.InputAgent;
import com.jaamsim.input.Keyword;
import com.jaamsim.input.KeywordIndex;
import com.jaamsim.input.Output;
import com.jaamsim.input.Vec3dInput;
import com.jaamsim.math.Vec3d;
import com.jaamsim.units.DimensionlessUnit;
import com.jaamsim.units.DistanceUnit;
public abstract class LinkedService extends LinkedDevice implements QueueUser {
@Keyword(description = "The position of the entity being processed relative to the processor.",
exampleList = {"1.0 0.0 0.01 m"})
protected final Vec3dInput processPosition;
@Keyword(description = "The queue in which the waiting DisplayEntities will be placed.",
exampleList = {"Queue1"})
protected final EntityInput<Queue> waitQueue;
@Keyword(description = "An expression returning a dimensionless integer value that can be "
+ "used to determine which of the queued entities is eligible for "
+ "processing.",
exampleList = {"this.obj.Attrib1"})
protected final SampleInput match;
private Integer matchValue;
{
stateGraphics.setHidden(false);
workingStateListInput.setHidden(false);
processPosition = new Vec3dInput("ProcessPosition", "Key Inputs", new Vec3d(0.0d, 0.0d, 0.01d));
processPosition.setUnitType(DistanceUnit.class);
this.addInput(processPosition);
waitQueue = new EntityInput<>(Queue.class, "WaitQueue", "Key Inputs", null);
waitQueue.setRequired(true);
this.addInput(waitQueue);
match = new SampleInput("Match", "Key Inputs", null);
match.setUnitType(DimensionlessUnit.class);
match.setEntity(this);
this.addInput(match);
}
public LinkedService() {}
@Override
public void earlyInit() {
super.earlyInit();
matchValue = null;
}
@Override
public void addEntity(DisplayEntity ent) {
if (isTraceFlag()) trace(0, "addEntity(%s)", ent);
// If there is no queue, then process the entity immediately
if (waitQueue.getValue() == null) {
super.addEntity(ent);
return;
}
// Add the entity to the queue
waitQueue.getValue().addEntity(ent);
}
// ********************************************************************************************
// SELECTING AN ENTITY FROM THE WAIT QUEUE
// ********************************************************************************************
/**
* Removes the next entity to be processed from the queue.
* If the specified match value is not null, then only the queued entities
* with the same match value are eligible to be removed.
* @param m - match value.
* @return next entity for processing.
*/
protected DisplayEntity getNextEntityForMatch(Integer m) {
DisplayEntity ent = waitQueue.getValue().removeFirstForMatch(m);
this.registerEntity(ent);
return ent;
}
/**
* Returns a value which determines which of the entities in the queue are
* eligible to be removed. Returns null if the Match keyword has not been set.
* @param simTime - present simulation time in seconds.
* @return match value.
*/
protected Integer getNextMatchValue(double simTime) {
SampleProvider samp = match.getValue();
if (samp == null)
return null;
return Integer.valueOf((int)samp.getNextSample(simTime));
}
protected void setMatchValue(Integer m) {
matchValue = m;
}
protected Integer getMatchValue() {
return matchValue;
}
// ********************************************************************************************
// WAIT QUEUE
// ********************************************************************************************
public void addQueue(Queue que) {
if (waitQueue.getHidden()) {
return;
}
ArrayList<String> toks = new ArrayList<>();
toks.add(que.getName());
KeywordIndex kw = new KeywordIndex(waitQueue.getKeyword(), toks, null);
InputAgent.apply(this, kw);
}
@Override
public ArrayList<Queue> getQueues() {
ArrayList<Queue> ret = new ArrayList<>();
if (waitQueue.getValue() != null)
ret.add(waitQueue.getValue());
return ret;
}
@Override
public void queueChanged() {
if (isTraceFlag()) trace(0, "queueChanged");
this.startStep();
}
// ********************************************************************************************
// DEVICE METHODS
// ********************************************************************************************
@Override
protected void updateProgress(double dt) {}
@Override
protected void processChanged() {}
@Override
protected boolean isNewStepReqd(boolean completed) {
return completed;
}
@Override
protected void setProcessStopped() {}
// ********************************************************************************************
// GRAPHICS
// ********************************************************************************************
protected final void moveToProcessPosition(DisplayEntity ent) {
Vec3d pos = this.getGlobalPosition();
pos.add3(processPosition.getValue());
ent.setGlobalPosition(pos);
}
@Override
public ArrayList<Entity> getSourceEntities() {
ArrayList<Entity> ret = super.getSourceEntities();
ArrayList<Queue> queues = getQueues();
ret.addAll(queues);
return ret;
}
// ********************************************************************************************
// OUTPUTS
// ********************************************************************************************
@Output(name = "MatchValue",
description = "The present value to be matched in the queue.",
sequence = 0)
public Integer getMatchValue(double simTime) {
return matchValue;
}
}