org.eclipse.ice.item.nuclear.MOOSE.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ice.item.nuclear.MOOSE.java

Source

/*******************************************************************************
 * Copyright (c) 2012, 2014 UT-Battelle, LLC.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Initial API and implementation and/or initial documentation - Jay Jay Billings,
 *   Jordan H. Deyton, Dasha Gorin, Alexander J. McCaskey, Taylor Patterson,
 *   Claire Saunders, Matthew Wang, Anna Wojtowicz
 *******************************************************************************/
package org.eclipse.ice.item.nuclear;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

import org.apache.commons.io.FilenameUtils;
import org.eclipse.core.resources.IProject;
import org.eclipse.ice.datastructures.ICEObject.Component;
import org.eclipse.ice.datastructures.ICEObject.IUpdateable;
import org.eclipse.ice.datastructures.form.AllowedValueType;
import org.eclipse.ice.datastructures.form.BasicEntryContentProvider;
import org.eclipse.ice.datastructures.form.DataComponent;
import org.eclipse.ice.datastructures.form.Entry;
import org.eclipse.ice.datastructures.form.Form;
import org.eclipse.ice.datastructures.form.FormStatus;
import org.eclipse.ice.datastructures.form.IEntryContentProvider;
import org.eclipse.ice.datastructures.form.ResourceComponent;
import org.eclipse.ice.datastructures.form.TableComponent;
import org.eclipse.ice.datastructures.form.TreeComposite;
import org.eclipse.ice.datastructures.form.iterator.BreadthFirstTreeCompositeIterator;
import org.eclipse.ice.datastructures.resource.ICEResource;
import org.eclipse.ice.item.Item;
import org.eclipse.ice.item.jobLauncher.JobLauncherForm;
import org.eclipse.ice.item.messaging.Message;
import org.eclipse.ice.item.utilities.moose.MOOSEFileHandler;
import org.eclipse.remote.core.IRemoteConnection;
import org.eclipse.remote.core.IRemoteConnectionHostService;

/**
 * The MOOSE Item represents a unification of the MOOSEModel and MOOSELauncher.
 * This Item essentially provides a Composite Item composed of the model and
 * launcher, and as such brokers the data necessary for user input during an
 * entire MOOSE workflow, ie input generation to launching and data
 * visualization.
 * 
 * @author Alex McCaskey
 *
 */
@XmlRootElement(name = "MOOSE")
public class MOOSE extends Item {

    /**
     * Reference to the MOOSE Input Model for this MOOSE workflow.
     */
    @XmlTransient()
    private MOOSEModel mooseModel;

    /**
     * Reference to the MOOSELauncher used in executing a constructed MOOSE
     * input file.
     */
    @XmlTransient()
    private MOOSELauncher mooseLauncher;

    /**
     * Reference to the Model's list of files.
     */
    @XmlTransient()
    private DataComponent modelFiles;

    /**
     * Reference to the DataComponent containing the Postprocessors to display
     * automatically.
     */
    @XmlTransient()
    private DataComponent postProcessorsData;

    /**
     * Reference to the Model's input tree.
     */
    @XmlTransient()
    private TreeComposite modelTree;

    /**
     * Reference to teh mapping between created Postprocessor VizResources and
     * their names.
     */
    @XmlTransient()
    private HashMap<String, ICEResource> postProcessorResources;

    /**
     * This map keeps track of File Entries in the modelFiles DataComponent and
     * their corresponding parent TreeComposites so that we can keep them in
     * sync.
     */
    @XmlTransient()
    private HashMap<String, TreeComposite> fileEntryTreeMapping;

    /**
     * Reference to the id of the DataComponent containign the Postprocessors
     * the user would like to automatically display.
     */
    @XmlTransient()
    public static final int ppDataId = 10;

    /**
     * Boolean to indicate whether this Item has already registered with the
     * necessary Tree blocks.
     */
    @XmlTransient()
    private boolean registered = false;

    /**
     * Nullary constructor.
     */
    public MOOSE() {
        this(null);
        mooseModel = new MOOSEModel(null);
        mooseLauncher = new MOOSELauncher(null);
        addComponents();
    }

