org.eclipse.ice.client.widgets.moose.MOOSEFormEditor.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ice.client.widgets.moose.MOOSEFormEditor.java

Source

/*******************************************************************************
 * Copyright (c) 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.client.widgets.moose;

import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.net.URL;
import java.util.ArrayList;

import org.apache.commons.io.FilenameUtils;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.ice.client.common.ActionTree;
import org.eclipse.ice.client.widgets.ICEFormEditor;
import org.eclipse.ice.client.widgets.ICEFormInput;
import org.eclipse.ice.client.widgets.ICEFormPage;
import org.eclipse.ice.client.widgets.jme.ViewFactory;
import org.eclipse.ice.client.widgets.moose.components.PlantBlockManager;
import org.eclipse.ice.client.widgets.reactoreditor.plant.PlantAppState;
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.ResourceComponent;
import org.eclipse.ice.datastructures.form.TreeComposite;
import org.eclipse.ice.datastructures.resource.ICEResource;
import org.eclipse.ice.item.nuclear.MOOSE;
import org.eclipse.ice.item.nuclear.MOOSEModel;
import org.eclipse.ice.reactor.plant.PlantComposite;
import org.eclipse.ice.viz.service.jme3.application.ViewAppState;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.editor.IFormPage;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;

import com.jme3.math.Vector3f;

/**
 * This class extends the default {@link ICEFormEditor} to enable it to draw a
 * {@link PlantAppState}, a 3D view built on jME3 for viewing plant models.
 * 
 * @author Jordan H. Deyton
 * 
 */
public class MOOSEFormEditor extends ICEFormEditor {

    /**
     * ID for Eclipse, used for the bundle's editor extension point.
     */
    public static final String ID = "org.eclipse.ice.client.widgets.moose.MOOSEFormEditor";

    /**
     * The Eclipse IFormPage ID used for the Plant View page.
     */
    private static final String PLANT_PAGE_ID = "Plant View";

    /**
     * The {@link Entry} corresponding to the available apps in the MOOSE Model
     * Builder.
     */
    private Entry appsEntry;

    private DataComponent postProcessors;

    // ---- Plant Page variables ---- //
    /**
     * The PlantAppState rendered on the Plant View page.
     */
    private PlantAppState plantView;

    /**
     * The factory responsible for synchronizing the current "Components"
     * TreeComposite with the {@link #plantApplication}'s current
     * {@link PlantComposite}.
     */
    private final PlantBlockManager factory = new PlantBlockManager();

    /**
     * Whether or not to render the plant view with wireframes.
     */
    private boolean wireframe;

    // ------------------------------ //

    /**
     * In addition to the default behavior, this method registers with the MOOSE
     * form's mesh {@link ResourceComponent} to listen for add/insert/remove
     * events. The intent is to pull the current {@link #meshURI} from the model
     * and render it in the {@link #plot} on the mesh page.
     * 
     * @param input
     *            The editor's input. This should be of the type
     *            {@link ICEFormInput}.
     */
    @Override
    protected void setInput(IEditorInput input) {
        super.setInput(input);

        if (input instanceof ICEFormInput) {
            // Get the ResourceComponent from the MOOSE Model.
            Form form = ((ICEFormInput) input).getForm();

            // Get the Entry that contains the available apps.
            DataComponent dataComp = (DataComponent) form.getComponent(MOOSEModel.fileDataComponentId);
            appsEntry = dataComp.retrieveEntry("MOOSE-Based Application");
            postProcessors = (DataComponent) form.getComponent(MOOSE.ppDataId);
        }

        return;
    }

