Skip to content

Commit 9231219

Browse files
authored
Merge pull request #374 from scijava/named-objects
Add named object index and improve ObjectService
2 parents fee2644 + d5dfb5d commit 9231219

File tree

6 files changed

+205
-33
lines changed

6 files changed

+205
-33
lines changed

src/main/java/org/scijava/object/DefaultObjectService.java

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,10 @@
3232

3333
package org.scijava.object;
3434

35-
import java.util.List;
36-
3735
import org.scijava.event.EventHandler;
3836
import org.scijava.event.EventService;
3937
import org.scijava.object.event.ObjectCreatedEvent;
4038
import org.scijava.object.event.ObjectDeletedEvent;
41-
import org.scijava.object.event.ObjectsAddedEvent;
42-
import org.scijava.object.event.ObjectsRemovedEvent;
4339
import org.scijava.plugin.Parameter;
4440
import org.scijava.plugin.Plugin;
4541
import org.scijava.service.AbstractService;
@@ -68,7 +64,7 @@ public final class DefaultObjectService extends AbstractService implements
6864
private EventService eventService;
6965

7066
/** Index of registered objects. */
71-
private ObjectIndex<Object> objectIndex;
67+
private NamedObjectIndex<Object> objectIndex;
7268

7369
// -- ObjectService methods --
7470

@@ -78,35 +74,15 @@ public EventService eventService() {
7874
}
7975

