/* * 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.model.activity; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import li.strolch.exception.StrolchPolicyException; import li.strolch.model.GroupedParameterizedElement; import li.strolch.model.Locator; import li.strolch.model.Locator.LocatorBuilder; import li.strolch.model.PolicyContainer; import li.strolch.model.Resource; import li.strolch.model.State; import li.strolch.model.StrolchRootElement; import li.strolch.model.policy.PolicyDefs; import li.strolch.model.timevalue.IValue; import li.strolch.model.timevalue.IValueChange; /** * An {@link Action} represents a single step within an {@link Activity}, that is, one that is not further decomposed * within the {@link Activity}. A {@link Activity} applies {@link IValueChange} objects at the start and end time of the * {@link Activity}. * * @author Martin Smock <martin.smock@bluewin.ch> */ public class Action extends GroupedParameterizedElement implements IActivityElement, PolicyContainer { protected static final long serialVersionUID = 1L; protected Activity parent; protected String resourceId; protected String resourceType; protected State state; protected PolicyDefs policyDefs; protected List<IValueChange<? extends IValue<?>>> changes; /** * Empty constructor - for marshalling only! */ public Action() { super(); } public Action(String id, String name, String type) { super(id, name, type); this.state = State.CREATED; } public Action(String id, String name, String type, String resourceId, String resourceType) { super(id, name, type); this.resourceId = resourceId; this.resourceType = resourceType; this.state = State.CREATED; } private void initChanges() { if (this.changes == null) this.changes = new ArrayList<>(); } /** * @return the id of the {@link Resource} the {@link Action} acts on */ public String getResourceId() { return this.resourceId; } /** * @param resourceId * the id of the {@link Resource} the {@link Action} acts on */ public void setResourceId(String resourceId) { this.resourceId = resourceId; } /** * @return the current <code>State</code> of the a<code>Action</code> */ @Override public State getState() { return this.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; } /** * Returns true if this {@link Action} contains any {@link IValueChange changes}, false if not * * @return true if this {@link Action} contains any {@link IValueChange changes}, false if not */ public boolean hasChanges() { return this.changes != null && !this.changes.isEmpty(); } /** * @param add * <code>IValueChange</code> to be applied to the <code>Resource</code> * * @return <tt>true</tt> (as specified by {@link Collection#add}) */ public boolean addChange(IValueChange<? extends IValue<?>> change) { initChanges(); return this.changes.add(change); } /** * @return the list of <code>IValueChange</code> attached to the <code>Action</code> start */ public List<IValueChange<? extends IValue<?>>> getChanges() { if (this.changes == null) return Collections.emptyList(); return this.changes; } public Iterator<IValueChange<? extends IValue<?>>> changesIterator() { if (this.changes == null) return Collections.<IValueChange<? extends IValue<?>>> emptyList().iterator(); return this.changes.iterator(); } @Override public Activity getParent() { return this.parent; } @Override public StrolchRootElement getRootElement() { return (this.parent == null) ? null : this.parent.getRootElement(); } @Override public boolean isRootElement() { return false; } @Override public Action getClone() { Action clone = new Action(); super.fillClone(clone); clone.setResourceId(this.resourceId); clone.setResourceType(this.resourceType); clone.setState(this.state); if (this.changes != null) { for (IValueChange<? extends IValue<?>> change : getChanges()) { clone.addChange(change.getClone()); } } return clone; } @Override public PolicyDefs getPolicyDefs() { if (this.policyDefs == null) throw new StrolchPolicyException(getLocator() + " has no Policies defined!"); return this.policyDefs; } @Override public boolean hasPolicyDefs() { return this.policyDefs != null; } @Override public void setPolicyDefs(PolicyDefs policyDefs) { this.policyDefs = policyDefs; this.policyDefs.setParent(this); } @Override public Locator getLocator() { LocatorBuilder lb = new LocatorBuilder(); this.parent.fillLocator(lb); fillLocator(lb); return lb.build(); } @Override protected void fillLocator(LocatorBuilder locatorBuilder) { locatorBuilder.append(this.id); } @Override public String toString() { final StringBuilder builder = new StringBuilder(); builder.append("Action [id="); builder.append(this.id); builder.append(", name="); 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("]"); return builder.toString(); } @Override public void setParent(Activity activity) { this.parent = activity; } @Override public Long getStart() { Long start = Long.MAX_VALUE; if (this.changes == null) return start; for (IValueChange<?> change : this.changes) { start = Math.min(start, change.getTime()); } return start; } @Override public Long getEnd() { Long end = 0L; if (this.changes == null) return end; for (IValueChange<?> change : this.changes) { end = Math.max(end, change.getTime()); } return end; } }