001 package com.hammurapi.eventbus.tests.familyties;
002
003 import java.util.ArrayList;
004 import java.util.Collection;
005 import java.util.Iterator;
006 import java.util.Map;
007 import java.util.concurrent.locks.ReadWriteLock;
008
009 import com.hammurapi.eventbus.AbstractEventBus;
010 import com.hammurapi.eventbus.HandleExtractor;
011 import com.hammurapi.eventbus.tests.familyties.model.Person;
012 import com.hammurapi.eventbus.tests.familyties.model.Relative;
013 import com.hammurapi.eventbus.tests.familyties.rules.FamilyTiesRules;
014 import com.hammurapi.extract.Extractor;
015 import com.hammurapi.extract.Predicate;
016 import com.hammurapi.store.AbstractStore;
017 import com.hammurapi.store.DeputyStore;
018 import com.hammurapi.store.Index;
019 import com.hammurapi.store.LiveView;
020 import com.hammurapi.store.MultiIndex;
021 import com.hammurapi.store.UnmodifiableStore;
022 import com.hammurapi.store.local.LocalStoreBase;
023
024 /**
025 * Implementation of event store.
026 * @author Pavel Vlasov
027 *
028 * @param <E>
029 * @param <P>
030 * @param <C>
031 */
032 public class FamilyTiesEventStoreImpl extends LocalStoreBase<AbstractEventBus.Handle<com.hammurapi.eventbus.tests.familyties.model.Relative,java.lang.Integer,com.hammurapi.eventbus.tests.familyties.rules.FamilyTiesRules,Long>, com.hammurapi.eventbus.tests.familyties.model.Relative, FamilyTiesEventStore> implements FamilyTiesEventStore {
033
034 /**
035 * Config class with bound generic parameters.
036 * @author Pavel Vlasov
037 *
038 */
039 public static class Config extends LocalStoreBase.Config<AbstractEventBus.Handle<com.hammurapi.eventbus.tests.familyties.model.Relative,java.lang.Integer,com.hammurapi.eventbus.tests.familyties.rules.FamilyTiesRules,Long>, com.hammurapi.eventbus.tests.familyties.model.Relative, FamilyTiesEventStore> {
040
041 public Config() {
042 setPrimaryKeyExtractor(new HandleExtractor<com.hammurapi.eventbus.tests.familyties.model.Relative, java.lang.Integer, com.hammurapi.eventbus.tests.familyties.rules.FamilyTiesRules, Long, AbstractEventBus.Handle<com.hammurapi.eventbus.tests.familyties.model.Relative,java.lang.Integer,com.hammurapi.eventbus.tests.familyties.rules.FamilyTiesRules,Long>, FamilyTiesEventStore>());
043 }
044 }
045
046 private MultiIndex<AbstractEventBus.Handle<Relative, Integer, FamilyTiesRules, Long>, Relative, Person, FamilyTiesEventStore> subjectIndex;
047
048 public FamilyTiesEventStoreImpl(Config config) {
049 super(config);
050
051 FamilyTiesEventStoreExtractor<Person> subjectExtractor = new FamilyTiesEventStoreAbstractExtractor<Person>(0, null, false) {
052
053 @Override
054 protected Person extractInternal(
055 FamilyTiesEventStore context,
056 Map<FamilyTiesEventStore, Map<Extractor<com.hammurapi.eventbus.AbstractEventBus.Handle<Relative, Integer, FamilyTiesRules, Long>, ? super Person, FamilyTiesEventStore>, ? super Person>> cache,
057 com.hammurapi.eventbus.AbstractEventBus.Handle<Relative, Integer, FamilyTiesRules, Long>... obj) {
058
059 return obj[0].getEvent().getSubject();
060 }
061
062 };
063 subjectIndex = (MultiIndex<com.hammurapi.eventbus.AbstractEventBus.Handle<Relative, Integer, FamilyTiesRules, Long>, Relative, Person, FamilyTiesEventStore>) addIndex(null, subjectExtractor, Index.Type.LAZY, false, null);
064 }
065
066 @Override
067 public Iterable<Relative> getRelatives(Person subject) {
068 Collection<Relative> ret = new ArrayList<Relative>();
069 Z: for (AbstractEventBus.Handle<Relative, Integer, FamilyTiesRules, Long> h: subjectIndex.find(subject)) {
070 if (h.isValid()) {
071 Relative newRelative = h.getEvent();
072 Iterator<Relative> rit = ret.iterator();
073 while (rit.hasNext()) {
074 Relative eRelative = rit.next();
075 switch (supercedes(eRelative, newRelative)) {
076 case 0:
077 // Unrelated - go further.
078 break;
079 case 1:
080 // No need to add this new relative, jump to next new relative
081 continue Z;
082 case -1:
083 // New relative supercedes this one.
084 rit.remove();
085 break;
086 }
087 }
088 ret.add(newRelative);
089 }
090 }
091 return ret;
092 }
093
094 /**
095 *
096 * @param r0
097 * @param r1
098 * @return -1 - r1 is more specific (e.g. Daughter instead of Child) than r0, 0 - unrelated, 1 - r0 is more specific or equal.
099 */
100 private int supercedes(Relative r0, Relative r1) {
101 if (r0.equals(r1)) {
102 return 1;
103 }
104 if (r0.getSubject().equals(r1.getSubject()) && r0.getObject().equals(r1.getObject())) {
105 if (r0.getClass().isInstance(r1)) { // r1 is more specific
106 return -1;
107 }
108
109 if (r1.getClass().isInstance(r0)) { // r0 is more specific
110 return 1;
111 }
112
113 }
114 return 0;
115 }
116
117 protected static class FamilyTiesEventDeputyStore extends DeputyStore<AbstractEventBus.Handle<com.hammurapi.eventbus.tests.familyties.model.Relative,java.lang.Integer,com.hammurapi.eventbus.tests.familyties.rules.FamilyTiesRules,Long>, com.hammurapi.eventbus.tests.familyties.model.Relative, FamilyTiesEventStore> implements FamilyTiesEventStore {
118
119 public FamilyTiesEventDeputyStore(
120 AbstractStore<AbstractEventBus.Handle<com.hammurapi.eventbus.tests.familyties.model.Relative, java.lang.Integer, com.hammurapi.eventbus.tests.familyties.rules.FamilyTiesRules, Long>, com.hammurapi.eventbus.tests.familyties.model.Relative, FamilyTiesEventStore> master,
121 ReadWriteLock masterLock) {
122 super(master, masterLock);
123 }
124
125 @Override
126 protected FamilyTiesEventStore createDeputy() {
127 return new FamilyTiesEventDeputyStore(this, createMasterLock());
128 }
129
130 @Override
131 public FamilyTiesEventStore createUnmodifiableFacade() {
132 return new FamilyTiesEventUnmodifiableStore(this);
133 }
134
135 @Override
136 protected FamilyTiesEventStore createLiveView(Predicate<AbstractEventBus.Handle<com.hammurapi.eventbus.tests.familyties.model.Relative,java.lang.Integer,com.hammurapi.eventbus.tests.familyties.rules.FamilyTiesRules,Long>, FamilyTiesEventStore> selector) {
137 return new FamilyTiesEventLiveView(this, selector);
138 }
139
140 @Override
141 public Iterable<Relative> getRelatives(Person subject) {
142 return ((FamilyTiesEventStore) master).getRelatives(subject);
143 }
144
145 }
146
147 protected static class FamilyTiesEventUnmodifiableStore extends UnmodifiableStore<AbstractEventBus.Handle<com.hammurapi.eventbus.tests.familyties.model.Relative,java.lang.Integer,com.hammurapi.eventbus.tests.familyties.rules.FamilyTiesRules,Long>, com.hammurapi.eventbus.tests.familyties.model.Relative, FamilyTiesEventStore> implements FamilyTiesEventStore {
148
149 public FamilyTiesEventUnmodifiableStore(FamilyTiesEventStore master) {
150 super(master);
151 }
152
153 @Override
154 public Iterable<Relative> getRelatives(Person subject) {
155 return ((FamilyTiesEventStore) master).getRelatives(subject);
156 }
157
158 }
159
160 protected static class FamilyTiesEventLiveView extends LiveView<AbstractEventBus.Handle<com.hammurapi.eventbus.tests.familyties.model.Relative,java.lang.Integer,com.hammurapi.eventbus.tests.familyties.rules.FamilyTiesRules,Long>, com.hammurapi.eventbus.tests.familyties.model.Relative, FamilyTiesEventStore> implements FamilyTiesEventStore {
161
162 public FamilyTiesEventLiveView(
163 FamilyTiesEventStore master,
164 Predicate<AbstractEventBus.Handle<com.hammurapi.eventbus.tests.familyties.model.Relative, java.lang.Integer, com.hammurapi.eventbus.tests.familyties.rules.FamilyTiesRules, Long>, FamilyTiesEventStore> selector) {
165 super(master, selector);
166 }
167
168 @Override
169 public FamilyTiesEventStore createUnmodifiableFacade() {
170 return new FamilyTiesEventUnmodifiableStore(this);
171 }
172
173 @Override
174 public Iterable<Relative> getRelatives(Person subject) {
175 return ((FamilyTiesEventStore) master).getRelatives(subject);
176 }
177
178 }
179
180 @Override
181 protected FamilyTiesEventStore createDeputy() {
182 return new FamilyTiesEventDeputyStore(this, createMasterLock());
183 }
184
185 @Override
186 public FamilyTiesEventStore createUnmodifiableFacade() {
187 return new FamilyTiesEventUnmodifiableStore(this);
188 }
189
190 @Override
191 protected FamilyTiesEventStore createLiveView(Predicate<AbstractEventBus.Handle<com.hammurapi.eventbus.tests.familyties.model.Relative,java.lang.Integer,com.hammurapi.eventbus.tests.familyties.rules.FamilyTiesRules,Long>, FamilyTiesEventStore> selector) {
192 return new FamilyTiesEventLiveView(this, selector);
193 }
194
195 }