001 package com.sptci.prevayler;
002
003 import java.util.Collection;
004 import java.util.LinkedHashMap;
005 import java.util.LinkedHashSet;
006 import java.util.Map;
007 import java.util.logging.Logger;
008
009 /**
010 * The base class for the prevalent system that provides the storage engine
011 * for storing the various prevalent object maintained by the system.
012 *
013 * <p>© Copyright 2008 <a href='http://sptci.com/' target='_top'>Sans Pareil Technologies, Inc.</a></p>
014 * @author Rakesh 2008-05-22
015 * @version $Id: StorageSystem.java 22 2008-11-24 19:04:25Z sptrakesh $
016 */
017 abstract class StorageSystem implements DatabaseSystem
018 {
019 private static final long serialVersionUID = 1L;
020
021 /** The logger to use to log messages/errors. */
022 protected static transient final Logger logger =
023 Logger.getLogger( "SPTODBLogger" );
024
025 /**
026 * A map used to manage the various prevalent objects that may be managed
027 * by this prevalent system. This map provides the primary storage for
028 * the prevalent objects maintained in the system. The <code>key</code>
029 * for the map are the various classes that are stored in the prevalent
030 * system while the values are the {@link PrimaryStorage} instances that
031 * store the prevalent objects of each type.
032 */
033 private final Map<String,PrimaryStorage> classMap =
034 new LinkedHashMap<String,PrimaryStorage>();
035
036 /**
037 * A map used to maintain indices for the various prevalent object types
038 * that are managed by this prevalent system. The <code>key</code> for
039 * the map are the various classes that are stored in the prevalent
040 * system while the values are the {@link IndexStorage} instances that
041 * store the indices for the indexed fields in the prevalent objects of
042 * each type.
043 */
044 private final Map<String,IndexStorage> indexMap =
045 new LinkedHashMap<String,IndexStorage>();
046
047 /**
048 * A map used to maintain the references in a prevalent object to other
049 * prevalent objects. This is used to ensure that references are
050 * properly reconstituted when de-serialised. The <code>key</code> for
051 * the map are the various classes that are stored in the prevalent
052 * system while the values are the {@link ReferenceStorage} instances that
053 * store the references for the prevalent objects referenced by the
054 * prevalent object being managed.
055 */
056 private final Map<String,ReferenceStorage> referenceMap =
057 new LinkedHashMap<String,ReferenceStorage>();
058
059 /**
060 * A map used to maintain the reverse relationships from prevalent objects
061 * to their parents. This is used to implement configured actions when
062 * deleting a prevalent object.
063 */
064 private final Map<String,RelationStorage> relationMap =
065 new LinkedHashMap<String,RelationStorage>();
066
067 /**
068 * A task queue used when persisting object graphs to avoid infinite loops
069 * due to the recursive nature of following object graphs.
070 */
071 private static transient TaskQueue taskQueue = new TaskQueue();
072
073 /** The sequence used to generate object ids. */
074 private long sequence = 0;
075
076 /**
077 * Generate the oid to assign to the specified prevalent object. Default
078 * implementation returns an incremented {@link #sequence} value if the
079 * prevalent object does not already have an object id.
080 *
081 * @param object The prevalent object for which an oid is to be generated.
082 * @return The oid to assign to the prevalent object.
083 */
084 @SuppressWarnings( value = "unchecked" )
085 protected Object generateOid( final PrevalentObject object )
086 {
087 Object oid = object.getObjectId();
088 if ( oid == null )
089 {
090 oid = ++sequence;
091 }
092
093 return oid;
094 }
095
096 /**
097 * Return the map used to maintain instances of the specified type of
098 * prevalent objects by its object id.
099 *
100 * @see #getPrimaryStorage( String )
101 * @param cls The class whose primary storage is to be retrieved.
102 * @return The primary storage used for the specified prevalent type.
103 */
104 protected PrimaryStorage getPrimaryStorage( final Class cls )
105 {
106 return getPrimaryStorage( cls.getName() );
107 }
108
109 /**
110 * Return the map used to maintain instances of the specified type of
111 * prevalent objects by its object id.
112 *
113 * @param name The fully qualified name of the class whose primary storage
114 * is to be retrieved.
115 * @return The primary storage used for the specified prevalent type.
116 */
117 protected PrimaryStorage getPrimaryStorage( final String name )
118 {
119 if ( ! classMap.containsKey( name ) )
120 {
121 classMap.put( name, new PrimaryStorage() );
122 }
123
124 return classMap.get( name );
125 }
126
127 /**
128 * Return the map in which the indices for the prevalent class are
129 * stored with the indexed field name.
130 *
131 * @see #getIndexStorage( String )
132 * @param cls The class whose index storage is to be retrieved.
133 * @return The index storage for the specified prevalent type.
134 */
135 protected IndexStorage getIndexStorage( final Class cls )
136 {
137 return getIndexStorage( cls.getName() );
138 }
139
140 /**
141 * Return the map in which the indices for the prevalent class are
142 * stored with the indexed field name.
143 *
144 * @param name The fully qualified name of the class whose index storage
145 * is to be retrieved.
146 * @return The index storage for the specified prevalent type.
147 */
148 protected IndexStorage getIndexStorage( final String name )
149 {
150 if ( ! indexMap.containsKey( name ) )
151 {
152 indexMap.put( name, new IndexStorage() );
153 }
154
155 return indexMap.get( name );
156 }
157
158 /**
159 * Return the map used to manage the references to other prevalent objects
160 * for the specified prevalent class.
161 *
162 * @see #getReferenceStorage( String )
163 * @param cls The class whose reference storage is to be retrieved.
164 * @return The reference storage for the prevalent class.
165 */
166 protected ReferenceStorage getReferenceStorage( final Class cls )
167 {
168 return getReferenceStorage( cls.getName() );
169 }
170
171 /**
172 * Return the map used to manage the references to other prevalent objects
173 * for the specified prevalent class.
174 *
175 * @param name The fully qualified name of the class whose reference storage
176 * is to be retrieved.
177 * @return The reference storage for the prevalent class.
178 */
179 protected ReferenceStorage getReferenceStorage( final String name )
180 {
181 if ( ! referenceMap.containsKey( name ) )
182 {
183 referenceMap.put( name, new ReferenceStorage() );
184 }
185
186 return referenceMap.get( name );
187 }
188
189 /**
190 * Return the map used to manage the relations to other prevalent objects
191 * for the specified prevalent class.
192 *
193 * @see #getRelationStorage( String )
194 * @param cls The class whose relations storage is to be retrieved.
195 * @return The relations storage for the prevalent class.
196 */
197 protected RelationStorage getRelationStorage( final Class cls )
198 {
199 return getRelationStorage( cls.getName() );
200 }
201
202 /**
203 * Return the map used to manage the relations to other prevalent objects
204 * for the specified prevalent class.
205 *
206 * @param name The fully qualified name of the class whose relation storage
207 * is to be retrieved.
208 * @return The relations storage for the prevalent class.
209 */
210 protected RelationStorage getRelationStorage( final String name )
211 {
212 if ( ! relationMap.containsKey( name ) )
213 {
214 relationMap.put( name, new RelationStorage( name ) );
215 }
216
217 return relationMap.get( name );
218 }
219
220 /**
221 * Return the task queue used when persisting objects by reachability.
222 *
223 * @return The queue of prevalent objects in the object graph.
224 */
225 protected Collection<PrevalentObject> getTaskQueue()
226 {
227 return taskQueue.get();
228 }
229
230 /**
231 * The task queue used to ensure that recursive loops when persisting
232 * inter-related object graphs do not result in infinite loops.
233 */
234 protected static class TaskQueue extends ThreadLocal<Collection<PrevalentObject>>
235 {
236 protected synchronized Collection<PrevalentObject> initialValue()
237 {
238 return new LinkedHashSet<PrevalentObject>();
239 }
240 }
241 }