001    package org.hackystat.sensorbase.db;
002    
003    import java.util.List;
004    import java.util.Set;
005    import java.util.logging.Logger;
006    
007    import javax.xml.datatype.XMLGregorianCalendar;
008    
009    import org.hackystat.sensorbase.resource.projects.ProjectManager;
010    import org.hackystat.sensorbase.resource.projects.jaxb.Project;
011    import org.hackystat.sensorbase.resource.projects.jaxb.ProjectSummary;
012    import org.hackystat.sensorbase.resource.sensordata.SensorDataManager;
013    import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorData;
014    import org.hackystat.sensorbase.resource.sensordatatypes.SdtManager;
015    import org.hackystat.sensorbase.resource.sensordatatypes.jaxb.SensorDataType;
016    import org.hackystat.sensorbase.resource.users.UserManager;
017    import org.hackystat.sensorbase.resource.users.jaxb.User;
018    import org.hackystat.sensorbase.server.Server;
019    
020    /**
021     * Provides a specification of the operations that must be implemented by every
022     * SensorBase storage system.  Also provides some 'helper' methods, which return
023     * the Managers for the various resources. 
024     * @author Philip Johnson
025     */
026    public abstract class DbImplementation {
027      
028      /**
029       * To be called as part of the startup process for a storage system. This method should:
030       * <ul>
031       * <li> Check to see if this storage system has already been created during a previous session.
032       * <li> If no storage system exists, it should create one and initialize it appropriately.
033       * </ul>
034       */
035      public abstract void initialize();
036      
037      /**
038       * Returns true if the initialize() method did indeed create a fresh storage system.
039       * This is used by the ResourceManagers to determine if they should read in default data or not.
040       * @return True if the storage system is freshly created.
041       */
042      public abstract boolean isFreshlyCreated();
043      
044      /**
045       * Returns the XML SensorDataIndex for all sensor data in this server.
046       * @return The XML String containing an index to all Sensor Data.
047       */
048      public abstract String getSensorDataIndex();
049      
050      /**
051       * Returns the XML SensorDataIndex for all sensor data for this user. 
052       * @param user The User whose sensor data is to be returned. 
053       * @return The XML String providing an index of all relevent sensor data resources.
054       */
055      public abstract String getSensorDataIndex(User user);
056      
057      /**
058       * Returns the XML SensorDataIndex for all sensor data for this user and sensor data type.
059       * @param user The User whose sensor data is to be returned. 
060       * @param sdtName The sensor data type name.
061       * @return The XML String providing an index of all relevent sensor data resources.
062       */
063      public abstract String getSensorDataIndex(User user, String sdtName);
064      
065      /**
066       * Returns an XML SensorDataIndex representing the SensorData for the given user between
067       * start and end time whose resource string matches at least one of the UriPatterns.
068       * @param users The list of users whose SensorData will be returned.
069       * @param startTime The earliest Sensor Data to be returned.
070       * @param endTime The latest SensorData to be returned.
071       * @param uriPatterns At least one UriPattern must match the SensorData resource field.
072       * @param sdt The SDT of interest, or null if data from all SDTs should be retrieved.
073       * @return An XML String containing a SensorDataIndex of matching SensorData. 
074       */
075      public abstract String getSensorDataIndex(List<User> users, XMLGregorianCalendar startTime, 
076          XMLGregorianCalendar endTime, List<String> uriPatterns, String sdt);
077      
078      /**
079       * Returns an XML SensorDataIndex representing the SensorData for the given user between
080       * start and end time whose resource string matches at least one of the UriPatterns.
081       * @param users The list of users whose SensorData will be returned.
082       * @param startTime The earliest Sensor Data to be returned.
083       * @param endTime The latest SensorData to be returned.
084       * @param uriPatterns At least one UriPattern must match the SensorData resource field.
085       * @param sdt The SDT of interest. Should not be null.
086       * @param tool The tool of interest. Should not be null.
087       * @return An XML String containing a SensorDataIndex of matching SensorData. 
088       */
089      public abstract String getSensorDataIndex(List<User> users, XMLGregorianCalendar startTime, 
090          XMLGregorianCalendar endTime, List<String> uriPatterns, String sdt, String tool);
091    
092      
093      /**
094       * Returns the XML SensorDataIndex for all sensor data matching these users, start/end time, and 
095       * whose resource string matches at least one in the list of UriPatterns. 
096       * Client must guarantee that startTime and endTime are within Project dates, and that 
097       * startIndex and maxInstances are non-negative.
098       * @param users The users. 
099       * @param startTime The start time. 
100       * @param endTime The end time. 
101       * @param uriPatterns A list of UriPatterns. 
102       * @param startIndex The starting index.
103       * @param maxInstances The maximum number of instances to return.
104       * @return The XML SensorDataIndex string corresponding to the matching sensor data. 
105       */
106      public abstract String getSensorDataIndex(List<User> users, XMLGregorianCalendar startTime, 
107          XMLGregorianCalendar endTime, List<String> uriPatterns, int startIndex, int maxInstances);
108    
109      
110      /**
111       * Returns the XML SensorDataIndex for all sensor data for the given user that arrived
112       * at the server since the given start and end timestamps.  
113       * This method uses the LastMod timestamp
114       * rather than the "regular" timestamp, and is used for real-time monitoring of data
115       * arriving at the server. 
116       * @param user The user whose data is being monitored.
117       * @param lastModStartTime  The beginning lastMod timestamp of interest. 
118       * @param lastModEndTime  The ending lastMod timestamp of interest. 
119       * @return The XML SensorDataIndex for the recently arrived data based upon the lastMod tstamps.
120       */
121      public abstract String getSensorDataIndexLastMod(User user, XMLGregorianCalendar lastModStartTime,
122          XMLGregorianCalendar lastModEndTime);
123      
124    
125      /**
126       * Returns an XML SensorDataIndex to sensor data for the given time interval and sdt with
127       * the most recent runtime value.  This constitutes the "snapshot" of the data with the given
128       * sdt. If the tool parameter is null, then the last runtime snapshot is returned without regard
129       * to the tool.
130       * @param users The list of users whose sensor data will be checked.
131       * @param startTime The start time.
132       * @param endTime The end time. 
133       * @param uriPatterns The uripatterns that must match the resource string. 
134       * @param sdt The sensor data type of interest.
135       * @param tool The tool of interest, or null if any tool is OK.
136       * @return A string containing the XML representation of the SensorDataIndex for this snapshot.
137       */
138      public abstract String getProjectSensorDataSnapshot(List<User> users, XMLGregorianCalendar 
139          startTime, XMLGregorianCalendar endTime, List<String> uriPatterns, String sdt, String tool);
140      
141      /**
142       * Returns the SensorData instance as XML string, or null if not found.
143       * @param user The user.
144       * @param timestamp The timestamp associated with this sensor data.
145       * @return The SensorData XML string, or null.
146       */
147      public abstract String getSensorData(User user, XMLGregorianCalendar timestamp);
148      
149      /**
150       * Returns true if the passed [key, timestamp] has sensor data defined for it.
151       * @param user The user.
152       * @param timestamp The timestamp
153       * @return True if there is any sensor data for this [key, sdtName, timestamp].
154       */
155      public abstract boolean hasSensorData(User user, XMLGregorianCalendar timestamp);
156      
157      /**
158       * Persists a SensorData instance.  If SensorData with this [email, timestamp] 
159       * already exists in the storage system, it should be overwritten.
160       * @param data The sensor data. 
161       * @param xmlSensorData The SensorData marshalled into an XML String.  
162       * @param xmlSensorDataRef The corresponding SensorDataRef marshalled into an XML String
163       * @return True if the sensor data was successfully inserted.
164       */
165      public abstract boolean storeSensorData(SensorData data, String xmlSensorData, 
166          String xmlSensorDataRef);
167      
168    
169      /**
170       * Ensures that sensor data with the given user and timestamp is no longer
171       * present in this manager.
172       * @param user The user.
173       * @param timestamp The timestamp associated with this sensor data.
174       */
175      public abstract void deleteSensorData(User user, XMLGregorianCalendar timestamp);
176      
177      /**
178       * Ensures that sensor data with the given user is no longer present in this manager.
179       * @param user The user.
180       */
181      public abstract void deleteSensorData(User user);
182      
183      /**
184       * Returns the XML SensorDataTypeIndex for all SDTs in this server.
185       * @return The XML String containing an index to all SensorDataTypes.
186       */
187      public abstract String getSensorDataTypeIndex();
188      
189      /**
190       * Returns the SensorDataType instance as XML string, or null if not found.
191       * @param sdtName The SDT name.
192       * @return The SensorDataType XML string, or null.
193       */
194      public abstract String getSensorDataType(String sdtName);
195      
196      
197      /**
198       * Persists a SensorDataType instance.  If a SensorDataType with this name
199       * already exists in the storage system, it will be overwritten.
200       * @param sdt The sensor data type 
201       * @param xmlSensorDataType The SensorDataType marshalled into an XML String.  
202       * @param xmlSensorDataTypeRef The corresponding SensorDataTypeRef marshalled into an XML String
203       * @return True if the SDT was successfully inserted.
204       */
205      public abstract boolean storeSensorDataType(SensorDataType sdt, String xmlSensorDataType, 
206          String xmlSensorDataTypeRef);
207      
208      /**
209       * Ensures that the SensorDataType with the given name is no longer present in this manager.
210       * @param sdtName The SDT name.
211       */
212      public abstract void deleteSensorDataType(String sdtName);
213      
214      /**
215       * Returns the XML UserIndex for all Users in this server.
216       * @return The XML String containing an index to all Users.
217       */
218      public abstract String getUserIndex();
219      
220      /**
221       * Returns the User instance as XML string, or null if not found.
222       * @param email The user's email.
223       * @return The User XML string, or null.
224       */
225      public abstract String getUser(String email);
226      
227      /**
228       * Persists a User instance.  If a User with this name
229       * already exists in the storage system, it will be overwritten.
230       * @param user The user
231       * @param xmlUser The User marshalled into an XML String.  
232       * @param xmlUserRef The corresponding UserRef marshalled into an XML String
233       * @return True if the user was successfully inserted.
234       */
235      public abstract boolean storeUser(User user, String xmlUser, String xmlUserRef);
236      
237      /**
238       * Ensures that the User with the given email is no longer present in this manager.
239       * @param email The user's email address.
240       */
241      public abstract void deleteUser(String email);
242      
243      /**
244       * Returns the XML ProjectIndex for all Projects in this server.
245       * @return The XML String containing an index to all Projects.
246       */
247      public abstract String getProjectIndex();
248      
249      /**
250       * Returns the Project instance as XML string, or null if not found.
251       * @param owner The user who owns the project.
252       * @param projectName The name of the Project.
253       * @return The Project XML string, or null.
254       */
255      public abstract String getProject(User owner, String projectName);
256      
257      /**
258       * Persists a Project instance.  If a Project with this owner and name
259       * already exists in the storage system, it will be overwritten.
260       * @param project The Project.
261       * @param xmlProject The Project marshalled into an XML String.  
262       * @param xmlProjectRef The corresponding ProjectRef marshalled into an XML String
263       * @return True if the user was successfully inserted.
264       */
265      public abstract boolean storeProject(Project project, String xmlProject, String xmlProjectRef);
266      
267      /**
268       * Ensures that the Project with the given owner and projectName is no longer present in the db.
269       * @param owner The User who owns this project.
270       * @param projectName The name of the Project.
271       */
272      public abstract void deleteProject(User owner, String projectName);
273      
274      /**
275       * Returns a ProjectSummary instance constructed for the given Project between the startTime
276       * and endTime. This summary provides a breakdown of the number of sensor data instances found
277       * of the given type during the given time period.
278       * @param users The users in this project.
279       * @param startTime The startTime
280       * @param endTime The endTime.
281       * @param uriPatterns The UriPatterns for this project.
282       * @param href The URL naming this resource. 
283       * @return The ProjectSummary instance. 
284       */
285      public abstract ProjectSummary getProjectSummary(List<User> users, XMLGregorianCalendar startTime,
286          XMLGregorianCalendar endTime, List<String> uriPatterns, String href);
287    
288      
289      /** Keeps a pointer to this Server for use in accessing the managers. */
290      protected Server server;
291      
292      /** Keep a pointer to the Logger. */
293      protected Logger logger;
294      
295      /**
296       * Constructs a new DbImplementation.
297       * @param server The server. 
298       */
299      public DbImplementation(Server server) {
300        this.server = server;
301        this.logger = server.getLogger();
302      }
303      
304      /**
305       * Returns the UserManager associated with this server.
306       * Since the DbManager is initialized before all other managers, we will simply 
307       * get these other Managers on demand and not cache them. 
308       * @return The User Manager. 
309       */
310      protected UserManager getUserManager() {
311        return (UserManager)server.getContext().getAttributes().get("UserManager");
312      }
313      
314      /**
315       * Returns the SensorDataManager associated with this server. 
316       * Since the DbManager is initialized before all other managers, we will simply 
317       * get these other Managers on demand and not cache them. 
318       * @return The Sensor Data Manager. 
319       */
320      protected SensorDataManager getSensorDataManager() {
321        return (SensorDataManager)server.getContext().getAttributes().get("SensorDataManager");
322      }
323      
324      /**
325       * Returns the SdtManager associated with this server. 
326       * Since the DbManager is initialized before all other managers, we will simply 
327       * get these other Managers on demand and not cache them. 
328       * @return The SdtManager. 
329       */
330      protected SdtManager getSdtManager() {
331        return (SdtManager)server.getContext().getAttributes().get("SdtManager");
332      }
333      
334      /**
335       * Returns the ProjectManager associated with this server. 
336       * Since the DbManager is initialized before all other managers, we will simply 
337       * get these other Managers on demand and not cache them. 
338       * @return The ProjectManager. 
339       */
340      protected ProjectManager getProjectManager() {
341        return (ProjectManager)server.getContext().getAttributes().get("ProjectManager");
342      }
343      
344      
345      /**
346       * Databases like Derby require an explicit compress command for releasing disk space 
347       * after a large number of rows have been deleted.  This operation invokes the compress
348       * command on all tables in the database.  If a database implementation does not support
349       * explicit compression, then this command should do nothing but return true.   
350       * @return True if the compress command succeeded or if the database does not support
351       * compression. 
352       */
353      public abstract boolean compressTables();
354      
355      /**
356       * The most appropriate set of indexes for the database has been evolving over time as we 
357       * develop new queries.  This command sets up the appropriate set of indexes.  It should be
358       * able to be called repeatedly without error. 
359       * @return True if the index commands succeeded. 
360       */
361      public abstract boolean indexTables(); 
362      
363      /**
364       * Returns the current number of rows in the specified table.  
365       * @param table The table whose rows are to be counted. 
366       * @return The number of rows in the table, or -1 if the table does not exist or an error occurs. 
367       */
368      public abstract int getRowCount(String table); 
369      
370      /**
371       * Returns a set containing the names of all tables in this database.  Used by clients to 
372       * invoke getRowCount with a legal table name. 
373       * @return A set of table names.
374       */
375      public abstract Set<String> getTableNames(); 
376      
377    }