Skip to content

Commit a0b69e6

Browse files
gselzerctrueden
authored andcommitted
Extract OpRef interface
This commit also makes some changes to SimplifiedOpRef that make it more correct. I chose to throw UnsupportedOperationException for many of the standard OpRef methods because the concrete type that the SimplifiedOpRef is asking for is rather indeterminate - it is really asking for an Op that is of a set of Types, so to pin a particualar set of arguments, a particular output type, etc. is not possible until you have a SimplifiedOpInfo to narrow down these Types. Similarly, we throw an UnsupportedOperationException for typesMatch because the typing of the SimplifiedOpRef is unclear. We could match against all possible permutations of the input/output types, but we don't really have enough information about how to form the opType. We could probably find a way to devise all opType permutations, but this would be a pretty computationally expensive method to run, so for now we'll just throw an error
1 parent eb53ac4 commit a0b69e6

17 files changed

+273
-100
lines changed

scijava/scijava-ops/src/main/java/org/scijava/ops/OpEnvironment.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131

3232
import java.lang.reflect.Type;
3333

34-
import org.scijava.ops.matcher.OpRef;
3534
import org.scijava.types.Nil;
3635

3736
/**

scijava/scijava-ops/src/main/java/org/scijava/ops/OpInfo.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@
88
import java.util.Map;
99

1010
import org.scijava.log.Logger;
11-
import org.scijava.ops.hint.ImmutableHints;
1211
import org.scijava.ops.matcher.OpCandidate;
13-
import org.scijava.ops.matcher.OpRef;
1412
import org.scijava.param.ValidityException;
1513
import org.scijava.struct.Member;
1614
import org.scijava.struct.Struct;
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* #%L
3+
* ImageJ software for multidimensional image processing and analysis.
4+
* %%
5+
* Copyright (C) 2014 - 2018 ImageJ developers.
6+
* %%
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright notice,
11+
* this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
* #L%
28+
*/
29+
30+
package org.scijava.ops;
31+
32+
import java.lang.reflect.Type;
33+
import java.lang.reflect.TypeVariable;
34+
import java.util.Arrays;
35+
import java.util.Map;
36+
import java.util.Objects;
37+
38+
import org.scijava.ops.matcher.OpMatcher;
39+
import org.scijava.types.Types;
40+
41+
/**
42+
* Data structure which identifies an op by name and/or type(s) and/or argument
43+
* type(s), along with a list of input arguments.
44+
* <p>
45+
* With the help of the {@link OpMatcher}, an {@code OpRef} holds all
46+
* information needed to create an appropriate {@link Op}.
47+
* </p>
48+
*
49+
* @author Christian Dietz (University of Konstanz)
50+
* @author Curtis Rueden
51+
*/
52+
public interface OpRef {
53+
54+
// -- OpRef methods --
55+
56+
/** Gets the name of the op. */
57+
public String getName();
58+
59+
/** Gets the type which the op must match. */
60+
public Type getType();
61+
62+
/**
63+
* Gets the op's output type constraint, or null for no constraint.
64+
*/
65+
public Type getOutType();
66+
67+
/** Gets the op's arguments. */
68+
public Type[] getArgs();
69+
70+
/**
71+
* Gets a label identifying the op's scope (i.e., its name and/or types).
72+
*/
73+
public String getLabel();
74+
75+
public boolean typesMatch(final Type opType);
76+
77+
/**
78+
* Determines whether the specified type satisfies the op's required types
79+
* using {@link Types#isApplicable(Type[], Type[])}.
80+
*/
81+
public boolean typesMatch(final Type opType, final Map<TypeVariable<?>, Type> typeVarAssigns);
82+
83+
// -- Object methods --
84+
85+
default String refString() {
86+
String n = getName() == null ? "" : "Name: \"" + getName() + "\", Types: ";
87+
n += getType() + "\n";
88+
n += "Input Types: \n";
89+
for (Type arg : getArgs()) {
90+
n += "\t\t* ";
91+
n += arg == null ? "" : arg.getTypeName();
92+
n += "\n";
93+
}
94+
n += "Output Type: \n";
95+
n += "\t\t* ";
96+
n += getOutType() == null ? "" : getOutType().getTypeName();
97+
n += "\n";
98+
return n.substring(0, n.length() - 1);
99+
}
100+
101+
default boolean refEquals(final Object obj) {
102+
if (this == obj)
103+
return true;
104+
if (obj == null)
105+
return false;
106+
if (getClass() != obj.getClass())
107+
return false;
108+
final OpRef other = (OpRef) obj;
109+
if (!Objects.equals(getName(), other.getName()))
110+
return false;
111+
if (!Objects.equals(getType(), other.getType()))
112+
return false;
113+
if (!Objects.equals(getOutType(), other.getOutType()))
114+
return false;
115+
if (!Arrays.equals(getArgs(), other.getArgs()))
116+
return false;
117+
return true;
118+
}
119+
120+
default int refHashCode() {
121+
return Arrays.deepHashCode(new Object[] {getName(), getType(), getOutType(), getArgs()});
122+
}
123+
124+
// -- Utility methods --
125+
126+
public static Type[] filterNulls(final Type... types) {
127+
Type[] ts = Arrays.stream(types).filter(t -> t != null).toArray(Type[]::new);
128+
return ts == null ? null : ts;
129+
}
130+
131+
// -- Helper methods --
132+
133+
static void append(final StringBuilder sb, final String s) {
134+
if (s == null)
135+
return;
136+
if (sb.length() > 0)
137+
sb.append("/");
138+
sb.append(s);
139+
}
140+
}