    /**
     * The constructor.
     * 
     * @param projectSpace
     */
    public MOOSE(IProject projectSpace) {
        super(projectSpace);
        mooseModel = new MOOSEModel(projectSpace);
        mooseLauncher = new MOOSELauncher(projectSpace);
        addComponents();
    }

    /**
     * 
     */
    private void addComponents() {
        // Loop over all components and add them to this form
        for (Component c : mooseModel.getForm().getComponents()) {
            if (c.getName().equals("Mesh")) {
                c.setName("Mesh and Output Files");
            }
            form.addComponent(c);
        }

        // Grab an explicit reference to the files component from the Model
        modelFiles = (DataComponent) form.getComponent(1);

        // Register this Item as a listener to the MOOSE-Based Application
        // Entry so that if it changes to Remote, we can grab the
        // IRemoteConnection
        modelFiles.retrieveEntry("MOOSE-Based Application").register(this);

        // Add the parallel execution component
        form.addComponent(mooseLauncher.getForm().getComponent(3));

        // Get a handle to the model input tree
        modelTree = (TreeComposite) form.getComponent(2);

        fileEntryTreeMapping = new HashMap<String, TreeComposite>();

        // Initialize the postProcessor Mapping
        postProcessorResources = new HashMap<String, ICEResource>();

        // Create the Postprocessors DataComponent
        postProcessorsData = new DataComponent();
        postProcessorsData.setName("Show Postprocessors?");
        postProcessorsData.setDescription("Enable the Postprocessors you would like to monitor in real time.");
        postProcessorsData.setId(MOOSE.ppDataId);
        form.addComponent(postProcessorsData);

        TreeComposite ppTree;
        if ((ppTree = getTreeByName("Postprocessors")) != null) {
            setupPostprocessorData(ppTree);
        }
    }

    /**
     * Very simply, this method just creates a new Form that we will populate
     * later in the constructor.
     */
    @Override
    protected void setupForm() {
        form = new Form();
    }

    /**
     * Sets the information that identifies the MOOSE Item.
     */
    @Override
    protected void setupItemInfo() {

        // Local declarations
        String description = "The Multiphysics Object-Oriented Simulation "
                + "Environment (MOOSE) is a multiphysics framework developed " + "by Idaho National Laboratory.";

        // Set the model defaults
        setName("MOOSE Workflow");
        setDescription(description);
        setItemBuilderName("MOOSE Workflow");

        // Setup the action list. Remove key-value pair support.
        allowedActions.remove(taggedExportActionString);
        allowedActions.remove(nativeExportActionString);
        allowedActions.add("Launch the Job");
        allowedActions.add("Write MOOSE File");
        return;
    }

    /**
     * (non-Javadoc)
     * 
     * @see org.eclipse.ice.item.Item#cancelProcess()
     */
    @Override
    public FormStatus cancelProcess() {

        // Only cancel if the Item is actuallly processing
        if (status.equals(FormStatus.Processing)) {
            // Try to cancel the action
            mooseLauncher.cancelProcess();
            // Reset the state to "ready" since it was clearly able to process.
            status = FormStatus.ReadyToProcess;
        }

        return status;
    }

    /**
     * (non-Javadoc)
     * 
     * @see org.eclipse.ice.item.Item#reviewEntries(org.eclipse.ice.datastructures.form.Form)
     */
    @Override
    protected FormStatus reviewEntries(Form preparedForm) {

        // Tell the model to review its entries
        FormStatus status = mooseModel.reviewEntries(preparedForm);

        // If the Model finished correctly, clear the old
        // file entries and load new ones.
        if (status.equals(FormStatus.ReadyToProcess)) {
            clearModelFiles();
            loadFileEntries();
        }

        // Register this Item as a listener to the Variables block
        // this is so we can use the variables to populate things like
        // kernel variable entries.
        TreeComposite variablesTree = getTreeByName("Variables");

        if (!registered && variablesTree != null) {
            variablesTree.register(this);
            modelTree.register(this);
            registered = true;
        }

        TreeComposite ppTree;
        if ((ppTree = getTreeByName("Postprocessors")) != null) {
            setupPostprocessorData(ppTree);
        }

        return status;
    }

