/*******************************************************************************
* CogTool Copyright Notice and Distribution Terms
* CogTool 1.3, Copyright (c) 2005-2013 Carnegie Mellon University
* This software is distributed under the terms of the FSF Lesser
* Gnu Public License (see LGPL.txt).
*
* CogTool is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* CogTool is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CogTool; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* CogTool makes use of several third-party components, with the
* following notices:
*
* Eclipse SWT version 3.448
* Eclipse GEF Draw2D version 3.2.1
*
* Unless otherwise indicated, all Content made available by the Eclipse
* Foundation is provided to you under the terms and conditions of the Eclipse
* Public License Version 1.0 ("EPL"). A copy of the EPL is provided with this
* Content and is also available at http://www.eclipse.org/legal/epl-v10.html.
*
* CLISP version 2.38
*
* Copyright (c) Sam Steingold, Bruno Haible 2001-2006
* This software is distributed under the terms of the FSF Gnu Public License.
* See COPYRIGHT file in clisp installation folder for more information.
*
* ACT-R 6.0
*
* Copyright (c) 1998-2007 Dan Bothell, Mike Byrne, Christian Lebiere &
* John R Anderson.
* This software is distributed under the terms of the FSF Lesser
* Gnu Public License (see LGPL.txt).
*
* Apache Jakarta Commons-Lang 2.1
*
* This product contains software developed by the Apache Software Foundation
* (http://www.apache.org/)
*
* jopt-simple version 1.0
*
* Copyright (c) 2004-2013 Paul R. Holser, Jr.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Mozilla XULRunner 1.9.0.5
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (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.mozilla.org/MPL/.
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The J2SE(TM) Java Runtime Environment version 5.0
*
* Copyright 2009 Sun Microsystems, Inc., 4150
* Network Circle, Santa Clara, California 95054, U.S.A. All
* rights reserved. U.S.
* See the LICENSE file in the jre folder for more information.
******************************************************************************/
package edu.cmu.cs.hcii.cogtool.model;
import java.io.IOException;
import java.util.Collection;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import edu.cmu.cs.hcii.cogtool.util.EmptyIterator;
import edu.cmu.cs.hcii.cogtool.util.GlobalAttributed;
import edu.cmu.cs.hcii.cogtool.util.ObjectLoader;
import edu.cmu.cs.hcii.cogtool.util.ObjectSaver;
/**
* This class contains the set of objects representing a demonstration,
* the scripts generated from it by ICognitiveModelGenerator algorithms,
* and the results of analyzing those scripts by IPredictionAlgo algorithms.
*
* @author alexeiser
*/
public class TaskApplication extends GlobalAttributed
{
protected static class ScriptResults
{
public static final int edu_cmu_cs_hcii_cogtool_model_TaskApplication$ScriptResults_version = 0;
protected static final String scriptVAR = "script";
protected static final String resultsVAR = "results";
public Script script;
public Map<IPredictionAlgo, APredictionResult> results = null;
private static ObjectSaver.IDataSaver<ScriptResults> SAVER =
new ObjectSaver.ADataSaver<ScriptResults>() {
@Override
public int getVersion()
{
return edu_cmu_cs_hcii_cogtool_model_TaskApplication$ScriptResults_version;
}
@Override
public void saveData(ScriptResults v, ObjectSaver saver)
throws IOException
{
saver.saveObject(v.script, scriptVAR);
saver.saveObject(v.results, resultsVAR);
}
};
public static void registerSaver()
{
ObjectSaver.registerSaver(ScriptResults.class.getName(), SAVER);
}
private static ObjectLoader.IObjectLoader<ScriptResults> LOADER =
new ObjectLoader.AObjectLoader<ScriptResults>() {
@Override
public ScriptResults createObject()
{
return new ScriptResults();
}
@Override
public void set(ScriptResults target, String variable, Object value)
{
if (variable != null) {
if (variable.equals(scriptVAR)) {
target.script = (Script) value;
}
}
}
@Override
public Map<?, ?> createMap(ScriptResults target,
String variable,
int size)
{
if (variable != null) {
if (variable.equals(resultsVAR)) {
if (target.results == null) {
target.results =
new HashMap<IPredictionAlgo, APredictionResult>();
}
return target.results;
}
}
return super.createMap(target, variable, size);
}
};
public static void registerLoader()
{
ObjectLoader.registerLoader(ScriptResults.class.getName(),
edu_cmu_cs_hcii_cogtool_model_TaskApplication$ScriptResults_version,
LOADER);
}
protected ScriptResults()
{
// For loading
}
public ScriptResults(Script s)
{
script = s;
}
}
public static final int edu_cmu_cs_hcii_cogtool_model_TaskApplication_version = 3;
// Used for loading version 3 instances
protected static final String externalPathVAR = "externalPath";
// Used for loading version 2 instances
protected static final String algorithmVAR = "algorithm";
protected static final String computeBackgroundVAR = "compBackgrnd";
// Used for loading version 1 instances
protected static final String demonstrationVAR = "demonstration";
protected static final String designVAR = "design";
protected static final String taskVAR = "task";
protected static final String scriptResultsVAR = "scriptResults";
// Used for loading version 0 instances
protected static final String scriptsVAR = "scripts";
protected static final String resultsVAR = "results";
protected static final String invalidAlgorithmsVAR = "invalidAlgorithms";
/**
* The associated demonstration.
*/
protected Demonstration demonstration;
/**
* The associated design.
*/
protected Design design;
/**
* The associated task.
*/
protected AUndertaking task;
/**
* Map from ICognitiveModelGenerator to ScriptResults
*/
protected Map<CognitiveModelGenerator, ScriptResults> scriptResults =
new HashMap<CognitiveModelGenerator, ScriptResults>();
/**
* Default prediction computation Algorithm. A null value indicates that
* the TaskApplication should get its "active" algorithm from the project.
*/
protected IPredictionAlgo activeAlgo = null;
/**
* Maintains whether or not prediction computation should happen in a
* background thread; default is to use the value specified by the project.
*/
protected Boolean computeInBackground = TaskApplication.USE_PROJECT_DEFAULT;
/**
* A default associated path, primarily useful for TaskApplications that
* have no demonstrations and were created by importing result data.
*/
protected String defaultExternalPath = null;
public static final Boolean USE_PROJECT_DEFAULT = null;
public static final Boolean RUN_IN_BACKGROUND = Boolean.TRUE;
// Constants for keeping track of how to run the prediction algorithm
public static final Boolean RUN_IN_FOREGROUND = Boolean.FALSE;
private static ObjectSaver.IDataSaver<TaskApplication> SAVER =
new ObjectSaver.ADataSaver<TaskApplication>() {
@Override
public int getVersion()
{
return edu_cmu_cs_hcii_cogtool_model_TaskApplication_version;
}
@Override
public void saveData(TaskApplication v, ObjectSaver saver)
throws java.io.IOException
{
// Demonstration should be saved before design (see below)!
saver.saveObject(v.demonstration, demonstrationVAR);
saver.saveObject(v.design, designVAR);
saver.saveObject(v.task, taskVAR);
saver.saveObject(v.scriptResults, scriptResultsVAR);
saver.saveObject(v.activeAlgo, algorithmVAR);
saver.saveObject(v.computeInBackground, computeBackgroundVAR);
saver.saveObject(v.defaultExternalPath, externalPathVAR);
}
};
public static void registerSaver()
{
ObjectSaver.registerSaver(TaskApplication.class.getName(), SAVER);
ScriptResults.registerSaver();
}
// For version 0, the only model gen algorithm is KLMCognitiveGenerator
private static ObjectLoader.IAggregateLoader scriptLoader =
new ObjectLoader.AAggregateLoader() {
@Override
@SuppressWarnings("unchecked")
public <K, V> void putInMap(ObjectLoader l, Map<K, V> m, K key, V v)
{
// m will be the TaskApplication's scriptResults member
// Ignore key (i.e., algo) -- use KLMCognitiveGenerator.ONLY
// v is the Script
m.put((K) KLMCognitiveGenerator.ONLY,
(V) new ScriptResults((Script) v));
}
};
protected static IPredictionAlgo determinePredictionAlg(APredictionResult r)
{
List<String> traceLines = r.getTraceLines();
IPredictionAlgo computeAlg = null;
if ((traceLines == null) || (traceLines.size() == 0)) {
computeAlg = ACTR6PredictionAlgo.ONLY;
}
else {
String firstLine = traceLines.get(0);
if (firstLine.toLowerCase().indexOf("actr6") >= 0) {
computeAlg = ACTR6PredictionAlgo.ONLY;
}
else {
computeAlg = ACTR5PredictionAlgo.ONLY;
}
}
return computeAlg;
}
// For version 0, the only model gen algorithm is KLMCognitiveGenerator and
// the prediction alg is either ACTR5PredictionAlgo or ACTR6PredictionAlgo
// It's ok to execute putInMap since scripts were saved *before* results!
private static ObjectLoader.IAggregateLoader resultLoader =
new ObjectLoader.AAggregateLoader() {
@Override
@SuppressWarnings("unchecked")
public <K, V> void putInMap(ObjectLoader l, Map<K, V> m, K key, V v)
{
// m will be the results member of the ScriptResults instance
// corresponding to the KLMCognitiveGenerator.ONLY entry
// Ignore key (i.e., algo) -- use ACTR5PredictionAlgo.ONLY
// or ACTR6PredictionAlgo.ONLY based on whether
// the first trace line contains the string "actr6"
// v is the APredictionResult
APredictionResult result = (APredictionResult) v;
m.put((K) determinePredictionAlg(result), v);
TaskApplication ta =
l.getPendingObject(TaskApplication.class);
result.setScript(ta.getScript(KLMCognitiveGenerator.ONLY));
}
};
// For version 0, the only model gen algorithm is KLMCognitiveGenerator and
// the prediction alg is either ACTR5PredictionAlgo or ACTR6PredictionAlgo
// It's ok to execute addToCollection since results were saved
// *before* invalidAlgorithms!
private static ObjectLoader.IAggregateLoader invalidAlgorithmLoader =
new ObjectLoader.AAggregateLoader() {
@Override
public <T> void addToCollection(ObjectLoader l,
Collection<? super T> c,
T v)
{
TaskApplication taskApp =
l.getPendingObject(TaskApplication.class);
if (taskApp != null) {
//TODO:mlh!! taskApp.getDemonstration().noteEdit(false);
}
// // c will be set to the enclosing TaskApplication's
// // scriptResults.values(), which will contain exactly one
// // ScriptResults instance; then, indicate the
// // need to recompute.
// Iterator singleElt = c.iterator();
//
// if (singleElt.hasNext()) {
// ScriptResults sr = (ScriptResults) singleElt.next();
//
// if (sr.results != null) {
// Iterator singleResult = sr.results.values().iterator();
//
// if (singleResult.hasNext()) {
// APredictionResult result =
// (APredictionResult) singleResult.next();
//
// // Need to access directly since the setResultState
// // method is now provided only by APredictionResult
// // and is checked for consistency.
// result.resultState =
// APredictionResult.REQUIRES_RECOMPUTE;
// }
// }
// }
}
};
// Should be called before the scripts get loaded
protected static void patchInvalidDemoSteps(Demonstration demo)
{
Design design = demo.getTaskApplication().getDesign();
Iterator<AScriptStep> loadedSteps = demo.getSteps().iterator();
while (loadedSteps.hasNext()) {
AScriptStep step = loadedSteps.next();
Frame destination = step.getDestinationFrame();
// Check for deleted destination frame
if (destination != null && destination.getDesign() == null) {
destination.setDesign(design);
}
}
}
private static ObjectLoader.IObjectLoader<TaskApplication> LOADER_v0 =
new ObjectLoader.AObjectLoader<TaskApplication>() {
@Override
public TaskApplication createObject()
{
TaskApplication taskApp = new TaskApplication();
Demonstration demo = new Demonstration();
demo.initialState = new DefaultModelGeneratorState();
taskApp.demonstration = demo;
taskApp.demonstration.setTaskApplication(taskApp);
return taskApp;
}
@Override
public Collection<?> createCollection(TaskApplication target,
String variable,
int size)
{
if (variable != null) {
if (variable.equals(invalidAlgorithmsVAR)) {
// See invalidAlgorithmLoader above
return target.scriptResults.values();
}
}
return null;
}
@Override
public Map<?, ?> createMap(TaskApplication target,
String variable,
int size)
{
if (variable != null) {
if (variable.equals(scriptsVAR)) {
// See scriptLoader above
return target.scriptResults;
}
else if (variable.equals(resultsVAR)) {
// See resultLoader above
ScriptResults sr =
target.scriptResults.get(KLMCognitiveGenerator.ONLY);
if (sr != null) {
if (sr.results == null) {
sr.results =
new HashMap<IPredictionAlgo,
APredictionResult>();
}
return sr.results;
}
// Otherwise, returning null will cause ObjectLoader
// code to throw an exception.
}
}
return null;
}
@Override
public ObjectLoader.IAggregateLoader getLoader(String variable)
{
if (variable != null) {
if (variable.equals(scriptsVAR)) {
return scriptLoader;
}
if (variable.equals(resultsVAR)) {
return resultLoader;
}
if (variable.equals(invalidAlgorithmsVAR)) {
return invalidAlgorithmLoader;
}
}
return super.getLoader(variable);
}
};
private static ObjectLoader.IObjectLoader<TaskApplication> LOADER =
new ObjectLoader.AObjectLoader<TaskApplication>() {
@Override
public TaskApplication createObject()
{
return new TaskApplication();
}
@Override
public void set(TaskApplication target, String variable, Object value)
{
if (variable != null) {
if (variable.equals(demonstrationVAR)) {
Demonstration demo = (Demonstration) value;
target.demonstration = demo;
demo.setTaskApplication(target);
}
else if (variable.equals(designVAR)) {
target.design = (Design) value;
// Depends on demonstration being saved first!
patchInvalidDemoSteps(target.getDemonstration());
}
else if (variable.equals(taskVAR)) {
target.task = (AUndertaking) value;
}
else if (variable.equals(algorithmVAR)) {
target.activeAlgo = (IPredictionAlgo) value;
}
else if (variable.equals(computeBackgroundVAR)) {
target.computeInBackground = (Boolean) value;
}
else if (variable.equals(externalPathVAR)) {
target.defaultExternalPath = (String) value;
}
}
}
@Override
public void set(TaskApplication target, String variable, boolean value)
{
if (variable != null) {
if (variable.equals(computeBackgroundVAR)) {
target.computeInBackground =
value ? TaskApplication.RUN_IN_BACKGROUND : TaskApplication.RUN_IN_FOREGROUND;
}
}
}
@Override
public Map<?, ?> createMap(TaskApplication target,
String variable,
int size)
{
if (variable != null) {
if (variable.equals(scriptResultsVAR)) {
return target.scriptResults;
}
}
return super.createMap(target, variable, size);
}
};
public static void registerLoader()
{
ObjectLoader.registerLoader(TaskApplication.class.getName(),
0,
LOADER_v0);
ObjectLoader.registerLoader(TaskApplication.class.getName(),
1,
LOADER);
ObjectLoader.registerLoader(TaskApplication.class.getName(),
2,
LOADER);
ObjectLoader.registerLoader(TaskApplication.class.getName(),
edu_cmu_cs_hcii_cogtool_model_TaskApplication_version,
LOADER);
ScriptResults.registerLoader();
}
/**
* Zero-argument constructor for use by loading
*/
protected TaskApplication() { }
public TaskApplication(AUndertaking t, Design d)
{
design = d;
task = t;
// Must occur after the previous statements
demonstration = new Demonstration(this);
}
/**
* Fetch the associated demonstration.
*/
public Demonstration getDemonstration()
{
return demonstration;
}
/**
* Fetch the Design corresponding to this task-application.
*/
public Design getDesign()
{
return design;
}
/**
* Set the Design corresponding to this task-application.
*/
public void setDesign(Design d)
{
design = d;
}
/**
* Fetch the task corresponding to this task-application.
*/
public AUndertaking getTask()
{
return task;
}
/**
* Set the task corresponding to this task-application.
*/
public void setTask(AUndertaking t)
{
task = t;
}
/**
* Store a script associated with the given cognitive model generation
* algorithm.
*/
public void setScript(CognitiveModelGenerator modelGen, Script script)
{
ScriptResults sr = scriptResults.get(modelGen);
if (sr != null) {
sr.script = script;
}
else {
sr = new ScriptResults(script);
scriptResults.put(modelGen, sr);
}
design.raiseAlert(new TaskApplication.TaskApplicationResultChange(this));
}
/**
* Fetch the script associated with the given cognitive model generation
* algorithm. If none yet assigned, <code>null</code> will be returned.
*/
public Script getScript(CognitiveModelGenerator modelGen)
{
ScriptResults sr = scriptResults.get(modelGen);
if (sr != null) {
return sr.script;
}
return null;
}
/**
* Has a script?
*/
public boolean hasScript()
{
return scriptResults.size() != 0;
}
/**
* Has a computable script?
*/
public boolean hasComputableScript()
{
return hasScript() && getDemonstration().isStartFrameChosen();
}
/**
* Fetch iterator for all ICognitiveModelGenerator values that have
* associated Script values.
*/
public Iterator<CognitiveModelGenerator> getModelGenerators()
{
return scriptResults.keySet().iterator();
}
/**
* Associate with the given result from the given prediction algorithm
* and the given cognitive model generation algorithm (which effectively
* specifies which Script to associate the result with).
* NOTE that one can fetch the ICognitiveModelGenerator from an Script.
*/
public void setResult(CognitiveModelGenerator modelGen,
IPredictionAlgo computeAlg,
APredictionResult result)
{
ScriptResults sr = scriptResults.get(modelGen);
if (sr != null) {
if (sr.results == null) {
sr.results = new HashMap<IPredictionAlgo, APredictionResult>();
}
if (result != null) {
sr.results.put(computeAlg, result);
}
else {
sr.results.remove(computeAlg);
}
design.raiseAlert(new TaskApplication.TaskApplicationResultChange(this));
}
else {
throw new IllegalStateException("Can't set a result for a non-existent script!");
}
}
/**
* Unset the specific result specified by the given prediction algorithm
* and the given cognitive model generation algorithm.
*/
public void unsetResult(CognitiveModelGenerator modelGen,
IPredictionAlgo computeAlg)
{
setResult(modelGen, computeAlg, null);
}
/**
* Clear all results, putting "old" results into given previousResults,
* which is *not* cleared first (if that is desired, the caller should).
* Suitable for undo/redo
*/
public void clearResults(CognitiveModelGenerator modelGen,
Map<IPredictionAlgo, APredictionResult> previousResults)
{
ScriptResults sr = scriptResults.get(modelGen);
if ((sr != null) && (sr.results != null)) {
Iterator<Map.Entry<IPredictionAlgo, APredictionResult>> results =
sr.results.entrySet().iterator();
while (results.hasNext()) {
Map.Entry<IPredictionAlgo, APredictionResult> compAlgResult =
results.next();
previousResults.put(compAlgResult.getKey(),
compAlgResult.getValue());
results.remove();
}
design.raiseAlert(new TaskApplication.TaskApplicationResultChange(this));
}
}
/**
* Fetch the result associated with the given prediction algorithm
* and the given cognitive model generation algorithm (which effectively
* specifies which Script to associate the result with).
* NOTE that one can fetch the ICognitiveModelGenerator from an Script.
*/
public APredictionResult getResult(CognitiveModelGenerator modelGen,
IPredictionAlgo computeAlg)
{
ScriptResults sr = scriptResults.get(modelGen);
if (sr != null) {
if (sr.results != null) {
return sr.results.get(computeAlg);
}
}
return null;
}
/**
* Is there a computed result?
*/
public boolean hasComputedResult()
{
Iterator<ScriptResults> allScriptResults =
scriptResults.values().iterator();
while (allScriptResults.hasNext()) {
ScriptResults sr = allScriptResults.next();
if (sr.results != null) {
Iterator<APredictionResult> testResults =
sr.results.values().iterator();
while (testResults.hasNext()) {
APredictionResult r = testResults.next();
if (r.getResultState() == APredictionResult.IS_COMPUTED) {
return true;
}
}
}
}
return false;
}
/**
* Is there a computed/failed result with traces?
*/
public boolean hasResultTraces()
{
Iterator<ScriptResults> allScriptResults =
scriptResults.values().iterator();
while (allScriptResults.hasNext()) {
ScriptResults sr = allScriptResults.next();
if (sr.results != null) {
Iterator<APredictionResult> testResults =
sr.results.values().iterator();
while (testResults.hasNext()) {
APredictionResult r = testResults.next();
List<String> traceLines = r.getTraceLines();
List<String> errorLines = r.getErrorLines();
if (((traceLines != null) && ! traceLines.isEmpty()) ||
((errorLines != null) && ! errorLines.isEmpty()))
{
return true;
}
}
}
}
return false;
}
/**
* Is there a computed result with steps?
*/
public boolean hasResultSteps()
{
Iterator<ScriptResults> allScriptResults =
scriptResults.values().iterator();
while (allScriptResults.hasNext()) {
ScriptResults sr = allScriptResults.next();
if (sr.results != null) {
Iterator<APredictionResult> testResults =
sr.results.values().iterator();
while (testResults.hasNext()) {
APredictionResult r = testResults.next();
List<ResultStep> parsedSteps = r.getModelSteps();
if ((parsedSteps != null) && ! parsedSteps.isEmpty()) {
return true;
}
}
}
}
return false;
}
public boolean hasResultSteps(IPredictionAlgo algo)
{
Iterator<ScriptResults> allScriptResults =
scriptResults.values().iterator();
while (allScriptResults.hasNext()) {
ScriptResults sr = allScriptResults.next();
if (sr.results != null) {
APredictionResult result = sr.results.get(algo);
if (result != null) {
List<ResultStep> parsedSteps = result.getModelSteps();
return (parsedSteps != null) && ! parsedSteps.isEmpty();
}
}
}
return false;
}
/**
* Fetch iterator for all IPredictionAlgo values associated with
* the given ICognitiveModelGenerator.
*/
public Iterator<IPredictionAlgo> getPredictionAlgs(CognitiveModelGenerator modelGen)
{
ScriptResults sr = scriptResults.get(modelGen);
if ((sr != null) && (sr.results != null)) {
return sr.results.keySet().iterator();
}
return new EmptyIterator<IPredictionAlgo>();
}
/**
* Support for finding the design components referred to by steps
* when duplicating. IMPORTANT: Currently assumes steps are duplicated
* IN ORDER! (This avoids quadratic behavior for determining the current
* frame during the duplication of an Demonstration.)
*/
protected class DemoDuplicateScope implements SimpleWidgetGroup.IWidgetDuplicator
{
protected Design design;
// Maps original frame to frame duplicate
protected Map<Frame, Frame> duplicatedFrames =
new HashMap<Frame, Frame>();
// Maps deleted original widget to widget duplicate
protected Map<IWidget, IWidget> duplicatedWidgets =
new HashMap<IWidget, IWidget>();
// Maps deleted original transition to transition duplicate
protected Map<Transition, Transition> duplicatedTransitions =
new HashMap<Transition, Transition>();
// A group to hold all deleted widgets that should be part of a group
protected SimpleWidgetGroup deletedWidgetGroup = new SimpleWidgetGroup();
protected Frame.IFrameDuplicator deletedFrameDuplicator =
new Frame.IFrameDuplicator()
{
// Maps deleted original frame to frame duplicate
protected Map<Frame, Frame> duplicatedFrames =
new HashMap<Frame, Frame>();
public Frame getOrDuplicate(Frame frameToCopy)
{
Design originalDesign = frameToCopy.getDesign();
// Check if frameToCopy has been deleted
if ((originalDesign != null) &&
originalDesign.containsFrame(frameToCopy))
{
// Not deleted; find from the duplicated design
return design.getFrame(frameToCopy.getName());
}
// Deleted; check if previously duplicated
Frame frameDuplicate =
duplicatedFrames.get(frameToCopy);
if (frameDuplicate == null) {
frameDuplicate =
frameToCopy.duplicate(frameToCopy.getName(), this);
frameDuplicate.setDesign(design);
duplicatedFrames.put(frameToCopy, frameDuplicate);
}
return frameDuplicate;
}
public void recordDuplicateFrame(Frame originalFrame,
Frame frameDuplicate)
{
// Nothing to do
}
};
public DemoDuplicateScope(Design d)
{
design = d;
}
public Frame getFrame(Frame original)
{
Frame frameDuplicate = duplicatedFrames.get(original);
if (frameDuplicate == null) {
frameDuplicate =
(original == null)
? null
: deletedFrameDuplicator.getOrDuplicate(original);
if (frameDuplicate != null) {
duplicatedFrames.put(original, frameDuplicate);
}
}
return frameDuplicate;
}
public IWidget getWidget(IWidget original)
{
Frame originalFrame = original.getFrame();
Frame frameDuplicate = getFrame(originalFrame);
// Check if original has been deleted; frameDuplicate
// cannot be non-null if originalFrame is null!
if ((frameDuplicate != null) &&
originalFrame.containsWidget(original))
{
// Not deleted; find from the duplicated frame
return frameDuplicate.getWidget(original.getName());
}
// Deleted; check if previously duplicated
IWidget widgetCopy = duplicatedWidgets.get(original);
if (widgetCopy == null) {
widgetCopy = Frame.duplicateWidget(original,
deletedFrameDuplicator,
this);
if (widgetCopy != null) {
Frame.duplicateRemoteLabel(original, widgetCopy,
deletedFrameDuplicator, this,
0.0, 0.0);
widgetCopy.setFrame(frameDuplicate);
}
}
return widgetCopy;
}
public TransitionSource getSource(TransitionSource original)
{
if (original == null) {
return null;
}
if (original instanceof IWidget) {
return getWidget((IWidget) original);
}
if (original instanceof InputDevice) {
Frame frameDuplicate = getFrame(original.getFrame());
DeviceType originalType =
((InputDevice) original).getDeviceType();
if (frameDuplicate != null) {
return frameDuplicate.getInputDevice(originalType);
}
throw new IllegalStateException("Device context missing");
}
throw new IllegalStateException("Not a widget nor a device");
}
public Transition getTransition(Transition original)
{
TransitionSource originalSource = original.getSource();
TransitionSource sourceCopy = getSource(originalSource);
// Check if the original has been deleted
if (originalSource.containsTransition(original)) {
// Not deleted; find from the duplicated source
return sourceCopy.getTransition(original.getAction());
}
// Deleted; check if previously duplicated
Transition transitionCopy =
duplicatedTransitions.get(original);
// Check for deleted transition
if (transitionCopy == null) {
transitionCopy =
original.duplicate(sourceCopy,
deletedFrameDuplicator);
duplicatedTransitions.put(original, transitionCopy);
}
return transitionCopy;
}
public Frame.IFrameDuplicator getFrameDuplicator()
{
return deletedFrameDuplicator;
}
public SimpleWidgetGroup getGroup(SimpleWidgetGroup existingGroup)
{
return deletedWidgetGroup;
}
public void placeInContext(IWidget origWidget, IWidget widgetCopy)
{
duplicatedWidgets.put(origWidget, widgetCopy);
}
public IWidget getDuplicate(IWidget origWidget)
{
return duplicatedWidgets.get(origWidget);
}
public void completeWork()
{
// Nothing to do
}
}
/**
* Defines an event which indicates that an item in the list has changed
* such that the contents were re-computed. This event indicates that
* change and requests a redisplay of the results
*
* @author alexeiser
*/
public static class TaskApplicationResultChange extends EventObject
{
public AUndertaking task;
public TaskApplicationResultChange(TaskApplication ta)
{
this(ta.getDesign(), ta.getTask());
}
public TaskApplicationResultChange(Design design, AUndertaking t)
{
super(design);
task = t;
}
}
/**
* Duplicate the TaskApplication, its Demonstration, and all of its
* Scripts and results. Design elements are fetched from the given design.
*/
public TaskApplication duplicate(AUndertaking t, Design d)
{
// Create a scope for looking up objects from the given design.
// Create the duplicate and populate
DemoDuplicateScope duplicateScope = new DemoDuplicateScope(d);
TaskApplication copy = new TaskApplication(t, d);
// Reset the initial state for the demonstration; start frame first
Demonstration copyDemo = copy.getDemonstration();
Frame startFrame =
duplicateScope.getFrame(demonstration.getStartFrame());
copyDemo.setStartFrame(startFrame);
copyDemo.setStartFrameChosen(demonstration.isStartFrameChosen());
// Copy the initial state; this will include the user's mouse hand
// and where that hand starts off initially.
copyDemo.getInitialState().copy(demonstration.getInitialState());
// Copy the demonstration's AScriptStep sequence
copyDemo.copySteps(demonstration.getSteps(), duplicateScope);
// Copy the active algorithm and how to compute
copy.activeAlgo = activeAlgo;
copy.setComputeInBackground(computeInBackground);
// Copy the scripts and results
Iterator<Map.Entry<CognitiveModelGenerator, ScriptResults>> modelGens =
scriptResults.entrySet().iterator();
while (modelGens.hasNext()) {
Map.Entry<CognitiveModelGenerator, ScriptResults> modelGenScriptResult =
modelGens.next();
CognitiveModelGenerator modelGen = modelGenScriptResult.getKey();
ScriptResults scriptAndResults = modelGenScriptResult.getValue();
// Copy the script and set in the new TaskApplication
copy.setScript(modelGen,
scriptAndResults.script.duplicate(copyDemo,
modelGen,
duplicateScope));
// If there are any computed results, copy them
if (scriptAndResults.results != null) {
Iterator<Map.Entry<IPredictionAlgo, APredictionResult>> results =
scriptAndResults.results.entrySet().iterator();
while (results.hasNext()) {
Map.Entry<IPredictionAlgo, APredictionResult> compAlgResult =
results.next();
APredictionResult result = compAlgResult.getValue();
//xyzzymlh What if the result is a proxy?
copy.setResult(modelGen,
compAlgResult.getKey(),
result.duplicate(copy));
}
}
}
copy.copyAttributes(this);
return copy;
}
public void setActiveAlgorithm(IPredictionAlgo computeAlg)
{
activeAlgo = computeAlg;
// Make sure the UI knows to update the cell display based on
// the new active algorithm
// TODO: Should we have a specific change event?
design.raiseAlert(new TaskApplication.TaskApplicationResultChange(this));
}
public IPredictionAlgo getActiveAlgorithm()
{
return activeAlgo;
}
public IPredictionAlgo determineActiveAlgorithm(Project project)
{
// If the activeAlgo is null, return the project default
return ((activeAlgo == null) ? project.getDefaultAlgo()
: activeAlgo);
}
public void setComputeInBackground(Boolean background)
{
computeInBackground = background;
}
public Boolean getComputeInBackground()
{
return computeInBackground;
}
public boolean determineComputeInBackground(Project project)
{
if (computeInBackground == TaskApplication.RUN_IN_BACKGROUND) {
return true;
}
if (computeInBackground == TaskApplication.RUN_IN_FOREGROUND) {
return false;
}
return project.getDefaultRunInBackground();
}
public String getDefaultAssociatedPath()
{
return defaultExternalPath;
}
public void setDefaultAssociatedPath(String s)
{
defaultExternalPath = s;
}
public CognitiveModelGenerator getFirstModelGenerator()
{
Iterator<CognitiveModelGenerator> gens = getModelGenerators();
CognitiveModelGenerator gen = null;
if (gens.hasNext()) {
gen = gens.next();
}
return gen;
}
/**
* Assumes only one model generator per task application - if exactly one
* mapping exists, returns the corresponding script; if none exist, returns
* null; and if more than one exists, throws an exception.
*/
public Script getOnlyScript()
{
if (scriptResults.size() > 1) {
throw new IllegalStateException("More than one script exists in this task application!");
}
CognitiveModelGenerator gen = getFirstModelGenerator();
return getScript(gen);
}
}