001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/assignment/tags/sakai_2-4-1/assignment-impl/impl/src/java/org/sakaiproject/assignment/impl/DbAssignmentService.java $
003: * $Id: DbAssignmentService.java 8331 2006-04-26 14:32:54Z ggolden@umich.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.assignment.impl;
021:
022: import java.sql.Connection;
023: import java.sql.ResultSet;
024: import java.sql.SQLException;
025: import java.util.List;
026:
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029: import org.sakaiproject.assignment.api.Assignment;
030: import org.sakaiproject.assignment.api.AssignmentContent;
031: import org.sakaiproject.assignment.api.AssignmentContentEdit;
032: import org.sakaiproject.assignment.api.AssignmentEdit;
033: import org.sakaiproject.assignment.api.AssignmentSubmission;
034: import org.sakaiproject.assignment.api.AssignmentSubmissionEdit;
035: import org.sakaiproject.db.api.SqlReader;
036: import org.sakaiproject.db.api.SqlService;
037: import org.sakaiproject.util.BaseDbSingleStorage;
038: import org.sakaiproject.util.Xml;
039: import org.w3c.dom.Document;
040: import org.w3c.dom.Element;
041:
042: /**
043: * <p>
044: * DbAssignmentService is the database-storing service class for Assignments.
045: * </p>
046: */
047: public class DbAssignmentService extends BaseAssignmentService {
048: /** Our logger. */
049: private static Log M_log = LogFactory
050: .getLog(DbAssignmentService.class);
051:
052: /** The name of the db table holding assignment objects. */
053: protected String m_assignmentsTableName = "ASSIGNMENT_ASSIGNMENT";
054:
055: /** The name of the db table holding assignment content objects. */
056: protected String m_contentsTableName = "ASSIGNMENT_CONTENT";
057:
058: /** The name of the db table holding assignment submission objects. */
059: protected String m_submissionsTableName = "ASSIGNMENT_SUBMISSION";
060:
061: /** If true, we do our locks in the remote database, otherwise we do them here. */
062: protected boolean m_locksInDb = true;
063:
064: /** Extra fields to store in the db with the XML. */
065: protected static final String[] FIELDS = { "CONTEXT" };
066:
067: /**********************************************************************************************************************************************************************************************************************************************************
068: * Constructors, Dependencies and their setter methods
069: *********************************************************************************************************************************************************************************************************************************************************/
070:
071: /** Dependency: SqlService */
072: protected SqlService m_sqlService = null;
073:
074: /**
075: * Dependency: SqlService.
076: *
077: * @param service
078: * The SqlService.
079: */
080: public void setSqlService(SqlService service) {
081: m_sqlService = service;
082: }
083:
084: /**
085: * Configuration: set the table name for assignments.
086: *
087: * @param path
088: * The table name for assignments.
089: */
090: public void setAssignmentTableName(String name) {
091: m_assignmentsTableName = name;
092: }
093:
094: /**
095: * Configuration: set the table name for contents.
096: *
097: * @param path
098: * The table name for contents.
099: */
100: public void setContentTableName(String name) {
101: m_contentsTableName = name;
102: }
103:
104: /**
105: * Configuration: set the table name for submissions.
106: *
107: * @param path
108: * The table name for submissions.
109: */
110: public void setSubmissionTableName(String name) {
111: m_submissionsTableName = name;
112: }
113:
114: /**
115: * Configuration: set the locks-in-db
116: *
117: * @param value
118: * The locks-in-db value.
119: */
120: public void setLocksInDb(String value) {
121: m_locksInDb = new Boolean(value).booleanValue();
122: }
123:
124: /** Set if we are to run the to-context conversion. */
125: protected boolean m_convertToContext = false;
126:
127: /**
128: * Configuration: run the to-context conversion
129: *
130: * @param value
131: * The locks-in-db value.
132: */
133: public void setConvertToContext(String value) {
134: m_convertToContext = new Boolean(value).booleanValue();
135: }
136:
137: /** Configuration: to run the ddl on init or not. */
138: protected boolean m_autoDdl = false;
139:
140: /**
141: * Configuration: to run the ddl on init or not.
142: *
143: * @param value
144: * the auto ddl value.
145: */
146: public void setAutoDdl(String value) {
147: m_autoDdl = new Boolean(value).booleanValue();
148: }
149:
150: /**********************************************************************************************************************************************************************************************************************************************************
151: * Init and Destroy
152: *********************************************************************************************************************************************************************************************************************************************************/
153:
154: /**
155: * Final initialization, once all dependencies are set.
156: */
157: public void init() {
158: try {
159: // if we are auto-creating our schema, check and create
160: if (m_autoDdl) {
161: m_sqlService.ddl(this .getClass().getClassLoader(),
162: "sakai_assignment");
163: }
164:
165: super .init();
166:
167: M_log.info("init: assignments table: "
168: + m_assignmentsTableName + " contents table: "
169: + m_contentsTableName + " submissions table: "
170: + m_submissionsTableName + " locks-in-db"
171: + m_locksInDb);
172:
173: // convert?
174: if (m_convertToContext) {
175: m_convertToContext = false;
176: convertToContext();
177: }
178: } catch (Throwable t) {
179: M_log.warn(this + ".init(): ", t);
180: }
181: }
182:
183: /**********************************************************************************************************************************************************************************************************************************************************
184: * BaseAssignmentService extensions
185: *********************************************************************************************************************************************************************************************************************************************************/
186:
187: /**
188: * Construct a Storage object for Assignments.
189: *
190: * @return The new storage object for Assignments.
191: */
192: protected AssignmentStorage newAssignmentStorage() {
193: return new DbCachedAssignmentStorage(
194: new AssignmentStorageUser());
195:
196: } // newAssignmentStorage
197:
198: /**
199: * Construct a Storage object for AssignmentsContents.
200: *
201: * @return The new storage object for AssignmentContents.
202: */
203: protected AssignmentContentStorage newContentStorage() {
204: return new DbCachedAssignmentContentStorage(
205: new AssignmentContentStorageUser());
206:
207: } // newContentStorage
208:
209: /**
210: * Construct a Storage object for AssignmentSubmissions.
211: *
212: * @return The new storage object for AssignmentSubmissions.
213: */
214: protected AssignmentSubmissionStorage newSubmissionStorage() {
215: return new DbCachedAssignmentSubmissionStorage(
216: new AssignmentSubmissionStorageUser());
217:
218: } // newSubmissionStorage
219:
220: /**********************************************************************************************************************************************************************************************************************************************************
221: * Storage implementations
222: *********************************************************************************************************************************************************************************************************************************************************/
223:
224: /**********************************************************************************************************************************************************************************************************************************************************
225: * AssignmentStorage implementation
226: *********************************************************************************************************************************************************************************************************************************************************/
227:
228: /**
229: * Covers for the BaseDbSingleStorage, providing Assignment and AssignmentEdit parameters
230: */
231: protected class DbCachedAssignmentStorage extends
232: BaseDbSingleStorage implements AssignmentStorage {
233: /**
234: * Construct.
235: *
236: * @param assignment
237: * The StorageUser class to call back for creation of Resource and Edit objects.
238: */
239: public DbCachedAssignmentStorage(
240: AssignmentStorageUser assignment) {
241: super (m_assignmentsTableName, "ASSIGNMENT_ID", FIELDS,
242: m_locksInDb, "assignment", assignment, m_sqlService);
243:
244: } // DbCachedAssignmentStorage
245:
246: public boolean check(String id) {
247: return super .checkResource(id);
248: }
249:
250: public Assignment get(String id) {
251: return (Assignment) super .getResource(id);
252: }
253:
254: public List getAll(String context) {
255: return super .getAllResourcesWhere(FIELDS[0], context);
256: }
257:
258: public AssignmentEdit put(String id, String context) {
259: // pack the context in an array
260: Object[] others = new Object[1];
261: others[0] = context;
262: return (AssignmentEdit) super .putResource(id, others);
263: }
264:
265: public AssignmentEdit edit(String id) {
266: return (AssignmentEdit) super .editResource(id);
267: }
268:
269: public void commit(AssignmentEdit edit) {
270: super .commitResource(edit);
271: }
272:
273: public void cancel(AssignmentEdit edit) {
274: super .cancelResource(edit);
275: }
276:
277: public void remove(AssignmentEdit edit) {
278: super .removeResource(edit);
279: }
280:
281: } // DbCachedAssignmentStorage
282:
283: /**********************************************************************************************************************************************************************************************************************************************************
284: * AssignmentContentStorage implementation
285: *********************************************************************************************************************************************************************************************************************************************************/
286:
287: /**
288: * Covers for the BaseDbSingleStorage, providing AssignmentContent and AssignmentContentEdit parameters
289: */
290: protected class DbCachedAssignmentContentStorage extends
291: BaseDbSingleStorage implements AssignmentContentStorage {
292: /**
293: * Construct.
294: *
295: * @param content
296: * The StorageUser class to call back for creation of Resource and Edit objects.
297: */
298: public DbCachedAssignmentContentStorage(
299: AssignmentContentStorageUser content) {
300: super (m_contentsTableName, "CONTENT_ID", FIELDS,
301: m_locksInDb, "content", content, m_sqlService);
302:
303: } // DbCachedAssignmentContentStorage
304:
305: public boolean check(String id) {
306: return super .checkResource(id);
307: }
308:
309: public AssignmentContent get(String id) {
310: return (AssignmentContent) super .getResource(id);
311: }
312:
313: public List getAll(String context) {
314: return super .getAllResourcesWhere(FIELDS[0], context);
315: }
316:
317: public AssignmentContentEdit put(String id, String context) {
318: // pack the context in an array
319: Object[] others = new Object[1];
320: others[0] = context;
321: return (AssignmentContentEdit) super
322: .putResource(id, others);
323: }
324:
325: public AssignmentContentEdit edit(String id) {
326: return (AssignmentContentEdit) super .editResource(id);
327: }
328:
329: public void commit(AssignmentContentEdit edit) {
330: super .commitResource(edit);
331: }
332:
333: public void cancel(AssignmentContentEdit edit) {
334: super .cancelResource(edit);
335: }
336:
337: public void remove(AssignmentContentEdit edit) {
338: super .removeResource(edit);
339: }
340:
341: } // DbCachedAssignmentContentStorage
342:
343: /**********************************************************************************************************************************************************************************************************************************************************
344: * AssignmentSubmissionStorage implementation
345: *********************************************************************************************************************************************************************************************************************************************************/
346:
347: /**
348: * Covers for the BaseDbSingleStorage, providing AssignmentSubmission and AssignmentSubmissionEdit parameters
349: */
350: protected class DbCachedAssignmentSubmissionStorage extends
351: BaseDbSingleStorage implements AssignmentSubmissionStorage {
352: /**
353: * Construct.
354: *
355: * @param submission
356: * The StorageUser class to call back for creation of Resource and Edit objects.
357: */
358: public DbCachedAssignmentSubmissionStorage(
359: AssignmentSubmissionStorageUser submission) {
360: super (m_submissionsTableName, "SUBMISSION_ID", FIELDS,
361: m_locksInDb, "submission", submission, m_sqlService);
362:
363: } // DbCachedAssignmentSubmissionStorage
364:
365: public boolean check(String id) {
366: return super .checkResource(id);
367: }
368:
369: public AssignmentSubmission get(String id) {
370: return (AssignmentSubmission) super .getResource(id);
371: }
372:
373: public List getAll(String context) {
374: return super .getAllResourcesWhere(FIELDS[0], context);
375: }
376:
377: public AssignmentSubmissionEdit put(String id, String context,
378: String assignmentId) {
379: // pack the context in an array
380: Object[] others = new Object[2];
381: others[0] = context;
382: others[1] = assignmentId;
383: return (AssignmentSubmissionEdit) super .putResource(id,
384: others);
385: }
386:
387: public AssignmentSubmissionEdit edit(String id) {
388: return (AssignmentSubmissionEdit) super .editResource(id);
389: }
390:
391: public void commit(AssignmentSubmissionEdit edit) {
392: super .commitResource(edit);
393: }
394:
395: public void cancel(AssignmentSubmissionEdit edit) {
396: super .cancelResource(edit);
397: }
398:
399: public void remove(AssignmentSubmissionEdit edit) {
400: super .removeResource(edit);
401: }
402:
403: } // DbCachedAssignmentSubmissionStorage
404:
405: /**
406: * fill in the context field for any record missing it
407: */
408: protected void convertToContext() {
409: M_log.info("convertToContext");
410:
411: try {
412: // get a connection
413: final Connection connection = m_sqlService
414: .borrowConnection();
415: boolean wasCommit = connection.getAutoCommit();
416: connection.setAutoCommit(false);
417:
418: // read all assignment records
419: String sql = "select XML from ASSIGNMENT_ASSIGNMENT where CONTEXT is null";
420: m_sqlService.dbRead(connection, sql, null, new SqlReader() {
421: public Object readSqlResultRecord(ResultSet result) {
422: try {
423: // create the Resource from the db xml
424: String xml = result.getString(1);
425:
426: // read the xml
427: Document doc = Xml.readDocumentFromString(xml);
428:
429: // verify the root element
430: Element root = doc.getDocumentElement();
431: if (!root.getTagName().equals("assignment")) {
432: M_log
433: .warn("convertToContext(): XML root element not assignment: "
434: + root.getTagName());
435: return null;
436: }
437: Assignment a = new BaseAssignment(root);
438: // context is context
439: String context = a.getContext();
440: String id = a.getId();
441:
442: // update
443: String update = "update ASSIGNMENT_ASSIGNMENT set CONTEXT = ? where ASSIGNMENT_ID = ?";
444: Object fields[] = new Object[2];
445: fields[0] = context;
446: fields[1] = id;
447: boolean ok = m_sqlService.dbWrite(connection,
448: update, fields);
449:
450: M_log.info("convertToContext: assignment id: "
451: + id + " context: " + context + " ok: "
452: + ok);
453:
454: return null;
455: } catch (SQLException ignore) {
456: return null;
457: }
458: }
459: });
460:
461: // read all content records
462: sql = "select XML from ASSIGNMENT_CONTENT where CONTEXT is null";
463: m_sqlService.dbRead(connection, sql, null, new SqlReader() {
464: public Object readSqlResultRecord(ResultSet result) {
465: try {
466: // create the Resource from the db xml
467: String xml = result.getString(1);
468:
469: // read the xml
470: Document doc = Xml.readDocumentFromString(xml);
471:
472: // verify the root element
473: Element root = doc.getDocumentElement();
474: if (!root.getTagName().equals("content")) {
475: M_log
476: .warn("convertToContext(): XML root element not content: "
477: + root.getTagName());
478: return null;
479: }
480: AssignmentContent c = new BaseAssignmentContent(
481: root);
482: // context is creator
483: String context = c.getCreator();
484: String id = c.getId();
485:
486: // update
487: String update = "update ASSIGNMENT_CONTENT set CONTEXT = ? where CONTENT_ID = ?";
488: Object fields[] = new Object[2];
489: fields[0] = context;
490: fields[1] = id;
491: boolean ok = m_sqlService.dbWrite(connection,
492: update, fields);
493:
494: M_log.info("convertToContext: content id: "
495: + id + " context: " + context + " ok: "
496: + ok);
497:
498: return null;
499: } catch (SQLException ignore) {
500: return null;
501: }
502: }
503: });
504:
505: // read all submission records
506: sql = "select XML from ASSIGNMENT_SUBMISSION where CONTEXT is null";
507: m_sqlService.dbRead(connection, sql, null, new SqlReader() {
508: public Object readSqlResultRecord(ResultSet result) {
509: try {
510: // create the Resource from the db xml
511: String xml = result.getString(1);
512:
513: // read the xml
514: Document doc = Xml.readDocumentFromString(xml);
515:
516: // verify the root element
517: Element root = doc.getDocumentElement();
518: if (!root.getTagName().equals("submission")) {
519: M_log
520: .warn("convertToContext(): XML root element not submission: "
521: + root.getTagName());
522: return null;
523: }
524: AssignmentSubmission s = new BaseAssignmentSubmission(
525: root);
526: // context is assignment id
527: String context = s.getAssignmentId();
528: String id = s.getId();
529:
530: // update
531: String update = "update ASSIGNMENT_SUBMISSION set CONTEXT = ? where SUBMISSION_ID = ?";
532: Object fields[] = new Object[2];
533: fields[0] = context;
534: fields[1] = id;
535: boolean ok = m_sqlService.dbWrite(connection,
536: update, fields);
537:
538: M_log.info("convertToContext: submission id: "
539: + id + " context: " + context + " ok: "
540: + ok);
541:
542: return null;
543: } catch (SQLException ignore) {
544: return null;
545: }
546: }
547: });
548:
549: connection.commit();
550: connection.setAutoCommit(wasCommit);
551: m_sqlService.returnConnection(connection);
552: } catch (Throwable t) {
553: M_log.warn("convertToContext: failed: " + t);
554: }
555:
556: // TODO:
557: M_log.info("convertToContext: done");
558: }
559: }
|