Package eu.scape_project.planning.model

Source Code of eu.scape_project.planning.model.Plan

/*******************************************************************************
* Copyright 2006 - 2014 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.
*
* This work originates from the Planets project, co-funded by the European Union under the Sixth Framework Programme.
******************************************************************************/
package eu.scape_project.planning.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Transient;
import javax.validation.Valid;

import eu.scape_project.planning.exception.PlanningException;
import eu.scape_project.planning.model.aggregators.WeightedMultiplication;
import eu.scape_project.planning.model.beans.ResultNode;
import eu.scape_project.planning.model.measurement.Measurement;
import eu.scape_project.planning.model.scales.BooleanScale;
import eu.scape_project.planning.model.transform.NumericTransformer;
import eu.scape_project.planning.model.transform.OrdinalTransformer;
import eu.scape_project.planning.model.transform.TransformationMode;
import eu.scape_project.planning.model.transform.Transformer;
import eu.scape_project.planning.model.tree.Leaf;
import eu.scape_project.planning.model.tree.Node;
import eu.scape_project.planning.model.tree.ObjectiveTree;
import eu.scape_project.planning.model.tree.TreeNode;
import eu.scape_project.planning.model.values.INumericValue;
import eu.scape_project.planning.model.values.Value;

/**
* This is a preservation planning project, the root class of all domain model
* data. Please refer to the terminology in deliverable PP4-D1 for an
* explanation of terms.
*
* @author Christoph Becker
*/
@Entity
public class Plan implements Serializable, ITouchable {

    private static final long serialVersionUID = 7855716962826361459L;

    /**
     * the Go/No-Go-decision
     */
    @OneToOne(cascade = CascadeType.ALL)
    private Decision decision = new Decision();

    @Id
    @GeneratedValue
    private int id;

    @OneToOne(cascade = CascadeType.ALL)
    private PlanProperties planProperties = new PlanProperties();

    @OneToOne(cascade = CascadeType.ALL)
    private SampleRecordsDefinition sampleRecordsDefinition = new SampleRecordsDefinition();

    @OneToOne(cascade = CascadeType.ALL)
    private ProjectBasis projectBasis = new ProjectBasis();

    @OneToOne(cascade = CascadeType.ALL)
    private RequirementsDefinition requirementsDefinition = new RequirementsDefinition();

