diff --git a/src/main/java/org/apache/commons/lang3/builder/Builder.java b/src/main/java/org/apache/commons/lang3/builder/Builder.java new file mode 100644 index 000000000..10da0b35c --- /dev/null +++ b/src/main/java/org/apache/commons/lang3/builder/Builder.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.commons.lang3.builder; + +/** + *

+ * The Builder interface is designed to designate a class as a builder + * object in the Builder design pattern. Builders are capable of creating and + * configuring objects or results that normally take multiple steps to construct + * or are very complex to derive. + *

+ * + *

+ * The builder interface defines a single method, {@link #build()}, that + * classes must implement. The result of this method should be the final + * configured object or result after all building operations are performed. + *

+ * + *

+ * It is a recommended practice that the methods supplied to configure the + * object or result being built return a reference to this so that + * method calls can be chained together. + *

+ * + *

+ * Example Builder: + *

+ * class FontBuilder implements Builder<Font> {
+ *     private Font font;
+ *     
+ *     public FontBuilder(String fontName) {
+ *         this.font = new Font(fontName, Font.PLAIN, 12);
+ *     }
+ * 
+ *     public FontBuilder bold() {
+ *         this.font = this.font.deriveFont(Font.BOLD);
+ *         return this; // Reference returned so calls can be chained
+ *     }
+ *     
+ *     public FontBuilder size(float pointSize) {
+ *         this.font = this.font.deriveFont(pointSize);
+ *         return this; // Reference returned so calls can be chained
+ *     }
+ * 
+ *     // Other Font construction methods
+ * 
+ *     public Font build() {
+ *         return this.font;
+ *     }
+ * }
+ * 
+ * + * Example Builder Usage: + *
+ * Font bold14ptSansSerifFont = new FontBuilder(Font.SANS_SERIF).bold()
+ *                                                              .size(14.0f)
+ *                                                              .build();
+ * 
+ *

+ * + * @param the type of object that the builder will construct or compute. + * + * @author Michael Wooten + * @since 3.0 + */ +public interface Builder { + + /** + * Returns a reference to the object being constructed or result being + * calculated by the builder. + * + * @return the object constructed or result calculated by the builder. + */ + public T build(); +} diff --git a/src/main/java/org/apache/commons/lang3/builder/CompareToBuilder.java b/src/main/java/org/apache/commons/lang3/builder/CompareToBuilder.java index 50d5407e1..70fac50a2 100644 --- a/src/main/java/org/apache/commons/lang3/builder/CompareToBuilder.java +++ b/src/main/java/org/apache/commons/lang3/builder/CompareToBuilder.java @@ -89,7 +89,7 @@ * @since 1.0 * @version $Id$ */ -public class CompareToBuilder { +public class CompareToBuilder implements Builder { /** * Current state of the comparison as appended fields are checked. @@ -1043,5 +1043,18 @@ public int toComparison() { return comparison; } + /** + * Returns a negative integer, a positive integer, or zero as + * the builder has judged the "left-hand" side + * as less than, greater than, or equal to the "right-hand" + * side. + * + * @return final comparison result + * + * @since 3.0 + */ + public Integer build() { + return toComparison(); + } } diff --git a/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java b/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java index c725cfffd..7db4a0708 100644 --- a/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java +++ b/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java @@ -86,7 +86,7 @@ * @since 1.0 * @version $Id$ */ -public class EqualsBuilder { +public class EqualsBuilder implements Builder { /** *

@@ -968,6 +968,19 @@ public EqualsBuilder append(boolean[] lhs, boolean[] rhs) { public boolean isEquals() { return this.isEquals; } + + /** + *

Returns true if the fields that have been checked + * are all equal.

+ * + * @return true if all of the fields that have been checked + * are equal, false otherwise. + * + * @since 3.0 + */ + public Boolean build() { + return isEquals(); + } /** * Sets the isEquals value. diff --git a/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java b/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java index c6fe82c27..290e70936 100644 --- a/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java +++ b/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java @@ -93,7 +93,7 @@ * @since 1.0 * @version $Id$ */ -public class HashCodeBuilder { +public class HashCodeBuilder implements Builder { /** *

* A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops. @@ -976,6 +976,17 @@ public HashCodeBuilder appendSuper(int superHashCode) { public int toHashCode() { return iTotal; } + + /** + * Returns the computed hashCode. + * + * @return hashCode based on the fields appended + * + * @since 3.0 + */ + public Integer build() { + return toHashCode(); + } /** *

diff --git a/src/main/java/org/apache/commons/lang3/builder/ToStringBuilder.java b/src/main/java/org/apache/commons/lang3/builder/ToStringBuilder.java index c368126b6..cc360c670 100644 --- a/src/main/java/org/apache/commons/lang3/builder/ToStringBuilder.java +++ b/src/main/java/org/apache/commons/lang3/builder/ToStringBuilder.java @@ -89,7 +89,7 @@ * @since 1.0 * @version $Id$ */ -public class ToStringBuilder { +public class ToStringBuilder implements Builder { /** * The default style of output to use, not null. @@ -1065,4 +1065,17 @@ public String toString() { return this.getStringBuffer().toString(); } + /** + * Returns the String that was build as an object representation. The + * default implementation utilizes the {@link #toString()} implementation. + * + * @return the String toString + * + * @see #toString() + * + * @since 3.0 + */ + public String build() { + return toString(); + } } diff --git a/src/main/java/org/apache/commons/lang3/concurrent/BasicThreadFactory.java b/src/main/java/org/apache/commons/lang3/concurrent/BasicThreadFactory.java index 7ba8cf206..e2441334a 100644 --- a/src/main/java/org/apache/commons/lang3/concurrent/BasicThreadFactory.java +++ b/src/main/java/org/apache/commons/lang3/concurrent/BasicThreadFactory.java @@ -250,7 +250,9 @@ private void initializeThread(Thread t) { * * @version $Id: $ */ - public static class Builder { + public static class Builder + implements org.apache.commons.lang3.builder.Builder { + /** The wrapped factory. */ private ThreadFactory wrappedFactory; diff --git a/src/test/java/org/apache/commons/lang3/builder/CompareToBuilderTest.java b/src/test/java/org/apache/commons/lang3/builder/CompareToBuilderTest.java index 49ebd5ab6..9c053f4a6 100644 --- a/src/test/java/org/apache/commons/lang3/builder/CompareToBuilderTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/CompareToBuilderTest.java @@ -272,6 +272,20 @@ public void testObject() { assertTrue(new CompareToBuilder().append((Object) null, (Object) null).toComparison() == 0); assertTrue(new CompareToBuilder().append(null, o1).toComparison() < 0); } + + public void testObjectBuild() { + TestObject o1 = new TestObject(4); + TestObject o2 = new TestObject(4); + assertTrue(new CompareToBuilder().append(o1, o1).build() == 0); + assertTrue(new CompareToBuilder().append(o1, o2).build() == 0); + o2.setA(5); + assertTrue(new CompareToBuilder().append(o1, o2).build() < 0); + assertTrue(new CompareToBuilder().append(o2, o1).build() > 0); + + assertTrue(new CompareToBuilder().append(o1, null).build() > 0); + assertTrue(new CompareToBuilder().append((Object) null, (Object) null).build() == 0); + assertTrue(new CompareToBuilder().append(null, o1).build() < 0); + } public void testObjectEx2() { TestObject o1 = new TestObject(4); diff --git a/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java index 382997080..f03d6b394 100644 --- a/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java @@ -305,6 +305,21 @@ public void testObject() { assertTrue(!new EqualsBuilder().append(null, o2).isEquals()); assertTrue(new EqualsBuilder().append((Object) null, (Object) null).isEquals()); } + + public void testObjectBuild() { + TestObject o1 = new TestObject(4); + TestObject o2 = new TestObject(5); + assertTrue(new EqualsBuilder().append(o1, o1).build()); + assertTrue(!new EqualsBuilder().append(o1, o2).build()); + o2.setA(4); + assertTrue(new EqualsBuilder().append(o1, o2).build()); + + assertTrue(!new EqualsBuilder().append(o1, this).build()); + + assertTrue(!new EqualsBuilder().append(o1, null).build()); + assertTrue(!new EqualsBuilder().append(null, o2).build()); + assertTrue(new EqualsBuilder().append((Object) null, (Object) null).build()); + } public void testLong() { long o1 = 1L; diff --git a/src/test/java/org/apache/commons/lang3/builder/HashCodeBuilderTest.java b/src/test/java/org/apache/commons/lang3/builder/HashCodeBuilderTest.java index 64b34f907..3ce645fdd 100644 --- a/src/test/java/org/apache/commons/lang3/builder/HashCodeBuilderTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/HashCodeBuilderTest.java @@ -205,6 +205,13 @@ public void testObject() { obj = new Object(); assertEquals(17 * 37 + obj.hashCode(), new HashCodeBuilder(17, 37).append(obj).toHashCode()); } + + public void testObjectBuild() { + Object obj = null; + assertEquals(17 * 37, new HashCodeBuilder(17, 37).append(obj).build().intValue()); + obj = new Object(); + assertEquals(17 * 37 + obj.hashCode(), new HashCodeBuilder(17, 37).append(obj).build().intValue()); + } @SuppressWarnings("cast") // cast is not really needed, keep for consistency public void testLong() { diff --git a/src/test/java/org/apache/commons/lang3/builder/ToStringBuilderTest.java b/src/test/java/org/apache/commons/lang3/builder/ToStringBuilderTest.java index f2085b2ce..b15515e35 100644 --- a/src/test/java/org/apache/commons/lang3/builder/ToStringBuilderTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/ToStringBuilderTest.java @@ -619,6 +619,23 @@ public void testObject() { assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", (Object) new String[0], false).toString()); assertEquals(baseStr + "[a={}]", new ToStringBuilder(base).append("a", (Object) new String[0], true).toString()); } + + public void testObjectBuild() { + Integer i3 = new Integer(3); + Integer i4 = new Integer(4); + assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) null).build()); + assertEquals(baseStr + "[3]", new ToStringBuilder(base).append(i3).build()); + assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", (Object) null).build()); + assertEquals(baseStr + "[a=3]", new ToStringBuilder(base).append("a", i3).build()); + assertEquals(baseStr + "[a=3,b=4]", new ToStringBuilder(base).append("a", i3).append("b", i4).build()); + assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", i3, false).build()); + assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", new ArrayList(), false).build()); + assertEquals(baseStr + "[a=[]]", new ToStringBuilder(base).append("a", new ArrayList(), true).build()); + assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", new HashMap(), false).build()); + assertEquals(baseStr + "[a={}]", new ToStringBuilder(base).append("a", new HashMap(), true).build()); + assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", (Object) new String[0], false).build()); + assertEquals(baseStr + "[a={}]", new ToStringBuilder(base).append("a", (Object) new String[0], true).build()); + } public void testLong() { assertEquals(baseStr + "[3]", new ToStringBuilder(base).append(3L).toString());