implemented core planning functionality where activity with all child

elements is created programmatically and the time and values of the
changes is set by the programmmer. Note, that the persistence and xml
serialization is not implemented yet.
This commit is contained in:
msmock 2015-05-22 21:04:37 +02:00
parent 74366ea8a5
commit cce0fdc50b
16 changed files with 999 additions and 257 deletions

View File

@ -109,6 +109,7 @@ public class ModelGenerator {
public static final long STATE_TIME_10 = 10L;
public static final long STATE_TIME_20 = 20L;
public static final long STATE_TIME_30 = 30L;
public static final long STATE_TIME_40 = 40L;
public static final Double STATE_FLOAT_TIME_0 = 0.0D;
public static final Double STATE_FLOAT_TIME_10 = 10.0D;

View File

@ -23,7 +23,8 @@ public enum State {
CREATED("Created"), //$NON-NLS-1$
OPEN("Open"), //$NON-NLS-1$
EXECUTION("Execution"), //$NON-NLS-1$
CLOSED("Closed"); //$NON-NLS-1$
CLOSED("Closed"), //$NON-NLS-1$
PLANNED("Planned"); //$NON-NLS-1$
private String state;

View File

@ -41,6 +41,9 @@ public class Tags {
public static final String FILE = "file";
public static final String BAG = "Bag";
public static final String AUDIT = "Audit";
public static final String ACTIVITY = "Activity";
public static final String ACTION = "Action";
public class Audit {
public static final String ID = Tags.ID;

View File

@ -8,6 +8,7 @@ import li.strolch.model.GroupedParameterizedElement;
import li.strolch.model.Locator;
import li.strolch.model.Locator.LocatorBuilder;
import li.strolch.model.Resource;
import li.strolch.model.State;
import li.strolch.model.StrolchElement;
import li.strolch.model.StrolchRootElement;
import li.strolch.model.timevalue.IValueChange;
@ -21,38 +22,26 @@ import org.w3c.dom.Element;
* {@link Activity} applies {@link IValueChange} objects at the start and end
* time of the {@link Activity}.
*
* @author Martin Smock <smock.martin@gmail.com>
* @author Martin Smock <martin.smock@bluewin.ch>
*/
public class Action extends GroupedParameterizedElement implements IActivityElement {
protected static final long serialVersionUID = 1L;
protected Long start;
protected Long end;
protected Long end;
protected String resourceId;
protected final List<IValueChange<?>> startChanges = new ArrayList<>();
protected final List<IValueChange<?>> endChanges = new ArrayList<>();
protected ActionState state = ActionState.CREATED;
protected Activity parent;
/**
* no argument constructor
*/
protected Action() {
super();
}
protected State state = State.CREATED;
protected Activity parent;
private String resourceType;
/**
* Default constructor
*
* @param id
* @param name
* @param type
*/
public Action(String id, String name, String type) {
super(id, name, type);
}
@ -103,7 +92,40 @@ public class Action extends GroupedParameterizedElement implements IActivityElem
}
/**
* @param e
* @return the current <code>State</code> of the a<code>Action</code>
*/
public State getState() {
return state;
}
/**
* @param state
* the target <code>State</code> of the a<code>Action</code>
*/
public void setState(State state) {
this.state = state;
}
/**
* @return the type of the <code>Resource</code> this <code>Action</code>
* acts on
*/
public String getResourceType() {
return this.resourceType;
}
/**
* @param resourceType
*/
public void setResourceType(String resourceType) {
this.resourceType = resourceType;
}
/**
* @param add
* <code>IValueChange</code> to be applied to the
* <code>Resource</code> to time <code>Action.getStart()<code>
*
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean addStartChange(IValueChange<?> change) {
@ -112,19 +134,28 @@ public class Action extends GroupedParameterizedElement implements IActivityElem
/**
* @param change
* the {@link IValueChange} the action applies at end time
* <code>IValueChange</code> to be applied to the
* <code>Resource</code> at time <code>Action.getEnd()<code>
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean addEndChange(IValueChange<?> change) {
return endChanges.add(change);
}
/**
* @return the list of <code>IValueChange</code> attached to the
* <code>Action</code> start
*/
public List<IValueChange<?>> getStartChanges() {
return new ArrayList<IValueChange<?>>(startChanges);
return startChanges;
}
/**
* @return the list of <code>IValueChange</code> attached to the
* <code>Action</code> end
*/
public List<IValueChange<?>> getEndChanges() {
return new ArrayList<IValueChange<?>>(endChanges);
return endChanges;
}
@Override
@ -135,37 +166,48 @@ public class Action extends GroupedParameterizedElement implements IActivityElem
@Override
public StrolchElement getParent() {
// TODO Auto-generated method stub
return null;
return parent;
}
@Override
public StrolchRootElement getRootElement() {
// TODO Auto-generated method stub
return null;
return (parent == null) ? null : parent.getRootElement();
}
@Override
public boolean isRootElement() {
// TODO Auto-generated method stub
return false;
}
@Override
public StrolchElement getClone() {
// TODO Auto-generated method stub
return null;
Action clone = new Action(getId(), getName(), getType());
clone.setDbid(getDbid());
clone.setEnd(end);
clone.setResourceId(resourceId);
clone.setResourceType(resourceType);
clone.setStart(start);
clone.setState(state);
for (IValueChange<?> change : getStartChanges()) {
clone.startChanges.add(change.getClone());
}
for (IValueChange<?> change : getEndChanges()) {
clone.endChanges.add(change.getClone());
}
return clone;
}
@Override
public Locator getLocator() {
// TODO Auto-generated method stub
return null;
LocatorBuilder lb = new LocatorBuilder();
this.parent.fillLocator(lb);
fillLocator(lb);
return lb.build();
}
@Override
protected void fillLocator(LocatorBuilder locatorBuilder) {
// TODO Auto-generated method stub
locatorBuilder.append(this.id);
}
@Override
@ -177,6 +219,10 @@ public class Action extends GroupedParameterizedElement implements IActivityElem
builder.append(this.name);
builder.append(", type=");
builder.append(this.type);
builder.append(", resourceId=");
builder.append(this.resourceId);
builder.append(", state=");
builder.append(this.state);
builder.append(", start=");
builder.append(this.start);
builder.append(", end=");
@ -185,12 +231,9 @@ public class Action extends GroupedParameterizedElement implements IActivityElem
return builder.toString();
}
public ActionState getState() {
return state;
}
public void setState(ActionState state) {
this.state = state;
@Override
public void setParent(Activity activity) {
this.parent = activity;
}
}

View File

@ -1,28 +0,0 @@
/*
* Copyright 2013 Martin Smock <smock.martin@gmail.com>
*
* 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 li.strolch.model.activity;
/**
* Traces the state of the {@link Action} in the sequence of creation, scheduling and planning.
*
* @author Martin Smock <smock.martin@gmail.com>
*/
public enum ActionState {
CREATED,
SCHEDULED, // when the start and end time is set and the value changes have been attached
PLANNED; // when the value changes have been registered to the states of the resources
}

View File

@ -15,14 +15,20 @@
*/
package li.strolch.model.activity;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import li.strolch.exception.StrolchException;
import li.strolch.model.GroupedParameterizedElement;
import li.strolch.model.Locator;
import li.strolch.model.Locator.LocatorBuilder;
import li.strolch.model.State;
import li.strolch.model.StrolchElement;
import li.strolch.model.StrolchRootElement;
import li.strolch.model.Tags;
import li.strolch.model.visitor.StrolchRootElementVisitor;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@ -31,61 +37,142 @@ import org.w3c.dom.Element;
* Parameterized object grouping a collection of {@link Activity} and
* {@link Action} objects defining the process to be scheduled
*
* @author Martin Smock <smock.martin@gmail.com>
* @author Martin Smock <martin.smock@bluewin.ch>
*/
public class Activity extends GroupedParameterizedElement implements IActivityElement {
public class Activity extends GroupedParameterizedElement implements IActivityElement, StrolchRootElement {
private static final long serialVersionUID = 1L;
protected List<IActivityElement> elements = new ArrayList<>();
protected Activity parent;
public boolean addElement(IActivityElement e) {
return elements.add(e);
public Activity(String id, String name, String type) {
super(id, name, type);
}
public List<IActivityElement> getElements() {
// use a LinkedHashMap since we will iterate elements in the order added and
// lookup elements by ID
protected Map<String, IActivityElement> elements = new LinkedHashMap<String, IActivityElement>();
/**
* add an activity element to the <code>LinkedHashMap</code> of
* <code>IActivityElements</code>
*
* @param activityElement
* @return the element added
*/
public IActivityElement addElement(IActivityElement activityElement) {
String id = activityElement.getId();
if (id == null)
throw new StrolchException("Cannot add IActivityElement without id.");
else if (elements.containsKey(id))
throw new StrolchException("Activiy " + getLocator() + " already contains an activity element with id = " + id);
else {
activityElement.setParent(this);
return elements.put(activityElement.getId(), activityElement);
}
}
/**
* get <code>IActivityElement</code> by id
*
* @param id
* the id of the <code>IActivityElement</code>
* @return IActivityElement
*/
public IActivityElement getElement(String id) {
return elements.get(id);
}
/**
* @return get the <code>LinkedHashMap</code> of
* <code>IActivityElements</code>
*/
public Map<String, IActivityElement> getElements() {
return elements;
}
/**
* @return the iterator for entries, which include the id as key and the
* {@link IActivityElement} as value
*/
public Iterator<Entry<String, IActivityElement>> elementIterator() {
return elements.entrySet().iterator();
}
public Long getStart() {
Long start = Long.MAX_VALUE;
Iterator<Entry<String, IActivityElement>> elementIterator = elementIterator();
while (elementIterator.hasNext()) {
IActivityElement action = elementIterator.next().getValue();
start = Math.min(start, action.getStart());
}
return start;
}
public Long getEnd() {
Long end = 0L;
Iterator<Entry<String, IActivityElement>> elementIterator = elementIterator();
while (elementIterator.hasNext()) {
IActivityElement action = elementIterator.next().getValue();
end = Math.max(end, action.getEnd());
}
return end;
}
public State getState() {
State state = State.PLANNED;
Iterator<Entry<String, IActivityElement>> elementIterator = elementIterator();
while (elementIterator.hasNext()) {
IActivityElement child = elementIterator.next().getValue();
State childState = child.getState();
if (childState.ordinal() < state.ordinal()) {
state = childState;
}
}
return state;
}
@Override
public Locator getLocator() {
// TODO Auto-generated method stub
return null;
}
@Override
public Element toDom(Document doc) {
// TODO Auto-generated method stub
return null;
}
@Override
public StrolchElement getParent() {
// TODO Auto-generated method stub
return null;
}
@Override
public StrolchRootElement getRootElement() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isRootElement() {
// TODO Auto-generated method stub
return false;
}
@Override
public StrolchElement getClone() {
// TODO Auto-generated method stub
return null;
LocatorBuilder lb = new LocatorBuilder();
fillLocator(lb);
return lb.build();
}
@Override
protected void fillLocator(LocatorBuilder locatorBuilder) {
// TODO Auto-generated method stub
locatorBuilder.append(Tags.ACTIVITY).append(getType()).append(getId());
}
@Override
public Element toDom(Document doc) {
throw new StrolchException("not implemented yet");
}
@Override
public StrolchElement getParent() {
return parent;
}
@Override
public StrolchRootElement getRootElement() {
return (parent == null) ? null : parent.getRootElement();
}
@Override
public boolean isRootElement() {
return (parent == null);
}
@Override
public StrolchElement getClone() {
Activity clone = new Activity(id, name, type);
Iterator<Entry<String, IActivityElement>> elementIterator = elementIterator();
while (elementIterator.hasNext()) {
Entry<String, IActivityElement> next = elementIterator.next();
clone.elements.put(next.getKey(), (IActivityElement) next.getValue().getClone());
}
return clone;
}
@Override
@ -97,9 +184,24 @@ public class Activity extends GroupedParameterizedElement implements IActivityEl
builder.append(this.name);
builder.append(", type=");
builder.append(this.type);
builder.append(", state=");
builder.append(this.getState());
builder.append(", start=");
builder.append(this.getStart());
builder.append(", end=");
builder.append(this.getEnd());
builder.append("]");
return builder.toString();
}
@Override
public <T> T accept(StrolchRootElementVisitor<T> visitor) {
throw new StrolchException("not implemented yet");
}
@Override
public void setParent(Activity activity) {
this.parent = activity;
}
}

View File

@ -15,12 +15,23 @@
*/
package li.strolch.model.activity;
import li.strolch.model.State;
import li.strolch.model.StrolchElement;
/**
* Marker for all child elememts of {@link Activity} objects
* Marker for all child elements of {@link Activity} objects
*
* @author Martin Smock <smock.martin@gmail.com>
* @author Martin Smock <martin.smock@bluewin.ch>
*
*/
public interface IActivityElement {
public interface IActivityElement extends StrolchElement {
Long getStart();
Long getEnd();
State getState();
void setParent(Activity activity);
}

View File

@ -59,5 +59,10 @@ public interface IValueChange<T extends IValue> {
* made to a {@link TimeVariable}.
*/
IValueChange<T> getInverse();
/**
* @return a copy of this
*/
IValueChange<T> getClone();
}

View File

@ -142,4 +142,10 @@ public class ValueChange<T extends IValue> implements IValueChange<T>, Serializa
this.stateId = id;
}
@SuppressWarnings("unchecked")
@Override
public IValueChange<T> getClone() {
return new ValueChange(time, value);
}
}

View File

@ -0,0 +1,52 @@
package li.strolch.model.activity;
import static li.strolch.model.ModelGenerator.STATE_INTEGER_ID;
import static li.strolch.model.ModelGenerator.STATE_TIME_10;
import static li.strolch.model.ModelGenerator.STATE_TIME_30;
import li.strolch.model.timevalue.IValueChange;
import li.strolch.model.timevalue.impl.IntegerValue;
import li.strolch.model.timevalue.impl.ValueChange;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class ActionTest {
Action action;
/**
* initialize the resources with states and the activity with 2 actions.
*/
@Before
public void init() {
// create action
action = new Action("action_1", "Action 1", "Use");
action.setStart(STATE_TIME_10);
action.setEnd(STATE_TIME_30);
IValueChange<IntegerValue> startChange = new ValueChange<>(action.getStart(), new IntegerValue(1));
startChange.setStateId(STATE_INTEGER_ID);
action.addStartChange(startChange);
IValueChange<IntegerValue> endChange = new ValueChange<>(action.getEnd(), new IntegerValue(-1));
endChange.setStateId(STATE_INTEGER_ID);
action.addEndChange(endChange);
}
@Test
public void testClone() {
Action clone = (Action) action.getClone();
Assert.assertEquals(action.toString(), clone.toString());
Assert.assertEquals(action.startChanges.size(), clone.startChanges.size());
Assert.assertEquals(action.endChanges.size(), clone.endChanges.size());
for (int i = 0; i < action.startChanges.size(); i++) {
Assert.assertEquals(action.startChanges.get(i).getTime(), clone.startChanges.get(i).getTime());
Assert.assertEquals(action.startChanges.get(i).getValue(), clone.startChanges.get(i).getValue());
}
for (int i = 0; i < action.endChanges.size(); i++) {
Assert.assertEquals(action.endChanges.get(i).getTime(), clone.endChanges.get(i).getTime());
Assert.assertEquals(action.endChanges.get(i).getValue(), clone.endChanges.get(i).getValue());
}
}
}

View File

@ -0,0 +1,106 @@
package li.strolch.model.activity;
import static li.strolch.model.ModelGenerator.STATE_TIME_10;
import static li.strolch.model.ModelGenerator.STATE_TIME_20;
import static li.strolch.model.ModelGenerator.STATE_TIME_30;
import static li.strolch.model.ModelGenerator.STATE_TIME_40;
import li.strolch.exception.StrolchException;
import li.strolch.model.State;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class ActivityTest {
Activity activity, childActivity;
Action action_1, action_2, action_3;
/**
* initialize the resources with states and the activity with 2 actions.
*/
@Before
public void init() {
// create activity element
activity = new Activity("activity", "Activity", "mayorType");
// create action 1
action_1 = new Action("action_1", "Action 1", "Use");
action_1.setStart(STATE_TIME_10);
action_1.setEnd(STATE_TIME_20);
action_1.setState(State.CREATED);
activity.addElement(action_1);
childActivity = new Activity("child_activity", "Child Activity", "childType");
// create action 2
action_2 = new Action("action_2", "Action 2", "Use");
action_2.setStart(STATE_TIME_20);
action_2.setEnd(STATE_TIME_30);
action_2.setState(State.PLANNED);
childActivity.addElement(action_2);
// create action 3
action_3 = new Action("action_3", "Action 3", "Use");
action_3.setStart(STATE_TIME_20);
action_3.setEnd(STATE_TIME_40);
action_3.setState(State.CREATED);
childActivity.addElement(action_3);
activity.addElement(childActivity);
Assert.assertEquals(2, activity.getElements().size());
Assert.assertEquals(2, childActivity.getElements().size());
}
@Test
public void testStart() {
Assert.assertEquals(action_1.getStart(), activity.getStart());
}
@Test
public void testEnd() {
Assert.assertEquals(action_3.getEnd(), activity.getEnd());
}
@Test
public void testState() {
Assert.assertEquals(State.CREATED, activity.getState());
}
@Test (expected = StrolchException.class)
public void testIdNull() {
activity.addElement(new Action(null, null, null));
}
@Test (expected = StrolchException.class)
public void testIdAlreadyExists() {
activity.addElement(new Action("action_1", "Action 1", "Use"));
}
@Test
public void getElementTest(){
Assert.assertNull(activity.getElement("not contained"));
Assert.assertEquals(action_1, activity.getElement(action_1.getId()));
}
@Test
public void cloneTest(){
Activity clone = (Activity) activity.getClone();
Assert.assertEquals(activity.toString(), clone.toString());
Assert.assertEquals(activity.getElements().size(), clone.getElements().size());
}
@Test
public void getParentTest(){
Assert.assertNull(activity.getParent());
Assert.assertNull(activity.getRootElement());
Assert.assertTrue(activity.isRootElement());
}
}

View File

@ -1,107 +1,115 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>li.strolch</groupId>
<artifactId>li.strolch.parent</artifactId>
<version>1.1.0-SNAPSHOT</version>
<relativePath>../li.strolch.parent/pom.xml</relativePath>
</parent>
<parent>
<groupId>li.strolch</groupId>
<artifactId>li.strolch.parent</artifactId>
<version>1.1.0-SNAPSHOT</version>
<relativePath>../li.strolch.parent/pom.xml</relativePath>
</parent>
<artifactId>li.strolch.service</artifactId>
<artifactId>li.strolch.service</artifactId>
<name>li.strolch.service</name>
<description>Service API for Strolch</description>
<name>li.strolch.service</name>
<description>Service API for Strolch</description>
<url>https://github.com/eitchnet/li.strolch.service</url>
<url>https://github.com/eitchnet/li.strolch.service</url>
<inceptionYear>2011</inceptionYear>
<inceptionYear>2011</inceptionYear>
<issueManagement>
<system>Github Issues</system>
<url>https://github.com/eitchnet/li.strolch.service/issues</url>
</issueManagement>
<issueManagement>
<system>Github Issues</system>
<url>https://github.com/eitchnet/li.strolch.service/issues</url>
</issueManagement>
<scm>
<connection>scm:git:https://github.com/eitchnet/strolch.git</connection>
<developerConnection>scm:git:git@github.com:eitch/strolch.git</developerConnection>
<url>https://github.com/eitchnet/strolch</url>
</scm>
<scm>
<connection>scm:git:https://github.com/eitchnet/strolch.git</connection>
<developerConnection>scm:git:git@github.com:eitch/strolch.git</developerConnection>
<url>https://github.com/eitchnet/strolch</url>
</scm>
<dependencies>
<!-- main -->
<dependency>
<groupId>li.strolch</groupId>
<artifactId>li.strolch.model</artifactId>
</dependency>
<dependency>
<groupId>li.strolch</groupId>
<artifactId>li.strolch.agent</artifactId>
</dependency>
<dependencies>
<!-- main -->
<dependency>
<groupId>li.strolch</groupId>
<artifactId>li.strolch.model</artifactId>
</dependency>
<dependency>
<groupId>li.strolch</groupId>
<artifactId>li.strolch.agent</artifactId>
</dependency>
<dependency>
<groupId>ch.eitchnet</groupId>
<artifactId>ch.eitchnet.xmlpers</artifactId>
</dependency>
<dependency>
<groupId>ch.eitchnet</groupId>
<artifactId>ch.eitchnet.privilege</artifactId>
</dependency>
<dependency>
<groupId>ch.eitchnet</groupId>
<artifactId>ch.eitchnet.xmlpers</artifactId>
</dependency>
<dependency>
<groupId>ch.eitchnet</groupId>
<artifactId>ch.eitchnet.privilege</artifactId>
</dependency>
<!-- test -->
<dependency>
<groupId>li.strolch</groupId>
<artifactId>li.strolch.testbase</artifactId>
</dependency>
<dependency>
<groupId>li.strolch</groupId>
<artifactId>li.strolch.persistence.postgresql</artifactId>
<scope>test</scope>
</dependency>
<!-- mocking framework -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.0.8-beta</version>
</dependency>
</dependencies>
<!-- test -->
<dependency>
<groupId>li.strolch</groupId>
<artifactId>li.strolch.testbase</artifactId>
</dependency>
<dependency>
<groupId>li.strolch</groupId>
<artifactId>li.strolch.persistence.postgresql</artifactId>
<scope>test</scope>
</dependency>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/componentVersion.properties</include>
</includes>
</resource>
</resources>
</dependencies>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
</plugin>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/componentVersion.properties</include>
</includes>
</resource>
</resources>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
</plugin>
</plugins>
</build>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,5 +1,5 @@
/*
* Copyright 2014 Martin Smock <smock.martin@gmail.com>
* Copyright 2015 Martin Smock <martin.smock@bluewin.ch>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,9 +18,11 @@ package li.strolch.command.plan;
import java.util.List;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.model.Locator;
import li.strolch.model.Resource;
import li.strolch.model.State;
import li.strolch.model.Tags;
import li.strolch.model.activity.Action;
import li.strolch.model.activity.ActionState;
import li.strolch.model.timedstate.StrolchTimedState;
import li.strolch.model.timevalue.IValueChange;
import li.strolch.persistence.api.StrolchTransaction;
@ -34,12 +36,11 @@ import ch.eitchnet.utils.dbc.DBC;
* resulting changes on the {@link StrolchTimedState} objects assigned to the
* {@link Resource}.
*
* @author Martin Smock <smock.martin@gmail.com>
* @author Martin Smock <martin.smock@bluewin.ch>
*/
public class PlanActionCommand extends Command {
protected Action action;
protected Resource resource;
/**
* @param container
@ -52,65 +53,61 @@ public class PlanActionCommand extends Command {
@Override
public void validate() {
DBC.PRE.assertNotNull("Action may not be null!", this.action);
DBC.PRE.assertNotNull("Reosurce may not be null!", this.action);
// TODO validate action.start, resource.state are set
DBC.PRE.assertNotNull("Action attribute resourceId may not be null!", this.action.getResourceId());
DBC.PRE.assertNotNull("Action attribute resourceType may not be null!", this.action.getResourceType());
DBC.PRE.assertTrue("Action attribute start must be set!", this.action.getStart() > 0);
DBC.PRE.assertTrue("Action attribute end must later than start!", this.action.getEnd() > this.action.getStart());
}
/**
* Apply the {@link IValueChange} objects of the {@link Action} to the
* {@link Resource} states
*/
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public void doCommand() {
Locator locator = Locator.newBuilder(Tags.RESOURCE, action.getResourceType(), action.getResourceId()).build();
Resource resource = tx().findElement(locator);
tx().lock(resource);
final List<IValueChange<?>> startChanges = action.getStartChanges();
for (IValueChange<?> change : startChanges) {
final String stateId = change.getStateId();
final StrolchTimedState timedState = resource.getTimedState(stateId);
final StrolchTimedState timedState = resource.getTimedState(change.getStateId());
timedState.applyChange(change);
}
final List<IValueChange<?>> endChanges = action.getEndChanges();
for (IValueChange<?> change : endChanges) {
final String stateId = change.getStateId();
final StrolchTimedState timedState = resource.getTimedState(stateId);
final StrolchTimedState timedState = resource.getTimedState(change.getStateId());
timedState.applyChange(change);
}
// finally set the action state
action.setState(ActionState.PLANNED);
action.setState(State.PLANNED);
action.setResourceId(resource.getId());
}
/**
* Revert the changes induced by the {@link IValueChange} objects of the
* {@link Action} to the {@link Resource} states
*/
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public void undo() {
Locator locator = Locator.newBuilder(Tags.RESOURCE, action.getResourceType(), action.getResourceId()).build();
Resource resource = tx().findElement(locator);
final List<IValueChange<?>> startChanges = action.getStartChanges();
for (IValueChange<?> change : startChanges) {
final String stateId = change.getStateId();
final StrolchTimedState timedState = resource.getTimedState(stateId);
final StrolchTimedState timedState = resource.getTimedState(change.getStateId());
timedState.applyChange(change.getInverse());
}
final List<IValueChange<?>> endChanges = action.getEndChanges();
for (IValueChange<?> change : endChanges) {
final String stateId = change.getStateId();
final StrolchTimedState timedState = resource.getTimedState(stateId);
final StrolchTimedState timedState = resource.getTimedState(change.getStateId());
timedState.applyChange(change.getInverse());
}
// finally set the action state
action.setState(ActionState.CREATED);
action.setState(State.CREATED);
}
public void setAction(Action action) {
this.action = action;
}
public void setResource(Resource resource) {
this.resource = resource;
}
}

View File

@ -0,0 +1,188 @@
/*
* Copyright 2015 Martin Smock <martin.smock@bluewin.ch>
*
* 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 li.strolch.command.plan;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.exception.StrolchException;
import li.strolch.model.Locator;
import li.strolch.model.Resource;
import li.strolch.model.State;
import li.strolch.model.Tags;
import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
import li.strolch.model.activity.IActivityElement;
import li.strolch.model.timedstate.StrolchTimedState;
import li.strolch.model.timevalue.IValueChange;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.service.api.Command;
import ch.eitchnet.utils.dbc.DBC;
/**
* Command to plan an {@link Activity} to a {@link Resource}. This
* {@link Command} assumes that the {@link IValueChange} objects of the action
* are already constructed and {@link Action#resourceId} is set.
* <p/>
* It iterates the {@link IValueChange} operators and registers the resulting
* changes on the {@link StrolchTimedState} objects assigned to the
* {@link Resource}.
*
* @author Martin Smock <martin.smock@bluewin.ch>
*/
public class PlanActivityCommand extends Command {
protected Activity activity;
/**
* @param container
* @param tx
*/
public PlanActivityCommand(ComponentContainer container, StrolchTransaction tx) {
super(container, tx);
}
@Override
public void validate() {
DBC.PRE.assertNotNull("Activity may not be null!", this.activity);
validate(activity);
}
private void validate(Action action) {
DBC.PRE.assertNotNull("Action attribute resourceId may not be null!", action.getResourceId());
DBC.PRE.assertNotNull("Action attribute resourceType may not be null!", action.getResourceType());
DBC.PRE.assertTrue("Action attribute start must be set!", action.getStart() > 0);
DBC.PRE.assertTrue("Action attribute end must later than start!", action.getEnd() > action.getStart());
}
private void validate(Activity activity) {
Iterator<Entry<String, IActivityElement>> elementIterator = activity.elementIterator();
while (elementIterator.hasNext()) {
IActivityElement activityElement = elementIterator.next().getValue();
if (activityElement instanceof Activity)
validate((Activity) activityElement);
else if (activityElement instanceof Action)
validate((Action) activityElement);
}
}
@Override
public void doCommand() {
validate();
tx().lock(activity);
plan(activity);
}
/**
* plan an {@link Activity} by navigating to the {#link Action} and
* delegating the planning depending on the {@link IActivityElement} class.
*/
private void plan(Activity activity) {
Iterator<Entry<String, IActivityElement>> elementIterator = activity.elementIterator();
while (elementIterator.hasNext()) {
IActivityElement activityElement = elementIterator.next().getValue();
if (activityElement instanceof Activity)
plan((Activity) activityElement);
else if (activityElement instanceof Action)
plan((Action) activityElement);
}
}
/**
* plan an {@link Action}.It iterates the {@link IValueChange} operators and
* registers the changes on the {@link StrolchTimedState} objects assigned
* to the {@link Resource} referenced by type and id.
*
* @param action
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private void plan(Action action) {
Locator locator = Locator.newBuilder(Tags.RESOURCE, action.getResourceType(), action.getResourceId()).build();
Resource resource = tx().findElement(locator);
if (resource == null)
throw new StrolchException("Resource with " + locator + " referenced by " + action.getLocator()
+ " cannot be null!");
tx().lock(resource);
final List<IValueChange<?>> startChanges = action.getStartChanges();
for (IValueChange<?> change : startChanges) {
final StrolchTimedState timedState = resource.getTimedState(change.getStateId());
timedState.applyChange(change);
}
final List<IValueChange<?>> endChanges = action.getEndChanges();
for (IValueChange<?> change : endChanges) {
final StrolchTimedState timedState = resource.getTimedState(change.getStateId());
timedState.applyChange(change);
}
action.setState(State.PLANNED);
}
@Override
public void undo() {
tx().lock(activity);
unplanActivity(activity);
}
private void unplanActivity(Activity activity) {
Iterator<Entry<String, IActivityElement>> elementIterator = activity.elementIterator();
while (elementIterator.hasNext()) {
IActivityElement activityElement = elementIterator.next().getValue();
if (activityElement instanceof Activity)
unplanActivity((Activity) activityElement);
else if (activityElement instanceof Action)
unplanAction((Action) activityElement);
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private void unplanAction(Action action) {
Locator locator = Locator.newBuilder(Tags.RESOURCE, action.getResourceType(), action.getResourceId()).build();
Resource resource = tx().findElement(locator);
final List<IValueChange<?>> startChanges = action.getStartChanges();
for (IValueChange<?> change : startChanges) {
final StrolchTimedState timedState = resource.getTimedState(change.getStateId());
timedState.applyChange(change.getInverse());
}
final List<IValueChange<?>> endChanges = action.getEndChanges();
for (IValueChange<?> change : endChanges) {
final StrolchTimedState timedState = resource.getTimedState(change.getStateId());
timedState.applyChange(change.getInverse());
}
action.setState(State.CREATED);
}
public void setActivity(Activity activity) {
this.activity = activity;
}
}

View File

@ -21,14 +21,19 @@ import static li.strolch.model.ModelGenerator.STATE_INTEGER_TIME_0;
import static li.strolch.model.ModelGenerator.STATE_TIME_0;
import static li.strolch.model.ModelGenerator.STATE_TIME_10;
import static li.strolch.model.ModelGenerator.STATE_TIME_20;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.SortedSet;
import li.strolch.model.Locator;
import li.strolch.model.ModelGenerator;
import li.strolch.model.ParameterBag;
import li.strolch.model.Resource;
import li.strolch.model.State;
import li.strolch.model.Tags;
import li.strolch.model.activity.Action;
import li.strolch.model.activity.ActionState;
import li.strolch.model.parameter.IntegerParameter;
import li.strolch.model.parameter.Parameter;
import li.strolch.model.timedstate.IntegerTimedState;
@ -39,51 +44,62 @@ import li.strolch.model.timevalue.IValue;
import li.strolch.model.timevalue.IValueChange;
import li.strolch.model.timevalue.impl.IntegerValue;
import li.strolch.model.timevalue.impl.ValueChange;
import li.strolch.persistence.api.StrolchTransaction;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* @author Martin Smock <smock.martin@gmail.com>
* @author Martin Smock <martin.smock@bluewin.ch>
*/
public class PlanActionTest {
private Resource resource;
private Action action;
@Before
public void init() {
// add a resource with integer state variable
resource = ModelGenerator.createResource("@1", "Test With States", "Stated");
// add a integer state
final IntegerTimedState timedState = new IntegerTimedState(STATE_INTEGER_ID, STATE_INTEGER_NAME);
timedState.applyChange(new ValueChange<>(STATE_TIME_0, new IntegerValue(STATE_INTEGER_TIME_0)));
resource.addTimedState(timedState);
}
@Test
public void test() {
final Action action = new Action("action_1", "Action 1", "Use");
action = new Action("action_1", "Action 1", "Use");
action.setStart(STATE_TIME_10);
action.setEnd(STATE_TIME_20);
Assert.assertEquals(ActionState.CREATED, action.getState());
final IntegerParameter iP = new IntegerParameter("quantity", "Occupation", 1);
Assert.assertEquals(State.CREATED, action.getState());
IntegerParameter iP = new IntegerParameter("quantity", "Occupation", 1);
action.addParameterBag(new ParameterBag("objective", "Objective", "Don't know"));
action.addParameter("objective", iP);
createChanges(action);
final PlanActionCommand cmd = new PlanActionCommand(null, null);
action.setResourceId(resource.getId());
action.setResourceType(resource.getType());
}
@Test
public void test() {
StrolchTransaction tx = mock(StrolchTransaction.class);
Locator locator = Locator.newBuilder(Tags.RESOURCE, "Stated", "@1").build();
when(tx.findElement(eq(locator))).thenReturn(resource);
final PlanActionCommand cmd = new PlanActionCommand(null, tx);
cmd.setAction(action);
cmd.setResource(resource);
cmd.doCommand();
// check the state
Assert.assertEquals(ActionState.PLANNED, action.getState());
// check the state
Assert.assertEquals(State.PLANNED, action.getState());
// check the resource Id
Assert.assertEquals(resource.getId(), action.getResourceId());
// check if we get the expected result
StrolchTimedState<IValue<Integer>> timedState = resource.getTimedState(STATE_INTEGER_ID);
@ -103,8 +119,8 @@ public class PlanActionTest {
// call undo to clean up
cmd.undo();
Assert.assertEquals(ActionState.CREATED, action.getState());
Assert.assertEquals(State.CREATED, action.getState());
// and check again
values = timeEvolution.getValues();
@ -116,23 +132,23 @@ public class PlanActionTest {
}
/**
* problem specific method to create the {@link IValueChange} objects for
* the {@link Action} to be planned
* <p>
* add changes to action start and end time with a value defined in the
* action objective and set the stateId of the state variable to apply the change to
* </p>
*
* @param action
* the {@link Action} to create the {@link IValueChange} objects
* for
*/
private void createChanges(final Action action) {
protected static void createChanges(final Action action) {
final Parameter<Integer> parameter = action.getParameter("objective", "quantity");
final Integer quantity = parameter.getValue();
Parameter<Integer> parameter = action.getParameter("objective", "quantity");
Integer quantity = parameter.getValue();
final IValueChange<IntegerValue> startChange = new ValueChange<>(action.getStart(), new IntegerValue(quantity));
IValueChange<IntegerValue> startChange = new ValueChange<>(action.getStart(), new IntegerValue(quantity));
startChange.setStateId(STATE_INTEGER_ID);
action.addStartChange(startChange);
final IValueChange<IntegerValue> endChange = new ValueChange<>(action.getEnd(), new IntegerValue(-quantity));
IValueChange<IntegerValue> endChange = new ValueChange<>(action.getEnd(), new IntegerValue(-quantity));
endChange.setStateId(STATE_INTEGER_ID);
action.addEndChange(endChange);
}

View File

@ -0,0 +1,231 @@
package li.strolch.command.plan;
import static li.strolch.model.ModelGenerator.STATE_INTEGER_ID;
import static li.strolch.model.ModelGenerator.STATE_INTEGER_NAME;
import static li.strolch.model.ModelGenerator.STATE_INTEGER_TIME_0;
import static li.strolch.model.ModelGenerator.STATE_TIME_0;
import static li.strolch.model.ModelGenerator.STATE_TIME_10;
import static li.strolch.model.ModelGenerator.STATE_TIME_20;
import static li.strolch.model.ModelGenerator.STATE_TIME_30;
import static li.strolch.model.ModelGenerator.STATE_TIME_40;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.SortedSet;
import li.strolch.model.Locator;
import li.strolch.model.ModelGenerator;
import li.strolch.model.ParameterBag;
import li.strolch.model.Resource;
import li.strolch.model.State;
import li.strolch.model.Tags;
import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
import li.strolch.model.parameter.IntegerParameter;
import li.strolch.model.parameter.Parameter;
import li.strolch.model.timedstate.IntegerTimedState;
import li.strolch.model.timedstate.StrolchTimedState;
import li.strolch.model.timevalue.ITimeValue;
import li.strolch.model.timevalue.ITimeVariable;
import li.strolch.model.timevalue.IValue;
import li.strolch.model.timevalue.IValueChange;
import li.strolch.model.timevalue.impl.IntegerValue;
import li.strolch.model.timevalue.impl.ValueChange;
import li.strolch.persistence.api.StrolchTransaction;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
*
* @author Martin Smock <martin.smock@bluewin.ch>
*
*/
public class PlanActivityTest {
Activity activity, childActivity;
Resource resource_1, resource_2, resource_3;
IntegerTimedState timedState_1, timedState_2, timedState_3;
Action action_1, action_2, action_3;
/**
* initialize the resources with states and the activity with 2 actions.
*/
@Before
public void init() {
// create resource with integer state
resource_1 = ModelGenerator.createResource("@1", "Test With States 1", "Stated");
timedState_1 = new IntegerTimedState(STATE_INTEGER_ID, STATE_INTEGER_NAME);
timedState_1.applyChange(new ValueChange<>(STATE_TIME_0, new IntegerValue(STATE_INTEGER_TIME_0)));
resource_1.addTimedState(timedState_1);
// create resource with integer state
resource_2 = ModelGenerator.createResource("@2", "Test With States 2", "Stated");
timedState_2 = new IntegerTimedState(STATE_INTEGER_ID, STATE_INTEGER_NAME);
timedState_2.applyChange(new ValueChange<>(STATE_TIME_0, new IntegerValue(STATE_INTEGER_TIME_0)));
resource_2.addTimedState(timedState_2);
// create resource with integer state
resource_3 = ModelGenerator.createResource("@3", "Test With States 3", "Stated");
timedState_3 = new IntegerTimedState(STATE_INTEGER_ID, STATE_INTEGER_NAME);
timedState_3.applyChange(new ValueChange<>(STATE_TIME_0, new IntegerValue(STATE_INTEGER_TIME_0)));
resource_3.addTimedState(timedState_3);
// create activity element
activity = new Activity("activity", "Activity", "testType");
// create action 1
action_1 = new Action("action_1", "Action 1", "Use");
action_1.setStart(STATE_TIME_10);
action_1.setEnd(STATE_TIME_20);
IntegerParameter iP1 = new IntegerParameter("quantity", "Occupation", 1);
action_1.addParameterBag(new ParameterBag("objective", "Objective", "Don't know"));
action_1.addParameter("objective", iP1);
createChanges(action_1);
action_1.setResourceId(resource_1.getId());
action_1.setResourceType(resource_1.getType());
activity.addElement(action_1);
// create child activity
childActivity = new Activity("childActivity", "Child Activity", "childType");
// create action 2
action_2 = new Action("action_2", "Action 2", "Use");
action_2.setStart(STATE_TIME_20);
action_2.setEnd(STATE_TIME_30);
IntegerParameter iP2 = new IntegerParameter("quantity", "Occupation", 1);
action_2.addParameterBag(new ParameterBag("objective", "Objective", "Don't know"));
action_2.addParameter("objective", iP2);
createChanges(action_2);
action_2.setResourceId(resource_2.getId());
action_2.setResourceType(resource_2.getType());
childActivity.addElement(action_2);
// create action 3
action_3 = new Action("action_3", "Action 3", "Use");
action_3.setStart(STATE_TIME_20);
action_3.setEnd(STATE_TIME_40);
IntegerParameter iP3 = new IntegerParameter("quantity", "Occupation", 1);
action_3.addParameterBag(new ParameterBag("objective", "Objective", "Don't know"));
action_3.addParameter("objective", iP3);
createChanges(action_3);
action_3.setResourceId(resource_3.getId());
action_3.setResourceType(resource_3.getType());
childActivity.addElement(action_3);
activity.addElement(childActivity);
Assert.assertEquals(2, activity.getElements().size());
}
/**
* The test method. Create appropriate mocks and call the command
*/
@Test
public void test() {
StrolchTransaction tx = mock(StrolchTransaction.class);
Locator locator1 = Locator.newBuilder(Tags.RESOURCE, "Stated", "@1").build();
when(tx.findElement(eq(locator1))).thenReturn(resource_1);
Locator locator2 = Locator.newBuilder(Tags.RESOURCE, "Stated", "@2").build();
when(tx.findElement(eq(locator2))).thenReturn(resource_2);
Locator locator3 = Locator.newBuilder(Tags.RESOURCE, "Stated", "@3").build();
when(tx.findElement(eq(locator3))).thenReturn(resource_3);
PlanActivityCommand planActivityCommand = new PlanActivityCommand(null, tx);
planActivityCommand.setActivity(activity);
planActivityCommand.doCommand();
// check the states
Assert.assertEquals(State.PLANNED, action_1.getState());
Assert.assertEquals(State.PLANNED, action_2.getState());
// check the resource states
StrolchTimedState<IValue<Integer>> timedState_1 = resource_1.getTimedState(STATE_INTEGER_ID);
ITimeVariable<IValue<Integer>> timeEvolution_1 = timedState_1.getTimeEvolution();
SortedSet<ITimeValue<IValue<Integer>>> values_1 = timeEvolution_1.getValues();
Assert.assertEquals(3, values_1.size());
ITimeValue<IValue<Integer>> valueAt_1 = timeEvolution_1.getValueAt(STATE_TIME_0);
Assert.assertEquals(true, valueAt_1.getValue().equals(new IntegerValue(0)));
valueAt_1 = timeEvolution_1.getValueAt(STATE_TIME_10);
Assert.assertEquals(true, valueAt_1.getValue().equals(new IntegerValue(1)));
valueAt_1 = timeEvolution_1.getValueAt(STATE_TIME_20);
Assert.assertEquals(true, valueAt_1.getValue().equals(new IntegerValue(0)));
// the second resource
StrolchTimedState<IValue<Integer>> timedState_2 = resource_2.getTimedState(STATE_INTEGER_ID);
ITimeVariable<IValue<Integer>> timeEvolution_2 = timedState_2.getTimeEvolution();
SortedSet<ITimeValue<IValue<Integer>>> values_2 = timeEvolution_2.getValues();
Assert.assertEquals(3, values_2.size());
ITimeValue<IValue<Integer>> valueAt_2 = timeEvolution_2.getValueAt(STATE_TIME_0);
Assert.assertEquals(true, valueAt_2.getValue().equals(new IntegerValue(0)));
valueAt_2 = timeEvolution_2.getValueAt(STATE_TIME_20);
Assert.assertEquals(true, valueAt_2.getValue().equals(new IntegerValue(1)));
valueAt_2 = timeEvolution_2.getValueAt(STATE_TIME_30);
Assert.assertEquals(true, valueAt_2.getValue().equals(new IntegerValue(0)));
// test undo function
planActivityCommand.undo();
// check the states
Assert.assertEquals(State.CREATED, action_1.getState());
Assert.assertEquals(State.CREATED, action_2.getState());
// check the resource states
values_1 = timeEvolution_1.getValues();
Assert.assertEquals(1, values_1.size());
values_2 = timeEvolution_2.getValues();
Assert.assertEquals(1, values_2.size());
}
/**
* add changes to action start and end time with a value defined in the
* action objective and set the stateId of the state variable to apply the
* change to
*/
protected static void createChanges(final Action action) {
Parameter<Integer> parameter = action.getParameter("objective", "quantity");
Integer quantity = parameter.getValue();
IValueChange<IntegerValue> startChange = new ValueChange<>(action.getStart(), new IntegerValue(quantity));
startChange.setStateId(STATE_INTEGER_ID);
action.addStartChange(startChange);
IValueChange<IntegerValue> endChange = new ValueChange<>(action.getEnd(), new IntegerValue(-quantity));
endChange.setStateId(STATE_INTEGER_ID);
action.addEndChange(endChange);
}
}