Skip to content

Commit d1192fc

Browse files
gselzerctrueden
authored andcommitted
Therapi Discoverer
1 parent ae6697a commit d1192fc

3 files changed

Lines changed: 270 additions & 0 deletions

File tree

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
2+
package org.scijava.ops.engine.impl;
3+
4+
import com.github.therapi.runtimejavadoc.BaseJavadoc;
5+
import com.github.therapi.runtimejavadoc.ClassJavadoc;
6+
import com.github.therapi.runtimejavadoc.FieldJavadoc;
7+
import com.github.therapi.runtimejavadoc.MethodJavadoc;
8+
import com.github.therapi.runtimejavadoc.RuntimeJavadoc;
9+
10+
import java.io.File;
11+
import java.io.IOException;
12+
import java.lang.reflect.AnnotatedElement;
13+
import java.lang.reflect.Field;
14+
import java.lang.reflect.Method;
15+
import java.util.ArrayList;
16+
import java.util.Arrays;
17+
import java.util.Collections;
18+
import java.util.Enumeration;
19+
import java.util.HashMap;
20+
import java.util.List;
21+
import java.util.Map;
22+
import java.util.function.BiFunction;
23+
import java.util.function.BiPredicate;
24+
import java.util.jar.JarEntry;
25+
import java.util.jar.JarFile;
26+
import java.util.stream.Collectors;
27+
28+
import org.scijava.discovery.Discoverer;
29+
30+
public class TherapiDiscoverer implements Discoverer {
31+
32+
BiPredicate<BaseJavadoc, String[]> hasTags = (mjavadoc, tags) -> {
33+
for (String tag : tags) {
34+
boolean hasTag = mjavadoc.getOther().parallelStream() //
35+
.anyMatch(m -> m
36+
.getName().equals("implNote") && m.getComment().toString().contains(
37+
tag));
38+
if (!hasTag)
39+
return false;
40+
}
41+
return true;
42+
};
43+
44+
@Override
45+
public List<AnnotatedElement> elementsTaggedWith(String... tags) {
46+
List<String> paths = new ArrayList<>(Arrays.asList(System.getProperty(
47+
"java.class.path").split(File.pathSeparator)));
48+
paths.addAll(Arrays.asList(System.getProperty("jdk.module.path").split(
49+
File.pathSeparator)));
50+
Map<String, List<String>> javadocedFiles = new HashMap<>();
51+
paths.parallelStream().forEach(p -> {
52+
List<String> files = getJavadocedFiles(p).parallelStream().map(
53+
f -> getFullyQualifiedName(f, p)).collect(Collectors.toList());
54+
if (!files.isEmpty()) javadocedFiles.put(p, files);
55+
});
56+
Map<ClassJavadoc, String> javadocData = new HashMap<>();
57+
javadocedFiles.entrySet().parallelStream().forEach(e -> {
58+
Class<?> c;
59+
try {
60+
c = Class.forName(e.getValue().get(0));
61+
e.getValue().parallelStream().forEach(s -> javadocData.put(
62+
RuntimeJavadoc.getJavadoc(s, c), s));
63+
}
64+
catch (ClassNotFoundException exc) {
65+
return;
66+
}
67+
});
68+
69+
List<AnnotatedElement> taggedClasses = javadocData.entrySet()
70+
.parallelStream() //
71+
.filter(e -> hasTags.test(e.getKey(), tags)) //
72+
.map(e -> {
73+
try {
74+
return Class.forName(e.getValue());
75+
}
76+
catch (ClassNotFoundException exc) {
77+
return null;
78+
}
79+
}).filter(c -> c != null).collect(Collectors.toList());
80+
List<AnnotatedElement> taggedMethods = javadocData.entrySet()
81+
.parallelStream() //
82+
.map(e -> taggedMethodFinder.apply(e, tags)) //
83+
.flatMap(list -> list.parallelStream()) //
84+
.collect(Collectors.toList());
85+
List<AnnotatedElement> taggedFields = javadocData.entrySet()
86+
.parallelStream() //
87+
.map(e -> taggedFieldFinder.apply(e, tags)) //
88+
.flatMap(list -> list.parallelStream()) //
89+
.collect(Collectors.toList());
90+
taggedClasses.addAll(taggedMethods);
91+
taggedClasses.addAll(taggedFields);
92+
return taggedClasses;
93+
}
94+
95+
/**
96+
* Using a string {@code className}, finds a list of tagged methods
97+
*/
98+
private final BiFunction<Map.Entry<ClassJavadoc, String>, String[], List<Method>> taggedMethodFinder =
99+
(entry, tags) -> {
100+
List<MethodJavadoc> taggedJavadoc = entry.getKey().getMethods()
101+
.parallelStream().filter(m -> hasTags.test(m, tags)).collect(Collectors.toList());
102+
103+
if (taggedJavadoc.isEmpty()) return Collections.emptyList();
104+
105+
Method[] methods;
106+
try {
107+
methods = Class.forName(entry.getValue()).getDeclaredMethods();
108+
}
109+
catch (SecurityException | ClassNotFoundException exc) {
110+
return Collections.emptyList();
111+
}
112+
List<Method> taggedClassMethods = taggedJavadoc.parallelStream() //
113+
.map(mJavadoc -> Arrays.stream(methods).filter(m -> mJavadoc.matches(m))
114+
.findAny()) //
115+
.filter(optional -> optional.isPresent()) //
116+
.map(o -> o.get()).collect(Collectors.toList());
117+
return taggedClassMethods;
118+
119+
};
120+
121+
private final BiFunction<Map.Entry<ClassJavadoc, String>, String[], List<Field>> taggedFieldFinder =
122+
(entry, tags) -> {
123+
List<FieldJavadoc> taggedJavadoc = entry.getKey().getFields()
124+
.parallelStream().filter(j -> hasTags.test(j, tags)).collect(Collectors.toList());
125+
126+
if (taggedJavadoc.isEmpty()) return Collections.emptyList();
127+
128+
Field[] fields;
129+
try {
130+
fields = Class.forName(entry.getValue()).getDeclaredFields();
131+
}
132+
catch (SecurityException | ClassNotFoundException exc) {
133+
return Collections.emptyList();
134+
}
135+
List<Field> taggedClassFields = taggedJavadoc.parallelStream() //
136+
.map(fJavadoc -> Arrays.stream(fields).filter(f -> fJavadoc.getName()
137+
.equals(f.getName())).findAny()) //
138+
.filter(optional -> optional.isPresent()) //
139+
.map(o -> o.get()).collect(Collectors.toList());
140+
return taggedClassFields;
141+
142+
};
143+
144+
/**
145+
* list files in the given directory and subdirs (with recursion)
146+
*
147+
* @param paths
148+
* @return
149+
*/
150+
public static List<File> getJavadocedFiles(String path) {
151+
List<File> filesList = new ArrayList<File>();
152+
final File file = new File(path);
153+
if (file.isDirectory()) {
154+
recurse(filesList, file);
155+
}
156+
else if (file.getPath().endsWith(".jar")) {
157+
try {
158+
for (String s : getJarContent(path))
159+
if (s.endsWith("__Javadoc.json")) filesList.add(file);
160+
}
161+
catch (IOException exc) {
162+
// TODO Auto-generated catch block
163+
exc.printStackTrace();
164+
}
165+
}
166+
else {
167+
if (path.endsWith("__Javadoc.json")) filesList.add(file);
168+
}
169+
return filesList;
170+
}
171+
172+
private static void recurse(List<File> filesList, File f) {
173+
File list[] = f.listFiles();
174+
for (File file : list) {
175+
if (file.isDirectory()) {
176+
recurse(filesList, file);
177+
}
178+
else {
179+
if (file.getPath().endsWith("__Javadoc.json")) filesList.add(file);
180+
}
181+
}
182+
}
183+
184+
private static String getFullyQualifiedName(File f, String path) {
185+
return f.getPath().substring(path.length() + 1, f.getPath().indexOf(
186+
"__Javadoc.json")).replace(System.getProperty("file.separator"), ".");
187+
}
188+
189+
/**
190+
* List the content of the given jar
191+
*
192+
* @param jarPath
193+
* @return
194+
* @throws IOException
195+
*/
196+
public static List<String> getJarContent(String jarPath) throws IOException {
197+
List<String> content = new ArrayList<String>();
198+
JarFile jarFile = new JarFile(jarPath);
199+
Enumeration<JarEntry> e = jarFile.entries();
200+
while (e.hasMoreElements()) {
201+
JarEntry entry = (JarEntry) e.nextElement();
202+
String name = entry.getName();
203+
content.add(name);
204+
}
205+
return content;
206+
}
207+
208+
}