    /*
     * This method is overridden to provide an additional SelectionAdapter to
     * the Go button that automatically displays requested Postprocessors.
     * 
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.ice.client.widgets.ICEFormEditor#createHeaderContents(org
     * .eclipse.ui.forms.IManagedForm)
     */
    @Override
    protected void createHeaderContents(IManagedForm headerForm) {

        // Do the regular create Header Contents
        super.createHeaderContents(headerForm);

        // Add another SelectionAdapter that kicks off a new
        // thread to handle automatically showing specified
        // Postprocessors.
        goButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {

                if ("Launch the Job".equals(processName)) {
                    Thread ppThread = new Thread(new Runnable() {
                        @Override
                        public void run() {

                            // Local Declarations
                            ArrayList<ICEResource> resourceList = new ArrayList<ICEResource>();
                            ArrayList<String> enabledPPs = new ArrayList<String>();
                            ResourceComponent resources;

                            // / Loop over the Postprocessors and add their
                            // names
                            // to the String list if they are enabled by the
                            // user
                            for (Entry postProcessor : postProcessors.retrieveAllEntries()) {
                                if ("yes".equals(postProcessor.getValue())) {
                                    enabledPPs.add(postProcessor.getName());
                                }
                            }

                            // If we have enabled Postprocessors, then let's
                            // display
                            // them now that the user has selected Go
                            if (!enabledPPs.isEmpty()) {

                                // Kick off a little event loop that loads up a
                                // list of the Resources corresponding to the
                                // enabled
                                // Postprocessors.
                                while (resourceList.size() != enabledPPs.size()) {

                                    // Grab the ResourceComponent
                                    resources = resourceComponentPage.getResourceComponent();

                                    // Sleep a little bit
                                    try {
                                        Thread.sleep(500);
                                    } catch (InterruptedException e) {
                                        logger.error(getClass().getName() + " Exception!", e);
                                    }

                                    // Loop over the ICEResources and add them
                                    // to the list if they correspond to enabled
                                    // Postprocessors and have valid data
                                    for (ICEResource r : resources.getResources()) {
                                        if (enabledPPs.contains(FilenameUtils.removeExtension(r.getName()))
                                                && hasValidPostprocessorData(r)) {
                                            resourceList.add(r);
                                        }
                                    }
                                }

                                // Now that we have the total list of
                                // ICEResources
                                // let's show the Output FormPage, which should
                                // be index 1,
                                // and then show the ICEResource on the
                                // ICEResourcePage.
                                for (final ICEResource r : resourceList) {

                                    // Kick off on UI thread
                                    PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
                                        @Override
                                        public void run() {
                                            try {
                                                MOOSEFormEditor.this.setActivePage(1);

                                                resourceComponentPage.showResource(r);
                                            } catch (PartInitException e) {
                                                logger.error(getClass().getName() + " Exception!", e);
                                            }
                                        }

                                    });

                                }
                            }
                        }
                    });

                    // Start that thread.
                    ppThread.start();
                }

            }
        });

        return;
    }

    /**
     * This private method is used to decide whether or not the given
     * ICEResource contains valid Postprocessor data to plot. Basically, for now
     * it naively checks that there is more than one line in the file, because
     * if there was 1 or less, then we would have no data or just the feature
     * line describing the data.
     * 
     * @param r
     * @return validData Whether or not there is valid data in the resource
     */
    private boolean hasValidPostprocessorData(ICEResource r) {

        // Simply count the number of lines in the resource file
        try {
            LineNumberReader reader = new LineNumberReader(new FileReader(r.getPath().getPath()));
            int cnt = 0;
            String lineRead = "";
            while ((lineRead = reader.readLine()) != null) {
            }

            cnt = reader.getLineNumber();
            reader.close();

            if (cnt <= 1) {
                return false;
            } else {
                return true;
            }
        } catch (IOException e) {
            logger.error(getClass().getName() + " Exception!", e);
            return false;
        }
    }

    /**
     * Provides a Plant View page with a single {@link PlantApplication} for use
     * with RELAP-7.
     */
    private void addPlantPage() {
        // Do not add more than one plant page.
        if (findPage(PLANT_PAGE_ID) == null) {

            // Add a page with a plant view.
            try {
                addPage(new ICEFormPage(this, PLANT_PAGE_ID, "Plant View") {
                    @Override
                    protected void createFormContent(IManagedForm managedForm) {

                        // The plant view should consume the whole page.
                        Section section;
                        FormToolkit toolkit = managedForm.getToolkit();

                        // Set up the overall layout (FillLayout).
                        Composite body = managedForm.getForm().getBody();
                        body.setLayout(new FillLayout());

                        // Create a Section for the plant view.
                        section = toolkit.createSection(body,
                                ExpandableComposite.NO_TITLE | ExpandableComposite.EXPANDED);
                        populatePlantViewSection(section, toolkit);
                        // No layout data to set for FillLayouts.

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

        return;
    }

    /**
     * Creates the content used for the plant view.
     * 
     * @param section
     *            The {@code Section} that should contain the plant view.
     * @param toolkit
     *            The {@code FormToolkit} used to decorate widgets as necessary.
     */
    private void populatePlantViewSection(Section section, FormToolkit toolkit) {
        // Get the background color to use later.
        Color background = section.getBackground();

        // Create an analysis composite to contain a ToolBar and an
        // analysis-based view.
        Composite analysisComposite = new Composite(section, SWT.NONE);
        analysisComposite.setBackground(background);
        analysisComposite.setLayout(new GridLayout(1, false));
        // Set the overall client of the plant view's Section.
        section.setClient(analysisComposite);

        // Create a ToolBarManager so we can add JFace Actions to it.
        ToolBarManager toolBarManager = new ToolBarManager(SWT.RIGHT);
        // Fill the ToolBar with customized controls.
        fillPlantViewToolBar(toolBarManager);
        toolBarManager.update(true);
        // Add it to the view.
        ToolBar toolBar = toolBarManager.createControl(analysisComposite);
        toolBar.setBackground(background);
        toolBar.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));

        // Create the plant view.
        TreeComposite components = findComponentBlock();
        factory.setTree(components);
        PlantComposite plant = factory.getPlant();
        plantView = new ViewFactory().createPlantView(plant);

        // Render the plant view in the analysis Composite.
        Composite plantComposite = plantView.createComposite(analysisComposite);
        plantComposite.setBackground(background);
        plantComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        // Make sure the factory/plant is reset when the plant view is disposed.
        plantComposite.addDisposeListener(new DisposeListener() {
            @Override
            public void widgetDisposed(DisposeEvent e) {
                factory.setTree(new TreeComposite());
            }
        });

        return;
    }

    /**
     * Fills the plant view's {@code ToolBar} with supported actions.
     * 
     * @param toolBar
     *            The plant view's {@code ToolBar}'s manager.
     */
    private void fillPlantViewToolBar(ToolBarManager toolBar) {
        Action action;

        // Set the action's image (a camera).
        Bundle bundle = FrameworkUtil.getBundle(getClass());
        Path imagePath;
        URL imageURL;
        ImageDescriptor image;

        // TODO Use an ImageRegistry instead of hard-coded ImageDescriptors.

        final float moveRate = 1f;
        final float rotateRate = (float) (Math.PI * 0.1);

        // Add an action that toggles the wireframe boolean.
        // Also clear the wireframe setting.
        wireframe = false;
        toolBar.add(new Action("Wireframe") {
            @Override
            public void run() {
                wireframe = !wireframe;
                plantView.setWireframe(wireframe);
            }
        });

        // Add a new menu with the following options:
        // Reset the camera - resets the camera's orientation
        // YZ - sets the camera to view the YZ plane
        // XY - sets the camera to view the XY plane
        // ZX - sets the camera to view the ZX plane
        ActionTree cameraTree = new ActionTree("Camera Orientation");
        cameraTree.add(new ActionTree(new Action("Reset to current default") {
            @Override
            public void run() {
                plantView.resetCamera();
            }
        }));
        cameraTree.add(new ActionTree(new Action("YZ (Y right, Z up - initial default)") {
            @Override
            public void run() {
                Vector3f position = new Vector3f(10f, 0f, 0f);
                Vector3f dir = new Vector3f(-1f, 0f, 0f);
                Vector3f up = Vector3f.UNIT_Z;
                plantView.setDefaultCameraPosition(position);
                plantView.setDefaultCameraOrientation(dir, up);
                plantView.resetCamera();
            }
        }));
        cameraTree.add(new ActionTree(new Action("XY (X right, Y up)") {
            @Override
            public void run() {
                Vector3f position = new Vector3f(0f, 0f, 10f);
                Vector3f dir = new Vector3f(0f, 0f, -1f);
                Vector3f up = Vector3f.UNIT_Y;
                plantView.setDefaultCameraPosition(position);
                plantView.setDefaultCameraOrientation(dir, up);
                plantView.resetCamera();
            }
        }));
        cameraTree.add(new ActionTree(new Action("ZX (Z right, X up)") {
            @Override
            public void run() {
                Vector3f position = new Vector3f(0f, 10f, 0f);
                Vector3f dir = new Vector3f(0f, -1f, 0f);
                Vector3f up = Vector3f.UNIT_X;
                plantView.setDefaultCameraPosition(position);
                plantView.setDefaultCameraOrientation(dir, up);
                plantView.resetCamera();
            }
        }));
        toolBar.add(cameraTree.getContributionItem());

        // TODO Move this elsewhere in the ToolBar.
        action = new Action("Save Image") {
            @Override
            public void run() {
                plantView.exportImage();
            }
        };
        // Set the action's image (a camera).
        imagePath = new Path("icons" + System.getProperty("file.separator") + "camera.png");
        imageURL = FileLocator.find(bundle, imagePath, null);
        ImageDescriptor imageDescriptor = ImageDescriptor.createFromURL(imageURL);
        action.setImageDescriptor(imageDescriptor);
        ActionTree saveImageTree = new ActionTree(action);
        toolBar.add(saveImageTree.getContributionItem());

        toolBar.add(new Separator());

        // ---- Movement Arrow Buttons ---- //
        // Strafe left
        action = new Action("Move left (A)") {
            @Override
            public void run() {
                plantView.getFlightCamera().strafeCamera(-1f);
            }
        };
        imagePath = new Path("icons" + System.getProperty("file.separator") + "arrow-left-perspective-16.png");
        imageURL = FileLocator.find(bundle, imagePath, null);
        image = ImageDescriptor.createFromURL(imageURL);
        action.setImageDescriptor(image);
        toolBar.add(action);

        // Move forward
        action = new Action("Move forward (W)") {
            @Override
            public void run() {
                plantView.getFlightCamera().thrustCamera(moveRate);
            }
        };
        imagePath = new Path("icons" + System.getProperty("file.separator") + "arrow-up-perspective-16.png");
        imageURL = FileLocator.find(bundle, imagePath, null);
        image = ImageDescriptor.createFromURL(imageURL);
        action.setImageDescriptor(image);
        toolBar.add(action);

        // Move backward
        action = new Action("Move backward (S)") {
            @Override
            public void run() {
                plantView.getFlightCamera().thrustCamera(-moveRate);
            }
        };
        imagePath = new Path("icons" + System.getProperty("file.separator") + "arrow-down-perspective-16.png");
        imageURL = FileLocator.find(bundle, imagePath, null);
        image = ImageDescriptor.createFromURL(imageURL);
        action.setImageDescriptor(image);
        toolBar.add(action);

        // Strafe right
        action = new Action("Move right (D)") {
            @Override
            public void run() {
                plantView.getFlightCamera().strafeCamera(moveRate);
            }
        };
        imagePath = new Path("icons" + System.getProperty("file.separator") + "arrow-right-perspective-16.png");
        imageURL = FileLocator.find(bundle, imagePath, null);
        image = ImageDescriptor.createFromURL(imageURL);
        action.setImageDescriptor(image);
        toolBar.add(action);

        // Move up
        action = new Action("Move up (SPACE)") {
            @Override
            public void run() {
                plantView.getFlightCamera().raiseCamera(moveRate);
            }
        };
        imagePath = new Path("icons" + System.getProperty("file.separator") + "arrow-up-16.png");
        imageURL = FileLocator.find(bundle, imagePath, null);
        image = ImageDescriptor.createFromURL(imageURL);
        action.setImageDescriptor(image);
        toolBar.add(action);

        // Move down
        action = new Action("Move down (C)") {
            @Override
            public void run() {
                plantView.getFlightCamera().raiseCamera(-moveRate);
            }
        };
        imagePath = new Path("icons" + System.getProperty("file.separator") + "arrow-down-16.png");
        imageURL = FileLocator.find(bundle, imagePath, null);
        image = ImageDescriptor.createFromURL(imageURL);
        action.setImageDescriptor(image);
        toolBar.add(action);
        // -------------------------------- //

        toolBar.add(new Separator());

        // ---- Rotation Arrow Buttons ---- //
        // Roll left
        action = new Action("Roll Left (Q)") {
            @Override
            public void run() {
                plantView.getFlightCamera().rollCamera(-rotateRate);
            }
        };
        imagePath = new Path("icons" + System.getProperty("file.separator") + "arrow-roll-left-16.png");
        imageURL = FileLocator.find(bundle, imagePath, null);
        image = ImageDescriptor.createFromURL(imageURL);
        action.setImageDescriptor(image);
        toolBar.add(action);

        // Roll right
        action = new Action("Roll Right (E)") {
            @Override
            public void run() {
                plantView.getFlightCamera().rollCamera(rotateRate);
            }
        };
        imagePath = new Path("icons" + System.getProperty("file.separator") + "arrow-roll-right-16.png");
        imageURL = FileLocator.find(bundle, imagePath, null);
        image = ImageDescriptor.createFromURL(imageURL);
        action.setImageDescriptor(image);
        toolBar.add(action);

        // Pitch up
        action = new Action("Pitch Up (up arrow)") {
            @Override
            public void run() {
                plantView.getFlightCamera().pitchCamera(rotateRate);
            }
        };
        imagePath = new Path("icons" + System.getProperty("file.separator") + "arrow-pitch-up-16.png");
        imageURL = FileLocator.find(bundle, imagePath, null);
        image = ImageDescriptor.createFromURL(imageURL);
        action.setImageDescriptor(image);
        toolBar.add(action);
        // Pitch down
        action = new Action("Pitch down (down arrow)") {
            @Override
            public void run() {
                plantView.getFlightCamera().pitchCamera(-rotateRate);
            }
        };
        imagePath = new Path("icons" + System.getProperty("file.separator") + "arrow-pitch-down-16.png");
        imageURL = FileLocator.find(bundle, imagePath, null);
        image = ImageDescriptor.createFromURL(imageURL);
        action.setImageDescriptor(image);
        toolBar.add(action);

        // Yaw left
        action = new Action("Yaw Left (left arrow)") {
            @Override
            public void run() {
                plantView.getFlightCamera().yawCamera(-rotateRate);
            }
        };
        imagePath = new Path("icons" + System.getProperty("file.separator") + "arrow-yaw-left-16.png");
        imageURL = FileLocator.find(bundle, imagePath, null);
        image = ImageDescriptor.createFromURL(imageURL);
        action.setImageDescriptor(image);
        toolBar.add(action);
        // Yaw right
        action = new Action("Yaw Right (right arrow)") {
            @Override
            public void run() {
                plantView.getFlightCamera().yawCamera(rotateRate);
            }
        };
        imagePath = new Path("icons" + System.getProperty("file.separator") + "arrow-yaw-right-16.png");
        imageURL = FileLocator.find(bundle, imagePath, null);
        image = ImageDescriptor.createFromURL(imageURL);
        action.setImageDescriptor(image);
        toolBar.add(action);
        // -------------------------------- //

        // ---- Zoom Buttons ---- //
        // ---------------------- //

        return;
    }

    /**
     * Removes the Plant View page if possible.
     */
    private void removePlantPage() {
        // Dispose any resources required for the plant view.
        plantView = null;

        // Finally, remove the page itself.
        removePageWithID(PLANT_PAGE_ID);
    }

    /**
     * Removes the page with the specified ID.
     * 
     * @param id
     *            The ID of the page, e.g. {@link #PLANT_PAGE_ID} or
     *            {@link #MESH_PAGE_ID}.
     */
    private void removePageWithID(String id) {
        IFormPage page = findPage(id);
        if (page != null) {
            removePage(page.getIndex());
        }
    }

    /**
     * Finds the "Components" block in the MOOSE tree.
     * 
     * @return The "Components" block, or an empty, default tree if one could
     *         not be found.
     */
    private TreeComposite findComponentBlock() {
        // This is a convenience method. Currently, it is very similar to
        // findMeshBlock(), so the code has been relocated and shared in
        // findNamedRootBlock(), although this may change soon.
        return findNamedRootBlock("Components");
    }

    /**
     * Finds a block with the specified name under the top level of the MOOSE
     * data tree.
     * 
     * @param name
     *            The name of the block to find. This is not checked for null
     *            since this is a private method.
     * @return The first block ({@code TreeComposite}) with a matching name, or
     *         a default, empty TreeComposite.
     */
    private TreeComposite findNamedRootBlock(String name) {
        TreeComposite namedRootBlock = null;

        // Get the root TreeComposite from the form.
        TreeComposite root = (TreeComposite) iceDataForm.getComponent(MOOSEModel.mooseTreeCompositeId);

        // Find the "Mesh" TreeComposite. We will need to pull the mesh from
        // this node as a file resource.
        for (int i = 0; i < root.getNumberOfChildren(); i++) {
            TreeComposite child = root.getChildAtIndex(i);
            if (name.equals(child.getName())) {
                namedRootBlock = child;
                // Break from the loop.
                i = root.getNumberOfChildren();
            }
        }

        return (namedRootBlock != null ? namedRootBlock : new TreeComposite());
    }

    /**
     * Tells the FormEditor to use the {@link MOOSETreeCompositeViewer} instead
     * of the default TreeCompositeViewer.
     * 
     * @return The String ID of the MOOSETreeCompositeViewer
     */
    @Override
    protected String getTreeCompositeViewerID() {
        return MOOSETreeCompositeView.ID;
    }

    /**
     * Tells the FormEditor to use the MOOSE input tree instead of the first
     * available tree added to the Form.
     */
    @Override
    protected int getTreeCompositeViewerInputID() {
        return MOOSEModel.mooseTreeCompositeId;
    }

    /**
     * In additon to the default behavior when saved, this makes sure the plant
     * and/or mesh view pages are visible depending on the current MOOSE app and
     * input file settings.
     */
    @Override
    public void doSave(IProgressMonitor monitor) {
        super.doSave(monitor);

        // If the selection is for RELAP-7, create a Plant View page
        // if one doesn't already exist. If the selection is NOT for
        // RELAP-7, delete any existing Plant View page.
        String appStr = appsEntry.getValue().toLowerCase();
        if ("relap".equals(appStr)) {
            addPlantPage();
        } else {
            removePlantPage();
        }

        return;
    }
}