1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 | package Torello.Browser;
import Torello.JavaDoc.Annotations.LinkJavaSource;
import Torello.Java.StrIndent;
import Torello.Java.ReadOnly.ReadOnlyList;
/**
* A 'Builder' software design pattern that may be used to construct instances of any of the nested
* domain types & classes in CDP. The goal of this class is to make it easier to construct
* instances of CDP types that have <B><I>many, many</I></B> fields. Although it is perfectly
* legal to invoke the constructor of any CDP data type directly, a class with only 2 or 3 fields
* won't provide any benefit above and beyond using the constructor of the class.
*
* <BR /><BR />
* ⚠️ Only classes with "lots and lots" of fields will benefit from using the {@code 'TypeBuilder'}
* design pattern!
*
* <EMBED CLASS='external-html' DATA-FILE-ID=TB.Example>
*
* @param <CDP_TYPE> The CDP data type produced by this builder's {@link #build()} method.
*
* @see NestedDescriptor
* @see NestedHelper#descriptor()
*/
public class TypeBuilder<CDP_TYPE extends BaseType<CDP_TYPE>>
extends AbstractBuilder<CDP_TYPE>
implements java.io.Serializable, Cloneable
{
/** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
protected static final long serialVersionUID = 1L;
/**
* Convert 'this' Builder-Instance into an actual Object-Instance
* @return An instance of {@code CDP_TYPE}
*/
@Override
@SuppressWarnings("unchecked")
public CDP_TYPE build()
{
return BuildInstance.build
((NestedDescriptor<CDP_TYPE>) this.descriptor, this.assignments, this.assigned);
}
// used by 'clone'
private TypeBuilder(final TypeBuilder<CDP_TYPE> other)
{ super(other); }
// used by 'builder'
private TypeBuilder(final NestedDescriptor<CDP_TYPE> descriptor)
{ super(descriptor); }
/**
* Creates a new builder, ready to accept field assignments.
*
* @param <T> This is the object type, or {@code 'class'} which you would like to have built by
* this {@code TypeBuilder}.
*
* @param descriptor The singleton descriptor for the CDP data type being built.
* Retrieving a descriptor is as easy as invoking {@link NestedHelper#descriptor() descriptor()}
* on any CDP data type.
*
* @return a new builder instance of this class
*
* @see NestedHelper#descriptor()
*/
public static <T extends BaseType<T>> TypeBuilder<T> builder
(final NestedDescriptor<T> descriptor)
{
java.util.Objects.requireNonNull(descriptor, "parameter 'descriptor' is null");
return new TypeBuilder<>(descriptor);
}
/**
* This creates a new builder, but initializes it with an actual object instance
* @param <T> The {@code 'BaseType'} class.
* @param descriptor descriptor of the CDP data carrier class being constructed
* @param bt instance of the CDP data carrier class, used to populate the builder
* @return a {@code 'TypeBuilder'}, initialized with the values in {@code 'bt'}
*
* @see NestedHelper#descriptor()
*/
public static <T extends BaseType<T>> TypeBuilder<T> witherBuilder(
final NestedDescriptor<T> descriptor,
final BaseType<T> bt
)
{
java.util.Objects.requireNonNull(descriptor, "parameter 'descriptor' is null");
java.util.Objects.requireNonNull(bt, "parameter 'bt' is null");
if (! descriptor.baseTypeClass.isInstance(bt)) throw new IllegalArgumentException
("'bt' is not an instance of " + descriptor.baseTypeClass.getCanonicalName());
final TypeBuilder<T> tb = new TypeBuilder<>(descriptor);
final ReadOnlyList<Boolean> isPresent = bt.isPresent();
for (int i=0; i < descriptor.size; i++) if (isPresent.get(i))
{
tb.assigned[i] = true;
try
{
tb.assignments[i] = descriptor
.baseTypeClass
.getField(descriptor.names.get(i))
.get(bt);
}
catch (NoSuchFieldException | SecurityException | IllegalAccessException e)
{
throw new TypeBuilderError(
"Could not extract field [" + descriptor.names.get(i) + "] from instance of " +
descriptor.baseTypeClass.getCanonicalName(),
e
);
}
}
return tb;
}
/** {@inheritDoc} */
@Override
public TypeBuilder<CDP_TYPE> clone()
{ return new TypeBuilder<>(this); }
private static class TypeBuilderError extends Error
{
protected static final long serialVersionUID = 1L;
private TypeBuilderError(final String message, final Throwable cause)
{ super(message, cause); }
}
}
|