8076
@Override
81-
public ObjectIndex<Object> getIndex() {
77+
public NamedObjectIndex<Object> getIndex() {
8278
return objectIndex;
8379
}
8480

85-
@Override
86-
public <T> List<T> getObjects(final Class<T> type) {
87-
final List<Object> list = objectIndex.get(type);
88-
@SuppressWarnings("unchecked")
89-
final List<T> result = (List<T>) list;
90-
return result;
91-
}
92-
93-
@Override
94-
public void addObject(final Object obj) {
95-
objectIndex.add(obj);
96-
eventService.publish(new ObjectsAddedEvent(obj));
97-
}
98-
99-
@Override
100-
public void removeObject(final Object obj) {
101-
objectIndex.remove(obj);
102-
eventService.publish(new ObjectsRemovedEvent(obj));
103-
}
104-
10581
// -- Service methods --
10682

10783
@Override
10884
public void initialize() {
109-
objectIndex = new ObjectIndex<>(Object.class);
85+
objectIndex = new NamedObjectIndex<>(Object.class);
11086
}
11187

11288
// -- Event handlers --
@@ -120,5 +96,4 @@ protected void onEvent(final ObjectCreatedEvent event) {
12096
protected void onEvent(final ObjectDeletedEvent event) {
12197
removeObject(event.getObject());
12298
}
123-
12499
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package org.scijava.object;
2+
3+
import java.util.WeakHashMap;
4+
5+
/**
6+
* An {@link ObjectIndex} where each object can have an associated name.
7+
*
8+
* @author Jan Eglinger
9+
*/
10+
public class NamedObjectIndex<E> extends ObjectIndex<E> {
11+
12+
private WeakHashMap<Object, String> nameMap;
13+
14+
public NamedObjectIndex(final Class<E> baseClass) {
15+
super(baseClass);
16+
nameMap = new WeakHashMap<>();
17+
}
18+
19+
public boolean add(E object, String name) {
20+
if (name != null)
21+
nameMap.put(object, name);
22+
return add(object);
23+
}
24+
25+
public boolean add(E object, Class<?> type, String name, boolean batch) {
26+
if (name != null)
27+
nameMap.put(object, name);
28+
return add(object, type, batch);
29+
}
30+
31+
public String getName(E object) {
32+
return nameMap.get(object);
33+
}
34+
}

src/main/java/org/scijava/object/ObjectService.java

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@
3434

3535
import java.util.List;
3636

37+
import org.scijava.Named;
3738
import org.scijava.event.EventService;
39+
import org.scijava.object.event.ObjectsAddedEvent;
40+
import org.scijava.object.event.ObjectsRemovedEvent;
3841
import org.scijava.service.SciJavaService;
3942

4043
/**
@@ -49,16 +52,54 @@ default EventService eventService() {
4952
}
5053

5154
/** Gets the index of available objects. */
52-
ObjectIndex<Object> getIndex();
55+
NamedObjectIndex<Object> getIndex();
5356

5457
/** Gets a list of all registered objects compatible with the given type. */
55-
<T> List<T> getObjects(Class<T> type);
58+
default <T> List<T> getObjects(final Class<T> type) {
59+
final List<Object> list = getIndex().get(type);
60+
@SuppressWarnings("unchecked")
61+
final List<T> result = (List<T>) list;
62+
return result;
63+
}
64+
65+
/**
66+
* Gets the name belonging to a given object.
67+
* <p>
68+
* If no explicit name was provided at registration time, the name will be
69+
* derived from {@link Named#getName()} if the object implements
70+
* {@link Named}, or from the {@link Object#toString()} otherwise. It is
71+
* guaranteed that this method will not return {@code null}.
72+
* </p>
73+
**/
74+
default String getName(final Object obj) {
75+
if (obj == null) throw new NullPointerException();
76+
final String name = getIndex().getName(obj);
77+
if (name != null) return name;
78+
if (obj instanceof Named) {
79+
final String n = ((Named) obj).getName();
80+
if (n != null) return n;
81+
}
82+
final String s = obj.toString();
83+
if (s != null) return s;
84+
return obj.getClass().getName() + "@" + Integer.toHexString(obj.hashCode());
85+
}
5686

5787
/** Registers an object with the object service. */
58-
void addObject(Object obj);
88+
default void addObject(Object obj) {
89+
addObject(obj, null);
90+
}
91+
92+
/** Registers a named object with the object service. */
93+
default void addObject(final Object obj, final String name) {
94+
getIndex().add(obj, name);
95+
eventService().publish(new ObjectsAddedEvent(obj));
96+
}
5997

6098
/** Deregisters an object with the object service. */
61-
void removeObject(Object obj);
99+
default void removeObject(final Object obj) {
100+
getIndex().remove(obj);
101+
eventService().publish(new ObjectsRemovedEvent(obj));
102+
}
62103

63104
// -- Deprecated methods --
64105

src/main/java/org/scijava/widget/DefaultWidgetModel.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.scijava.module.Module;
4848
import org.scijava.module.ModuleItem;
4949
import org.scijava.module.ModuleService;
50+
import org.scijava.object.ObjectService;
5051
import org.scijava.plugin.Parameter;
5152
import org.scijava.thread.ThreadService;
5253
import org.scijava.util.NumberUtils;
@@ -74,6 +75,9 @@ public class DefaultWidgetModel extends AbstractContextual implements WidgetMode
7475
@Parameter
7576
private ModuleService moduleService;
7677

78+
@Parameter
79+
private ObjectService objectService;
80+
7781
@Parameter(required = false)
7882
private LogService log;
7983

@@ -227,7 +231,7 @@ public String[] getChoices() {
227231
final List<?> choicesList = item.getChoices();
228232
final String[] choices = new String[choicesList.size()];
229233
for (int i = 0; i < choices.length; i++) {
230-
choices[i] = choicesList.get(i).toString();
234+
choices[i] = objectService.getName(choicesList.get(i));
231235
}
232236
return choices;
233237
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package org.scijava.object;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertFalse;
5+
import static org.junit.Assert.assertTrue;
6+
import static org.junit.Assert.fail;
7+
8+
import org.junit.Test;
9+
10+
public class NamedObjectIndexTest {
11+
12+
@Test
13+
public void testNamedObjects() {
14+
NamedObjectIndex<String> index = new NamedObjectIndex<>(String.class);
15+
String obj1 = "obj1";
16+
String name1 = "name1";
17+
String obj2 = "obj1";
18+
String name2 = "name1";
19+
assertTrue(index.add(obj1, name1));
20+
assertTrue(index.add(obj2, String.class, name2, false));
21+
assertTrue(index.contains(obj1));
22+
assertTrue(index.contains(obj2));
23+
assertEquals(name1, index.getName(obj1));
24+
assertEquals(name2, index.getName(obj2));
25+
assertTrue(index.remove(obj1));
26+
assertTrue(index.remove(obj2));
27+
assertFalse(index.contains(obj1));
28+
assertFalse(index.contains(obj2));
29+
}
30+
31+
@Test
32+
public void testNullNames() {
33+
NamedObjectIndex<String> index = new NamedObjectIndex<>(String.class);
34+
String obj1 = "object1";
35+
String name1 = null;
36+
String obj2 = "object2";
37+
String name2 = "";
38+
assertTrue(index.add(obj1, name1));
39+
assertTrue(index.add(obj2, name2));
40+
assertEquals(name1, index.getName(obj1));
41+
assertEquals(name2, index.getName(obj2));
42+
}
43+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package org.scijava.object;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertFalse;
5+
import static org.junit.Assert.assertNotNull;
6+
import static org.junit.Assert.assertTrue;
7+
8+
import org.junit.After;
9+
import org.junit.Before;
10+
import org.junit.Test;
11+
import org.scijava.Context;
12+
import org.scijava.plugin.PluginInfo;
13+
import org.scijava.plugin.SciJavaPlugin;
14+
15+
public class ObjectServiceTest {
16+
17+
private Context context;
18+
private ObjectService objectService;
19+
20+
@Before
21+
public void setUp() {
22+
context = new Context(ObjectService.class);
23+
objectService = context.getService(ObjectService.class);
24+
}
25+
26+
@After
27+
public void tearDown() {
28+
context.dispose();
29+
}
30+
31+
@Test
32+
public void testAddRemoveObjects() {
33+
Object obj1 = new Object();
34+
String name1 = "Object 1";
35+
Object obj2 = "";
36+
Object obj3 = new Double(0.3);
37+
PluginInfo<SciJavaPlugin> obj4 = PluginInfo.create(TestPlugin.class, SciJavaPlugin.class);
38+
obj4.setName("TestPlugin name");
39+
40+
objectService.addObject(obj1, name1);
41+
assertEquals("Name of object 1", name1, objectService.getName(obj1));
42+
objectService.addObject(obj2);
43+
assertEquals("Name of object 2", obj2.toString(), objectService.getName(obj2));
44+
objectService.addObject(obj3, null);
45+
assertEquals("Name of object 3", obj3.toString(), objectService.getName(obj3));
46+
objectService.addObject(obj4);
47+
assertNotNull(objectService.getName(obj4));
48+
assertEquals("Name of object 4", obj4.getName(), objectService.getName(obj4));
49+
50+
assertTrue("Object 1 registered", objectService.getObjects(Object.class).contains(obj1));
51+
assertTrue("Object 2 registered", objectService.getObjects(Object.class).contains(obj2));
52+
assertTrue("Object 3 registered", objectService.getObjects(Object.class).contains(obj3));
53+
assertTrue("Object 4 registered", objectService.getObjects(Object.class).contains(obj4));
54+
55+
objectService.removeObject(obj1);
56+
objectService.removeObject(obj2);
57+
objectService.removeObject(obj3);
58+
objectService.removeObject(obj4);
59+
60+
assertFalse("Object 1 removed", objectService.getObjects(Object.class).contains(obj1));
61+
assertFalse("Object 2 removed", objectService.getObjects(Object.class).contains(obj2));
62+
assertFalse("Object 3 removed", objectService.getObjects(Object.class).contains(obj3));
63+
assertFalse("Object 4 removed", objectService.getObjects(Object.class).contains(obj4));
64+
}
65+
66+
@Test
67+
public void testNamedObjectIndex() {
68+
ObjectIndex<Object> index = objectService.getIndex();
69+
assertTrue(index instanceof NamedObjectIndex);
70+
}
71+
72+
private class TestPlugin implements SciJavaPlugin {
73+
74+
}
75+
}

0 commit comments

Comments
 (0)