1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.common.processing;
20
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.stream.Stream;
27
28 import org.apache.logging.log4j.LogManager;
29 import org.apache.logging.log4j.Logger;
30
31
32
33
34
35
36 public class MCRProcessableDefaultCollection implements MCRProcessableCollection {
37
38 private static Logger LOGGER = LogManager.getLogger();
39
40 private String name;
41
42 private final List<MCRProcessable> processables;
43
44 private Map<String, Object> properties;
45
46 private final List<MCRProcessableCollectionListener> listenerList;
47
48
49
50
51
52
53 public MCRProcessableDefaultCollection(String name) {
54 this.name = name;
55 this.processables = Collections.synchronizedList(new ArrayList<>());
56 this.properties = new HashMap<>();
57 this.listenerList = Collections.synchronizedList(new ArrayList<>());
58 }
59
60
61
62
63 public String getName() {
64 return name;
65 }
66
67 @Override
68 public void add(MCRProcessable processable) {
69 this.processables.add(processable);
70 fireAdded(processable);
71 }
72
73 @Override
74 public void remove(MCRProcessable processable) {
75 this.processables.remove(processable);
76 fireRemoved(processable);
77 }
78
79 @Override
80 public Stream<MCRProcessable> stream() {
81 List<MCRProcessable> snapshot;
82 synchronized (this.processables) {
83 snapshot = new ArrayList<>(this.processables);
84 }
85 return snapshot.stream();
86 }
87
88 @Override
89 public boolean isEmpty() {
90 return this.processables.isEmpty();
91 }
92
93 @Override
94 public Map<String, Object> getProperties() {
95 return this.properties;
96 }
97
98 public void setProperty(String propertyName, Object propertyValue) {
99 Object oldValue = this.properties.get(propertyName);
100 if (oldValue == null && propertyValue == null) {
101 return;
102 }
103 if (propertyValue == null) {
104 this.properties.remove(propertyName);
105 firePropertyChanged(propertyName, oldValue, null);
106 return;
107 }
108 if (propertyValue.equals(oldValue)) {
109 return;
110 }
111 this.properties.put(propertyName, propertyValue);
112 firePropertyChanged(propertyName, oldValue, propertyValue);
113 }
114
115 @Override
116 public void addListener(MCRProcessableCollectionListener listener) {
117 this.listenerList.add(listener);
118 }
119
120 @Override
121 public void removeListener(MCRProcessableCollectionListener listener) {
122 this.listenerList.remove(listener);
123 }
124
125 protected void fireAdded(MCRProcessable processable) {
126 List<MCRProcessableCollectionListener> listeners = listenersSnapshot();
127 listeners.forEach(listener -> {
128 try {
129 listener.onAdd(this, processable);
130 } catch (Exception exc) {
131 LOGGER.error("Unable to inform collection listener due internal error", exc);
132 }
133 });
134 }
135
136 protected void fireRemoved(MCRProcessable processable) {
137 List<MCRProcessableCollectionListener> listeners = listenersSnapshot();
138 listeners.forEach(listener -> {
139 try {
140 listener.onRemove(this, processable);
141 } catch (Exception exc) {
142 LOGGER.error("Unable to inform collection listener due internal error", exc);
143 }
144 });
145 }
146
147 protected void firePropertyChanged(String propertyName, Object oldValue, Object newValue) {
148 List<MCRProcessableCollectionListener> listeners = listenersSnapshot();
149 listeners.forEach(listener -> {
150 try {
151 listener.onPropertyChange(this, propertyName, oldValue, newValue);
152 } catch (Exception exc) {
153 LOGGER.error("Unable to inform collection listener due internal error", exc);
154 }
155 });
156 }
157
158 private List<MCRProcessableCollectionListener> listenersSnapshot() {
159 synchronized (this.listenerList) {
160 return new ArrayList<>(this.listenerList);
161 }
162 }
163
164 }