EMMA Coverage Report (generated Sun May 02 20:42:29 CEST 2010)
[all classes][hu.netmind.beankeeper.schema.impl]

COVERAGE SUMMARY FOR SOURCE FILE [SchemaManagerImpl.java]

nameclass, %method, %block, %line, %
SchemaManagerImpl.java100% (2/2)100% (9/9)84%  (343/409)89%  (68.5/77)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class SchemaManagerImpl100% (1/1)100% (8/8)84%  (320/383)89%  (68.6/77)
ensureSchema (ClassEntry): void 100% (1/1)80%  (246/309)86%  (53.6/62)
<static initializer> 100% (1/1)100% (4/4)100% (1/1)
SchemaManagerImpl (): void 100% (1/1)100% (28/28)100% (8/8)
getClassEntry (String): ClassEntry 100% (1/1)100% (11/11)100% (1/1)
getTableName (ClassEntry): String 100% (1/1)100% (13/13)100% (2/2)
getTableName (ClassEntry, String): String 100% (1/1)100% (16/16)100% (1/1)
init (Map): void 100% (1/1)100% (1/1)100% (1/1)
release (): void 100% (1/1)100% (1/1)100% (1/1)
     
class SchemaManagerImpl$1100% (1/1)100% (1/1)88%  (23/26)88%  (0.9/1)
<static initializer> 100% (1/1)88%  (23/26)88%  (0.9/1)

