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       * <p>Assists in implementing a consistent implementation of {@link ModuleDescriptor#equals(Object)} methods for
15       * module descriptors based on the complete key of the descriptor.</p>
16       *
17       * <p>The full specification of the <tt>equals(Object obj)</tt> contract is defined by
18       * {@link ModuleDescriptor#equals(Object)}</p>
19       *
20       * <p>Usage:
21       * <ol>
22       * <li>If you are using this builder to implement the <tt>equals(Object obj)</tt> method in a module descriptor
23       * implementation:
24       * <p>
25       * <code>
26       * new ModuleDescriptors.EqualsBuilder().descriptor(this).isEqualTo(obj);
27       * </code>
28       * </p>
29       * </li>
30       * <li>If you are using this builder to compare descriptors from outside a module descriptor implementation;
31       * given two descriptor instances, <tt>descriptor1</tt> and <tt>descriptor2</tt>:
32       * <p>
33       * <code>
34       * new ModuleDescriptors.EqualsBuilder().descriptor(descriptor1).isEqualTo(descriptor2);
35       * </code>
36       * </p>
37       * </li>
38       * </ol>
39       * </p>
40       *
41       * @since 2.8.0
42       */
43      @NotThreadSafe
44      public static class EqualsBuilder {
45          private ModuleDescriptor descriptor;
46  
47          /**
48           * Sets the module descriptor to create an <code>equals</code> implementation for.
49           *
50           * @param descriptor the module descriptor.
51           * @return this builder instance.
52           */
53          public EqualsBuilder descriptor(final ModuleDescriptor descriptor) {
54              checkNotNull(descriptor, "Tried to build an equals implementation for a null module descriptor. " +
55                      "This is not allowed.");
56              this.descriptor = descriptor;
57              return this;
58          }
59  
60          /**
61           * <p>Returns <tt>true</tt> if the given object is also a module descriptor and the two descriptors have the same
62           * &quot;complete key&quot; as determined by {@link com.atlassian.plugin.ModuleDescriptor#getCompleteKey()}.</p>
63           *
64           * @param obj object to be compared for equality with this module descriptor.
65           * @return <tt>true</tt> if the specified object is equal to this module descriptor.
66           */
67          public boolean isEqualTo(final Object obj) {
68              checkNotNull(descriptor, "Tried to build an equals implementation for a null module descriptor. " +
69                      "This is not allowed.");
70  
71              if (descriptor == obj) {
72                  return true;
73              }
74  
75              if (!(obj instanceof ModuleDescriptor)) {
76                  return false;
77              }
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         private ModuleDescriptor descriptor;
120 
121         /**
122          * Sets the module descriptor to create a <code>hashCode</code> implementation for.
123          *
124          * @param descriptor the descriptor. Must not be null.
125          * @return this builder.
126          */
127         public HashCodeBuilder descriptor(final ModuleDescriptor descriptor) {
128             checkNotNull(descriptor, "Tried to calculate the hash code of a null module descriptor.");
129             this.descriptor = descriptor;
130             return this;
131         }
132 
133         /**
134          * Return the computed <code>hashCode</code> for this module descriptor.
135          *
136          * @return <code>hashCode</code> based on the hashCode of the complete key of the module descriptor.
137          */
138         public int toHashCode() {
139             checkNotNull(descriptor, "Tried to calculate the hash code of a null module descriptor.");
140             return descriptor.getCompleteKey() == null ? 0 : descriptor.getCompleteKey().hashCode();
141         }
142 
143         /**
144          * The computed <code>hashCode</code> from toHashCode() is returned due to the likelihood
145          * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for
146          * HashCodeBuilder itself is.
147          *
148          * @return <code>hashCode</code> based on the complete key of the module descriptor.
149          */
150         public int hashCode() {
151             return toHashCode();
152         }
153     }
154 }