Skip to content

Commit a4b5edd

Browse files
committed
Add package javadoc
1 parent 1701d12 commit a4b5edd

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/**
2+
* Helpers for implementing optional parameters in a builder-like class.
3+
* <p>
4+
* The scenario is that certain methods take optional parameters, subsets of which can overlap.
5+
* For example, {@code FactoryA} should take {@code FactoryAOptions} and
6+
* {@code FactoryB} should take {@code FactoryBOptions}, where both {@code FactoryAOptions} and {@code FactoryBOptions}
7+
* expose an optional parameter "{@code int a}" with the same meaning and default values.
8+
* <p>
9+
* To maintain convenience and type-safety, both {@code FactoryAOptions} and {@code FactoryBOptions} should expose
10+
* a method {@code a(int)} to set the optional parameter. But {@code FactoryAOptions::a} should return an {@code FactoryAOptions},
11+
* and {@code FactoryBOptions::a} should return an {@code FactoryBOptions} to allow chaining more parameters of
12+
* {@code FactoryAOptions} and {@code FactoryBOptions} respectively, while retaining the type of the builder.
13+
* <p>
14+
* Using this package, this can be achieved as follows:
15+
* <p>
16+
* Each subset of optional parameters ("{@code int a}" in the above example) is implemented as two interfaces,
17+
* one exposing methods to set the parameters, one exposing methods to retrieve parameter values.
18+
* <p>
19+
* For setting:
20+
* <pre>{@code
21+
* interface OptionA< T extends OptionA< T > > extends Options< T > {
22+
* default T a( int a ) {
23+
* return add( "a", a );
24+
* }
25+
* }}</pre> where the {@code a()} method records the parameter value (with key {@code "a"}) via the
26+
* {@code add()} method of the {@code Options} super-interface.
27+
* <p>
28+
* For getting:
29+
* <pre>{@code
30+
* interface ValueA extends Values {
31+
* ...
32+
* default int a() {}
33+
* return value( "a", 0 );
34+
* }
35+
* }}</pre> where the {@code a()} method returns the parameter value (with key {@code "a"} and default value {@code 0})
36+
* via the {@code value()} method of the {@code Values} super-interface.
37+
* <p>
38+
* Finally, the implementation of {@code FactoryAOptions} derives from {@code AbstractOptions} and all desired
39+
* subsets of options
40+
* <pre>{@code public class FactoryAOptions
41+
* extends AbstractOptions< FactoryAOptions >
42+
* implements OptionA< FactoryAOptions >, ...
43+
* {
44+
* static class FactoryAValues
45+
* extends AbstractValues
46+
* implements ValueA, ...
47+
* {
48+
* ...
49+
* public FactoryAValues( final FactoryAOptions options ) {
50+
* super( options );
51+
* }
52+
* }
53+
*
54+
* public final FactoryAValues values = new FactoryAValues( this );
55+
*
56+
* // =======================================================================
57+
*
58+
* // If in-place modification of the options builder is desired,
59+
* // the following methods should be left out.
60+
*
61+
* public FactoryAOptions() {
62+
* super();
63+
* }
64+
*
65+
* private FactoryAOptions(FactoryAOptions that) {
66+
* super(that);
67+
* }
68+
*
69+
* \@Override
70+
* public FactoryAOptions copyOrThis() {
71+
* return new FactoryAOptions(this);
72+
* }
73+
*
74+
* // =======================================================================
75+
*
76+
* // The following is not necessary, but can be overridden like this
77+
* // to make it show up more nicely in IDE auto-complete
78+
*
79+
* \@Override
80+
* public FactoryAOptions a(int a) {
81+
* return OptionA.super.a(a);
82+
* }
83+
* }}</pre> The parameter values are exposed through inner class {@code FactoryAValues} that derives from {@code AbstractValues}
84+
* and all desired subsets of option values.
85+
* <p>
86+
* The only thing that has been omitted from the above example is the parts that provide a nice {@code toString} implementation
87+
* for the values. This is be achieved by
88+
* <pre>{@code
89+
* interface ValueA extends Values {
90+
* default void buildToString( AbstractValues.ValuesToString sb ) {
91+
* sb.append( "a", a() );
92+
* }
93+
*
94+
* default int a() {
95+
* return value( "a", 0 );
96+
* }
97+
* }}</pre> and <pre>{@code
98+
* static class FactoryAValues
99+
* extends AbstractValues
100+
* implements ValueA, ...
101+
* {
102+
* \@Override
103+
* public String toString() {
104+
* final ValuesToString sb = new ValuesToString();
105+
* ValueA.super.buildToString( sb );
106+
* return sb.toString();
107+
* }
108+
*
109+
* public FactoryAValues( final FactoryAOptions options ) {
110+
* super( options );
111+
* }
112+
* }}</pre>
113+
*/
114+
package org.scijava.optional;

0 commit comments

Comments
 (0)