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    }