2929
3030package 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-
3832import com .google .common .base .Strings ;
3933import org .scijava .ops .api .*;
4034import org .scijava .ops .engine .BaseOpHints ;
4741import org .scijava .types .Nil ;
4842import 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}
0 commit comments