    /**
     * (non-Javadoc)
     * 
     * @see org.eclipse.ice.item.Item#process(java.lang.String)
     */
    @Override
    public FormStatus process(String actionName) {
        // Local Declarations
        FormStatus retStatus = FormStatus.InfoError;

        // Set our outputFile as the MooseLauncher's output file
        // so we can see the streaming output
        outputFile = mooseLauncher.getOutputFile();

        // Parse the action name
        if ("Launch the Job".equals(actionName)) {

            // FIXME WE NEED TO DO A CHECK FOR ALL THE REQUIRED BLOCKS!!!!

            // Add the ICEUpdater tree block to Outputs
            TreeComposite outputs = getTreeByName("Outputs");
            TreeComposite postProcessors = getTreeByName("Postprocessors");

            // First check to see if we have any post processors to
            // watch for.
            if (postProcessors.isActive() && postProcessors.getNumberOfChildren() > 0) {

                // If we do, we should add an ICEUpdater
                boolean iNeedUpdater = true;

                // If we already have one, then we shouldn't add another one
                for (int i = 0; i < outputs.getNumberOfChildren(); i++) {
                    if ("ICEUpdater".equals(outputs.getChildAtIndex(i).getName())) {

                        // But if the current one is not configured correctly
                        // then we should add a new one, Here we make sure the
                        // Item Id is correct...
                        TreeComposite iceUpdater = outputs.getChildAtIndex(i);
                        DataComponent data = (DataComponent) iceUpdater.getDataNodes().get(0);
                        Entry itemIdEntry = data.retrieveEntry("item_id");
                        if (Integer.valueOf(itemIdEntry.getValue()) != getId()) {
                            itemIdEntry.setValue(String.valueOf(getId()));
                        }

                        // Now we have a valid ICEUpdater, so we don't need
                        // to create a new one.
                        iNeedUpdater = false;
                        break;
                    }
                }

                if (iNeedUpdater) {
                    for (int i = 0; i < outputs.getChildExemplars().size(); i++) {
                        if ("ICEUpdater".equals(outputs.getChildExemplars().get(i).getName())) {
                            TreeComposite updater = (TreeComposite) outputs.getChildExemplars().get(i).clone();
                            outputs.setNextChild(updater);

                            DataComponent data = (DataComponent) updater.getDataNodes().get(0);
                            data.retrieveEntry("item_id").setValue(String.valueOf(getId()));
                            data.retrieveEntry("url")
                                    .setValue("http://localhost:"
                                            + System.getProperty("org.eclipse.equinox.http.jetty.http.port")
                                            + "/ice/update");
                            updater.setActive(true);
                            updater.setActiveDataNode(data);
                            break;
                        }
                    }
                }
            }

            // Get a reference to the Launchers files component
            DataComponent launcherFiles = (DataComponent) mooseLauncher.getForm().getComponent(1);

            // Grab the file name the user has specified for the input file
            String fileName = modelFiles.retrieveEntry("Output File Name").getValue();

            // Write the Moose file if it doesn't exist
            retStatus = mooseModel.process("Write MOOSE File");
            if (!retStatus.equals(FormStatus.Processed)) {
                return retStatus;
            }

            // Set the value of the input file to the user-specified
            // file name
            launcherFiles.retrieveEntry("Input File").setValue(fileName);

            // Update the MooseLauncher's set of input files...
            mooseLauncher.update(launcherFiles.retrieveEntry("Input File"));
            for (Entry e : modelFiles.retrieveAllEntries()) {
                Entry launcherFile = launcherFiles.retrieveEntry(e.getName());
                if (launcherFile != null) {
                    launcherFile.setValue(e.getValue());
                }
            }

            // Get the application URI
            URI appUri = URI.create(modelFiles.retrieveEntry("MOOSE-Based Application").getValue());

            // Check if we're local or remote
            if ("ssh".equals(appUri.getScheme())) {

                mooseLauncher.setExecutable(Paths.get(appUri.getRawPath()).getFileName().toString(), "",
                        appUri.getRawPath() + " -i ${inputFile} --no-color");

                // Setup the hosts table to use the remote host
                TableComponent hostsTable = (TableComponent) mooseLauncher.getForm()
                        .getComponent(JobLauncherForm.parallelId + 1);
                IRemoteConnection remoteConnection = mooseLauncher.getRemoteConnection(appUri.getHost());
                String hostname = remoteConnection.getService(IRemoteConnectionHostService.class).getHostname();
                int index = hostsTable.addRow();
                ArrayList<Entry> row = hostsTable.getRow(index);
                ArrayList<Integer> selected = new ArrayList<Integer>();
                selected.add(new Integer(index));
                row.get(0).setValue(hostname);
                hostsTable.setSelectedRows(selected);

            } else {

                // Set the executable string
                mooseLauncher.setExecutable(new File(appUri).getName(), "",
                        appUri.getPath() + " -i ${inputFile} --no-color");
            }

            // Register as a listener of the resource component
            // so we can add the resources to our resource component
            ((ResourceComponent) mooseLauncher.getForm().getComponent(JobLauncherForm.outputId)).register(this);

            // Launch the Moose application
            retStatus = mooseLauncher.process(actionName);

        } else if ("Write MOOSE File".equals(actionName)) {
            // Simply pass this along to the Model
            retStatus = mooseModel.process(actionName);
        }

        // Set the status flag.
        status = retStatus;

        // Keep the status in sync
        if (status.equals(FormStatus.Processing)) {
            Thread statusThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    while (!status.equals(FormStatus.Processed)) {
                        // Sleep for a bit
                        Thread.currentThread();
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            logger.error(getClass().getName() + " Exception!", e);
                        }

                        // Set the status
                        status = mooseLauncher.getStatus();
                    }

                    return;
                }
            });

            statusThread.start();
        }
        return retStatus;
    }

    /**
     * This method just clears the Model Files DataComponent of its Entries so
     * that we can populate it with new Entries.
     */
    private void clearModelFiles() {

        ArrayList<String> toBeRemoved = new ArrayList<String>();
        for (Entry e : modelFiles.retrieveAllEntries()) {
            String name = e.getName();
            if (!"MOOSE-Based Application".equals(name) && !"Output File Name".equals(name)) {
                toBeRemoved.add(name);
            }
        }

        for (String e : toBeRemoved) {
            modelFiles.deleteEntry(e);
        }
    }

    /**
     * (non-Javadoc)
     * 
     * @see org.eclipse.ice.item.Item#loadInput(java.lang.String)
     */
    @Override
    public void loadInput(String input) {
        mooseModel.loadInput(input);

        form = new Form();

        String description = "The Multiphysics Object-Oriented Simulation "
                + "Environment (MOOSE) is a multiphysics framework developed " + "by Idaho National Laboratory.";

        // Set the model defaults
        form.setName("MOOSE Workflow");
        form.setDescription(description);
        form.setItemID(getId());
        form.setActionList(allowedActions);

        // Loop over all components and add them to this form
        for (Component c : mooseModel.getForm().getComponents()) {
            form.addComponent(c);
        }

        // Add the model files component
        modelFiles = (DataComponent) form.getComponent(1);

        // Loop over all components and add the parallel exec and output
        // components only
        for (Component c : mooseLauncher.getForm().getComponents()) {

            if ("Parallel Execution".equals(c.getName()) || "Output Files and Data".equals(c.getName())) {
                form.addComponent(c);
            }

        }

        // Set up the postProcessorData DataComponent to contain
        // a list of Boolean Discrete Entries for each Postprocessor
        postProcessorsData = new DataComponent();
        postProcessorsData.setName("Show Postprocessors?");
        postProcessorsData.setDescription("Enable the Postprocessors you would like to monitor in real time.");
        postProcessorsData.setId(MOOSE.ppDataId);
        form.addComponent(postProcessorsData);

        TreeComposite ppTree;
        if ((ppTree = getTreeByName("Postprocessors")) != null) {
            setupPostprocessorData(ppTree);
        }

        // Get a handle to the model input tree
        modelTree = (TreeComposite) form.getComponent(2);

        loadFileEntries();

        // Register this Item as a listener to the Variables block
        // this is so we can use the variables to populate things like
        // kernel variable entries.
        TreeComposite vars = getTreeByName("Variables");
        if (vars != null) {
            vars.register(this);
        }
        TreeComposite aux = getTreeByName("AuxVariables");
        if (aux != null) {
            aux.register(this);
        }
        modelTree.register(this);
        registered = true;

        return;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.ice.item.Item#update(org.eclipse.ice.datastructures.ICEObject
     * .IUpdateable)
     */
    @Override
    public void update(IUpdateable updateable) {

        if (updateable instanceof ResourceComponent) {
            ResourceComponent comp = (ResourceComponent) updateable;
            ResourceComponent ourComp = (ResourceComponent) form.getComponent(3);

            ArrayList<String> names = new ArrayList<String>();

            // Get a list of all our Resource Names:
            for (ICEResource r : ourComp.getResources()) {
                names.add(r.getName());
            }

            for (ICEResource r : comp.getResources()) {
                if (!names.contains(r.getName())) {
                    logger.info("Adding Resource to Moose: " + r.getName());
                    ourComp.add(r);
                }
            }

        } else if (updateable instanceof TreeComposite) {
            // If this is a tree composite we should reset our variables
            Thread varThread = new Thread(new Runnable() {

                @Override
                public void run() {
                    new MOOSEFileHandler().setupVariables(modelTree);
                    new MOOSEFileHandler().setupAuxVariables(modelTree);
                }

            });
            varThread.start();

        } else if (updateable instanceof Entry) {

            Entry entry = (Entry) updateable;

            // If we get here, then we have a file Entry that
            // has been changed on the modelFiles component
            // and we need to sync up the tree with it.

            // Grab the DataComponent
            if (fileEntryTreeMapping.containsKey(entry.getName())) {
                DataComponent data = (DataComponent) fileEntryTreeMapping.get(entry.getName()).getDataNodes()
                        .get(0);

                // If not null, loop over the Entries til we find
                // the file Entry.
                if (data != null) {
                    for (Entry e : data.retrieveAllEntries()) {

                        // If the Entry's tag is "false" it is a commented
                        // out
                        // parameter.
                        if (!"false".equals(e.getTag()) && e.getValue() != null && !e.getValue().isEmpty()
                                && (e.getName() + " = " + e.getValue())
                                        .matches(mooseLauncher.getFileDependenciesSearchString())) {

                            // Set the value of the tree's file entry.
                            e.setValue(entry.getValue());
                            break;
                        }
                    }
                }
            }
        }

    }

    /**
     * This method finds the child TreeComposite of modelTree that has the given
     * String name.
     * 
     * @param name
     * @return
     */
    private TreeComposite getTreeByName(String name) {

        for (int i = 0; i < modelTree.getNumberOfChildren(); i++) {
            TreeComposite child = modelTree.getChildAtIndex(i);
            if (child.getName().equals(name)) {
                return child;
            }
        }

        return null;
    }

    /**
     * This method searches the Model input tree and locates all file Entries
     * and loads them on the Model File DataComponent.
     */
    protected void loadFileEntries() {
        // Walk the tree and get all Entries that may represent a file
        BreadthFirstTreeCompositeIterator iter = new BreadthFirstTreeCompositeIterator(modelTree);
        while (iter.hasNext()) {
            TreeComposite child = iter.next();

            // Make sure we have a valid DataComponent
            if (child.getActiveDataNode() != null && child.isActive()) {
                DataComponent data = (DataComponent) child.getActiveDataNode();
                for (Entry e : data.retrieveAllEntries()) {

                    // If the Entry's tag is "false" it is a commented out
                    // parameter.
                    if (!"false".equals(e.getTag()) && e.getValue() != null && !e.getValue().isEmpty()
                            && (e.getName() + " = " + e.getValue())
                                    .matches(mooseLauncher.getFileDependenciesSearchString())) {

                        Entry clonedEntry = (Entry) e.clone();

                        // If this Entry does not have a very descriptive
                        // name
                        // we should reset its name to the block it belongs
                        // to
                        if ("file".equals(clonedEntry.getName().toLowerCase())
                                || "data_file".equals(clonedEntry.getName().toLowerCase())) {
                            clonedEntry.setName(child.getName());
                        }

                        if (!clonedEntry.getValueType().equals(AllowedValueType.File)) {
                            mooseModel.convertToFileEntry(clonedEntry);

                        }

                        // Setup allowed values correctly
                        String extension = FilenameUtils
                                .getExtension(project.getFile(clonedEntry.getValue()).getLocation().toOSString());

                        // Create a new content provider with the new file
                        // in the allowed values list
                        IEntryContentProvider prov = new BasicEntryContentProvider();
                        ArrayList<String> valueList = clonedEntry.getAllowedValues();

                        for (String file : getProjectFileNames(extension)) {
                            if (!valueList.contains(file)) {
                                valueList.add(file);
                            }
                        }
                        prov.setAllowedValueType(AllowedValueType.File);

                        // Finish setting the allowed values and default
                        // value
                        prov.setAllowedValues(valueList);

                        // Set the new provider
                        clonedEntry.setContentProvider(prov);

                        // Set the value
                        clonedEntry.setValue(e.getValue());

                        fileEntryTreeMapping.put(clonedEntry.getName(), child);

                        clonedEntry.register(this);

                        // Add it to the list of model files.
                        modelFiles.addEntry(clonedEntry);
                    }
                }
            }
        }

        return;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.ice.item.Item#update(org.eclipse.ice.item.messaging.Message)
     */
    @Override
    public boolean update(Message message) {

        // Get the message type and string text
        String type = message.getType();
        String text = message.getMessage();

        // Parse the message type
        if ("MESSAGE_POSTED".equals(type)) {

            // If its a message posted, we expect it to
            // be of the format pp_name:time:value
            String[] data = text.split(":");
            String name = data[0];
            Double time = Double.valueOf(data[1]);
            Double value = Double.valueOf(data[2]);

            // We need the jobLaunch directory to create new VizResources
            String directory = mooseLauncher.getJobLaunchDirectory();

            // Get a reference to the VizResource file we are going
            // to create and populate
            File dataFile = new File(directory + System.getProperty("file.separator") + name + ".csv");

            // Get a reference to the ResourceComponent
            ResourceComponent comp = (ResourceComponent) form.getComponent(3);

            try {

                if (!dataFile.exists()) {
                    // If the file hasn't been created yet, we need to create
                    // it and start filling it with post processor data
                    dataFile.createNewFile();

                    // Write the new incoming data
                    PrintWriter printWriter = new PrintWriter(new FileOutputStream(dataFile, true));
                    printWriter.write("Time, " + name + "\n");
                    printWriter.write(time + ", " + value + "\n");
                    printWriter.close();

                    // Create the VizResource, and add it to the
                    // ResourceComponent
                    ICEResource resource = getResource(dataFile.getAbsolutePath());
                    comp.add(resource);

                    // Remember the name of the resource for next time
                    postProcessorResources.put(name, resource);

                } else {

                    // Write the data to the existing resource
                    PrintWriter printWriter = new PrintWriter(new FileOutputStream(dataFile, true));
                    printWriter.write(time + ", " + value + "\n");

                    // Update the ICEResource
                    ICEResource r = postProcessorResources.get(name);

                    // Here we are faking a VizResource notification
                    // by setting the name with its current name
                    r.setName(r.getName());

                    // Close the writer
                    printWriter.close();
                }

            } catch (IOException e) {
                logger.error(getClass().getName() + " Exception!", e);
            }
        }

        return true;
    }

    /**
     * This private method takes the Postprocessor tree node and populates the
     * postProcessorData DataComponent.
     * 
     * @param ppTree
     */
    private void setupPostprocessorData(TreeComposite ppTree) {
        postProcessorsData.clearEntries();
        for (int i = 0; i < ppTree.getNumberOfChildren(); i++) {
            Entry ppEntry = new Entry() {
                @Override
                public void setup() {
                    allowedValueType = AllowedValueType.Discrete;
                    allowedValues.add("yes");
                    allowedValues.add("no");
                    defaultValue = "no";
                }
            };
            ppEntry.setName(ppTree.getChildAtIndex(i).getName());
            ppEntry.setDescription("Select whether this Postprocessor should be displayed in real-time.");
            ppEntry.setId(i);
            postProcessorsData.addEntry(ppEntry);
        }
    }

    /**
     * This operation is used to check equality between the MOOSE Item and
     * another MOOSE Item. It returns true if the Items are equal and false if
     * they are not.
     * 
     * @param otherMoose
     *            The MOOSE Item that should be checked for equality.
     * @return True if the launchers are equal, false if not
     */
    @Override
    public boolean equals(Object other) {

        boolean retVal;
        // Check if they are the same reference in memory
        if (this == other) {
            return true;
        }

        // Check that the object is not null, and that it is an Item
        // Check that these objects have the same ICEObject data
        if (other == null || !(other instanceof MOOSE) || !super.equals(other)) {
            return false;
        }

        // Check data
        MOOSE otherMoose = (MOOSE) other;
        retVal = (this.allowedActions.equals(otherMoose.allowedActions)) && (this.form.equals(otherMoose.form))
                && (this.itemType == otherMoose.itemType) && (this.status.equals(otherMoose.status));

        // Check project
        if (this.project != null && otherMoose.project != null && (!(this.project.equals(otherMoose.project)))) {
            return false;

        }

        // Check project - set to null

        if (this.project == null && otherMoose.project != null
                || this.project != null && otherMoose.project == null) {
            return false;
        }

        if (!mooseModel.equals(otherMoose.mooseModel) && !mooseLauncher.equals(otherMoose.mooseLauncher)) {
            return false;
        }

        return retVal;
    }

    /**
     * This operation returns the hashcode value of the MooseItem.
     * 
     * @return
     *       <p>
     *         The hashcode
     *         </p>
     */
    @Override
    public int hashCode() {

        // Local Declaration
        int hash = 9;
        // Compute hash code from Item data
        hash = 31 * hash + super.hashCode();
        hash = 31 * hash + mooseModel.hashCode();
        hash = 31 * hash + mooseLauncher.hashCode();

        return hash;
    }

    /**
     * Copy the provided Item into this Item.
     * 
     * @param otherMoose
     *            <p>
     *            This operation performs a deep copy of the attributes of
     *            another MOOSE Item into the current MOOSE Item.
     *            </p>
     */
    @Override
    public void copy(Item otherItem) {

        // Return if otherMoose is null
        if (otherItem == null) {
            return;
        }

        // Cast to a MOOSE Item
        MOOSE otherMoose = (MOOSE) otherItem;

        // Copy contents into super and current object
        super.copy(otherMoose);

        // Add the model files component
        modelFiles = (DataComponent) form.getComponent(1);

        // Get a handle to the model input tree
        modelTree = (TreeComposite) form.getComponent(2);

        // Must do this or we can't walk the tree to
        // get file entries correctly
        mooseModel.setActiveDataNodes(modelTree);

        return;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.ice.item.Item#setProject(org.eclipse.core.resources.IProject)
     */
    @Override
    public void setProject(IProject projectSpace) {
        super.setProject(projectSpace);
        mooseModel.setProject(projectSpace);
        mooseLauncher.setProject(projectSpace);
    }

    /**
     * <p>
     * This operation provides a deep copy of the MOOSE Item.
     * </p>
     * 
     * @return
     *       <p>
     *         A clone of the Moose Item.
     *         </p>
     */
    @Override
    public Object clone() {

        // Create a new instance of JobLauncher and copy the contents
        MOOSE clone = new MOOSE();
        clone.copy(this);

        return clone;
    }

}