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 * "complete key" 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 }