Skip to content

Commit 11e53d4

Browse files
committed
Clean up DefaultOpDescriptionGenerator
1 parent 9bcaf07 commit 11e53d4

File tree

9 files changed

+107
-146
lines changed

9 files changed

+107
-146
lines changed

scijava-ops-engine/src/main/java/org/scijava/ops/engine/impl/DefaultOpDescriptionGenerator.java

Lines changed: 93 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,6 @@
2929

3030
package org.scijava.ops.engine.impl;
3131

32-
import java.lang.reflect.Type;
33-
import java.util.*;
34-
import java.util.function.Function;
35-
import java.util.stream.Collectors;
36-
import java.util.stream.Stream;
37-
3832
import com.google.common.base.Strings;
3933
import org.scijava.ops.api.*;
4034
import org.scijava.ops.engine.BaseOpHints;
@@ -47,6 +41,18 @@
4741
import org.scijava.types.Nil;
4842
import org.scijava.types.Types;
4943

44+
import java.lang.reflect.Type;
45+
import java.util.ArrayList;
46+
import java.util.Collection;
47+
import java.util.List;
48+
import java.util.Optional;
49+
import java.util.function.Function;
50+
import java.util.stream.Collectors;
51+
import java.util.stream.Stream;
52+
53+
import static org.scijava.struct.ItemIO.CONTAINER;
54+
import static org.scijava.struct.ItemIO.MUTABLE;
55+
5056
/**
5157
* An {@link OpDescriptionGenerator} implementation which makes use of
5258
* {@link ConvertedOpInfo}s to provide "simple" descriptions.
@@ -62,93 +68,26 @@ public double getPriority() {
6268

6369
@Override
6470
public String simpleDescriptions(OpEnvironment env, OpRequest req) {
65-
String name = req.getName();
66-
Optional<String> nsString = getNonOpString(env, name);
67-
if (nsString.isPresent()) return nsString.get();
68-
var infos = env.infos(name);
69-
Function<OpInfo, String> descriptor = (info) -> {
70-
final StringBuilder sb = new StringBuilder("(");
71-
// Step 2: Inputs
72-
var inputs = info.inputs().stream().map(member -> {
73-
var str = "";
74-
var description = describeType(env, Nil.of(member.getType()));
75-
switch (member.getIOType()) {
76-
case INPUT:
77-
str += description;
78-
break;
79-
case MUTABLE:
80-
str += "@MUTABLE " + description;
81-
break;
82-
case CONTAINER:
83-
str += "@CONTAINER " + description;
84-
break;
85-
default:
86-
throw new IllegalArgumentException("Invalid IO type: " + member
87-
.getIOType());
88-
}
89-
if (!member.isRequired()) {
90-
str += " = null";
91-
}
92-
return str;
93-
}).collect(Collectors.joining(", "));
94-
sb.append(inputs);
95-
sb.append(")");
96-
// Step 3: Output
97-
var output = info.output();
98-
sb.append(" -> ");
99-
switch (output.getIOType()) {
100-
case OUTPUT:
101-
var description = describeType(env, Nil.of(output.getType()));
102-
sb.append(description);
103-
break;
104-
case MUTABLE:
105-
case CONTAINER:
106-
sb.append("None");
107-
break;
108-
default:
109-
throw new IllegalArgumentException("Invalid IO type: " + output
110-
.getIOType());
111-
}
112-
return sb.toString();
113-
};
114-
return buildOpString(infos, req, descriptor);
115-
}
116-
117-
private static <T> String describeType(OpEnvironment env, Nil<T> from) {
118-
Type specialType = Types.parameterize(Function.class, new Type[] { Types
119-
.parameterize(Nil.class, new Type[] { from.getType() }), String.class });
120-
@SuppressWarnings("unchecked")
121-
Nil<Function<Nil<T>, String>> specialTypeNil =
122-
(Nil<Function<Nil<T>, String>>) Nil.of(specialType);
123-
try {
124-
Type nilFromType = Types.parameterize(Nil.class, new Type[] { from
125-
.getType() });
126-
Hints h = new Hints( //
127-
BaseOpHints.Adaptation.FORBIDDEN, //
128-
BaseOpHints.Conversion.FORBIDDEN, //
129-
BaseOpHints.History.IGNORE //
130-
);
131-
Function<Nil<T>, String> op = env.op("engine.describe", specialTypeNil,
132-
new Nil[] { Nil.of(nilFromType) }, Nil.of(String.class), h);
133-
return op.apply(from);
134-
}
135-
catch (OpMatchingException e) {
136-
return Types.raw(from.getType()).getSimpleName();
137-
}
71+
return buildOpString(req, env, info -> describeUsingOps(info, env));
13872
}
13973

14074
@Override
14175
public String verboseDescriptions(OpEnvironment env, OpRequest req) {
142-
String name = req.getName();
143-
Optional<String> nsString = getNonOpString(env, name);
144-
if (nsString.isPresent()) return nsString.get();
145-
var infos = env.infos(name);
146-
return buildOpString(infos, req, Infos::describeVerbose);
76+
return buildOpString(req, env, Infos::describe);
14777
}
14878

149-
private String buildOpString(Collection<OpInfo> infos, OpRequest req,
79+
private static String buildOpString(OpRequest req, OpEnvironment env,
15080
Function<OpInfo, String> descriptionFunction)
15181
{
82+
// handle namespaces queries
83+
String name = req.getName();
84+
Optional<String> nsString = getNonOpString(env, name);
85+
if (nsString.isPresent()) {
86+
return nsString.get();
87+
}
88+
89+
// handle name queries
90+
Collection<OpInfo> infos = env.infos(name);
15291
var filtered = filterInfos(infos, req);
15392
String opString = filtered.stream() //
15493
.map(descriptionFunction) //
@@ -170,7 +109,9 @@ private String buildOpString(Collection<OpInfo> infos, OpRequest req,
170109
* namespace. Returns {@code Optional.empty()} if this is a legitimate
171110
* op request.
172111
*/
173-
private Optional<String> getNonOpString(OpEnvironment env, String name) {
112+
private static Optional<String> getNonOpString(OpEnvironment env,
113+
String name)
114+
{
174115
String prefix = null;
175116
Stream<String> nsStream = null;
176117
if (Strings.isNullOrEmpty(name)) {
@@ -200,7 +141,7 @@ else if (env.infos(name).isEmpty()) {
200141
* @return A stream of strings for each Op info not in a protected namespace
201142
* (e.g. 'engine')
202143
*/
203-
private Stream<String> publicOpStream(OpEnvironment env) {
144+
private static Stream<String> publicOpStream(OpEnvironment env) {
204145
return env.infos().stream() //
205146
// Get all names from each Op
206147
.flatMap(info -> info.names().stream()) //
@@ -211,7 +152,7 @@ private Stream<String> publicOpStream(OpEnvironment env) {
211152
.filter(ns -> !ns.startsWith("engine"));
212153
}
213154

214-
private List<OpInfo> filterInfos(Iterable<? extends OpInfo> infos,
155+
private static List<OpInfo> filterInfos(Iterable<? extends OpInfo> infos,
215156
OpRequest req)
216157
{
217158
List<OpInfo> filtered = new ArrayList<>();
@@ -236,4 +177,68 @@ private List<OpInfo> filterInfos(Iterable<? extends OpInfo> infos,
236177
}
237178
return filtered;
238179
}
180+
181+
private static String describeUsingOps(final OpInfo info,
182+
final OpEnvironment env)
183+
{
184+
final StringBuilder sb = new StringBuilder("(");
185+
// describe inputs
186+
var memberItr = info.inputs().iterator();
187+
while (memberItr.hasNext()) {
188+
var m = memberItr.next();
189+
// MUTABLE annotation
190+
if (m.getIOType() == MUTABLE) {
191+
sb.append("@MUTABLE ");
192+
}
193+
// CONTAINER annotation
194+
else if (m.getIOType() == CONTAINER) {
195+
sb.append("@CONTAINER ");
196+
}
197+
// describe member type
198+
sb.append(describeType(env, Nil.of(m.getType())));
199+
if (!m.isRequired()) {
200+
sb.append(" = null");
201+
}
202+
// describe member optionality
203+
if (memberItr.hasNext()) {
204+
sb.append(", ");
205+
}
206+
}
207+
sb.append(")");
208+
// describe output
209+
var output = info.output();
210+
sb.append(" -> ");
211+
if (output.isInput()) {
212+
sb.append("None");
213+
}
214+
else {
215+
sb.append(describeType(env, Nil.of(output.getType())));
216+
}
217+
// return concatenation
218+
return sb.toString();
219+
}
220+
221+
private static <T> String describeType(OpEnvironment env, Nil<T> from) {
222+
Type specialType = Types.parameterize(Function.class, new Type[] { Types
223+
.parameterize(Nil.class, new Type[] { from.getType() }), String.class });
224+
@SuppressWarnings("unchecked")
225+
Nil<Function<Nil<T>, String>> specialTypeNil =
226+
(Nil<Function<Nil<T>, String>>) Nil.of(specialType);
227+
try {
228+
Type nilFromType = Types.parameterize(Nil.class, new Type[] { from
229+
.getType() });
230+
Hints h = new Hints( //
231+
BaseOpHints.Adaptation.FORBIDDEN, //
232+
BaseOpHints.Conversion.FORBIDDEN, //
233+
BaseOpHints.History.IGNORE //
234+
);
235+
Function<Nil<T>, String> op = env.op("engine.describe", specialTypeNil,
236+
new Nil[] { Nil.of(nilFromType) }, Nil.of(String.class), h);
237+
return op.apply(from);
238+
}
239+
catch (OpMatchingException e) {
240+
return Types.raw(from.getType()).getSimpleName();
241+
}
242+
}
243+
239244
}

scijava-ops-engine/src/main/java/org/scijava/ops/engine/matcher/MatchingResult.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ public static String matchInfo(final MatchingResult res) {
151151
int count = 0;
152152
for (final OpCandidate candidate : candidates) {
153153
sb.append(++count + ". ");
154-
sb.append("\t" + Infos.describeVerbose(candidate.opInfo()) + "\n");
154+
sb.append("\t" + Infos.describe(candidate.opInfo()) + "\n");
155155
final String status = candidate.getStatus();
156156
if (status != null) sb.append("\t" + status + "\n");
157157
if (candidate.getStatusCode() == StatusCode.DOES_NOT_CONFORM) {

scijava-ops-engine/src/main/java/org/scijava/ops/engine/matcher/adapt/OpAdaptationInfo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ public String id() {
173173
@Override
174174
public String toString() {
175175
// Get the original description
176-
String description = Infos.describeVerbose(this);
176+
String description = Infos.describe(this);
177177
// Make the name friendlier
178178
StringBuilder sb = new StringBuilder();
179179
sb.append(srcInfo.implementationName());

scijava-ops-engine/src/main/java/org/scijava/ops/engine/matcher/convert/ConvertedOpInfo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ public StructInstance<?> createOpInstance(List<?> dependencies) {
244244

245245
@Override
246246
public String toString() {
247-
return Infos.describeVerbose(this);
247+
return Infos.describe(this);
248248
}
249249

250250
@Override

scijava-ops-engine/src/main/java/org/scijava/ops/engine/matcher/impl/OpClassInfo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ public int hashCode() {
190190

191191
@Override
192192
public String toString() {
193-
return Infos.describeVerbose(this);
193+
return Infos.describe(this);
194194
}
195195

196196
@Override

scijava-ops-engine/src/main/java/org/scijava/ops/engine/matcher/impl/OpFieldInfo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ public int hashCode() {
239239

240240
@Override
241241
public String toString() {
242-
return Infos.describeVerbose(this);
242+
return Infos.describe(this);
243243
}
244244

245245
}

scijava-ops-engine/src/main/java/org/scijava/ops/engine/matcher/impl/OpMethodInfo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ public int hashCode() {
237237

238238
@Override
239239
public String toString() {
240-
return Infos.describeVerbose(this);
240+
return Infos.describe(this);
241241
}
242242

243243
@Override

scijava-ops-engine/src/main/java/org/scijava/ops/engine/matcher/reduce/ReducedOpInfo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ public int paramsReduced() {
230230

231231
@Override
232232
public String toString() {
233-
return Infos.describeVerbose(this);
233+
return Infos.describe(this);
234234
}
235235

236236
}

scijava-ops-engine/src/main/java/org/scijava/ops/engine/util/Infos.java

Lines changed: 7 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,21 @@
3636
import java.util.List;
3737
import java.util.Objects;
3838
import java.util.Optional;
39+
import java.util.function.Function;
3940
import java.util.stream.Collectors;
4041

42+
import org.scijava.ops.api.Hints;
43+
import org.scijava.ops.api.OpEnvironment;
4144
import org.scijava.ops.api.OpInfo;
45+
import org.scijava.ops.api.OpMatchingException;
46+
import org.scijava.ops.engine.BaseOpHints;
4247
import org.scijava.ops.engine.OpDependencyMember;
4348
import org.scijava.ops.engine.exceptions.impl.InvalidOpNameException;
4449
import org.scijava.ops.engine.exceptions.impl.MultipleOutputsOpException;
4550
import org.scijava.ops.engine.exceptions.impl.UnnamedOpException;
4651
import org.scijava.struct.ItemIO;
4752
import org.scijava.struct.Member;
53+
import org.scijava.types.Nil;
4854
import org.scijava.types.Types;
4955

5056
/**
@@ -143,7 +149,7 @@ public static List<OpDependencyMember<?>> dependencies(OpInfo info) {
143149
* @param info an {@link OpInfo}
144150
* @return a verbose description of {@code info}
145151
*/
146-
public static String describeVerbose(final OpInfo info) {
152+
public static String describe(final OpInfo info) {
147153
final StringBuilder sb = new StringBuilder(info.implementationName());
148154
// Step 2: Inputs
149155
for (var member : info.inputs()) {
@@ -172,56 +178,6 @@ else if (member.getIOType() == ItemIO.MUTABLE) {
172178
return sb.toString();
173179
}
174180

175-
/**
176-
* Forms a brief description of {@code info}
177-
*
178-
* @param info an {@link OpInfo}
179-
* @return a brief description of {@code info}
180-
*/
181-
public static String describe(final OpInfo info) {
182-
final StringBuilder sb = new StringBuilder("(");
183-
// Step 2: Inputs
184-
var inputs = info.inputs().stream().map(member -> {
185-
var str = "";
186-
switch (member.getIOType()) {
187-
case INPUT:
188-
str += member.getKey();
189-
break;
190-
case MUTABLE:
191-
str += "@MUTABLE " + member.getKey();
192-
break;
193-
case CONTAINER:
194-
str += "@CONTAINER " + member.getKey();
195-
break;
196-
default:
197-
throw new IllegalArgumentException("Invalid IO type: " + member
198-
.getIOType());
199-
}
200-
if (!member.isRequired()) {
201-
str += " = null";
202-
}
203-
return str;
204-
}).collect(Collectors.joining(", "));
205-
sb.append(inputs);
206-
sb.append(")");
207-
// Step 3: Output
208-
Member<?> output = info.output();
209-
sb.append(" -> ");
210-
switch (output.getIOType()) {
211-
case OUTPUT:
212-
sb.append(typeString(output.getType(), false));
213-
break;
214-
case MUTABLE:
215-
case CONTAINER:
216-
sb.append("None");
217-
break;
218-
default:
219-
throw new IllegalArgumentException("Invalid IO type: " + output
220-
.getIOType());
221-
}
222-
return sb.toString();
223-
}
224-
225181
private static String typeString(final Type input, final boolean verbose) {
226182
var str = input.getTypeName();
227183
if (verbose) return str;

0 commit comments

Comments
 (0)