Package eu.scape_project.planning.model

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

/*******************************************************************************
* 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.
*
* 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.Lob;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.OrderColumn;

import eu.scape_project.planning.exception.PlanningException;

import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

/**
* Class containing all properties for workflow step 'Define Alternatives'.
*
* @author Hannes Kulovits
*/
@Entity
public class AlternativesDefinition implements Serializable, ITouchable {

    private static final long serialVersionUID = 5305133244443843393L;

    @Id
    @GeneratedValue
    private int id;

    @Lob
    private String description;

    public Alternative alternativeByName(String name) {
        for (Alternative a : alternatives) {
            if (a.getName().equals(name)) {
                return a;
            }
        }
        return null;
    }

    /**
     *
     * One reason we had to use @IndexColumn was because of fetch type EAGER.
     * This problem can be resolved by using @Fetch(FetchMode.SUBSELECT)
     */
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    @OrderColumn(name = "alt_index")
    @JoinColumn(name = "parent_id", nullable = false)
    @Fetch(value = FetchMode.SELECT)
    private List<Alternative> alternatives = new ArrayList<Alternative>();

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

    // /**
    // * List of alternative preservation solutions that shall not be considered
    // for evaluation because
    // * they are definitely inappropriate for instance. Consequently they need
    // not to be deleted
    // * to finish the workflow.
    // */
    // @Transient
    // private List<Alternative> consideredAlternatives;

    public List<Alternative> getAlternatives() {
        return Collections.unmodifiableList(alternatives);
    }

    // /**
    // * Sets the list of alternatives.
    // *
    // * @param alternatives
    // */
    // private void setAlternatives(List<Alternative> alternatives) {
    // this.alternatives = alternatives;
    // }

    public int getId() {
        return id;
    }

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

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    /**
     * Returns a list of alternatives which shall be evaluated.
     *
     * NOTE: There is no caching, the resulting list is created every time this
     * method is invoked therefore use with care.
     *
     * @return alternatives that shall be considered for evaluation
     */
    public List<Alternative> getConsideredAlternatives() {
        ArrayList<Alternative> consideredAlternatives = new ArrayList<Alternative>();

        for (Alternative alt : alternatives) {
            if (!alt.isDiscarded()) {
                consideredAlternatives.add(alt);
            }
        }

        return consideredAlternatives;
    }

    public void setConsideredAlternatives(List<Alternative> consideredAlternatives) {

    }

    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 elementss
        for (Alternative alt : alternatives) {
            alt.handleChanges(h);
        }
    }

    public void removeAlternative(Alternative alternative) {
        alternatives.remove(alternative);
    }

    /**
     * returns a list containing the lower case names of all alternatives
     * (including discarded)
     */
    private List<String> getUsedNames() {
        List<String> usedNames = new ArrayList<String>();
        for (Alternative a : alternatives) {
            usedNames.add(a.getName().toLowerCase());
        }
        return usedNames;
    }

    /**
     * Creates a unique alternative name based on <code>name</code> and adds the
     * new name to the list of <code>usedNames</code>
     *
     * @param usedNames
     *            a list of all names of the alternatives in the current project
     * @param name
     *            alternative name to create an unique name from
     * @return a unique alternative name with a maximum length of 20 characters.
     */
    public String createUniqueName(String name) {
        List<String> usedNames = getUsedNames();

        // Note: not all databases consider trailing whitespace for comparison (unique key constraints)
        // and it is hard to make out the difference in the UI,
        // therefore we remove trailing whitespace before checking for uniqueness
        String shortname = name.substring(0, Math.min(30, name.length())).trim();
        if (!usedNames.contains(shortname.toLowerCase())) {
            return shortname;
        } else {
            // start with 1-digit numbers
            int i = 1;
            int exp = 0;
            String base;
            if (shortname.length() <= 28)
                base = shortname;
            else
                // note that the name could contain whitespace, remove trailing whitespace(again)
                base = shortname.substring(0, 28).trim();
            String newName = base + "-" + i;
            while (usedNames.contains(newName.toLowerCase())) {
                i++;
                if ((int) Math.log10(i) > exp) {
                    // i-digits are not enough - extend the postfix
                    exp = (int) Math.log10(i);
                    // and reduce the length of the base if necessary, and remove trailing whitespace(again)
                    base = shortname.substring(0, Math.min(shortname.length(), 28 - exp)).trim();
                }
                newName = base + "-" + i;
            }
            return newName;
        }
    }

    /**
     * adds the given alternative to the list of alternatives. used for
     * importing by the digester.
     *
     * we have to ensure referential integrity!
     *
     * @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 {
        if (!isAlternativeNameUnique(alternative.getName())) {
            throw new PlanningException("A unique name must be provided for the alternative.");
        }

        if (!isAlternativeNameValid(alternative.getName())) {
            String msg = String.format("The alternative name must not start or end with a whitespace. [%s]", alternative.getName());
            throw new PlanningException(msg);
        }

        alternative.setAlternativesDefinition(this);
        alternatives.add(alternative);
    }

    /**
     * Method responsible for giving an Alternative a new name.
     *
     * @param alternative
     *            Alternative to modify.
     * @param newName
     *            New name of the Alternative
     * @throws PlanningException
     *             If an error occurs at changing the name this exception is
     *             thrown.
     */

    @SuppressWarnings("deprecation")
    public void renameAlternative(Alternative alternative, String newName) throws PlanningException {
        // check if the alternative to change exists
        if (alternativeByName(alternative.getName()) == null) {
            throw new PlanningException("Alternative to rename does not exists.");
        }

        // check if the new-name is unique
        if (!alternative.getName().equals(newName) && !isAlternativeNameUnique(newName)) {
            throw new PlanningException("A unique name must be provided for the alternative.");
        }

        if (!isAlternativeNameValid(newName)) {
            throw new PlanningException("The alternative name must not start or end with a whitespace.");
        }

        // At this stage renaming of the alternative is okay
        alternative.setName(newName);
    }

    /**
     * Checks if there is already an alternative with the given name in the list
     * of the defined alternatives.
     *
     * Note: The check is done case-insensitive
     *
     * @param name
     * @return true if there is no alternative with the same
     */
    private boolean isAlternativeNameUnique(String name) {
        for (Alternative alt : alternatives) {
            if (alt.getName().equalsIgnoreCase(name)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Checks if the alternative name is valid.
     *
     * @param name
     *            the name to check
     * @return true if valid, false otherwise
     */
    private boolean isAlternativeNameValid(String name) {
        if (name.length() != name.trim().length()) {
            return false;
        }
        return true;
    }
}
TOP

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

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.