scijava/scijava-ops-engine/src/main/java/org/scijava/ops/engine/math/Sqrt.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
import org.scijava.ops.spi.OpField;
99
import org.scijava.plugin.Plugin;
1010

11+
/**
12+
* @implNote op
13+
* @author gselz
14+
*
15+
*/
1116
@Plugin(type = OpCollection.class)
1217
public class Sqrt {
1318

@@ -33,4 +38,10 @@ public class Sqrt {
3338
for(int i = 0; i < arr.length; i++) arr[i] = Math.sqrt(arr[i]);
3439
};
3540

41+
/**
42+
* TEMP op used for testing
43+
* @implNote op
44+
*/
45+
public static final Function<Long, Long> MathSqrtLongFunction = (in) -> (long) Math.sqrt(in);
46+
3647
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package org.scijava.ops.engine.impl;
2+
3+
import java.lang.reflect.AnnotatedElement;
4+
import java.lang.reflect.Field;
5+
import java.util.List;
6+
import java.util.function.Function;
7+
8+
import org.junit.Assert;
9+
import org.junit.Test;
10+
11+
public class TherapiDiscovererTest extends TherapiDiscoverer {
12+
13+
@Test
14+
public void discoverClass() {
15+
List<AnnotatedElement> list = new TherapiDiscoverer().elementsTaggedWith("test");
16+
Assert.assertTrue(list.contains(ClassTest.class));
17+
}
18+
19+
@Test
20+
public void discoverField() throws NoSuchFieldException, SecurityException {
21+
List<AnnotatedElement> list = new TherapiDiscoverer().elementsTaggedWith("test");
22+
Assert.assertTrue(list.contains(this.getClass().getDeclaredField("fieldTest")));
23+
}
24+
25+
@Test
26+
public void discoverMethod() throws NoSuchMethodException, SecurityException {
27+
List<AnnotatedElement> list = new TherapiDiscoverer().elementsTaggedWith("test");
28+
Assert.assertTrue(list.contains(this.getClass().getDeclaredMethod("methodTest")));
29+
}
30+
31+
/**
32+
* @implNote test
33+
*/
34+
public void methodTest() {
35+
36+
}
37+
38+
/**
39+
* @implNote test
40+
*/
41+
public final Function<Integer, Integer> fieldTest = (in) -> in+ 1;
42+
}
43+
44+
/**
45+
* @implNote test
46+
* @author gselz
47+
*
48+
*/
49+
class ClassTest {
50+
51+
}

0 commit comments

Comments
 (0)