/*
* Licensed Materials - Property of Perforce Software, Inc.
* © Copyright Perforce Software, Inc. 2014, 2021
* © Copyright IBM Corp. 2009, 2014
* © Copyright ILOG 1996, 2009
* All Rights Reserved.
*
* Note to U.S. Government Users Restricted Rights:
* The Software and Documentation were developed at private expense and
* are "Commercial Items" as that term is defined at 48 CFR 2.101,
* consisting of "Commercial Computer Software" and
* "Commercial Computer Software Documentation", as such terms are
* used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
* as applicable.
*/
package database;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import ilog.views.gantt.IlvActivity;
import ilog.views.gantt.IlvConstraint;
import ilog.views.gantt.IlvConstraintType;
import ilog.views.gantt.IlvGanttModel;
import ilog.views.gantt.IlvHierarchyNode;
import ilog.views.gantt.IlvReservation;
import ilog.views.gantt.IlvResource;
import ilog.views.gantt.IlvTimeInterval;
import ilog.views.gantt.model.IlvAbstractActivity;
import ilog.views.gantt.model.IlvAbstractConstraint;
import ilog.views.gantt.model.IlvAbstractGanttModel;
import ilog.views.gantt.model.IlvAbstractReservation;
import ilog.views.gantt.model.IlvAbstractResource;
/**
* <code>DBROGanttModel</code> is a read-only Gantt data model that connects to
* an underlying {@link GanttDBRO}. The data model caches the results of
* querying the database to optimize speed at the expense of memory usage.
* Activities, resources, constraints, and reservations are defined as inner
* classes.
*/
public class DBROGanttModel extends IlvAbstractGanttModel {
// =========================================
// Class Constants
// =========================================
/**
* Log ID.
*/
public static final String logID = "DBModel";
// =========================================
// Instance Variables
// =========================================
/**
* The database.
*/
private GanttDBRO db;
// =========================================
// Instance Construction and Initialization
// =========================================
/**
* Creates a new <code>DBROGanttModel</code> that queries the specified
* database.
*/
public DBROGanttModel(GanttDBRO database) {
db = database;
initActivities();
initResources();
initConstraints();
initReservations();
}
// =========================================
// Accessing
// =========================================
/**
* Returns the underlying database.
*/
public GanttDBRO getDatabase() {
return db;
}
// =========================================
// Activities and Resources
// =========================================
/**
* Returns whether the specified activity or resource is a member of the data
* model.
*
* @param activityOrResource
* The activity or resource.
*/
Override
public boolean contains(IlvHierarchyNode activityOrResource) {
if (activityOrResource instanceof IlvActivity)
return contains((IlvActivity) activityOrResource);
else
return contains((IlvResource) activityOrResource);
}
// =========================================
// Activities
// =========================================
/**
* The database lookup key of the root activity.
*/
private String rootActivityKey;
/**
* Indicates whether <code>rootActivityKey</code> is valid.
*/
private boolean rootActivityQueried;
/**
* Cached {@link ActivityState}s, indexed by their database lookup key.
*/
private Map<String, ActivityState> activityCache;
/**
* The <code>ActivityState</code> inner class. Each instance maintains state
* info on an activity's hierarchical relationships.
*/
class ActivityState {
/**
* The activity for this state info.
*/
Activity activity;
/**
* Indicates whether the parent ID for the activity has been queried. If
* <code>true</code>, then the value in <code>parentKey</code> is valid.
*/
boolean parentQueried;
/**
* The database lookup key of the activity's parent. If <code>null</code>,
* then the activity is the root activity and has no parent. This value is
* only valid if <code>parentQueried</code> is <code>true</code>.
*/
String parentKey;
/**
* The list of lookup keys for the activity's children. If the child keys
* have not been queried yet, then <code>childKeys</code> will be
* <code>null</code>.
*/
List<String> childKeys;
/**
* Creates an <code>ActivityState</code> for the specified activity.
*/
public ActivityState(Activity activity) {
this.activity = activity;
}
/**
* Returns the activity.
*/
public final Activity getActivity() {
return activity;
}
/**
* Returns the activity-state for the parent of the activity or
* <code>null</code> if the activity is the root activity.
*/
public final ActivityState getParentState() {
if (!parentQueried) {
Activity activity = getActivity();
if (activity == getRootActivity())
parentKey = null;
else
parentKey = getDatabase().queryActivityParent(getActivity().getDBKey());
parentQueried = true;
}
if (parentKey == null)
return null;
return getActivityState(parentKey);
}
/**
* Returns the parent of the activity or <code>null</code> if the activity
* is the root activity.
*/
public final Activity getParent() {
ActivityState parentState = getParentState();
if (parentState == null)
return null;
return parentState.getActivity();
}
/**
* If needed, queries the database for the child activity lookup keys.
*/
private final void initChildrenIfNeeded() {
if (childKeys != null)
return;
String[] keyArray = getDatabase().queryActivityChildren(getActivity().getDBKey());
childKeys = new ArrayList<String>(keyArray.length);
for (int i = 0; i < keyArray.length; i++)
childKeys.add(keyArray[i]);
}
/**
* Returns the number of children.
*/
public final int getChildCount() {
initChildrenIfNeeded();
return childKeys.size();
}
/**
* Returns the activity-state for the child activity at the specified index.
*/
public final ActivityState getChildState(int index) {
initChildrenIfNeeded();
String childKey = childKeys.get(index);
return getActivityState(childKey);
}
/**
* Returns the child activity at the specified index.
*/
public final IlvActivity getChild(int index) {
ActivityState childState = getChildState(index);
return childState.getActivity();
}
/**
* Returns the index of the specified child.
*/
public final int getChildIndex(String dbKey) {
initChildrenIfNeeded();
return childKeys.indexOf(dbKey);
}
}
/**
* Initializes the collection of activities of this data model.
*/
private void initActivities() {
rootActivityKey = null;
rootActivityQueried = false;
activityCache = new HashMap<String, DBROGanttModel.ActivityState>();
}
/**
* Verify that the specified activity is an instance of <code>Activity</code>.
* If not, this method throws an <code>IllegalArgumentException</code>.
*/
protected final Activity checkActivity(IlvActivity activity) {
if (!(activity instanceof Activity))
throw new IllegalArgumentException(activity + " is not a member of " + this);
return (Activity) activity;
}
/**
* Returns the activity-state for the specified activity. If the activity is
* not already cached, an activity and its associated state object are created
* and inserted into the cache.
*
* @param dbKey
* The lookup key for the activity. It is assumed that the key
* represents a valid activity in the database.
*/
protected final ActivityState getActivityState(String dbKey) {
ActivityState activityState = activityCache.get(dbKey);
if (activityState == null) {
Activity a = createActivity(dbKey);
activityState = new ActivityState(a);
activityCache.put(dbKey, activityState);
}
return activityState;
}
/**
* Creates a new activity object from the specified lookup key. It is assumed
* that the key represents a valid activity in the database. In general, the
* activity instance should not query the database immediately when it is
* created. Instead, it should lazy query the database when properties are are
* first accessed. Subclasses can override this method as needed to create
* customized activities.
*
* @param dbKey
* The database lookup key.
*/
protected Activity createActivity(String dbKey) {
Logger.getLogger(logID).log(Level.INFO, "[Model] Creating Activity instance for {0}", dbKey);
Activity newActivity = new Activity(dbKey);
return newActivity;
}
/**
* Returns whether the specified activity is a member of the data model.
*
* @param activity
* The activity.
*/
protected synchronized boolean contains(IlvActivity activity) {
if (!(activity instanceof Activity))
return false;
Activity a = (Activity) activity;
String dbKey = a.getDBKey();
ActivityState activityState = activityCache.get(dbKey);
if (activityState != null)
return true;
GanttDBRO.ActivityRecord dbRecord = getDatabase().queryActivity(dbKey);
if (dbRecord != null) {
a.dbRecord = dbRecord;
activityState = new ActivityState(a);
activityCache.put(dbKey, activityState);
return true;
} else {
return false;
}
}
/**
* Returns the root activity of the data model or <code>null</code> if the
* data model contains no activities.
*/
Override
public synchronized IlvActivity getRootActivity() {
if (!rootActivityQueried) {
rootActivityKey = db.queryRootActivityKey();
rootActivityQueried = true;
}
if (rootActivityKey == null)
return null;
ActivityState activityState = getActivityState(rootActivityKey);
return activityState.getActivity();
}
/**
* Sets the root activity of the data model.
*/
Override
public void setRootActivity(IlvActivity root) {
}
/**
* Returns the parent activity of the specified activity or <code>null</code>
* if the activity is the root activity of the data model.
*
* @param activity
* The activity.
*/
Override
public synchronized IlvActivity getParentActivity(IlvActivity activity) {
Activity a = checkActivity(activity);
if (a == getRootActivity())
return null;
String id = a.getDBKey();
ActivityState activityState = getActivityState(id);
return activityState.getParent();
}
/**
* Returns the index of the specified activity within its parent activity. If
* the activity is the root activity of the data model, then -1 is returned.
*
* @param activity
* The activity.
*/
Override
public synchronized int getParentActivityIndex(IlvActivity activity) {
Activity a = checkActivity(activity);
if (a == getRootActivity())
return -1;
String childKey = a.getDBKey();
ActivityState childState = getActivityState(childKey);
ActivityState parentState = childState.getParentState();
return parentState.getChildIndex(childKey);
}
/**
* Returns the number of children of the specified parent activity.
*
* @param parent
* The parent activity.
* @return The number of child activities.
*/
Override
public synchronized int getChildActivityCount(IlvActivity parent) {
Activity p = checkActivity(parent);
ActivityState parentState = getActivityState(p.getDBKey());
return parentState.getChildCount();
}
/**
* Returns the child of the specified parent activity at index
* <code>index</code>.
*
* @param parent
* The parent activity.
* @param index
* The child index.
* @return The child activity at index <code>index</code>.
*/
Override
public synchronized IlvActivity getChildActivity(IlvActivity parent, int index) {
Activity p = checkActivity(parent);
ActivityState parentState = getActivityState(p.getDBKey());
return parentState.getChild(index);
}
/**
* Returns the index of the specified child in the parent activity's list of
* children.
*
* @param parent
* The parent activity.
* @param child
* The child activity to find the index of.
* @return The index of the child activity, or -1 if the activity is not a
* child of parent.
*/
Override
public synchronized int getChildActivityIndex(IlvActivity parent, IlvActivity child) {
Activity p = checkActivity(parent);
Activity c = checkActivity(child);
ActivityState parentState = getActivityState(p.getDBKey());
return parentState.getChildIndex(c.getDBKey());
}
/**
* Adds <i>newActivity</i> as a child of <i>parent</i> activity at the
* specified location in its list of child activities.
*/
Override
public void addActivity(IlvActivity newActivity, IlvActivity parent, int index) {
}
/**
* Removes the child activity from <i>parent</i> at the specified location in
* its list of child activities.
*/
Override
public void removeActivity(IlvActivity parent, int index) {
}
/**
* Removes the specified child <i>activity</i> from its parent.
*/
Override
public void removeActivity(IlvActivity activity) {
}
/**
* Moves the specified activity from its current location in the tree to a new
* location.
*/
Override
public void moveActivity(IlvActivity activity, IlvActivity newParent, int newIndex) {
}
/**
* <code>Activity</code> is an inner class that implements a read-only
* activity object.
*/
public class Activity extends IlvAbstractActivity {
private String key;
private GanttDBRO.ActivityRecord dbRecord;
private IlvTimeInterval interval; // duplicate of start and end in db record
/**
* Creates a new <code>Activity</code> from the specified database key.
*
* @param key
* The database lookup key.
*/
protected Activity(String key) {
if (key == null)
throw new IllegalArgumentException("Null database key");
this.key = key;
}
/**
* Queries the database for the properties of this activity.
*/
protected void queryPropertiesIfNeeded() {
if (dbRecord != null)
return;
dbRecord = getDatabase().queryActivity(key);
interval = new IlvTimeInterval(dbRecord.getStart(), dbRecord.getEnd());
}
/**
* Returns the database key of this activity.
*/
public String getDBKey() {
return key;
}
/**
* Sets the data model to which the activity and all its children belong.
*/
Override
public void setGanttModelImpl(IlvGanttModel model) {
}
/**
* Returns the name of the activity.
*/
Override
public String getName() {
queryPropertiesIfNeeded();
return dbRecord.getName();
}
/**
* Sets the name of the activity.
*/
Override
public void setName(String name) {
}
/**
* Returns the activity ID.
*/
Override
public String getID() {
queryPropertiesIfNeeded();
return dbRecord.getID();
}
/**
* Sets the activity ID.
*/
Override
public void setID(String id) {
}
/**
* Returns the time interval of the activity.
*/
Override
public IlvTimeInterval getTimeInterval() {
queryPropertiesIfNeeded();
return interval;
}
/**
* Sets the time interval of the activity.
*/
Override
public void setTimeInterval(IlvTimeInterval interval) {
}
/**
* Returns a parameter string that represents the state of this activity.
*/
Override
protected String paramString() {
StringBuffer buf = new StringBuffer("key=");
buf.append(getDBKey());
buf.append(',');
buf.append(super.paramString());
return buf.toString();
}
}
// =========================================
// Resources
// =========================================
/**
* The database lookup key of the root resource.
*/
private String rootResourceKey;
/**
* Indicates whether <code>rootResourceKey</code> is valid.
*/
private boolean rootResourceQueried;
/**
* Cached {@link ResourceState}s, indexed by their database lookup key.
*/
private Map<String, ResourceState> resourceCache;
/**
* The <code>ResourceState</code> inner class. Each instance maintains state
* info on a resource's hierarchical relationships.
*/
class ResourceState {
/**
* The resource for this state info.
*/
Resource resource;
/**
* Indicates whether the parent ID for the resource has been queried. If
* <code>true</code>, then the value in <code>parentKey</code> is valid.
*/
boolean parentQueried;
/**
* The database lookup key of the resource's parent. If <code>null</code>,
* then the resource is the root resource and has no parent. This value is
* only valid if <code>parentQueried</code> is <code>true</code>.
*/
String parentKey;
/**
* The list of lookup keys for the resource's children. If the child keys
* have not been queried yet, then <code>childKeys</code> will be
* <code>null</code>.
*/
List<String> childKeys;
/**
* Creates a <code>ResourceState</code> for the specified resource.
*/
public ResourceState(Resource resource) {
this.resource = resource;
}
/**
* Returns the resource.
*/
public final Resource getResource() {
return resource;
}
/**
* Returns the resource-state for the parent of the resource or
* <code>null</code> if the resource is the root resource.
*/
public final ResourceState getParentState() {
if (!parentQueried) {
Resource resource = getResource();
if (resource == getRootResource())
parentKey = null;
else
parentKey = getDatabase().queryResourceParent(getResource().getDBKey());
parentQueried = true;
}
if (parentKey == null)
return null;
return getResourceState(parentKey);
}
/**
* Returns the parent of the resource or <code>null</code> if the resource
* is the root resource.
*/
public final Resource getParent() {
ResourceState parentState = getParentState();
if (parentState == null)
return null;
return parentState.getResource();
}
/**
* If needed, queries the database for the child resource lookup keys.
*/
private final void initChildrenIfNeeded() {
if (childKeys != null)
return;
String[] keyArray = getDatabase().queryResourceChildren(getResource().getDBKey());
childKeys = new ArrayList<String>(keyArray.length);
for (int i = 0; i < keyArray.length; i++)
childKeys.add(keyArray[i]);
}
/**
* Returns the number of children.
*/
public final int getChildCount() {
initChildrenIfNeeded();
return childKeys.size();
}
/**
* Returns the resource-state for the child resource at the specified index.
*/
public final ResourceState getChildState(int index) {
initChildrenIfNeeded();
String childKey = childKeys.get(index);
return getResourceState(childKey);
}
/**
* Returns the child resource at the specified index.
*/
public final IlvResource getChild(int index) {
ResourceState childState = getChildState(index);
return childState.getResource();
}
/**
* Returns the index of the specified child.
*/
public final int getChildIndex(String dbKey) {
initChildrenIfNeeded();
return childKeys.indexOf(dbKey);
}
}
/**
* Initializes the collection of resources of this data model.
*/
private void initResources() {
rootResourceKey = null;
rootResourceQueried = false;
resourceCache = new HashMap<String, DBROGanttModel.ResourceState>();
}
/**
* Verify that the specified resource is an instance of <code>Resource</code>.
* If not, this method throws an <code>IllegalArgumentException</code>.
*/
protected final Resource checkResource(IlvResource resource) {
if (!(resource instanceof Resource))
throw new IllegalArgumentException(resource + " is not a member of " + this);
return (Resource) resource;
}
/**
* Returns the resource-state for the specified resource. If the resource is
* not already cached, a resource and its associated state object are created
* and inserted into the cache.
*
* @param dbKey
* The lookup key for the resource. It is assumed that the key
* represents a valid resource in the database.
*/
protected final ResourceState getResourceState(String dbKey) {
ResourceState resourceState = resourceCache.get(dbKey);
if (resourceState == null) {
Resource r = createResource(dbKey);
resourceState = new ResourceState(r);
resourceCache.put(dbKey, resourceState);
}
return resourceState;
}
/**
* Creates a new resource object from the specified lookup key. It is assumed
* that the key represents a valid resource in the database. In general, the
* resource instance should not query the database immediately when it is
* created. Instead, it should lazy query the database when properties are are
* first accessed. Subclasses can override this method as needed to create
* customized resources.
*
* @param dbKey
* The database lookup key.
*/
protected Resource createResource(String dbKey) {
Logger.getLogger(logID).log(Level.INFO, "[Model] Creating Resource instance for {0}", dbKey);
Resource newResource = new Resource(dbKey);
return newResource;
}
/**
* Returns whether the specified resource is a member of the data model.
*
* @param resource
* The resource.
*/
protected synchronized boolean contains(IlvResource resource) {
if (!(resource instanceof Resource))
return false;
Resource r = (Resource) resource;
String dbKey = r.getDBKey();
ResourceState resourceState = resourceCache.get(dbKey);
if (resourceState != null)
return true;
GanttDBRO.ResourceRecord dbRecord = getDatabase().queryResource(dbKey);
if (dbRecord != null) {
r.dbRecord = dbRecord;
resourceState = new ResourceState(r);
resourceCache.put(dbKey, resourceState);
return true;
} else {
return false;
}
}
/**
* Returns the root resource of the data model or <code>null</code> if the
* data model contains no resources.
*/
Override
public synchronized IlvResource getRootResource() {
if (!rootResourceQueried) {
rootResourceKey = db.queryRootResourceKey();
rootResourceQueried = true;
}
if (rootResourceKey == null)
return null;
ResourceState resourceState = getResourceState(rootResourceKey);
return resourceState.getResource();
}
/**
* Sets the root resource of the data model.
*/
Override
public void setRootResource(IlvResource root) {
}
/**
* Returns the parent resource of the specified resource or <code>null</code>
* if the resource is the root resource of the data model.
*
* @param resource
* The resource.
*/
Override
public synchronized IlvResource getParentResource(IlvResource resource) {
Resource r = checkResource(resource);
if (r == getRootResource())
return null;
String id = r.getDBKey();
ResourceState resourceState = getResourceState(id);
return resourceState.getParent();
}
/**
* Returns the index of the specified resource within its parent resource. If
* the resource is the root resource of the data model, then -1 is returned.
*
* @param resource
* The resource.
*/
Override
public synchronized int getParentResourceIndex(IlvResource resource) {
Resource r = checkResource(resource);
if (r == getRootResource())
return -1;
String childKey = r.getDBKey();
ResourceState childState = getResourceState(childKey);
ResourceState parentState = childState.getParentState();
return parentState.getChildIndex(childKey);
}
/**
* Returns the number of children of the specified parent resource.
*
* @param parent
* The parent resource.
* @return The number of child resources.
*/
Override
public synchronized int getChildResourceCount(IlvResource parent) {
Resource p = checkResource(parent);
ResourceState parentState = getResourceState(p.getDBKey());
return parentState.getChildCount();
}
/**
* Returns the child of the specified parent resource at index
* <code>index</code>.
*
* @param parent
* The parent resource.
* @param index
* The child index.
* @return The child resource at index <code>index</code>.
*/
Override
public synchronized IlvResource getChildResource(IlvResource parent, int index) {
Resource p = checkResource(parent);
ResourceState parentState = getResourceState(p.getDBKey());
return parentState.getChild(index);
}
/**
* Returns the index of the specified child in the parent resource's list of
* children.
*
* @param parent
* The parent resource.
* @param child
* The child resource to find the index of.
* @return The index of the child resource, or -1 if the resource is not a
* child of parent.
*/
Override
public synchronized int getChildResourceIndex(IlvResource parent, IlvResource child) {
Resource p = checkResource(parent);
Resource c = checkResource(child);
ResourceState parentState = getResourceState(p.getDBKey());
return parentState.getChildIndex(c.getDBKey());
}
/**
* Adds <i>newResource</i> as a child of <i>parent</i> resource at the
* specified location in its list of child resources.
*/
Override
public void addResource(IlvResource newResource, IlvResource parent, int index) {
}
/**
* Removes the child resource from <i>parent</i> at the specified location in
* its list of child resources.
*/
Override
public void removeResource(IlvResource parent, int index) {
}
/**
* Removes the specified child <i>resource</i> from its parent.
*/
Override
public void removeResource(IlvResource resource) {
}
/**
* Moves the specified resource from its current location in the tree to a new
* location.
*/
Override
public void moveResource(IlvResource resource, IlvResource newParent, int newIndex) {
}
/**
* <code>Resource</code> is an inner class that implements a read-only
* resource object.
*/
public class Resource extends IlvAbstractResource {
private String key;
private GanttDBRO.ResourceRecord dbRecord;
/**
* Creates a new <code>Resource</code> from the specified database key.
*
* @param key
* The database lookup key.
*/
protected Resource(String key) {
if (key == null)
throw new IllegalArgumentException("Null database key");
this.key = key;
}
/**
* Queries the database for the properties of this resource.
*/
protected void queryPropertiesIfNeeded() {
if (dbRecord != null)
return;
dbRecord = getDatabase().queryResource(key);
}
/**
* Returns the database key of this resource.
*/
public String getDBKey() {
return key;
}
/**
* Sets the data model to which the resource and all its children belong.
*/
Override
public void setGanttModelImpl(IlvGanttModel model) {
}
/**
* Returns the name of the resource.
*/
Override
public String getName() {
queryPropertiesIfNeeded();
return dbRecord.getName();
}
/**
* Sets the name of the resource.
*/
Override
public void setName(String name) {
}
/**
* Returns the resource ID.
*/
Override
public String getID() {
queryPropertiesIfNeeded();
return dbRecord.getID();
}
/**
* Sets the resource ID.
*/
Override
public void setID(String id) {
}
/**
* Returns the resource's quantity.
*/
Override
public float getQuantity() {
queryPropertiesIfNeeded();
return dbRecord.getQuantity();
}
/**
* Sets the resource's quantity.
*/
Override
public void setQuantity(float x) {
}
/**
* Returns a parameter string that represents the state of this resource.
*/
Override
protected String paramString() {
StringBuffer buf = new StringBuffer("key=");
buf.append(getDBKey());
buf.append(',');
buf.append(super.paramString());
return buf.toString();
}
}
// =========================================
// Constraints
// =========================================
/**
* Cached constraints, indexed by their database lookup key.
*/
private Map<String, Constraint> constraintCache;
/**
* Initializes the collection of constraints of this data model.
*/
private void initConstraints() {
constraintCache = new HashMap<String, DBROGanttModel.Constraint>();
}
/**
* Returns the constraint specified by its lookup key. If the constraint is
* not already cached, a constraint object is created and inserted into the
* cache.
*
* @param dbKey
* The lookup key for the constraint. It is assumed that the key
* represents a valid constraint in the database.
*/
protected final IlvConstraint getConstraint(String dbKey) {
Constraint constraint = constraintCache.get(dbKey);
if (constraint == null) {
constraint = createConstraint(dbKey);
constraintCache.put(dbKey, constraint);
}
return constraint;
}
/**
* Creates a new constraint object from the specified lookup key. It is
* assumed that the key represents a valid constraint in the database. In
* general, the constraint instance should not query the database immediately
* when it is created. Instead, it should lazy query the database when
* properties are first accessed. Subclasses can override this method as
* needed to create customized constraints.
*
* @param dbKey
* The database lookup key.
*/
protected Constraint createConstraint(String dbKey) {
Logger.getLogger(logID).log(Level.INFO, "[Model] Creating Constraint instance for {0}", dbKey);
Constraint newConstraint = new Constraint(dbKey);
return newConstraint;
}
/**
* Returns whether the specified constraint is a member of the data model.
*
* @param constraint
* The constraint.
*/
Override
public synchronized boolean contains(IlvConstraint constraint) {
if (!(constraint instanceof Constraint))
return false;
Constraint c = (Constraint) constraint;
String dbKey = c.getDBKey();
if (constraintCache.get(dbKey) != null)
return true;
GanttDBRO.ConstraintRecord dbRecord = getDatabase().queryConstraint(dbKey);
if (dbRecord != null) {
c.dbRecord = dbRecord;
constraintCache.put(dbKey, c);
return true;
} else {
return false;
}
}
/**
* Returns an iterator that will traverse over the constraints specified by an
* array of database keys.
*/
protected Iterator<IlvConstraint> constraintIterator(final String[] constraintKeys) {
return new Iterator<IlvConstraint>() {
Iterator<String> keyIterator = Arrays.asList(constraintKeys).iterator();
Override
public boolean hasNext() {
return keyIterator.hasNext();
}
Override
public IlvConstraint next() {
String dbKey = keyIterator.next();
return getConstraint(dbKey);
}
Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/**
* Return an iterator over the constraints in the data model.
*/
Override
public Iterator<IlvConstraint> constraintIterator() {
return constraintIterator(db.queryConstraints());
}
/**
* Returns an iterator over the constraints in the data model that have the
* specified activity as their source or <i>from</i> activity.
*/
Override
public Iterator<IlvConstraint> constraintIteratorFromActivity(IlvActivity fromActivity) {
return constraintIterator(db.queryConstraintsFromActivity(((Activity) fromActivity).getDBKey()));
}
/**
* Returns an iterator over the constraints in the data model that have the
* specified activity as their target or <i>to</i> activity.
*/
Override
public Iterator<IlvConstraint> constraintIteratorToActivity(IlvActivity toActivity) {
return constraintIterator(db.queryConstraintsToActivity(((Activity) toActivity).getDBKey()));
}
/**
* Adds a constraint to the data model.
*/
Override
public void addConstraint(IlvConstraint newConstraint) {
}
/**
* Removes the specified <i>constraint</i> from the data model.
*/
Override
public void removeConstraint(IlvConstraint constraint) {
}
/**
* <code>Constraint</code> is an inner class that implements a read-only
* constraint object.
*/
public class Constraint extends IlvAbstractConstraint {
private String key;
private GanttDBRO.ConstraintRecord dbRecord;
/**
* Creates a new <code>Constraint</code> from the specified database key.
*
* @param key
* The database lookup key.
*/
private Constraint(String key) {
if (key == null)
throw new IllegalArgumentException("Null database key");
this.key = key;
}
/**
* Queries the database for the properties of this constraint.
*/
protected void queryPropertiesIfNeeded() {
if (dbRecord != null)
return;
dbRecord = getDatabase().queryConstraint(key);
}
/**
* Returns this constraint's database key.
*/
public String getDBKey() {
return key;
}
/**
* Sets the data model to which the resource belongs.
*/
Override
public void setGanttModelImpl(IlvGanttModel model) {
}
/**
* Returns the type of this constraint.
*/
Override
public IlvConstraintType getType() {
queryPropertiesIfNeeded();
return dbRecord.getType();
}
/**
* Sets the type of this constraint.
*/
Override
public void setType(IlvConstraintType type) {
}
/**
* Returns the source or <i>From</i> activity for this constraint.
*/
Override
public IlvActivity getFromActivity() {
queryPropertiesIfNeeded();
ActivityState activityState = getActivityState(dbRecord.getFromActivityKey());
return activityState.getActivity();
}
/**
* Returns the target or <i>To</i> activity for this constraint.
*/
Override
public IlvActivity getToActivity() {
queryPropertiesIfNeeded();
ActivityState activityState = getActivityState(dbRecord.getToActivityKey());
return activityState.getActivity();
}
}
// =========================================
// Reservations
// =========================================
/**
* Cached reservations, indexed by their database lookup key.
*/
private Map<String, Reservation> reservationCache;
/**
* Initializes the collection of reservations of this data model.
*/
private void initReservations() {
reservationCache = new HashMap<String, DBROGanttModel.Reservation>();
}
/**
* Returns the reservation specified by its lookup key. If the reservation is
* not already cached, a reservation object is created and inserted into the
* cache.
*
* @param dbKey
* The lookup key for the reservation. It is assumed that the key
* represents a valid reservation in the database.
*/
protected final IlvReservation getReservation(String dbKey) {
Reservation reservation = reservationCache.get(dbKey);
if (reservation == null) {
reservation = createReservation(dbKey);
reservationCache.put(dbKey, reservation);
}
return reservation;
}
/**
* Creates a new reservation object from the specified lookup key. It is
* assumed that the key represents a valid reservation in the database. In
* general, the reservation instance should not query the database immediately
* when it is created. Instead, it should lazy query the database when
* properties are first accessed. Subclasses can override this method as
* needed to create customized reservations.
*
* @param dbKey
* The database lookup key.
*/
protected Reservation createReservation(String dbKey) {
Logger.getLogger(logID).log(Level.INFO, "[Model] Creating Reservation instance for {0}", dbKey);
Reservation newReservation = new Reservation(dbKey);
return newReservation;
}
/**
* Returns whether the specified reservation is a member of the data model.
*
* @param reservation
* The reservation.
*/
Override
public synchronized boolean contains(IlvReservation reservation) {
if (!(reservation instanceof Reservation))
return false;
Reservation r = (Reservation) reservation;
String dbKey = r.getDBKey();
if (reservationCache.get(dbKey) != null)
return true;
GanttDBRO.ReservationRecord dbRecord = getDatabase().queryReservation(dbKey);
if (dbRecord != null) {
r.dbRecord = dbRecord;
reservationCache.put(dbKey, r);
return true;
} else {
return false;
}
}
/**
* Returns an iterator that will traverse over the reservations specified by
* an array of database keys.
*/
protected Iterator<IlvReservation> reservationIterator(final String[] reservationKeys) {
return new Iterator<IlvReservation>() {
Iterator<String> keyIterator = Arrays.asList(reservationKeys).iterator();
Override
public boolean hasNext() {
return keyIterator.hasNext();
}
Override
public IlvReservation next() {
String dbKey = keyIterator.next();
return getReservation(dbKey);
}
Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/**
* Returns an iterator over all of the reservations in the data model.
*/
Override
public Iterator<IlvReservation> reservationIterator() {
return reservationIterator(db.queryReservations());
}
/**
* Returns an iterator over all of the reservations in the data model that are
* associated with the specified activity.
*/
Override
public Iterator<IlvReservation> reservationIterator(IlvActivity activity) {
return reservationIterator(db.queryReservationsForActivity(((Activity) activity).getDBKey()));
}
/**
* Returns an iterator over all of the reservations in the data model that are
* associated with the specified resource.
*/
Override
public Iterator<IlvReservation> reservationIterator(IlvResource resource) {
return reservationIterator(db.queryReservationsForResource(((Resource) resource).getDBKey()));
}
/**
* Returns an iterator over all of the reservations in the data model that are
* associated with the specified resource and where the assigned activity
* intersects the specified time interval.
*/
Override
public Iterator<IlvReservation> reservationIterator(IlvResource resource, IlvTimeInterval interval) {
return reservationIterator(
db.queryReservationsForResource(((Resource) resource).getDBKey(), interval.getStart(), interval.getEnd()));
}
/**
* Adds a reservation to the data model.
*/
Override
public void addReservation(IlvReservation newReservation) {
}
/**
* Removes the specified <i>reservation</i> from the data model.
*/
Override
public void removeReservation(IlvReservation reservation) {
}
/**
* <code>Reservation</code> is an inner class that implements a read-only
* reservation object.
*/
public class Reservation extends IlvAbstractReservation {
private String key;
private GanttDBRO.ReservationRecord dbRecord;
/**
* Creates a new <code>Reservation</code> from the specified database key.
*
* @param key
* The database lookup key.
*/
private Reservation(String key) {
if (key == null)
throw new IllegalArgumentException("Null database key");
this.key = key;
}
/**
* Queries the database for the properties of this reservation.
*/
protected void queryPropertiesIfNeeded() {
if (dbRecord != null)
return;
dbRecord = getDatabase().queryReservation(key);
}
/**
* Returns this reservation's database key.
*/
public String getDBKey() {
return key;
}
/**
* Sets the data model to which the resource belongs.
*/
Override
public void setGanttModelImpl(IlvGanttModel model) {
}
/**
* Returns the resource for this reservation.
*/
Override
public IlvResource getResource() {
queryPropertiesIfNeeded();
ResourceState resourceState = getResourceState(dbRecord.getResourceKey());
return resourceState.getResource();
}
/**
* Sets the resource for this reservation.
*/
Override
public void setResource(IlvResource resource) {
}
/**
* Returns the activity for this reservation.
*/
Override
public IlvActivity getActivity() {
queryPropertiesIfNeeded();
ActivityState activityState = getActivityState(dbRecord.getActivityKey());
return activityState.getActivity();
}
/**
* Returns a parameter string that represents the state of this reservation.
*/
Override
protected String paramString() {
StringBuffer buf = new StringBuffer("key=");
buf.append(getDBKey());
buf.append(',');
buf.append(super.paramString());
return buf.toString();
}
}
}