Skip to content

Commit a3508fb

Browse files
committed
Support similar ScriptLanguages
If we have multiple languages that support the same extension/name we now use the highest priority ScriptLanguage that isActive (a new helper method for ScriptLanguages) instead of overwriting the language for that extension/name. This allows multiple language implementations to co-exist and take priority based on the execution context (e.g. Jython works in Java-based environments, PyImageJ works in python mode apps).
1 parent 2c09289 commit a3508fb

File tree

3 files changed

+40
-60
lines changed

3 files changed

+40
-60
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
</parent>
1111

1212
<artifactId>scijava-common</artifactId>
13-
<version>2.99.3-SNAPSHOT</version>
13+
<version>2.100.0-SNAPSHOT</version>
1414

1515
<name>SciJava Common</name>
1616
<description>SciJava Common is a shared library for SciJava software. It provides a plugin framework, with an extensible mechanism for service discovery, backed by its own annotation processor, so that plugins can be loaded dynamically. It is used by downstream projects in the SciJava ecosystem, such as ImageJ and SCIFIO.</description>

src/main/java/org/scijava/script/ScriptLanguage.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@ default boolean isCompiledLanguage() {
7575
return false;
7676
}
7777

78+
/**
79+
* Flag for complex languages that need to limit execution to a specific
80+
* context.
81+
*
82+
* @return true if this language is available for selection
83+
*/
84+
default boolean isActive() {
85+
return true;
86+
}
87+
7888
/**
7989
* Performs any necessary conversion of an encoded object retrieved from the
8090
* language's script engine.

src/main/java/org/scijava/script/ScriptLanguageIndex.java

Lines changed: 29 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939

4040
import org.scijava.log.LogService;
4141
import org.scijava.util.FileUtils;
42-
import org.scijava.util.Types;
4342

4443
/**
4544
* Data structure for managing registered scripting languages.
@@ -51,17 +50,12 @@ public class ScriptLanguageIndex extends ArrayList<ScriptLanguage> {
5150

5251
private static final long serialVersionUID = 1L;
5352

54-
private final Map<String, ScriptLanguage> byExtension = new HashMap<>();
53+
private final Map<String, List<ScriptLanguage>> byExtension = new HashMap<>();
5554

56-
private final Map<String, ScriptLanguage> byName = new HashMap<>();
55+
private final Map<String, List<ScriptLanguage>> byName = new HashMap<>();
5756

5857
private final LogService log;
5958

60-
@Deprecated
61-
public ScriptLanguageIndex() {
62-
this(null);
63-
}
64-
6559
/**
6660
* Instantiates an index of the available script languages.
6761
*
@@ -71,33 +65,48 @@ public ScriptLanguageIndex(final LogService log) {
7165
this.log = log;
7266
}
7367

74-
public boolean add(final ScriptEngineFactory factory, final boolean gently) {
68+
/**
69+
* @deprecated Gently flag is no longer respected. Use
70+
* {@link #add(ScriptLanguage)}.
71+
*/
72+
@Deprecated
73+
boolean add(final ScriptEngineFactory factory, final boolean gently) {
7574
boolean result = false;
7675

7776
final ScriptLanguage language = wrap(factory);
7877

7978
// add language names
80-
result |= put("name", byName, language.getLanguageName(), language, gently);
79+
result |= put(byName, language.getLanguageName(), language, gently);
8180
for (final String name : language.getNames()) {
82-
result |= put("name", byName, name, language, gently);
81+
result |= put(byName, name, language, gently);
8382
}
8483

8584
// add file extensions
8685
for (final String extension : language.getExtensions()) {
8786
if ("".equals(extension)) continue;
88-
result |= put("extension", byExtension, extension, language, gently);
87+
result |= put(byExtension, extension, language, gently);
8988
}
9089

9190
result |= super.add(language);
9291
return result;
9392
}
9493

9594
public ScriptLanguage getByExtension(final String extension) {
96-
return byExtension.get(extension);
95+
List<ScriptLanguage> langs = byExtension.get(extension);
96+
if (langs == null) return null;
97+
for (ScriptLanguage lang : langs) {
98+
if (lang.isActive()) return lang;
99+
}
100+
return null;
97101
}
98102

99103
public ScriptLanguage getByName(final String name) {
100-
return byName.get(name);
104+
List<ScriptLanguage> langs = byName.get(name);
105+
if (langs == null) return null;
106+
for (ScriptLanguage lang : langs) {
107+
if (lang.isActive()) return lang;
108+
}
109+
return null;
101110
}
102111

103112
public String[] getFileExtensions(final ScriptLanguage language) {
@@ -126,59 +135,20 @@ public boolean add(final ScriptLanguage language) {
126135

127136
// -- Helper methods --
128137

129-
private boolean put(final String type, final Map<String, ScriptLanguage> map,
138+
private boolean put(final Map<String, List<ScriptLanguage>> map,
130139
final String key, final ScriptLanguage value, final boolean gently)
131140
{
132-
final ScriptLanguage existing = map.get(key);
133-
134-
if (existing == value) {
135-
// Duplicate key/value pair; do not overwrite.
136-
if (log != null && log.isDebug()) {
137-
// In debug mode, warn about the duplicate (since it is atypical).
138-
log.debug(overwriteMessage(false, type, key, value, existing));
139-
}
140-
return false;
141+
List<ScriptLanguage> list = map.get(key);
142+
if (list == null) {
143+
list = new ArrayList<>();
144+
map.put(key, list);
141145
}
142-
143-
if (existing != null) {
144-
// Conflicting value; behavior depends on mode.
145-
if (gently) {
146-
// Do not overwrite the previous value.
147-
if (log != null && log.isDebug()) {
148-
log.debug(overwriteMessage(false, type, key, value, existing));
149-
}
150-
return false;
151-
}
152-
if (log != null && log.isDebug()) {
153-
// In debug mode, warn about overwriting.
154-
log.debug(overwriteMessage(true, type, key, value, existing));
155-
}
156-
}
157-
158-
map.put(key, value);
159-
return true;
146+
return list.add(value);
160147
}
161148

162149
/** Helper method of {@link #add(ScriptEngineFactory, boolean)}. */
163150
private ScriptLanguage wrap(final ScriptEngineFactory factory) {
164151
if (factory instanceof ScriptLanguage) return (ScriptLanguage) factory;
165152
return new AdaptedScriptLanguage(factory);
166153
}
167-
168-
/** Helper method of {@link #put}. */
169-
private String overwriteMessage(final boolean overwrite, final String type,
170-
final String key, final ScriptLanguage proposed,
171-
final ScriptLanguage existing)
172-
{
173-
return (overwrite ? "Overwriting " : "Not overwriting ") + //
174-
type + " '" + key + "':\n" + //
175-
"\tproposed = " + details(proposed) + "\n" + "\texisting = " + details(
176-
existing);
177-
}
178-
179-
/** Helper method of {@link #overwriteMessage}. */
180-
private String details(final ScriptLanguage language) {
181-
final Class<?> c = language.getClass();
182-
return c.getName() + " [" + Types.location(c);
183-
}
184154
}

0 commit comments

Comments
 (0)