001: /*
002: * The contents of this file are subject to the
003: * Mozilla Public License Version 1.1 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
006: *
007: * Software distributed under the License is distributed on an "AS IS"
008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
009: * See the License for the specific language governing rights and
010: * limitations under the License.
011: *
012: * The Initial Developer of the Original Code is Simulacra Media Ltd.
013: * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
014: *
015: * All Rights Reserved.
016: *
017: * Contributor(s):
018: */
019: package org.openharmonise.rm.resources.content;
020:
021: import java.sql.*;
022: import java.util.Vector;
023: import java.util.logging.*;
024:
025: import org.openharmonise.commons.cache.CacheException;
026: import org.openharmonise.commons.dsi.*;
027: import org.openharmonise.commons.dsi.dml.*;
028: import org.openharmonise.commons.net.MimeTypeMapping;
029: import org.openharmonise.rm.*;
030: import org.openharmonise.rm.dsi.ColumnRefCache;
031: import org.openharmonise.rm.publishing.*;
032: import org.openharmonise.rm.resources.AbstractChildObject;
033: import org.openharmonise.rm.resources.lifecycle.EditException;
034: import org.w3c.dom.*;
035:
036: /**
037: * General abstract class to represent plain text resources within Harmonise.
038: *
039: * @author Michael Bell
040: * @version $Revision: 1.4 $
041: *
042: */
043: abstract public class TextResource extends AbstractChildObject {
044:
045: //XML constants
046: /**
047: * Content tag name
048: */
049: public static final String TAG_CONTENT = "Content";
050:
051: /**
052: * Content type tag name
053: */
054: public static final String TAG_CONTENT_TYPE = "ContentType";
055:
056: //DB constants
057: /**
058: * Content database column name
059: */
060: private static final String CLMN_CONTENT = "content";
061: /**
062: * Mime-type database column name
063: */
064: private static final String CLMN_MIME_TYPE = "mime_type";
065:
066: //member fields
067: /**
068: * This <code>TextResource</code>'s content
069: */
070: protected String m_sContent = null;
071:
072: /**
073: * This <code>TextResource</code>'s mime-type, plain text by default.
074: */
075: protected String m_sContentType = MimeTypeMapping.TEXT
076: .getMimeType();
077:
078: /**
079: * <code>boolean</code> flag which indicates whether the content of this
080: * resource has been populated from the database.
081: */
082: private boolean m_bIsContentPopulated = false;
083:
084: /**
085: * Logger for this class.
086: */
087: private static final Logger m_logger = Logger
088: .getLogger(TextResource.class.getName());
089:
090: /**
091: * Contructs a new instance with no data store interface.
092: */
093: public TextResource() {
094: super ();
095: }
096:
097: /**
098: * Contructs a new or anonymous resource.
099: *
100: * @param dbintrf the data store interface
101: */
102: public TextResource(AbstractDataStoreInterface dbintrf) {
103: super (dbintrf);
104: }
105:
106: /**
107: * Constructs a known resource which may be historical.
108: *
109: * @param dbintrf the data store interface
110: * @param nId the id resource
111: * @param nKey the unique key of the version of the resource
112: * @param bIsHist <code>true</code> if the version of the resource is historical, otherwise <code>false</code>
113: */
114: public TextResource(AbstractDataStoreInterface dbintrf, int nId,
115: int nKey, boolean bIsHist) {
116: super (dbintrf, nId, nKey, bIsHist);
117: }
118:
119: /**
120: * Contructs a known resurce object.
121: *
122: * @param dbintrf the data store interface
123: * @param nId the resource id
124: */
125: public TextResource(AbstractDataStoreInterface dbintrf, int nId) {
126: super (dbintrf, nId);
127: }
128:
129: /**
130: * Returns the text content of this resource object.
131: *
132: * @return the text content of this resource object
133: * @throws DataAccessException if there is an error populating the
134: * object from the database
135: */
136: public String getContent() throws DataAccessException {
137: try {
138: if (isPopulated() == false) {
139: populateFromDatabase();
140: }
141: } catch (PopulateException e) {
142: throw new DataAccessException(
143: "Problem occurred getting content", e);
144: }
145:
146: return m_sContent;
147: }
148:
149: /**
150: * Populates the resource's content from the database.
151: *
152: * @throws DataAccessException if there is an error getting data
153: * from the database
154: */
155: private void populateContent() throws DataAccessException {
156: if (m_nId > NOTDBSAVED_ID && isContentPopulated() == false
157: && isPopulated() == true) {
158: try {
159: String sContent = m_dsi.getClob(
160: getTableName(isHistorical()), CLMN_CONTENT,
161: this .getInstanceColumnRef(ATTRIB_KEY,
162: isHistorical()).getColumn()
163: + "=" + getKey());
164:
165: if ((sContent != null) && (sContent.length() > 0)) {
166: if ((m_sContent == null)
167: || (m_sContent.length() == 0)) {
168: m_sContent = sContent;
169: } else if (m_sContent.equals(sContent) == false) {
170: m_bIsChanged = true;
171: }
172: }
173: m_bIsContentPopulated = true;
174: } catch (DataStoreException e) {
175: throw new DataAccessException(
176: "Error occured getting content from DB:", e);
177: }
178: }
179: }
180:
181: /**
182: * Sets the text content of this resource.
183: *
184: * @param sContent the text content
185: * @throws PopulateException if the specified content is invalid for this
186: * resource
187: */
188: public void setContent(String sContent) throws PopulateException {
189: if (isContentPopulated() == true) {
190: if (m_sContent != null
191: && m_sContent.equals(sContent) == false) {
192: setIsChanged(true);
193: }
194: }
195:
196: m_sContent = sContent;
197: }
198:
199: /**
200: * Returns <code>true</code> if the text content has been populated
201: * from the database.
202: *
203: * @return <code>true</code> if the content is populated and <code>false</code> otherwise.
204: */
205: public boolean isContentPopulated() {
206: return m_bIsContentPopulated;
207: }
208:
209: /**
210: * Returns the content type/mime-type of this text resource.
211: *
212: * @return the content type/mime-type of this text resource
213: * @throws DataAccessException if an error occurs populating this object
214: * from the database
215: */
216: public String getContentType() throws DataAccessException {
217: if (isPopulated() == false) {
218: try {
219: populateFromDatabase();
220: } catch (PopulateException e) {
221: throw new DataAccessException(
222: "Error occured populating from DB", e);
223: }
224: }
225:
226: return m_sContentType;
227: }
228:
229: /**
230: * Sets the content type/mime-type of this text resource.
231: *
232: * @param sContentType the mime-type
233: */
234: public void setContentType(String sContentType) {
235: if (isPopulated() == true) {
236: if ((m_sContentType == null && sContentType != null)
237: || m_sContentType.equals(sContentType) == false) {
238: setIsChanged(true);
239: }
240: }
241:
242: m_sContentType = sContentType;
243: }
244:
245: /* (non-Javadoc)
246: * @see org.openharmonise.rm.dsi.DataStoreObject#getInstanceColumnRef(java.lang.String, boolean)
247: */
248: public ColumnRef getInstanceColumnRef(String sColumn,
249: boolean bIsHist) throws DataStoreException {
250: ColumnRef colref = null;
251:
252: String sTable = getTableName(bIsHist);
253:
254: if (sColumn.equals(CLMN_CONTENT) == true
255: || sColumn.equals(TAG_CONTENT) == true) {
256: colref = new ColumnRef(sTable, CLMN_CONTENT, ColumnRef.TEXT);
257: } else if (sColumn.equals(CLMN_MIME_TYPE) == true) {
258: colref = new ColumnRef(sTable, CLMN_MIME_TYPE,
259: ColumnRef.TEXT);
260: } else {
261: colref = super .getInstanceColumnRef(sColumn, bIsHist);
262: }
263:
264: return colref;
265: }
266:
267: /* (non-Javadoc)
268: * @see org.openharmonise.rm.publishing.Publishable#populate(org.w3c.dom.Element, org.openharmonise.rm.publishing.State)
269: */
270: public void populate(Element xmlElement, State state)
271: throws PopulateException {
272: Text txt = null;
273: String sTagname = xmlElement.getTagName();
274:
275: if (sTagname.equals(TAG_CONTENT) == true) {
276: txt = (Text) xmlElement.getFirstChild();
277: setContent(txt.getNodeValue());
278: } else if (sTagname.equals(TAG_CONTENT_TYPE) == true) {
279: txt = (Text) xmlElement.getFirstChild();
280: setContentType(txt.getNodeValue());
281: } else {
282: super .populate(xmlElement, state);
283: }
284:
285: }
286:
287: /* (non-Javadoc)
288: * @see org.openharmonise.rm.publishing.Publishable#publish(org.w3c.dom.Element, org.openharmonise.rm.publishing.HarmoniseOutput, org.openharmonise.rm.publishing.State)
289: */
290: public Element publish(Element topEl, HarmoniseOutput xmlDoc,
291: State state) throws PublishException {
292: Element docEl = null;
293: Text txt = null;
294:
295: String sTagname = topEl.getTagName();
296:
297: if (sTagname.equals(TAG_CONTENT) == true) {
298: docEl = xmlDoc.createElement(sTagname);
299: try {
300: txt = xmlDoc.createTextNode(getContent());
301: } catch (DataAccessException e) {
302: throw new PublishException(
303: "Error occured getting content:"
304: + e.getLocalizedMessage());
305: }
306: docEl.appendChild(txt);
307: xmlDoc.copyChildren(docEl, topEl, new Vector());
308: } else if (sTagname.equals(TAG_CONTENT_TYPE) == true) {
309: docEl = xmlDoc.createElement(sTagname);
310: try {
311: txt = xmlDoc.createTextNode(getContentType());
312: } catch (DataAccessException e) {
313: throw new PublishException(
314: "Error occured getting content type:"
315: + e.getLocalizedMessage());
316: }
317: docEl.appendChild(txt);
318: xmlDoc.copyChildren(docEl, topEl, new Vector());
319: } else {
320: docEl = super .publish(topEl, xmlDoc, state);
321: }
322: return docEl;
323: }
324:
325: /*----------------------------------------------------------------------------
326: Protected methods
327: -----------------------------------------------------------------------------*/
328:
329: /* (non-Javadoc)
330: * @see org.openharmonise.rm.resources.AbstractEditableObject#saveCoreData()
331: */
332: protected void saveCoreData() throws EditException {
333:
334: super .saveCoreData();
335:
336: try {
337: m_dsi.updateClob(getTableName(isHistorical()),
338: CLMN_CONTENT, m_sContent, this
339: .getInstanceColumnRef(ATTRIB_KEY,
340: isHistorical()).getColumn()
341: + "=" + getKey());
342:
343: m_bIsContentPopulated = true;
344: } catch (DataAccessException e) {
345: throw new EditException(
346: "Error occured accessing object key", e);
347: } catch (DataStoreException e) {
348: throw new EditException(
349: "Error occured saving content to DB", e);
350: }
351: }
352:
353: /* (non-Javadoc)
354: * @see org.openharmonise.rm.resources.AbstractEditableObject#update()
355: */
356: protected void update() throws EditException, DataStoreException {
357:
358: super .update();
359:
360: try {
361: m_dsi.updateClob(m_sTable, CLMN_CONTENT, m_sContent, this
362: .getInstanceColumnRef(ATTRIB_KEY, isHistorical())
363: .getColumn()
364: + "=" + getKey());
365: } catch (DataAccessException e) {
366: throw new DataStoreException(
367: "Error occured accessing object key:"
368: + e.getLocalizedMessage());
369: }
370: }
371:
372: /* (non-Javadoc)
373: * @see org.openharmonise.rm.resources.AbstractEditableObject#addDataToSave(org.openharmonise.commons.dsi.dml.InsertStatement)
374: */
375: protected void addDataToSave(InsertStatement insert)
376: throws DataStoreException {
377:
378: insert.addColumnValue(this .getInstanceColumnRef(CLMN_MIME_TYPE,
379: isHistorical()), m_sContentType);
380:
381: super .addDataToSave(insert);
382: }
383:
384: /* (non-Javadoc)
385: * @see org.openharmonise.rm.resources.AbstractObject#populateFromResultSetRow(java.sql.ResultSet, org.openharmonise.commons.dsi.dml.SelectStatement)
386: */
387: protected void populateFromResultSetRow(ResultSet rs,
388: SelectStatement select) throws PopulateException {
389:
390: if (isPopulated() == false) {
391: String sTemp = null;
392: ColumnRef colref = null;
393:
394: try {
395: ColumnRefCache cache = ColumnRefCache.getInstance();
396:
397: boolean bIsHist = isHistorical();
398: colref = cache
399: .getColumnRef(this , CLMN_CONTENT, bIsHist);
400:
401: if (select.containsSelectColumn(colref) == true) {
402: sTemp = rs.getString(select
403: .getResultSetIndex(colref));
404:
405: if ((sTemp != null) && (sTemp.length() > 0)) {
406: if ((m_sContent == null)
407: || (m_sContent.length() == 0)) {
408: m_sContent = sTemp;
409: } else if (m_sContent.equals(sTemp) == false) {
410: setIsChanged(true);
411: }
412: }
413: }
414:
415: colref = cache.getColumnRef(this , CLMN_MIME_TYPE,
416: bIsHist);
417: if (select.containsSelectColumn(colref) == true) {
418: sTemp = rs.getString(select
419: .getResultSetIndex(colref));
420:
421: if ((sTemp != null) && (sTemp.length() > 0)) {
422: if ((m_sContentType == null)
423: || (m_sContentType.length() == 0)) {
424: m_sContentType = sTemp;
425: } else if (m_sContentType.equals(sTemp) == false) {
426: setIsChanged(true);
427: }
428: }
429: }
430: } catch (SQLException e) {
431: throw new PopulateException(
432: "SQL error occured populating", e);
433: } catch (CacheException e) {
434: throw new PopulateException(
435: "Cache error occured populating", e);
436: }
437:
438: super .populateFromResultSetRow(rs, select);
439: }
440: }
441:
442: /* (non-Javadoc)
443: * @see java.lang.Object#clone()
444: */
445: public Object clone() {
446: try {
447: if (m_bIsPopulated == false) {
448: populateFromDatabase();
449: }
450:
451: TextResource other = (TextResource) super .clone();
452:
453: return other;
454: } catch (PopulateException e) {
455: m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
456:
457: return null;
458: }
459: }
460:
461: /* (non-Javadoc)
462: * @see org.openharmonise.rm.resources.AbstractObject#addColumnsToPopulateQuery(org.openharmonise.commons.dsi.dml.SelectStatement, boolean)
463: */
464: protected void addColumnsToPopulateQuery(SelectStatement select,
465: boolean bIsHist) throws DataStoreException {
466:
467: try {
468: ColumnRefCache cache = ColumnRefCache.getInstance();
469:
470: select.addSelectColumn(cache.getColumnRef(this ,
471: CLMN_MIME_TYPE, bIsHist));
472:
473: } catch (CacheException e) {
474: throw new DataStoreException("Error with cached colref", e);
475: }
476: super .addColumnsToPopulateQuery(select, bIsHist);
477: }
478:
479: /* (non-Javadoc)
480: * @see org.openharmonise.rm.resources.AbstractObject#populateFromDatabase()
481: */
482: protected void populateFromDatabase() throws PopulateException {
483: super .populateFromDatabase(); // populate the main data
484:
485: // now populate the content.
486: try {
487: populateContent();
488: } catch (DataAccessException e) {
489: throw new PopulateException(
490: "Error occured populating content:", e);
491: }
492: }
493: }
|