/******************************************************************************* * Copyright 2006 - 2012 Vienna University of Technology, * Department of Software Technology and Interactive Systems, IFS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ /** * */ package eu.scape_project.planning.plato.wfview.full; import java.util.ArrayList; import java.util.List; import javax.enterprise.context.ConversationScoped; import javax.faces.model.SelectItem; import javax.inject.Inject; import javax.inject.Named; import eu.scape_project.planning.bean.CriterionSelector; import eu.scape_project.planning.manager.StorageException; import eu.scape_project.planning.model.DigitalObject; import eu.scape_project.planning.model.Plan; import eu.scape_project.planning.model.PlanState; import eu.scape_project.planning.model.policy.PreservationCase; import eu.scape_project.planning.model.scales.BooleanScale; import eu.scape_project.planning.model.scales.FloatRangeScale; import eu.scape_project.planning.model.scales.FloatScale; import eu.scape_project.planning.model.scales.FreeStringScale; import eu.scape_project.planning.model.scales.IntRangeScale; import eu.scape_project.planning.model.scales.IntegerScale; import eu.scape_project.planning.model.scales.OrdinalScale; import eu.scape_project.planning.model.scales.PositiveFloatScale; import eu.scape_project.planning.model.scales.PositiveIntegerScale; import eu.scape_project.planning.model.scales.Scale; import eu.scape_project.planning.model.scales.YanScale; import eu.scape_project.planning.model.tree.Leaf; import eu.scape_project.planning.model.tree.Node; import eu.scape_project.planning.model.tree.TreeNode; import eu.scape_project.planning.plato.bean.TreeHelperBean; import eu.scape_project.planning.plato.wf.AbstractWorkflowStep; import eu.scape_project.planning.plato.wf.IdentifyRequirements; import eu.scape_project.planning.plato.wfview.AbstractView; import eu.scape_project.planning.policies.OrganisationalPolicies; import eu.scape_project.planning.utils.Downloader; import org.richfaces.event.FileUploadEvent; import org.richfaces.model.UploadedFile; import org.slf4j.Logger; /** * @author Michael Kraxner, Markus Hamm */ @Named("identifyRequirements") @ConversationScoped public class IdentifyRequirementsView extends AbstractView { private static final long serialVersionUID = -1209024050675908703L; @Inject private Logger log; @Inject private IdentifyRequirements identifyRequirements; @Inject private Downloader downloader; /** * Supporting class for AJAX Criterion selection. This selection is used for * requirement - criterion mapping. */ @Inject private CriterionSelector critSelector; @Inject private TreeHelperBean requirementstreeHelper; @Inject private OrganisationalPolicies policies; /** * Indicates whether the nodes comments are edited or scale,restriction, * unit ... */ private boolean editingNodeComments = false; /** * Variable encapsulating the ObjectiveTree-Root in a list. This is * required, because <rich:treeModelRecursiveAdaptor> root variable requires * a list to work properly. */ private List<TreeNode> treeRoots; /** * Items for the scale SelectMenu. */ private List<SelectItem> scaleList; private DigitalObject importFile; /** * Leaf selected (last clicked) in the requirements-tree. */ private Leaf selectedLeaf; private PreservationCase selectedPreservationCase; /** * Creates a new view. */ public IdentifyRequirementsView() { currentPlanState = PlanState.RECORDS_CHOSEN; name = "Identify Requirements"; viewUrl = "/plan/identifyrequirements.jsf"; group = "menu.defineRequirements"; treeRoots = new ArrayList<TreeNode>(); scaleList = new ArrayList<SelectItem>(); importFile = null; } @Override public void init(Plan plan) { super.init(plan); treeRoots = new ArrayList<TreeNode>(); treeRoots.add(plan.getTree().getRoot()); populateScaleList(); critSelector.init(); policies.init(); selectedPreservationCase = policies .getPreservationCase(plan.getProjectBasis().getSelectedPreservationCaseURI()); if (plan.getTree().getRoot().getChildren().size() == 0) { generateTreeFromPolicies(); } requirementstreeHelper.expandAll(plan.getTree().getRoot()); } /** * Attaches a new Leaf to the given object (which is, hopefully, a Node). * * @param object * Node where the new Leaf should be attached. */ public void addLeaf(Object object) { if (object instanceof Node) { Node node = (Node) object; Leaf newLeaf = identifyRequirements.addNewLeaf(node); requirementstreeHelper.expandNode(newLeaf); } } /** * Attaches a new Node to the given object (which is, hopefully, a Node). * * @param object * Node where the new Node should be attached. */ public void addNode(Object object) { if (object instanceof Node) { Node node = (Node) object; Node newNode = identifyRequirements.addNewNode(node); requirementstreeHelper.expandNode(newNode); } } /** * Method responsible for removing a given node from the objective tree. * * @param objectToRemove * Node to remove from the objective tree. */ public void removeTreeNode(Object objectToRemove) { TreeNode nodeToRemove = (TreeNode) objectToRemove; requirementstreeHelper.closeNode(nodeToRemove); identifyRequirements.removeTreeNode(nodeToRemove); } /** * Converts a node to a leaf. * * @param object * Node to convert to a leaf. */ public void convertToLeaf(Object object) { identifyRequirements.convertToLeaf((Node) object); } /** * Converts a leaf to a node. * * @param object * Leaf to convert to a node. */ public void convertToNode(Object object) { identifyRequirements.convertToNode((Leaf) object); } /** * Method responsible for starting the download of a wanted file. * * @param object * DigitalObject wanted to download. */ public void downloadAttachedFile(DigitalObject object) { DigitalObject objectIncludingData = null; try { objectIncludingData = identifyRequirements.fetchAttachedFile(object); } catch (StorageException e) { log.error("Exception at trying to fetch attached file with pid " + object.getPid() + ": " + e.getMessage(), e); facesMessages.addError("importPanel", "Unable to fetch attached file. Please try again."); return; } downloader.download(objectIncludingData); } /** * Method responsible for uploading/attaching a file. * * @param event * Richfaces FileUploadEvent data. */ public void uploadFile(FileUploadEvent event) { UploadedFile file = event.getUploadedFile(); // Put file-data into a digital object DigitalObject digitalObject = new DigitalObject(); digitalObject.setFullname(file.getName()); digitalObject.getData().setData(file.getData()); digitalObject.setContentType(file.getContentType()); try { identifyRequirements.attachFile(digitalObject); } catch (StorageException e) { log.error("Exception at trying to attach file.", e); facesMessages.addError("Unable to attach file. Please try again."); } } /** * Method responsible for removing a previously attached file. * * @param fileToRemove * Attached file to remove. */ public void removeAttachedFile(DigitalObject fileToRemove) { identifyRequirements.removeAttachedFile(fileToRemove); } /** * Method responsible for selecting/setting a file for a later import. * * @param event * Richfaces FileUploadEvent data. */ public void selectImportFile(FileUploadEvent event) { UploadedFile file = event.getUploadedFile(); // Do some input checks if (!file.getName().endsWith("mm")) { facesMessages.addError("importPanel", "Please select a FreeMind file."); importFile = null; return; } // Put file-data into a digital object importFile = new DigitalObject(); importFile.setFullname(file.getName()); importFile.getData().setData(file.getData()); importFile.setContentType(file.getContentType()); } /** * Method responsible for importing a FreeMind file which does not contain * units. */ public void importFreeMindWithoutUnits() { boolean success = identifyRequirements.importTreeFromFreeMind(importFile, false); if (success) { facesMessages.addInfo("importPanel", "Tree imported successfully"); importFile = null; // reset tree root of objective tree treeRoots.clear(); treeRoots.add(plan.getTree().getRoot()); requirementstreeHelper.expandAll(plan.getTree().getRoot()); } else { facesMessages.addError("importPanel", "Error at importing FreeMind file. Maybe it is currupted. " + "Please make sure you added at least one level of nodes to the midmap."); } } /** * Method responsible for importing a FreeMind file which does contain * units. */ public void importFreeMindWithUnits() { boolean success = identifyRequirements.importTreeFromFreeMind(importFile, true); if (success) { facesMessages.addInfo("importPanel", "Tree imported successfully"); importFile = null; // reset tree root of objective tree treeRoots.clear(); treeRoots.add(plan.getTree().getRoot()); requirementstreeHelper.expandAll(plan.getTree().getRoot()); } else { facesMessages.addError("importPanel", "Error at importing FreeMind file. Maybe it is currupted. " + "Please make sure you added at least one level of nodes to the midmap."); } } /** * Method responsible for starting the download of the current requirement * tree represented in FreeMind format. */ public void downloadTreeAsFreeMind() { String freeMindXML = identifyRequirements.exportTreeAsFreeMindXML(); downloader.downloadMM(freeMindXML, plan.getPlanProperties().getName() + ".mm"); } /** * Method responsible for populating possible SelectItmes of the Scale * SelectBox (showing up in the requirements tree). */ private void populateScaleList() { if (scaleList.size() > 0) { return; } List<Scale> scales = new ArrayList<Scale>(); scales.add(new BooleanScale()); scales.add(new YanScale()); scales.add(new OrdinalScale()); scales.add(new IntegerScale()); scales.add(new IntRangeScale()); scales.add(new FloatScale()); scales.add(new FloatRangeScale()); scales.add(new PositiveFloatScale()); scales.add(new PositiveIntegerScale()); scales.add(new FreeStringScale()); for (Scale scale : scales) { scaleList.add(new SelectItem(scale.getClass().getCanonicalName(), scale.getDisplayName())); } } /** * Method responsible for setting the selected (last clicked) leaf. * * @param leaf * Selected leaf */ public void selectLeaf(Leaf leaf) { selectedLeaf = (Leaf) leaf; critSelector.selectMeasure(selectedLeaf.getMeasure()); log.debug("Selected leaf with id=" + selectedLeaf.getId()); } /** * Method responsible for attaching the user selected criterion to the * selected leaf. */ public void assignCriterionMapping() { identifyRequirements.assignMeasureToLeaf(critSelector.getSelectedMeasure(), selectedLeaf); } /** * Method responsible for detaching any criterion from the selected leaf. */ public void detachCriterionMapping() { identifyRequirements.detachCriterionFromLeaf(selectedLeaf); } public void generateTreeFromPolicies() { if (selectedPreservationCase == null) { return; } boolean success = identifyRequirements.createTreeFromPreservationCase(selectedPreservationCase); if (success) { facesMessages .addInfo("Decision criteria successfully created based on control policies of the selected preservation case."); treeRoots.clear(); treeRoots.add(plan.getTree().getRoot()); requirementstreeHelper.expandAll(plan.getTree().getRoot()); } } @Override protected AbstractWorkflowStep getWfStep() { return identifyRequirements; } // --------------- getter/setter --------------- public boolean isEditingNodeComments() { return editingNodeComments; } public void setEditingNodeComments(boolean editingNodeComments) { this.editingNodeComments = editingNodeComments; } public List<TreeNode> getTreeRoots() { return treeRoots; } public void setTreeRoots(List<TreeNode> treeRoots) { this.treeRoots = treeRoots; } public List<SelectItem> getScaleList() { return scaleList; } public void setScaleList(List<SelectItem> scaleList) { this.scaleList = scaleList; } public DigitalObject getImportFile() { return importFile; } public void setImportFile(DigitalObject importFile) { this.importFile = importFile; } public CriterionSelector getCritSelector() { return critSelector; } public void setCritSelector(CriterionSelector critSelector) { this.critSelector = critSelector; } public TreeHelperBean getRequirementstreeHelper() { return requirementstreeHelper; } public PreservationCase getSelectedPreservationCase() { return selectedPreservationCase; } }