001 package com.sptci.prevayler;
002
003 import com.sptci.prevayler.annotations.ForeignKey.DeleteAction;
004
005 import java.io.Serializable;
006 import java.util.Collection;
007 import java.util.Collections;
008 import java.util.LinkedHashMap;
009 import java.util.Map;
010
011 /**
012 * A store for maintaining the relations between a prevalent object and
013 * the other prevalent objects in the prevalent system. This store is
014 * consulted for determining the actions to be performed when deleting
015 * prevalent objects. This store is mainly responsible for enforcing
016 * managed relations between prevalent objects.
017 *
018 * <p>© Copyright 2008 <a href='http://sptci.com/' target='_top'>Sans Pareil Technologies, Inc.</a></p>
019 * @author Rakesh Vidyadharan 2008-05-23
020 * @version $Id: RelationStorage.java 4345 2008-06-30 21:22:03Z rakesh $
021 */
022 public class RelationStorage implements Serializable
023 {
024 private static final long serialVersionUID = 1L;
025
026 /**
027 * A map used to store the meta data associated with a prevalent object.
028 * The <code>key</code> to the map is the type of prevalent object, while
029 * the <code>value</code> is a {@link
030 * com.sptci.prevayler.annotations.ForeignKey.DeleteAction} object that
031 * defines the action to be applied.
032 */
033 private final Map<String,DeleteRule> map
034 = new LinkedHashMap<String,DeleteRule>();
035
036 /** The name of the prevalent object whose relations are being mapped. */
037 private final String className;
038
039 /**
040 * Create a new instance of the storage for the specified class name.
041 *
042 * @param name The {@link #className} value to use.
043 */
044 public RelationStorage( final String name )
045 {
046 this.className = name;
047 }
048
049 /**
050 * A a new relationship to the store for the specified prevalent object.
051 *
052 * @param object The prevalent object that is related to the prevalent
053 * object identified by {@link #className}.
054 * @param field The name of the field in <code>object</code> that is an
055 * instance of type {@link #className}.
056 * @param action The delete action to use on the <code>fiele</code> when
057 * the instance of type {@link #className} is deleted.
058 */
059 public void add( final PrevalentObject object, final String field,
060 final DeleteAction action )
061 {
062 final String name = object.getClass().getName();
063
064 if ( ! map.containsKey( name) )
065 {
066 map.put( name, new DeleteRule() );
067 }
068
069 map.get( name ).add( field, action );
070 }
071
072 /**
073 * Return the names of the classes that hold a reference to the prevalent
074 * class that is being managed.
075 *
076 * @return The collection of class names that hold references to
077 * instances of the managed class.
078 */
079 public Collection<String> getRelations()
080 {
081 return Collections.unmodifiableCollection( map.keySet() );
082 }
083
084 /**
085 * Return a map of field name of delete actions for the specified
086 * prevalent class with which the class being managed has relations.
087 *
088 * @see com.sptci.prevayler.RelationStorage.DeleteRule#getRules
089 * @param name The name of prevalent class with which relations are
090 * maintained.
091 * @return A map of field-delete rule mappings. Returns an empty
092 * map if no rules exist for the specified class.
093 */
094 public Map<String,DeleteAction> getDeleteRules( final String name )
095 {
096 final Map<String,DeleteAction> results = new LinkedHashMap<String,DeleteAction>();
097 final DeleteRule rule = map.get( name );
098 results.putAll( rule.getRules() );
099 return results;
100 }
101
102 /**
103 * Return the fully qualified class name of the prevalent object for which
104 * the reference relations are being stored.
105 *
106 * @return The {@link #className} value.
107 */
108 public String getClassName()
109 {
110 return className;
111 }
112
113 /**
114 * A class used to capture the names of the fields in a prevalent object
115 * that are related to the prevalent object being managed by this
116 * store.
117 */
118 private class DeleteRule implements Serializable
119 {
120 private static final long serialVersionUID = 1L;
121
122 /**
123 * The map used to maintain the field-name to delete rule mapping.
124 */
125 private Map<String,DeleteAction> actionMap =
126 new LinkedHashMap<String,DeleteAction>();
127
128 /**
129 * Add a mapping for the specified field name with the associated
130 * deleted rule.
131 *
132 * @param field The name of the field for the mapping.
133 * @param action The delete rule to apply for the field.
134 */
135 private void add( final String field, final DeleteAction action )
136 {
137 if ( ! actionMap.containsKey( field ) )
138 {
139 actionMap.put( field, action );
140 }
141 }
142
143 /**
144 * Return the {@link #actionMap} as an unmodifiable view.
145 *
146 * @return The mappings in {@link #actionMap}.
147 */
148 private Map<String,DeleteAction> getRules()
149 {
150 return Collections.unmodifiableMap( actionMap );
151 }
152 }
153 }