    @Valid
    @OneToOne(cascade = CascadeType.ALL)
    private ObjectiveTree tree = new ObjectiveTree();

    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "alternativesdefinition_id")
    private AlternativesDefinition alternativesDefinition = new AlternativesDefinition();

    @OneToOne(cascade = CascadeType.ALL)
    private Evaluation evaluation = new Evaluation();

    @OneToOne(cascade = CascadeType.ALL)
    private Transformation transformation = new Transformation();

    @OneToOne(cascade = CascadeType.ALL)
    private ImportanceWeighting importanceWeighting = new ImportanceWeighting();

    @OneToOne(cascade = CascadeType.ALL)
    private Recommendation recommendation = new Recommendation();

    @OneToOne(cascade = CascadeType.ALL)
    private ExecutablePlanDefinition executablePlanDefinition = new ExecutablePlanDefinition();

    @OneToOne(cascade = CascadeType.ALL)
    private DigitalObject preservationActionPlan = new DigitalObject();

    @OneToOne(cascade = CascadeType.ALL)
    private PlanDefinition planDefinition = new PlanDefinition();

    @OneToOne(cascade = CascadeType.ALL)
    private ChangeLog changeLog = new ChangeLog();

    /**
     * States if the plan was opened in read only mode
     */
    @Transient
    private boolean readOnly = false;

    public Plan() {
        TreeNode root = new Node();
        root.setName("Root");
        getTree().setRoot(root);
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Transient
    public String getStateName() {
        return this.getPlanProperties().getState().getName();
    }

    public ObjectiveTree getTree() {
        return tree;
    }

    public void setTree(ObjectiveTree tree) {
        this.tree = tree;
    }

    public Decision getDecision() {
        return decision;
    }

    public void setDecision(Decision decision) {
        this.decision = decision;
    }

    public SampleRecordsDefinition getSampleRecordsDefinition() {
        return sampleRecordsDefinition;
    }

    public void setSampleRecordsDefinition(SampleRecordsDefinition sampleRecords) {
        this.sampleRecordsDefinition = sampleRecords;
    }

    public PlanProperties getPlanProperties() {
        return planProperties;
    }

    public void setPlanProperties(PlanProperties planProperties) {
        this.planProperties = planProperties;
    }

    public ProjectBasis getProjectBasis() {
        return projectBasis;
    }

    public void setProjectBasis(ProjectBasis projectBasis) {
        this.projectBasis = projectBasis;
    }

    public ExecutablePlanDefinition getExecutablePlanDefinition() {
        return executablePlanDefinition;
    }

    public void setExecutablePlanDefinition(ExecutablePlanDefinition executablePlanDefinition) {
        this.executablePlanDefinition = executablePlanDefinition;
    }

    public DigitalObject getPreservationActionPlan() {
        return preservationActionPlan;
    }

    public void setPreservationActionPlan(DigitalObject preservationActionPlan) {
        this.preservationActionPlan = preservationActionPlan;
    }

    public PlanDefinition getPlanDefinition() {
        return planDefinition;
    }

    public void setPlanDefinition(PlanDefinition planDefinition) {
        this.planDefinition = planDefinition;
    }

    public AlternativesDefinition getAlternativesDefinition() {
        return alternativesDefinition;
    }

    public void setAlternativesDefinition(AlternativesDefinition alternativesDefinition) {
        this.alternativesDefinition = alternativesDefinition;
    }

    public Evaluation getEvaluation() {
        return evaluation;
    }

    public void setEvaluation(Evaluation evaluation) {
        this.evaluation = evaluation;
    }

    public Transformation getTransformation() {
        return transformation;
    }

    public void setTransformation(Transformation transformation) {
        this.transformation = transformation;
    }

    public ImportanceWeighting getImportanceWeighting() {
        return importanceWeighting;
    }

    public void setImportanceWeighting(ImportanceWeighting importanceWeighting) {
        this.importanceWeighting = importanceWeighting;
    }

    public ChangeLog getChangeLog() {
        return changeLog;
    }

    public void setChangeLog(ChangeLog value) {
        changeLog = value;
    }

    public boolean isChanged() {
        return changeLog.isAltered();
    }

    public void touch() {
        changeLog.touch();
    }

    /**
     * @see ITouchable#handleChanges(IChangesHandler)
     */
    public void handleChanges(IChangesHandler h) {
        h.visit(this);
        // call handleChanges of all child elements
        alternativesDefinition.handleChanges(h);
        if (decision != null)
            decision.handleChanges(h);
        evaluation.handleChanges(h);
        importanceWeighting.handleChanges(h);
        projectBasis.handleChanges(h);
        planProperties.handleChanges(h);
        recommendation.handleChanges(h);
        requirementsDefinition.handleChanges(h);
        sampleRecordsDefinition.handleChanges(h);
        transformation.handleChanges(h);
        executablePlanDefinition.handleChanges(h);
        preservationActionPlan.handleChanges(h);
        planDefinition.handleChanges(h);
        tree.getRoot().handleChanges(h);
    }

    public RequirementsDefinition getRequirementsDefinition() {
        return requirementsDefinition;
    }

    public void setRequirementsDefinition(RequirementsDefinition requirementsDefinition) {
        this.requirementsDefinition = requirementsDefinition;
    }

    public Recommendation getRecommendation() {
        return recommendation;
    }

    public void setRecommendation(Recommendation recommendation) {
        this.recommendation = recommendation;
    }

    /**
     * removes a sample object and its associated result files and values
     *
     * @param record
     *            SampleObject
     */
    public void removeSampleObject(SampleObject record) {
        int index = getSampleRecordsDefinition().getRecords().indexOf(record);
        getSampleRecordsDefinition().removeRecord(record);

        getTree().removeValues(getAlternativesDefinition().getAlternatives(), index);
        // this SampleRecordsDefinition has been changed
        getSampleRecordsDefinition().touch();

        for (Alternative alt : getAlternativesDefinition().getAlternatives()) {
            alt.getExperiment().getResults().remove(record);
            alt.getExperiment().getDetailedInfo().remove(record);
        }

        getAlternativesDefinition().touch();
    }

    /**
     * Adds an alternative.
     *
     * @param alternative
     *            Alternative to add.
     * @throws PlanningException
     *             if an error at adding occurs (e.g. want to add an Alternative
     *             with an already existing name).
     */
    public void addAlternative(Alternative alternative) throws PlanningException {
        alternativesDefinition.addAlternative(alternative);
        alternativesDefinition.touch();
    }

    /**
     * Removes an alternative AND also removes all associated evaluation values
     * contained in the tree, if there are any.
     *
     * @param alternative
     *            alternative to remove
     */
    public void removeAlternative(Alternative alternative) {
        if (recommendation.getAlternative() == alternative) {
            recommendation.setAlternative(null);
            recommendation.setReasoning("");
            recommendation.setEffects("");
        }

        alternativesDefinition.removeAlternative(alternative);
        alternativesDefinition.touch();

        tree.removeValues(alternative);
    }

    /**
     * Method responsible for renaming an alternative (including all necessary
     * follow-up actions).
     *
     * @param alternative
     *            Alternative to rename
     * @param newName
     *            New name of the alternative
     * @throws PlanningException
     *             This exception is thrown at any kind of problems at renaming.
     */
    public void renameAlternative(Alternative alternative, String newName) throws PlanningException {
        // renaming only makes sense if the name really changed
        if (alternative.getName().equals(newName)) {
            return;
        }

        String oldName = alternative.getName();

        // rename the alternative
        alternativesDefinition.renameAlternative(alternative, newName);

        // also update the alternative names in the tree
        tree.updateAlternativeName(oldName, newName);
    }

    /**
     * Sets the experiment workflow and removes associated evaluation values of
     * the alternative.
     *
     * @param alternative
     *            alternative to modify
     * @param workflow
     *            the workflow to set
     */
    public void setExperimentWorkflow(Alternative alternative, DigitalObject workflow) {
        alternative.getExperiment().setWorkflow(workflow);
        alternative.getExperiment().touch();
//        tree.removeValues(alternative);
    }

    /**
     * FIXME: are we really interested in the measures of detailedexperiment
     * info? why not either aggregate: - the measurements instead - the measures
     * mapped to decision criteria?
     *
     * @return
     */
    public List<String> getMeasuredMeasures() {
        List<String> measures = new ArrayList<String>();
        for (Alternative alternative : alternativesDefinition.getConsideredAlternatives()) {
            Experiment exp = alternative.getExperiment();
            for (SampleObject record : sampleRecordsDefinition.getRecords()) {
                // is there any migration-metadata info?
                DetailedExperimentInfo info = exp.getDetailedInfo().get(record);
                if (info != null) {
                    for (Measurement m : info.getMeasurements().values()) {
                        if (!measures.contains(m.getMeasureId()))
                            measures.add(m.getMeasureId());
                    }
                }
            }
        }
        Collections.sort(measures);
        return measures;
    }

    /**
     * sets primitive default values for all numeric and boolean transformers.
     * This is a minimalist approach for now, where we can plug in more
     * sophisticated heuristics in the future. Will on the other hand be less
     * necessary when we introduce property-specific transformers stored in the
     * knowledge base.
     */
    public void calculateDefaultTransformers() {
        for (Leaf leaf : tree.getRoot().getAllLeaves()) {
            Transformer t = leaf.getTransformer();
            if (t instanceof NumericTransformer) {
                // calculate min, max
                // set min,max
                NumericTransformer nt = (NumericTransformer) t;

                // A very specific assumption: the lower the better (!)
                // obviously often not true, e.g. for format/numberOfTools

                double min = Long.MAX_VALUE;
                double max = Long.MIN_VALUE;

                for (Alternative a : alternativesDefinition.getConsideredAlternatives()) {
                    for (Value v : leaf.getValues(a.getName()).getList()) {
                        INumericValue value = (INumericValue) v;
                        if (value.value() > max) {
                            max = value.value();
                        }
                        if (value.value() < min) {
                            min = value.value();
                        }
                    }
                }
                nt.defaults(min, max);
                nt.setMode(TransformationMode.LINEAR);
            } else {
                OrdinalTransformer ot = (OrdinalTransformer) t;
                if (leaf.getScale() instanceof BooleanScale) {

                    ot.getMapping().put("Yes", new TargetValueObject(5));
                    ot.getMapping().put("No", new TargetValueObject(1));
                } else {
                    // total nonsense placeholder for setting something
                    // until we have proper heuristics and property-specific
                    // transformers in the knowledge base
                    for (String s : ot.getMapping().keySet()) {
                        ot.getMapping().put(s, new TargetValueObject(3.33));
                    }
                }
            }
            t.touch();
        }
    }

    /**
     * Returns the acceptable alternatives of a plan. Acceptable alternatives
     * are alternatives which contain no knock-out(0 evaluation).
     *
     * @return List of acceptable alternatives.
     */
    public List<Alternative> getAcceptableAlternatives() {
        List<Alternative> acceptableAlternatives = new ArrayList<Alternative>();
        ResultNode multNode = new ResultNode(getTree().getRoot(), new WeightedMultiplication(),
            getAlternativesDefinition().getConsideredAlternatives());

        for (Alternative a : getAlternativesDefinition().getConsideredAlternatives()) {
            Double alternativeResult = multNode.getResults().get(a.getName());
            if (alternativeResult > 0.0) {
                acceptableAlternatives.add(a);
            }
        }
        return acceptableAlternatives;
    }

    /**
     * Returns a list of all digital objects in the plan.
     *
     * @return a list of digital objects
     */
    public List<DigitalObject> getDigitalObjects() {
        List<DigitalObject> list = new ArrayList<DigitalObject>();
        list.add(getPlanProperties().getReportUpload());
        list.addAll(getSampleRecordsDefinition().getRecords());
        list.addAll(getRequirementsDefinition().getUploads());
        for (Alternative a : getAlternativesDefinition().getAlternatives()) {
          if (a.getExperiment().getWorkflow() != null) {
            list.add(a.getExperiment().getWorkflow());
          }
            for (DigitalObject r : a.getExperiment().getResults().values()) {
                list.add(r);
            }
        }
        if (getExecutablePlanDefinition().getT2flowExecutablePlan() != null) {
            list.add(getExecutablePlanDefinition().getT2flowExecutablePlan());
        }
        if (getPreservationActionPlan() != null) {
            list.add(getPreservationActionPlan());
        }
        if (getSampleRecordsDefinition().getCollectionProfile() != null
            && getSampleRecordsDefinition().getCollectionProfile().getProfile() != null) {
            list.add(getSampleRecordsDefinition().getCollectionProfile().getProfile());
        }
        List<DigitalObject> xcdlObjects = new ArrayList<DigitalObject>();
        for (DigitalObject object : list) {
            if (object.getXcdlDescription() != null) {
                xcdlObjects.add(object.getXcdlDescription());
            }
        }
        list.addAll(xcdlObjects);
        return list;
    }

    /**
     * Method responsible for checking if the given alternative is the current
     * recommended one.
     *
     * @param alternative
     *            Alternative to check.
     * @return True if the given alternative is the current recommended one.
     *         False otherwise.
     */
    public boolean isGivenAlternativeTheCurrentRecommendation(Alternative alternative) {
        if (recommendation.getAlternative() == alternative) {
            return true;
        }

        return false;
    }

    public boolean isApproved() {
        return (getPlanProperties().getState() == PlanState.PLAN_VALIDATED);
    }

    /**
     * Method responsible for initializing not yet initialized experiment infos.
     */
    public void initializeExperimentInfos() {
        for (Alternative alternative : alternativesDefinition.getAlternatives()) {
            for (SampleObject sampleObject : sampleRecordsDefinition.getRecords()) {
                DetailedExperimentInfo experimentInfo = alternative.getExperiment().getDetailedInfo().get(sampleObject);

                if (experimentInfo == null) {
                    experimentInfo = new DetailedExperimentInfo();
                    alternative.getExperiment().getDetailedInfo().put(sampleObject, experimentInfo);
                }

                if (experimentInfo.getProgramOutput() == null) {
                    experimentInfo.setProgramOutput("");
                }
            }
        }
    }

    public boolean isReadOnly() {
        return readOnly;
    }

    public void setReadOnly(boolean readOnly) {
        this.readOnly = readOnly;
    }
}
TOP

Related Classes of eu.scape_project.planning.model.Plan

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.