1/**
2 * Copyright (C) 2010 NetMind Consulting Bt.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 3 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18 
19package hu.netmind.beankeeper.schema.impl;
20 
21import hu.netmind.beankeeper.schema.SchemaManager;
22import hu.netmind.beankeeper.db.Database;
23import hu.netmind.beankeeper.model.ClassTracker;
24import hu.netmind.beankeeper.model.ClassInfo;
25import hu.netmind.beankeeper.model.ClassEntry;
26import hu.netmind.beankeeper.type.TypeHandlerTracker;
27import hu.netmind.beankeeper.type.TypeHandler;
28import hu.netmind.beankeeper.transaction.Transaction;
29import hu.netmind.beankeeper.transaction.InternalTransactionTracker;
30import hu.netmind.beankeeper.common.StoreException;
31import hu.netmind.beankeeper.node.NodeManager;
32import java.util.*;
33import org.apache.log4j.Logger;
34 
35/**
36 * Manages the relations between the object model
37 * and the relational model.
38 */
39public class SchemaManagerImpl implements SchemaManager
40{
41   private static Logger logger = Logger.getLogger(SchemaManagerImpl.class);
42 
43   private Database database = null; // Injected
44   private ClassTracker classTracker = null; // Injected
45   private TypeHandlerTracker typeHandlerTracker = null; // Injected
46   private InternalTransactionTracker transactionTracker = null; // Injected
47   private NodeManager nodeManager = null; // Injected
48 
49   private Set<ClassEntry> ensuredEntries = new HashSet<ClassEntry>();
50   private Set<ClassEntry> processingEntries = new HashSet<ClassEntry>();
51 
52   /**
53    * Load the table names from database.
54    */
55   public void init(Map parameters)
56   {
57   }
58 
59   /**
60    * Release all resources.
61    */
62   public void release()
63   {
64   }
65 
66   /**
67    * Ensure that the specified entry is represented in the database
68    * and synchronized with the Java model.
69    */
70   public synchronized void ensureSchema(ClassEntry entry)
71   {
72      if ( (entry == null) || (processingEntries.contains(entry)) )
73         return;
74      processingEntries.add(entry);
75      try
76      {
77         // Determine if it needs to be ensured at all, or if it was before
78         ClassInfo info = classTracker.getClassInfo(entry);
79         if ( (ensuredEntries.contains(entry)) && (!info.hasChanged()) )
80            return; // We have it and it didn't change
81         // Mark it unensured
82         ensuredEntries.remove(entry);
83         // Make the info update itself to new structure
84         info.update();
85         // First, make sure superclasses are ensured
86         ensureSchema(entry.getSuperEntry());
87         // Make this call on sever but also remember locally
88         // Check whether this class is entitled to a table.
89         boolean create = info.isStorable();
90         if ( nodeManager.getRole() == NodeManager.NodeRole.CLIENT )
91         {
92            // Call server
93            nodeManager.callServer(SchemaManager.class.getName(),
94                  "ensureSchema",new Class[] { ClassEntry.class }, new Object[] { entry });
95            // We're local, so don't create
96            create = false;
97         }
98         if ( logger.isDebugEnabled() )
99            logger.debug("ensuring info: "+info+" (storable: "+create+"), attributes: "+info.getAttributeTypes(entry));
100         // Ensure the table
101         Transaction transaction = transactionTracker.getTransaction();
102         transaction.begin();
103         try
104         {
105            // Generate table schemas, one for class an also involve type handlers
106            Iterator iterator = info.getAttributeNames(entry).iterator();
107            HashMap attributeTypes = new HashMap();
108            while ( iterator.hasNext() )
109            {
110               String attributeName = iterator.next().toString();
111               Class type = info.getAttributeType(attributeName);
112               switch ( classTracker.getType(type) )
113               {
114                  case TYPE_PRIMITIVE:
115                     attributeTypes.put(attributeName,type);
116                     break;
117                  case TYPE_OBJECT:
118                     attributeTypes.put(attributeName,Long.class);
119                     break;
120                  case TYPE_HANDLED:
121                     TypeHandler handler = typeHandlerTracker.getHandler(type);
122                     handler.ensureTableExists(info,attributeName,create);
123                     attributeTypes.putAll(handler.getAttributeTypes(attributeName));
124                     break;
125                  default:
126                     // Unknown type, leave it
127                     logger.warn(entry+" has attribute '"+attributeName+"' of unhandled class: "+type);
128                     break;
129               }
130            }
131            // Remove reserved names
132            Iterator typesIterator = attributeTypes.keySet().iterator();
133            while ( typesIterator.hasNext() )
134            {
135               String name = (String) typesIterator.next();
136               if ( name.startsWith("persistence") )
137                  typesIterator.remove();
138            }
139            // Make object table
140            ArrayList objectKeys = new ArrayList();
141            objectKeys.add("persistence_id");
142            objectKeys.add("persistence_txstart");
143            attributeTypes.put("persistence_id",Long.class);
144            attributeTypes.put("persistence_start",Long.class);
145            attributeTypes.put("persistence_end",Long.class);
146            attributeTypes.put("persistence_txstartid",Long.class);
147            attributeTypes.put("persistence_txstart",Long.class);
148            attributeTypes.put("persistence_txendid",Long.class);
149            attributeTypes.put("persistence_txend",Long.class);
150            logger.debug("creating table for entry: "+entry+", fields: "+attributeTypes+", keys: "+objectKeys);
151            database.ensureTable(transaction,getTableName(entry),attributeTypes,objectKeys,create);
152         } catch ( StoreException e ) {
153            transaction.markRollbackOnly();
154            throw e;
155         } catch ( Throwable e ) {
156            transaction.markRollbackOnly();
157            throw new StoreException("unexpected error.",e);
158         } finally {
159            transaction.commit();
160         }
161         // Now if everything went ok, remember this entry as already ensured
162         ensuredEntries.add(entry);
163      } finally {
164         processingEntries.remove(entry);
165      }
166   }
167 
168   /**
169    * Get the table name for a given class entry.
170    */
171   public String getTableName(ClassEntry entry)
172   {
173      ensureSchema(entry);
174      return entry.getFullName().replace("_","__").replace('.','_').toLowerCase();
175   }
176 
177   /**
178    * Get the table name for an attribute in an entry.
179    * This can be used for attributes that need
180    * a separate table for information, like many-to-many
181    * relations, etc.
182    */
183   public String getTableName(ClassEntry entry, String attributeName)
184   {
185      return (getTableName(entry)+"_"+attributeName+"_").toLowerCase();
186   }
187 
188   /**
189    * Get a class entry for a table name.
190    */
191   public ClassEntry getClassEntry(String tableName)
192   {
193      return classTracker.getMatchingClassEntry(tableName.replace('_','.').replace("..","_"));
194   }
195}
196 

[all classes][hu.netmind.beankeeper.schema.impl]
EMMA 2.0.5312debian (C) Vladimir Roubtsov