View Javadoc

1   package com.atlassian.plugin.descriptors;
2   
3   import com.atlassian.plugin.ModuleDescriptor;
4   
5   import javax.annotation.concurrent.NotThreadSafe;
6   
7   import static com.google.common.base.Preconditions.checkNotNull;
8   
9   /**
10   * @since v2.8
11   */
12  public final class ModuleDescriptors
13  {
14      /**
15       * <p>Assists in implementing a consistent implementation of {@link ModuleDescriptor#equals(Object)} methods for
16       * module descriptors based on the complete key of the descriptor.</p>
17       *
18       * <p>The full specification of the <tt>equals(Object obj)</tt> contract is defined by
19       * {@link ModuleDescriptor#equals(Object)}</p>
20       *
21       * <p>Usage:
22       * <ol>
23       *     <li>If you are using this builder to implement the <tt>equals(Object obj)</tt> method in a module descriptor
24       *     implementation:
25       *     <p>
26       *          <code>
27       *              new ModuleDescriptors.EqualsBuilder().descriptor(this).isEqualTo(obj);
28       *          </code>
29       *     </p>
30       *     </li>
31       *     <li>If you are using this builder to compare descriptors from outside a module descriptor implementation;
32       *     given two descriptor instances, <tt>descriptor1</tt> and <tt>descriptor2</tt>:
33       *     <p>
34       *          <code>
35       *              new ModuleDescriptors.EqualsBuilder().descriptor(descriptor1).isEqualTo(descriptor2);
36       *          </code>
37       *     </p>
38       *     </li>
39       * </ol>
40       * </p>
41       *
42       * @since 2.8.0
43       */
44      @NotThreadSafe
45      public static class EqualsBuilder
46      {
47          private ModuleDescriptor descriptor;
48  
49          /**
50           * Sets the module descriptor to create an <code>equals</code> implementation for.
51           *
52           * @param descriptor the module descriptor.
53           * @return this builder instance.
54           */
55          public EqualsBuilder descriptor(final ModuleDescriptor descriptor)
56          {
57              checkNotNull(descriptor, "Tried to build an equals implementation for a null module descriptor. " +
58                      "This is not allowed.");
59              this.descriptor = descriptor;
60              return this;
61          }
62  
63          /**
64           * <p>Returns <tt>true</tt> if the given object is also a module descriptor and the two descriptors have the same
65           * &quot;complete key&quot; as determined by {@link com.atlassian.plugin.ModuleDescriptor#getCompleteKey()}.</p>
66           *
67           * @param obj object to be compared for equality with this module descriptor.
68           * @return <tt>true</tt> if the specified object is equal to this module descriptor.
69           */
70          public boolean isEqualTo(final Object obj)
71          {
72              checkNotNull(descriptor, "Tried to build an equals implementation for a null module descriptor. " +
73                      "This is not allowed.");
74  
75              if (descriptor == obj) { return true; }
76  
77              if (!(obj instanceof ModuleDescriptor)) { return false; }
78  
79              ModuleDescriptor rhs = (ModuleDescriptor) obj;
80  
81              return new org.apache.commons.lang.builder.EqualsBuilder().
82                      append(descriptor.getCompleteKey(), rhs.getCompleteKey()).
83                      isEquals();
84          }
85      }
86  
87      /**
88       * <p>Assists in implementing {@link Object#hashCode()} methods for module descriptors based on the <code>hashCode</code>
89       * of their complete key.</p>
90       *
91       * <p>The full specification of the <tt>hashCode()</tt> contract is defined by
92       * {@link ModuleDescriptor#hashCode()}</p>
93       *
94       * <p>Usage:
95       * <ol>
96       *     <li>If you are using this builder to implement the <tt>hashCode()</tt> method in a module descriptor
97       *     implementation:
98       *     <p>
99       *          <code>
100      *              new ModuleDescriptors.HashCodeBuilder().descriptor(this).toHashCode();
101      *          </code>
102      *     </p>
103      *     </li>
104      *     <li>If you are using this builder to calculate the hashCode of a descriptor from outside a module descriptor
105      *     implementation; given a descriptor instance <tt>desc</tt>:
106      *     <p>
107      *          <code>
108      *              new ModuleDescriptors.EqualsBuilder().descriptor(desc).toHashCode();
109      *          </code>
110      *     </p>
111      *     </li>
112      * </ol>
113      * </p>
114      *
115      * @since 2.8.0
116      */
117     @NotThreadSafe
118     public static class HashCodeBuilder
119     {
120         private ModuleDescriptor descriptor;
121 
122         /**
123          * Sets the module descriptor to create a <code>hashCode</code> implementation for.
124          *
125          * @param descriptor the descriptor. Must not be null.
126          * @return this builder.
127          */
128         public HashCodeBuilder descriptor(final ModuleDescriptor descriptor)
129         {
130             checkNotNull(descriptor, "Tried to calculate the hash code of a null module descriptor.");
131             this.descriptor = descriptor;
132             return this;
133         }
134 
135         /**
136          * Return the computed <code>hashCode</code> for this module descriptor.
137          *
138          * @return <code>hashCode</code> based on the hashCode of the complete key of the module descriptor.
139          */
140         public int toHashCode()
141         {
142             checkNotNull(descriptor, "Tried to calculate the hash code of a null module descriptor.");
143             return descriptor.getCompleteKey() == null ? 0 : descriptor.getCompleteKey().hashCode();
144         }
145 
146         /**
147          * The computed <code>hashCode</code> from toHashCode() is returned due to the likelihood
148          * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for
149          * HashCodeBuilder itself is.
150          *
151          * @return <code>hashCode</code> based on the complete key of the module descriptor.
152          */
153         public int hashCode()
154         {
155             return toHashCode();
156         }
157     }
158 }