001: /* *************************************************************************
002:
003: Millstone(TM)
004: Open Sourced User Interface Library for
005: Internet Development with Java
006:
007: Millstone is a registered trademark of IT Mill Ltd
008: Copyright (C) 2000-2005 IT Mill Ltd
009:
010: *************************************************************************
011:
012: This library is free software; you can redistribute it and/or
013: modify it under the terms of the GNU Lesser General Public
014: license version 2.1 as published by the Free Software Foundation.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: *************************************************************************
026:
027: For more information, contact:
028:
029: IT Mill Ltd phone: +358 2 4802 7180
030: Ruukinkatu 2-4 fax: +358 2 4802 7181
031: 20540, Turku email: info@itmill.com
032: Finland company www: www.itmill.com
033:
034: Primary source for MillStone information and releases: www.millstone.org
035:
036: ********************************************************************** */
037:
038: package org.millstone.base.data;
039:
040: import org.millstone.base.terminal.ErrorMessage;
041: import org.millstone.base.terminal.PaintException;
042: import org.millstone.base.terminal.PaintTarget;
043: import org.millstone.base.terminal.SystemError;
044:
045: /** <p>Defines the interface to commit and discard changes to an object,
046: * supporting read-through and write-through modes.</p>
047: *
048: * <p><i>Read-through mode</i> means that the value read from the buffered
049: * object is constantly up to date with the data source.
050: * <i>Write-through</i> mode means that all changes to the object are
051: * immediately updated to the data source.</p>
052: *
053: * <p>Since these modes are independent, their combinations may result in
054: * some behaviour that may sound surprising. For example, if a
055: * <code>Buffered</code> object is in read-through mode but not in
056: * write-through mode, the result is an object whose value is updated
057: * directly from the data source only if it's not locally modified. If the
058: * value is locally modified, retrieving the value from the object would
059: * result in a value that is different than the one stored in the data
060: * source, even though the object is in read-through mode.</p>
061: *
062: * @author IT Mill Ltd.
063: * @version 3.1.1
064: * @since 3.0
065: */
066: public interface Buffered {
067:
068: /** Updates all changes since the previous commit to the data source.
069: * The value stored in the object will always be updated into the data
070: * source when <code>commit</code> is called.
071: *
072: * @throws SourceException if the operation fails because of an
073: * exception is thrown by the data source. The cause is included in the
074: * exception.
075: */
076: public void commit() throws SourceException;
077:
078: /** Discards all changes since last commit. The object updates its value
079: * from the data source.
080: *
081: * @throws SourceException if the operation fails because of an
082: * exception is thrown by the data source. The cause is included in the
083: * exception.
084: */
085: public void discard() throws SourceException;
086:
087: /** Tests if the object is in write-through mode. If the object is in
088: * write-through mode, all modifications to it will result in
089: * <code>commit</code> being called after the modification.
090: *
091: * @return <code>true</code> if the object is in write-through mode,
092: * <code>false</code> if it's not.
093: */
094: public boolean isWriteThrough();
095:
096: /** Sets the object's write-through mode to the specified status. When
097: * switching the write-through mode on, the <code>commit()</code>
098: * operation will be performed.
099: *
100: * @param writeThrough Boolean value to indicate if the object should be
101: * in write-through mode after the call.
102: */
103: public void setWriteThrough(boolean writeThrough)
104: throws SourceException;
105:
106: /** Tests if the object is in read-through mode. If the object is in
107: * read-through mode, retrieving its value will result in the value
108: * being first updated from the data source to the object. The only
109: * exception to this rule is that when the object is not in
110: * write-through mode and it's buffer contains a modified value, the
111: * value retrieved from the object will be the locally modified value
112: * in the buffer which may differ from the value in the data source.
113: *
114: * @return <code>true</code> if the object is in read-through mode,
115: * <code>false</code> if it's not.
116: */
117: public boolean isReadThrough();
118:
119: /** Sets the object's read-through mode to the specified status. When
120: * switching read-through mode on, the object's value is updated from
121: * the data source.
122: *
123: * @param readThrough Boolean value to indicate if the object should be
124: * in read-through mode after the call.
125: *
126: * @throws SourceException if the operation fails because of an
127: * exception is thrown by the data source. The cause is included in the
128: * exception.
129: */
130: public void setReadThrough(boolean readThrough)
131: throws SourceException;
132:
133: /** Tests if the value stored in the object has been modified since it
134: * was last updated from the data source.
135: *
136: * @return <code>true</code> if the value in the object has been
137: * modified since the last data source update, <code>false</code> if
138: * not.
139: */
140: public boolean isModified();
141:
142: /** An exception that signals that one or more exceptions occurred
143: * while a buffered object tried to access its data source.
144: * @author IT Mill Ltd.
145: * @version 3.1.1
146: * @since 3.0
147: */
148: public class SourceException extends RuntimeException implements
149: ErrorMessage {
150:
151: /**
152: * Serial generated by eclipse.
153: */
154: private static final long serialVersionUID = 3256720671781630518L;
155:
156: /** Source class implementing the buffered interface */
157: private Buffered source;
158:
159: /** Original cause of the source exception */
160: private Throwable[] causes = {};
161:
162: /** Creates a source exception that does not include a cause.
163: *
164: * @param source the source object implementing the Buffered interface.
165: */
166: public SourceException(Buffered source) {
167: this .source = source;
168: }
169:
170: /** Creates a source exception from a cause exception.
171: *
172: * @param source the source object implementing the Buffered
173: * interface.
174: * @param cause the original cause for this exception.
175: */
176: public SourceException(Buffered source, Throwable cause) {
177: this .source = source;
178: causes = new Throwable[] { cause };
179: }
180:
181: /** Creates a source exception from multiplse causes.
182: *
183: * @param source the source object implementing the Buffered
184: * interface.
185: * @param causes the original causes for this exception.
186: */
187: public SourceException(Buffered source, Throwable[] causes) {
188: this .source = source;
189: this .causes = causes;
190: }
191:
192: /** Get the cause of the exception.
193: *
194: * @return The cause for the exception.
195: * @throws MoreThanOneCauseException if there is more than one cause
196: * for the exception. This is possible if the commit operation
197: * triggers more than one error at the same time.
198: */
199: public final Throwable getCause() {
200: if (causes.length == 0)
201: return null;
202: return causes[0];
203: }
204:
205: /** Get all the causes for this exception.
206: *
207: * @return throwables that caused this exception
208: */
209: public final Throwable[] getCauses() {
210: return causes;
211: }
212:
213: /** Get the source of the exception.
214: *
215: * @return the Buffered object which generated this exception.
216: */
217: public Buffered getSource() {
218: return source;
219: }
220:
221: /** Get the error level of this buffered source exception. The
222: * level of the exception is maximum error level of all the contained
223: * causes. The causes that do not specify error level default to
224: * <code>ERROR</code> level. Also source exception without any causes
225: * are of level <code>ERROR</code>.
226: *
227: * @see org.millstone.base.terminal.ErrorMessage#getErrorLevel()
228: */
229: public int getErrorLevel() {
230:
231: int level = Integer.MIN_VALUE;
232:
233: for (int i = 0; i < causes.length; i++) {
234: int causeLevel = (causes[i] instanceof ErrorMessage) ? ((ErrorMessage) causes[i])
235: .getErrorLevel()
236: : ErrorMessage.ERROR;
237: if (causeLevel > level)
238: level = causeLevel;
239: }
240:
241: return level == Integer.MIN_VALUE ? ErrorMessage.ERROR
242: : level;
243: }
244:
245: /* Documented in super interface */
246: public void paint(PaintTarget target) throws PaintException {
247: target.startTag("error");
248: int level = getErrorLevel();
249: if (level > 0 && level <= ErrorMessage.INFORMATION)
250: target.addAttribute("level", "info");
251: else if (level <= ErrorMessage.WARNING)
252: target.addAttribute("level", "warning");
253: else if (level <= ErrorMessage.ERROR)
254: target.addAttribute("level", "error");
255: else if (level <= ErrorMessage.CRITICAL)
256: target.addAttribute("level", "critical");
257: else
258: target.addAttribute("level", "system");
259:
260: // Paint all the exceptions
261: for (int i = 0; i < causes.length; i++) {
262: if (causes[i] instanceof ErrorMessage)
263: ((ErrorMessage) causes[i]).paint(target);
264: else
265: new SystemError(causes[i]).paint(target);
266: }
267:
268: target.endTag("error");
269:
270: }
271:
272: /* Documented in super interface */
273: public void addListener(RepaintRequestListener listener) {
274: }
275:
276: /* Documented in super interface */
277: public void removeListener(RepaintRequestListener listener) {
278: }
279:
280: /* Documented in super interface */
281: public void requestRepaint() {
282: }
283:
284: /* Documented in super interface */
285: public void requestRepaintRequests() {
286: }
287:
288: }
289: }
|