Skip to content

Commit bc1a2ff

Browse files
committed
Update README and package javadoc to reflect refactored API
Also add org.scijava.optional.examples.Playground that has the full implementation of the example given in the README and package javadoc.
1 parent c001390 commit bc1a2ff

File tree

3 files changed

+154
-83
lines changed

3 files changed

+154
-83
lines changed

README.md

Lines changed: 21 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ For example, `FactoryA` should take `FactoryAOptions` and
1010
expose an optional parameter "`int a`" with the same meaning and default values.
1111

1212
To maintain convenience and type-safety, both `FactoryAOptions` and `FactoryBOptions` should expose
13-
a method `a(int)` to set the optional parameter. But `FactoryAOptions::a` should return an `FactoryAOptions`,
14-
and `FactoryBOptions::a` should return an `FactoryBOptions` to allow chaining more parameters of
13+
a method `a(int)` to set the optional parameter. But `FactoryAOptions::a` should return a `FactoryAOptions`,
14+
and `FactoryBOptions::a` should return a `FactoryBOptions` to allow chaining more parameters of
1515
`FactoryAOptions` and `FactoryBOptions` respectively, while retaining the type of the builder.
1616

1717
Using scijava-optional, this can be achieved as follows:
@@ -21,26 +21,26 @@ one exposing methods to set the parameters, one exposing methods to retrieve par
2121

2222
For setting:
2323
```java
24-
interface OptionA<T extends OptionA<T>> extends Options<T> {
24+
interface OptionA<T> extends Options<T> {
2525
default T a(int a) {
26-
return add("a", a);
26+
return setValue("a", a);
2727
}
2828
}
2929
```
3030
where the `a()` method records the parameter value (with key `"a"`) via the
31-
`add()` method of the `Options` super-interface.
31+
`setValue()` method of the `Options` super-interface.
3232

3333
For getting:
3434
```java
3535
interface ValueA extends Values {
3636
...
37-
default int a() {}
38-
return value( "a", 0 );
37+
default int a() {
38+
return getValueOrDefault( "a", 0 );
3939
}
4040
}
4141
```
4242
where the `a()` method returns the parameter value (with key `"a"` and default value `0`)
43-
via the `value()` method of the `Values` super-interface.
43+
via the `getValueOrDefault()` method of the `Values` super-interface.
4444

