1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.observation;
35
36 import info.magnolia.cms.util.DelayedExecutor;
37
38 import java.util.ArrayList;
39 import java.util.Iterator;
40 import java.util.List;
41 import java.util.Objects;
42
43 import javax.jcr.observation.Event;
44 import javax.jcr.observation.EventIterator;
45 import javax.jcr.observation.EventListener;
46
47
48
49
50 public class DeferringEventListener implements EventListener {
51
52 private ObservationBasedDelayedExecutor executor;
53
54 private EventListener listener;
55
56 public DeferringEventListener(EventListener listener, long delay, long maxDelay) {
57 this.listener = listener;
58 executor = new ObservationBasedDelayedExecutor(listener, delay, maxDelay);
59 }
60
61 @Override
62 public void onEvent(EventIterator events) {
63 this.executor.consume(events);
64 }
65
66 @Override
67 public String toString() {
68 return super.toString() + ":" + this.listener;
69 }
70
71 @Override
72 public boolean equals(Object o) {
73 if (this == o) {
74 return true;
75 }
76 if (o == null || getClass() != o.getClass()) {
77 return false;
78 }
79 DeferringEventListener that = (DeferringEventListener) o;
80 return Objects.equals(listener, that.listener);
81 }
82
83 @Override
84 public int hashCode() {
85 return Objects.hash(listener);
86 }
87
88
89
90
91 private static class ObservationBasedDelayedExecutor {
92
93 private final DelayedExecutor delayedExecutor;
94 private final List<Event> eventsBuffer = new ArrayList<>();
95
96 public ObservationBasedDelayedExecutor(final EventListener listener, long delay, long maxDelay) {
97 delayedExecutor = new DelayedExecutor(new Runnable() {
98 @Override
99 public void run() {
100
101 synchronized (eventsBuffer) {
102 listener.onEvent(new ListBasedEventIterator(eventsBuffer));
103 eventsBuffer.clear();
104 }
105 }
106 }, delay, maxDelay);
107 }
108
109 protected void consume(EventIterator events) {
110 synchronized (this.eventsBuffer) {
111 while (events.hasNext()) {
112 this.eventsBuffer.add(events.nextEvent());
113 }
114 delayedExecutor.trigger();
115 }
116 }
117 }
118
119
120
121
122
123 private static class ListBasedEventIterator implements EventIterator {
124
125 private Iterator iterator;
126 private List events;
127 private int pos = 0;
128
129 public ListBasedEventIterator(List events) {
130 this.events = events;
131 this.iterator = events.iterator();
132 }
133
134 @Override
135 public boolean hasNext() {
136 return this.iterator.hasNext();
137 }
138
139 @Override
140 public Object next() {
141 pos++;
142 return this.iterator.next();
143 }
144
145 @Override
146 public void remove() {
147 this.iterator.remove();
148 }
149
150 @Override
151 public Event nextEvent() {
152 return (Event) next();
153 }
154
155 @Override
156 public long getPosition() {
157 return pos;
158 }
159
160 @Override
161 public long getSize() {
162 return events.size();
163 }
164
165 @Override
166 public void skip(long skipNum) {
167 for (int i = 0; i < skipNum; i++) {
168 next();
169 }
170 }
171 }
172 }