1 5 package com.tc.util; 6 7 import com.tc.logging.TCLogger; 8 import com.tc.logging.TCLogging; 9 10 import java.util.Collection ; 11 import java.util.HashMap ; 12 import java.util.Map ; 13 import java.util.SortedSet ; 14 import java.util.TreeSet ; 15 16 public class SequenceValidator { 17 18 private static final TCLogger logger = TCLogging.getLogger(SequenceValidator.class); 19 20 private final Map sequences = new HashMap (); 21 private final long start; 22 23 public SequenceValidator(long start) { 24 this.start = start; 25 } 26 27 public synchronized boolean isNext(Object key, SequenceID candidate) { 29 if (candidate.isNull()) return true; 30 Sequencer sequencer = getOrCreate(key); 31 return sequencer.isNext(candidate); 32 } 33 34 public synchronized void setCurrent(Object key, SequenceID next) throws InvalidSequenceIDException { 35 if (key == null || SequenceID.NULL_ID.equals(next)) return; 36 Sequencer s = getOrCreate(key); 37 s.setCurrent(next); 38 } 39 40 public synchronized SequenceID getCurrent(Object key) { 42 Sequencer s = (Sequencer) sequences.get(key); 43 Assert.assertNotNull(s); 44 return s.getCurrent(); 45 46 } 47 48 public synchronized void initSequence(Object key, Collection sequenceIDs) { 49 Assert.assertFalse(sequences.containsKey(key)); 50 sequences.put(key, new Sequencer(key, start, sequenceIDs)); 51 } 52 53 public synchronized void remove(Object key) { 54 sequences.remove(key); 55 } 56 57 public synchronized int size() { 58 return sequences.size(); 59 } 60 61 private Sequencer getOrCreate(Object key) { 62 Sequencer sequencer = (Sequencer) sequences.get(key); 63 if (sequencer == null) { 64 sequencer = new Sequencer(key, start); 65 sequences.put(key, sequencer); 66 } 67 return sequencer; 68 } 69 70 private static class Sequencer { 71 72 SortedSet sequenceIDs; 73 SequenceID current; 74 75 Sequencer(Object key, long start, Collection sequenceIDs) { 76 if (sequenceIDs.size() > 0) { 77 this.sequenceIDs = new TreeSet (SequenceID.COMPARATOR); 78 this.sequenceIDs.addAll(sequenceIDs); 79 current = new SequenceID(start); 80 } else { 81 throw new AssertionError ("Sequencer should be set to a valid SequenceID Sequence !!!"); 82 } 83 logger.info("Setting initial Sequence IDs for " + key + " current = " + current + " next = " + this.sequenceIDs); 84 } 85 86 Sequencer(Object key, long start) { 87 current = new SequenceID(start); 88 logger.debug("Setting initial Sequence IDs for " + key + " current = " + current); 89 } 90 91 public boolean isNext(SequenceID candidate) { 92 if (candidate.toLong() <= current.toLong()) { 93 logger.warn("Sequence IDs = " + sequenceIDs + " current = " + current + " but candidate = " + candidate); 94 return false; 95 } 96 if (sequenceIDs == null) { 97 return current.toLong() + 1 == candidate.toLong(); 98 } else { 99 return (((SequenceID) sequenceIDs.first()).toLong() == candidate.toLong()); 100 } 101 } 102 103 public void setCurrent(SequenceID next) throws InvalidSequenceIDException { 104 if (!isNext(next)) { throw new InvalidSequenceIDException("Trying to set to " + next + " but current = " 105 + current); } 106 if (sequenceIDs != null) { 107 logger.info("Setting current Sequence IDs from current = " + current + " to next = " + next); 108 sequenceIDs.headSet(next.next()).clear(); 109 if (sequenceIDs.size() == 0) { 110 sequenceIDs = null; 111 } 112 } 113 current = next; 114 } 115 116 public SequenceID getCurrent() { 117 return current; 118 } 119 } 120 } 121 | Popular Tags |