scijava/scijava-ops/src/main/java/org/scijava/ops/OpUtils.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
import org.scijava.ops.matcher.OpCandidate;
4141
import org.scijava.ops.matcher.OpCandidate.StatusCode;
4242
import org.scijava.ops.matcher.OpMatcher;
43-
import org.scijava.ops.matcher.OpRef;
4443
import org.scijava.param.ParameterMember;
4544
import org.scijava.param.ParameterStructs;
4645
import org.scijava.param.ValidityException;

scijava/scijava-ops/src/main/java/org/scijava/ops/impl/DefaultOpEnvironment.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,13 @@
6666
import org.scijava.ops.OpInfo;
6767
import org.scijava.ops.OpInstance;
6868
import org.scijava.ops.OpMethod;
69+
import org.scijava.ops.OpRef;
6970
import org.scijava.ops.OpUtils;
7071
import org.scijava.ops.hint.AdaptationHints;
7172
import org.scijava.ops.hint.DefaultHints;
7273
import org.scijava.ops.hint.SimplificationHints;
7374
import org.scijava.ops.matcher.DefaultOpMatcher;
75+
import org.scijava.ops.matcher.DefaultOpRef;
7476
import org.scijava.ops.matcher.DependencyMatchingException;
7577
import org.scijava.ops.matcher.MatchingUtils;
7678
import org.scijava.ops.matcher.OpAdaptationInfo;
@@ -81,7 +83,6 @@
8183
import org.scijava.ops.matcher.OpMatcher;
8284
import org.scijava.ops.matcher.OpMatchingException;
8385
import org.scijava.ops.matcher.OpMethodInfo;
84-
import org.scijava.ops.matcher.OpRef;
8586
import org.scijava.ops.provenance.OpHistoryService;
8687
import org.scijava.ops.simplify.SimplifiedOpInfo;
8788
import org.scijava.ops.util.OpWrapper;
@@ -198,7 +199,11 @@ public <T> T op(final String opName, final Nil<T> specialType,
198199

199200
@Override
200201
public <T> T op(final OpInfo info, final Nil<T> specialType, final Nil<?>[] inTypes, final Nil<?> outType) {
201-
return op(info, specialType, inTypes, outType, getHints());
202+
try {
203+
return findOp(info, specialType, inTypes, outType, getHints());
204+
} catch (OpMatchingException e) {
205+
throw new IllegalArgumentException(e);
206+
}
202207
}
203208

204209
@Override
@@ -249,7 +254,7 @@ public void register(final OpInfo info, final String name) {
249254
@SuppressWarnings("unchecked")
250255
private <T> T findOp(final String opName, final Nil<T> specialType, final Nil<?>[] inTypes,
251256
final Nil<?> outType, Hints hints) throws OpMatchingException {
252-
final OpRef ref = OpRef.fromTypes(opName, specialType.getType(), outType != null ? outType.getType() : null,
257+
final OpRef ref = DefaultOpRef.fromTypes(opName, specialType.getType(), outType != null ? outType.getType() : null,
253258
toTypes(inTypes));
254259
MatchingConditions conditions = MatchingConditions.from(ref, hints, true);
255260
generateOpInstance(conditions);
@@ -260,7 +265,7 @@ private <T> T findOp(final String opName, final Nil<T> specialType, final Nil<?>
260265
private <T> T findOp(final OpInfo info, final Nil<T> specialType, final Nil<?>[] inTypes,
261266
final Nil<?> outType, Hints hints) throws OpMatchingException
262267
{
263-
OpRef ref = OpRef.fromTypes(specialType.getType(), outType.getType(),
268+
OpRef ref = DefaultOpRef.fromTypes(specialType.getType(), outType.getType(),
264269
toTypes(inTypes));
265270
MatchingConditions conditions = MatchingConditions.from(ref, hints, true);
266271
generateOpInstance(conditions, info);
@@ -717,7 +722,7 @@ private OpRef inferOpRef(Type type, String name, Map<TypeVariable<?>, Type> type
717722
error += ". This is not supported.";
718723
throw new OpMatchingException(error);
719724
}
720-
return new OpRef(name, type, mappedOutputs[0], mappedInputs);
725+
return new DefaultOpRef(name, type, mappedOutputs[0], mappedInputs);
721726
}
722727

723728
private void initOpDirectory() {

scijava/scijava-ops/src/main/java/org/scijava/ops/impl/MatchingConditions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import java.util.Objects;
55

66
import org.scijava.ops.Hints;
7-
import org.scijava.ops.matcher.OpRef;
7+
import org.scijava.ops.OpRef;
88

99
public class MatchingConditions {
1010

scijava/scijava-ops/src/main/java/org/scijava/ops/matcher/DefaultOpMatcher.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.scijava.ops.Hints;
4848
import org.scijava.ops.OpEnvironment;
4949
import org.scijava.ops.OpInfo;
50+
import org.scijava.ops.OpRef;
5051
import org.scijava.ops.OpUtils;
5152
import org.scijava.ops.BaseOpHints.Simplification;
5253
import org.scijava.ops.hint.DefaultHints;

0 commit comments

Comments
 (0)