Version.java

  1. /* This software was designed and created by Jason Carroll.
  2.  * Copyright (c) 2002, 2003, 2004 Jason Carroll.
  3.  * The author can be reached at jcarroll@cowsultants.com
  4.  * ITracker website: http://www.cowsultants.com
  5.  * ITracker forums: http://www.cowsultants.com/phpBB/index.php
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify
  8.  * it only under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  */
  17. package org.itracker.model;

  18. import org.apache.commons.lang.builder.CompareToBuilder;
  19. import org.apache.commons.lang.builder.ToStringBuilder;

  20. import java.io.Serializable;
  21. import java.util.Comparator;

  22. /**
  23.  * A Project version.
  24.  * <p/>
  25.  * <p>
  26.  * A Version can only belong to 1 Project (composition).
  27.  * </p>
  28.  *
  29.  * @author ready
  30.  */
  31. public class Version extends AbstractEntity implements Comparable<Entity> {

  32.     /**
  33.      *
  34.      */
  35.     private static final long serialVersionUID = 1L;

  36.     /**
  37.      * Invariant: never <tt>null</tt>.
  38.      */
  39.     private Project project;

  40.     /**
  41.      * Invariant: never <tt>null</tt>.
  42.      */
  43.     private String number;

  44.     /*
  45.       * major and minor are only used to compare Versions. They can be computed
  46.       * from the <code>number</code> attribute, PENDING: We should also allow
  47.       * to specify them separately in order not to impose any constraint on the
  48.       * format of the version number.
  49.       */
  50.     private int major;
  51.     private int minor;

  52.     private String description;

  53.     /**
  54.      * Version status.
  55.      * <p>
  56.      * Invariant: never <tt>null</tt>.
  57.      * </p>
  58.      */
  59.     private Status status;

  60.     /*
  61.       * This class used to have a <code>issues</code> attribute, which was a
  62.       * Collection<Issue>. This has been removed because the association Version -
  63.       * Issue doesn't need to be navigatable in this direction.
  64.       */

  65.     public static final Comparator<Version> VERSION_COMPARATOR = new VersionComparator();

  66.     /**
  67.      * Default constructor (required by Hibernate).
  68.      * <p/>
  69.      * <p>
  70.      * PENDING: should be <code>private</code> so that it can only be used by
  71.      * Hibernate, to ensure that <code>project</code> and <code>number</code>,
  72.      * which form an instance's identity, are never <tt>null</tt>.
  73.      * </p>
  74.      */
  75.     public Version() {
  76.     }

  77.     /**
  78.      * Creates a new active Version for the given Project.
  79.      *
  80.      * @param project project to which this version belongs
  81.      * @param number  unique within the project
  82.      */
  83.     public Version(Project project, String number) {
  84.         setProject(project);
  85.         setVersionInfo(number);

  86.         // A new version is active by default.
  87.         this.status = Status.ACTIVE;
  88.     }

  89.     public int getMajor() {
  90.         return major;
  91.     }

  92.     public void setMajor(int getMajor) {
  93.         this.major = getMajor;
  94.     }

  95.     public int getMinor() {
  96.         return minor;
  97.     }

  98.     public void setMinor(int getMinor) {
  99.         this.minor = getMinor;
  100.     }

  101.     public String getNumber() {
  102.         return number;
  103.     }

  104.     public void setNumber(String getNumber) {
  105.         this.number = getNumber;
  106.     }

  107.     public String getDescription() {
  108.         return description;
  109.     }

  110.     public void setDescription(String getDescription) {
  111.         this.description = getDescription;
  112.     }

  113.     public Project getProject() {
  114.         return project;
  115.     }

  116.     public void setProject(Project project) {
  117.         if (project == null) {
  118.             throw new IllegalArgumentException("null project");
  119.         }
  120.         this.project = project;
  121.     }

  122.     /**
  123.      * Returns this version's status.
  124.      *
  125.      * @return enum constant
  126.      */
  127.     public Status getStatus() {
  128.         return status;
  129.     }

  130.     /**
  131.      * Sets this version's status.
  132.      *
  133.      * @param status enum constant
  134.      * @throws IllegalArgumentException <code>status</code> is <tt>null</tt>
  135.      */
  136.     public void setStatus(Status status) {
  137.         if (status == null) {
  138.             throw new IllegalArgumentException("null status");
  139.         }
  140.         this.status = status;
  141.     }

  142.     /**
  143.      * Convience method to set the number, major and minor fields with a single
  144.      * call. It will first set the number to the provided data, and then attempt
  145.      * to parse the info if in the form major.minor into parts to set the other
  146.      * information.
  147.      *
  148.      * @param versionInfo the version number string to use
  149.      */
  150.     public void setVersionInfo(String versionInfo) {
  151.         setNumber(versionInfo);

  152.         if (null == versionInfo) {
  153.             throw new IllegalArgumentException("version info must not be null.");
  154.         }
  155.         String versionNumber = this.number.trim();
  156.         int firstDot = versionNumber.indexOf('.');
  157.         String major = "0";
  158.         major = (firstDot > 0 ? versionNumber.substring(0, firstDot).trim()
  159.                 : versionNumber.trim());

  160.         try {
  161.             setMajor(Integer.parseInt(major));
  162.         } catch (NumberFormatException ex) {
  163.             setMajor(0);
  164.         }

  165.         int secondDot = (firstDot > -1 ? versionNumber.indexOf('.',
  166.                 firstDot + 1) : -1);
  167.         String minor = (secondDot > -1 ? versionNumber.substring(firstDot + 1,
  168.                 secondDot).trim() : versionNumber.substring(firstDot + 1)
  169.                 .trim());
  170.         try {
  171.             setMinor(Integer.parseInt(minor));
  172.         } catch (NumberFormatException ex) {
  173.             setMinor(0);
  174.         }
  175.     }

  176.     /**
  177.      * @return <tt>Version [id=<id>, project=<project>, number=<number>]</tt>
  178.      */
  179.     @Override
  180.     public String toString() {
  181.         return new ToStringBuilder(this).append("id", getId()).append("number",
  182.                 getNumber()).append("project", getProject()).append(getMajor()).append(getMinor())
  183.                 .append("status", getStatus()).toString();
  184.     }

  185.     /**
  186.      * Compares 2 Versions by major and minor number.
  187.      */
  188.     public static final class VersionComparator implements Comparator<Version>, Serializable {
  189.         /**
  190.          *
  191.          */
  192.         private static final long serialVersionUID = 1L;

  193.         private boolean ascending = true;

  194.         public VersionComparator() {
  195.         }

  196.         public VersionComparator(boolean ascending) {
  197.             setAscending(ascending);
  198.         }

  199.         private boolean isAscending() {
  200.             return ascending;
  201.         }

  202.         private void setAscending(boolean ascending) {
  203.             this.ascending = ascending;
  204.         }

  205.         public int compare(Version a, Version b) {
  206.             int result = new CompareToBuilder().append(a.getNumber(), b.getNumber())
  207.                     .append(a.getMajor(), b.getMajor()).append(a.getMinor(), b.getMinor()).toComparison();

  208.             return (isAscending() ? result : -result);
  209.         }

  210.     }

  211. }