/* * 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.input.Input; import com.jaamsim.input.InputAgent; import com.jaamsim.input.InputErrorException; import com.jaamsim.input.Keyword; import com.jaamsim.input.KeywordIndex; /** * Group class - for storing a list of objects * * For input of the form <object> <keyword> <value>: * If the group appears as the object in a line of input, then the keyword and value applies to each member of the group. * If the group appears as the value in a line of input, then the list of objects is used as the value. */ public class Group extends Entity { private Class<?> type; private final ArrayList<KeywordIndex> groupKeywordValues; private final ArrayList<Entity> list; // list of objects in group @Keyword(description = "The list of objects included in the group.", example = "Group1 List { DisplayEntity1 DisplayEntity2 }") private final GroupListInput groupListInput; @Keyword(description = "A list of additional objects to be included in " + "the already existing list of group objects. The added " + "objects will inherit all inputs previously set for the group.", example = "Group1 AppendList { DisplayEntity3 DisplayEntity4 }") private final GroupAppendListInput groupAppendListInput; @Keyword(description = "The object type for the group.", example = "Group1 GroupType { DisplayEntity }") private final GroupTypeInput groupTypeInput; { groupListInput = new Group.GroupListInput(); this.addInput(groupListInput); groupAppendListInput = new Group.GroupAppendListInput(); this.addInput(groupAppendListInput); groupTypeInput = new Group.GroupTypeInput(); this.addInput(groupTypeInput); } public Group() { list = new ArrayList<>(); type = null; groupKeywordValues = new ArrayList<>(); } private class GroupListInput extends Input<String> { public GroupListInput() { super("List", "Key Inputs", null); } @Override public void parse(KeywordIndex kw) { // If adding to the list if( kw.getArg( 0 ).equals( "++" ) ) { ArrayList<String> input = new ArrayList<>(kw.numArgs()-1); for (int i = 1; i < kw.numArgs(); i++) input.add(kw.getArg(i)); ArrayList<Entity> addedValues = Input.parseEntityList(input, Entity.class, true); for( Entity ent : addedValues ) { if( list.contains( ent ) ) throw new InputErrorException(INP_ERR_NOTUNIQUE, ent.getName()); list.add( ent ); // set values of appended objects to the group values if ( type != null ) { for ( int j = 0; j < groupKeywordValues.size(); j++ ) { KeywordIndex grpkw = groupKeywordValues.get(j); InputAgent.apply(ent, grpkw); } } } } // If removing from the list else if( kw.getArg( 0 ).equals( "--" ) ) { ArrayList<String> input = new ArrayList<>(kw.numArgs()-1); for (int i = 1; i < kw.numArgs(); i++) input.add(kw.getArg(i)); ArrayList<Entity> removedValues = Input.parseEntityList(input, Entity.class, true); for( Entity ent : removedValues ) { if( ! list.contains( ent ) ) InputAgent.logWarning( "Could not remove " + ent + " from " + this.getKeyword() ); list.remove( ent ); } } // Otherwise, just set the list normally else { ArrayList<Entity> temp = Input.parseEntityList(kw, Entity.class, true); list.clear(); list.addAll(temp); } Group.this.checkType(); } @Override public void setTokens(KeywordIndex kw) { isDef = false; String[] args = kw.getArgArray(); if (args.length > 0) { // Consider the following input case: // Group1 List { ++ Entity1 ... if (args[0].equals( "++" )) { this.addTokens(args); return; } // Consider the following input case: // Group1 List { -- Entity1 ... if (args[0].equals( "--" )) { if (this.removeTokens(args)) return; } } valueTokens = args; } } private class GroupAppendListInput extends Input<String> { public GroupAppendListInput() { super("AppendList", "Key Inputs", null); } @Override public void parse(KeywordIndex kw) { int originalListSize = list.size(); ArrayList<Entity> temp = Input.parseEntityList(kw, Entity.class, true); for (Entity each : temp) { if (!list.contains(each)) list.add(each); } Group.this.checkType(); // set values of appended objects to the group values if ( type != null ) { for ( int i = originalListSize; i < list.size(); i ++ ) { Entity ent = list.get( i ); for ( int j = 0; j < groupKeywordValues.size(); j++ ) { KeywordIndex grpkw = groupKeywordValues.get(j); InputAgent.apply(ent, grpkw); } } } } } private class GroupTypeInput extends Input<String> { public GroupTypeInput() { super("GroupType", "Key Inputs", null); } @Override public void parse(KeywordIndex kw) { Input.assertCount(kw, 1); type = Input.parseEntityType(kw.getArg(0)); Group.this.checkType(); } } public void saveGroupKeyword(KeywordIndex kw) { ArrayList<String> toks = new ArrayList<>(kw.numArgs()); for (int i = 0; i < kw.numArgs(); i++) toks.add(kw.getArg(i)); KeywordIndex saved = new KeywordIndex(kw.keyword, toks, kw.context); groupKeywordValues.add(saved); // If there can never be elements in the group, throw a warning if( type == null && list.size() == 0 ) { InputAgent.logWarning("The group %s has no elements to apply keyword: %s", this, kw.keyword); } } private void checkType() { if (type == null) return; for (Entity each : this.getList()) { if (!type.isInstance(each)) throw new InputErrorException("The Entity: %s is not of Type: %s", each, type.getSimpleName()); } } // ****************************************************************************************** // ACCESSING // ****************************************************************************************** public ArrayList<Entity> getList() { return list; } }