4545
Finally, the implementation of `FactoryAOptions` derives from `AbstractOptions` and all desired
4646
subsets of options
@@ -49,17 +49,12 @@ public class FactoryAOptions
4949
extends AbstractOptions< FactoryAOptions >
5050
implements OptionA< FactoryAOptions >, ...
5151
{
52-
static class FactoryAValues
52+
public class FactoryAValues
5353
extends AbstractValues
5454
implements ValueA, ...
55-
{
56-
...
57-
public FactoryAValues(FactoryAOptions options) {
58-
super( options );
59-
}
60-
}
55+
{}
6156

62-
public final FactoryAValues values = new FactoryAValues(this);;
57+
public final FactoryAValues values = new FactoryAValues();
6358

6459
// =======================================================================
6560

@@ -76,49 +71,36 @@ public class FactoryAOptions
7671
protected FactoryAOptions copyOrThis() {
7772
return new FactoryAOptions(this);
7873
}
79-
80-
// =======================================================================
81-
82-
// The following is not necessary, but can be overridden like this
83-
// to make it show up more nicely in IDE auto-complete
84-
85-
@Override
86-
public FactoryAOptions a(int a) {
87-
return OptionA.super.a(a);
88-
}
8974
}
9075
```
9176
The parameter values are exposed through inner class `FactoryAValues` that derives from `AbstractValues`
9277
and all desired subsets of option values.
9378

9479
The only thing that has been omitted from the above example is the parts that provide a nice `toString` implementation
95-
for the values. This is be achieved by
80+
for the values. This is be achieved by overriding the `forEach()` methods in the `Values` interfaces and
81+
implementation
9682
```java
9783
interface ValueA extends Values {
98-
default void buildToString(AbstractValues.ValuesToString sb) {
99-
sb.append("a", a());
84+
default void forEach(BiConsumer<String, Object> action) {
85+
action.accept("a", a());
86+
// and so on, for other parameters defined in this Values interface
10087
}
10188

10289
default int a() {
103-
return value("a", 0);
90+
return getValueOrDefault("a", 0);
10491
}
10592
}
10693
```
10794
and
10895
```java
109-
static class FactoryAValues
96+
public class FactoryAValues
11097
extends AbstractValues
11198
implements ValueA, ...
11299
{
113100
@Override
114-
public String toString() {
115-
final ValuesToString sb = new ValuesToString();
116-
ValueA.super.buildToString(sb);
117-
return sb.toString();
118-
}
119-
120-
public FactoryAValues(FactoryAOptions options) {
121-
super(options);
101+
default void forEach(BiConsumer<String, Object> action) {
102+
ValueA.super.forEach( action );
103+
// and so on, for other implemented Values interfaces
122104
}
123105
}
124106
```

src/main/java/org/scijava/optional/package-info.java

Lines changed: 26 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,51 +7,46 @@
77
* expose an optional parameter "{@code int a}" with the same meaning and default values.
88
* <p>
99
* 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
10+
* a method {@code a(int)} to set the optional parameter. But {@code FactoryAOptions::a} should return a {@code FactoryAOptions},
11+
* and {@code FactoryBOptions::a} should return a {@code FactoryBOptions} to allow chaining more parameters of
1212
* {@code FactoryAOptions} and {@code FactoryBOptions} respectively, while retaining the type of the builder.
1313
* <p>
1414
* Using this package, this can be achieved as follows:
1515
* <p>
1616
* 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.
17+
* one exposing methods to set the parameters, the other exposing methods to retrieve parameter values.
1818
* <p>
1919
* For setting:
2020
* <pre>{@code
21-
* interface OptionA< T extends OptionA< T > > extends Options< T > {
21+
* interface OptionA<T> extends Options<T> {
2222
* default T a( int a ) {
23-
* return add( "a", a );
23+
* return setValue( "a", a );
2424
* }
2525
* }}</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.
26+
* {@code setValue()} method of the {@code Options} super-interface.
2727
* <p>
2828
* For getting:
2929
* <pre>{@code
3030
* interface ValueA extends Values {
3131
* ...
3232
* default int a() {}
33-
* return value( "a", 0 );
33+
* return getValueOrDefault( "a", 0 );
3434
* }
3535
* }}</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.
36+
* via the {@code getValueOrDefault()} method of the {@code Values} super-interface.
3737
* <p>
3838
* Finally, the implementation of {@code FactoryAOptions} derives from {@code AbstractOptions} and all desired
3939
* subsets of options
4040
* <pre>{@code public class FactoryAOptions
41-
* extends AbstractOptions< FactoryAOptions >
42-
* implements OptionA< FactoryAOptions >, ...
41+
* extends AbstractOptions<FactoryAOptions>
42+
* implements OptionA<FactoryAOptions>, ...
4343
* {
44-
* static class FactoryAValues
44+
* public class FactoryAValues
4545
* extends AbstractValues
4646
* implements ValueA, ...
47-
* {
48-
* ...
49-
* public FactoryAValues( final FactoryAOptions options ) {
50-
* super( options );
51-
* }
52-
* }
47+
* {}
5348
*
54-
* public final FactoryAValues values = new FactoryAValues( this );
49+
* public final FactoryAValues values = new FactoryAValues();
5550
*
5651
* // =======================================================================
5752
*
@@ -60,52 +55,39 @@
6055
*
6156
* public FactoryAOptions() {}
6257
*
63-
* private FactoryAOptions(FactoryAOptions that) {
64-
* super(that);
58+
* private FactoryAOptions( FactoryAOptions that ) {
59+
* super( that );
6560
* }
6661
*
6762
* \@Override
6863
* protected FactoryAOptions copyOrThis() {
69-
* return new FactoryAOptions(this);
70-
* }
71-
*
72-
* // =======================================================================
73-
*
74-
* // The following is not necessary, but can be overridden like this
75-
* // to make it show up more nicely in IDE auto-complete
76-
*
77-
* \@Override
78-
* public FactoryAOptions a(int a) {
79-
* return OptionA.super.a(a);
64+
* return new FactoryAOptions( this );
8065
* }
8166
* }}</pre> The parameter values are exposed through inner class {@code FactoryAValues} that derives from {@code AbstractValues}
8267
* and all desired subsets of option values.
8368
* <p>
8469
* The only thing that has been omitted from the above example is the parts that provide a nice {@code toString} implementation
85-
* for the values. This is be achieved by
70+
* for the values. This is be achieved by overriding the {@code forEach()} methods in the {@code Values} interfaces and
71+
* implementation
8672
* <pre>{@code
8773
* interface ValueA extends Values {
88-
* default void buildToString( AbstractValues.ValuesToString sb ) {
89-
* sb.append( "a", a() );
74+
* default void forEach( BiConsumer<String, Object> action ) {
75+
* action.accept( "a", a() );
76+
* // and so on, for other parameters defined in this Values interface
9077
* }
9178
*
9279
* default int a() {
93-
* return value( "a", 0 );
80+
* return getValueOrDefault( "a", 0 );
9481
* }
9582
* }}</pre> and <pre>{@code
96-
* static class FactoryAValues
83+
* public class FactoryAValues
9784
* extends AbstractValues
9885
* implements ValueA, ...
9986
* {
10087
* \@Override
101-
* public String toString() {
102-
* final ValuesToString sb = new ValuesToString();
103-
* ValueA.super.buildToString( sb );
104-
* return sb.toString();
105-
* }
106-
*
107-
* public FactoryAValues( final FactoryAOptions options ) {
108-
* super( options );
88+
* public void forEach( BiConsumer<String, Object> action )
89+
* ValueA.super.forEach( action );
90+
* // and so on, for other implemented Values interfaces
10991
* }
11092
* }}</pre>
11193
*/
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package org.scijava.optional.examples;
2+
3+
import java.util.function.BiConsumer;
4+
import org.scijava.optional.AbstractOptions;
5+
import org.scijava.optional.Options;
6+
import org.scijava.optional.Values;
7+
8+
public class Playground
9+
{
10+
interface OptionA< T > extends Options< T >
11+
{
12+
default T a( final int a )
13+
{
14+
return setValue( "a", a );
15+
}
16+
17+
interface ValueA extends Values
18+
{
19+
default void forEach( BiConsumer< String, Object > action )
20+
{
21+
action.accept( "a", a() );
22+
}
23+
24+
default int a()
25+
{
26+
return getValueOrDefault( "a", 0 );
27+
}
28+
}
29+
}
30+
31+
// ====================================================================================== //
32+
33+
interface OptionB< T > extends Options< T >
34+
{
35+
default T b( final int b )
36+
{
37+
return setValue( "b", b );
38+
}
39+
40+
interface ValueB extends Values
41+
{
42+
default void forEach( BiConsumer< String, Object > action )
43+
{
44+
action.accept( "b", b() );
45+
}
46+
47+
default int b()
48+
{
49+
return getValueOrDefault( "b", 0 );
50+
}
51+
}
52+
}
53+
54+
// ====================================================================================== //
55+
56+
static class FactoryAOptions extends AbstractOptions< FactoryAOptions > implements OptionA< FactoryAOptions >, OptionB< FactoryAOptions >
57+
{
58+
class FactoryAValues extends AbstractValues implements ValueA, ValueB
59+
{
60+
@Override
61+
public void forEach( BiConsumer< String, Object > action )
62+
{
63+
ValueA.super.forEach( action );
64+
ValueB.super.forEach( action );
65+
}
66+
}
67+
68+
public final FactoryAValues values = new FactoryAValues();
69+
70+
/*
71+
* The following methods result in immutable FactoryAOptions instances,
72+
* where options.a(3) results in a new FactoryAOptions instance with the
73+
* same parameters as options, except a=3.
74+
*
75+
* If in-place modification of the options builder is desired,
76+
* the following methods should be left out. Then, options.a(3) modifies
77+
* the options instance, setting a=3
78+
*/
79+
80+
public FactoryAOptions()
81+
{}
82+
83+
private FactoryAOptions( FactoryAOptions that )
84+
{
85+
super( that );
86+
}
87+
88+
@Override
89+
protected FactoryAOptions copyOrThis()
90+
{
91+
return new FactoryAOptions( this );
92+
}
93+
}
94+
95+
static < O extends OptionA< O > & OptionB< O > > void factory( final O options )
96+
{
97+
System.out.println( "(factory) options = " + options );
98+
}
99+
100+
public static void main( final String[] args )
101+
{
102+
final FactoryAOptions options = new FactoryAOptions().a( 3 ).b( 2 );
103+
System.out.println( "options = " + options );
104+
factory( options );
105+
System.out.println( "options.values = " + options.values );
106+
}
107+
}

0 commit comments

Comments
 (0)