001    package com.sptci.prevayler;
002    
003    import java.io.Serializable;
004    import java.util.Collection;
005    import java.util.LinkedHashMap;
006    import java.util.LinkedHashSet;
007    import java.util.Map;
008    
009    /**
010     * A class used as the storage mechanism for storing the references to
011     * other prevalent objects from prevalent objects stored in the system.
012     *
013     * <p>&copy; Copyright 2008 <a href='http://sptci.com/' target='_top'>Sans Pareil Technologies, Inc.</a></p>
014     * @author Rakesh Vidyadharan 2008-05-23
015     * @version $Id: ReferenceStorage.java 4345 2008-06-30 21:22:03Z rakesh $
016     */
017    public class ReferenceStorage implements Serializable
018    {
019      private static final long serialVersionUID = 1L;
020    
021      /**
022       * A map used to maintain the references for a prevalent object identified
023       * by its object id.
024       */
025      private final Map<Object,FieldStorage> storage =
026        new LinkedHashMap<Object,FieldStorage>();
027    
028      /**
029       * Add the specified reference information for the prevalent object to
030       * the store.
031       *
032       * @see ReferenceStorage.FieldStorage#add
033       * @param object The prevalent object whose reference information is being
034       *   added to the store.
035       * @param name The name of the field that contains a reference.
036       * @param oid The oid for the referenced field.
037       */
038      public void add( final PrevalentObject object, final String name,
039          final Object oid )
040      {
041        if ( ! storage.containsKey( object.getObjectId() ) )
042        {
043          storage.put( object.getObjectId(), new FieldStorage() );
044        }
045    
046        storage.get( object.getObjectId() ).add( name, oid );
047      }
048    
049      /**
050       * Return a collection of field names that represent the references to
051       * other prevalent objects in the store for the specified prevalent
052       * object.
053       *
054       * @see ReferenceStorage.FieldStorage#getFields
055       * @param object The prevalent object whose references are to be fetched.
056       * @return The collection of referenced field names.
057       */
058      public Collection<String> getFields( final PrevalentObject object )
059      {
060        final Collection<String> collection = new LinkedHashSet<String>();
061        if ( object == null ) return collection;
062    
063        final FieldStorage store = storage.get( object.getObjectId() );
064        if ( store != null ) collection.addAll( store.getFields() );
065    
066        return collection;
067      }
068    
069      /**
070       * Return the value associated with the specified prevalent object and
071       * reference field name.
072       *
073       * @see ReferenceStorage.FieldStorage#getValue
074       * @param object The prevalent object in which the referenced field exists
075       * @param name The name of the reference field.
076       * @return The value associated with the object in the store.
077       */
078      public Object getValue( final PrevalentObject object, final String name )
079      {
080        Object value = null;
081        if ( object == null ) return value;
082    
083        final FieldStorage store = storage.get( object.getObjectId() );
084        if ( store != null ) value = store.getValue( name );
085    
086        return value;
087      }
088    
089      /**
090       * Remove the specified prevalent object from the store.
091       *
092       * @param object The prevalent object to remove from the store.
093       */
094      public void remove( final PrevalentObject object )
095      {
096        if ( object == null ) return;
097        storage.remove( object.getObjectId() );
098      }
099    
100      /**
101       * Remove the reference(s) for the specified field in the specified
102       * prevalent object.
103       *
104       * @param object The prevalent object whose field reference(s) are to be
105       *   removed.
106       * @param field The field whose reference(s) are to be removed.
107       */
108      public void remove( final PrevalentObject object, final String field )
109      {
110        if ( object == null ) return;
111        final FieldStorage store = storage.get( object.getObjectId() );
112        if ( store != null ) store.remove( field );
113      }
114    
115      /**
116       * Remove the reference for the specified prevalent object from the
117       * specified field.
118       *
119       * @param object The prevalent object whose reference is to be removed.
120       * @param field The field in the prevalent object whose reference is to
121       *   be removed.
122       * @param objectId The reference that is to be removed.
123       */
124      public void remove( final PrevalentObject object, final String field,
125          final Object objectId )
126      {
127        if ( object == null ) return;
128        final FieldStorage store = storage.get( object.getObjectId() );
129        if ( store != null ) store.remove( field, objectId );
130      }
131    
132      /**
133       * The storage for all the references fields in a prevalent object.
134       */
135      private class FieldStorage implements Serializable
136      {
137        private static final long serialVersionUID = 1L;
138    
139        /** The map used to maintain the field name to object id mappings. */
140        private final Map<String,Object> fieldStorage =
141          new LinkedHashMap<String,Object>();
142    
143        /**
144         * Add the specified mapping to the store.
145         *
146         * @param name The name of the reference field.
147         * @param oid The oid value for the referenced object.
148         */
149        private void add( final String name, final Object oid )
150        {
151          fieldStorage.put( name, oid );
152        }
153    
154        /**
155         * Remove the mapping for the specified field from {@link #fieldStorage}.
156         *
157         * @param name The name of the reference field whose mapping is to be
158         *   removed.
159         */
160        private void remove( final String name )
161        {
162          fieldStorage.remove( name );
163        }
164    
165        /**
166         * Remove the specified reference from the field.  If the field contains
167         * a collection of references, then the specified reference is removed
168         * from the collection.  Otherwise this method is identical to {@link
169         * #remove( String )}.
170         *
171         * @param name The name of the reference field whose mapping is to be
172         *   removed.
173         * @param objectId The object id that is to be removed from the mapping.
174         */
175        private void remove( final String name, final Object objectId )
176        {
177          final Object value = fieldStorage.get( name );
178          if ( value instanceof Collection )
179          {
180            ( (Collection) value ).remove( objectId );
181          }
182          else
183          {
184            remove( name );
185          }
186        }
187    
188        /**
189         * Return a collection of field names that are stored in in this store.
190         *
191         * @return The collection of field names.
192         */
193        private Collection<String> getFields()
194        {
195          return fieldStorage.keySet();
196        }
197    
198        /**
199         * Return the value associated with the field with the specified name.
200         *
201         * @param name The name of the field whose value is to be retrieved.
202         * @return The value associated with the name.
203         */
204        private Object getValue( final String name )
205        {
206          return fieldStorage.get( name );
207        }
208      }
209    }