001: /*
002: JSPWiki - a JSP-based WikiWiki clone.
003:
004: Copyright (C) 2001 Janne Jalkanen (Janne.Jalkanen@iki.fi)
005:
006: This program is free software; you can redistribute it and/or modify
007: it under the terms of the GNU Lesser General Public License as published by
008: the Free Software Foundation; either version 2.1 of the License, or
009: (at your option) any later version.
010:
011: This program is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: GNU Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public License
017: along with this program; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020: package com.ecyrd.jspwiki;
021:
022: import java.util.Date;
023: import java.util.HashMap;
024: import java.util.Map;
025:
026: import com.ecyrd.jspwiki.auth.acl.Acl;
027: import com.ecyrd.jspwiki.providers.WikiPageProvider;
028:
029: /**
030: * Simple wrapper class for the Wiki page attributes. The Wiki page
031: * content is moved around in Strings, though.
032: */
033:
034: // FIXME: We need to rethink how metadata is being used - probably the
035: // author, date, etc. should also be part of the metadata. We also
036: // need to figure out the metadata lifecycle.
037: public class WikiPage implements Cloneable, Comparable {
038: private static final long serialVersionUID = 1L;
039:
040: private String m_name;
041: private WikiEngine m_engine;
042: private String m_wiki;
043: private Date m_lastModified;
044: private long m_fileSize = -1;
045: private int m_version = WikiPageProvider.LATEST_VERSION;
046: private String m_author = null;
047: private final HashMap m_attributes = new HashMap();
048:
049: /**
050: * "Summary" is a short summary of the page. It is a String.
051: */
052: public static final String DESCRIPTION = "summary";
053:
054: /** A special variable name for storing a page alias. */
055: public static final String ALIAS = "alias";
056:
057: /** A special variable name for storing a redirect note */
058: public static final String REDIRECT = "redirect";
059:
060: /** A special variable name for storing a changenote. */
061: public static final String CHANGENOTE = "changenote";
062:
063: private Acl m_accessList = null;
064:
065: /**
066: * Create a new WikiPage using a given engine and name.
067: *
068: * @param engine The WikiEngine that owns this page.
069: * @param name The name of the page.
070: */
071: public WikiPage(WikiEngine engine, String name) {
072: m_engine = engine;
073: m_name = name;
074: m_wiki = engine.getApplicationName();
075: }
076:
077: /**
078: * Returns the name of the page.
079: *
080: * @return The page name.
081: */
082: public String getName() {
083: return m_name;
084: }
085:
086: /**
087: * A WikiPage may have a number of attributes, which might or might not be
088: * available. Typically attributes are things that do not need to be stored
089: * with the wiki page to the page repository, but are generated
090: * on-the-fly. A provider is not required to save them, but they
091: * can do that if they really want.
092: *
093: * @param key The key using which the attribute is fetched
094: * @return The attribute. If the attribute has not been set, returns null.
095: */
096: public Object getAttribute(String key) {
097: return m_attributes.get(key);
098: }
099:
100: /**
101: * Sets an metadata attribute.
102: *
103: * @see #getAttribute()
104: * @param key The key for the attribute used to fetch the attribute later on.
105: * @param attribute The attribute value
106: */
107: public void setAttribute(String key, Object attribute) {
108: m_attributes.put(key, attribute);
109: }
110:
111: /**
112: * Returns the full attributes Map, in case external code needs
113: * to iterate through the attributes.
114: *
115: * @return The attribute Map. Please note that this is a direct
116: * reference, not a copy.
117: */
118: public Map getAttributes() {
119: return m_attributes;
120: }
121:
122: /**
123: * Removes an attribute from the page, if it exists.
124: *
125: * @param key The key for the attribute
126: * @return If the attribute existed, returns the object.
127: * @since 2.1.111
128: */
129: public Object removeAttribute(String key) {
130: return m_attributes.remove(key);
131: }
132:
133: /**
134: * Returns the date when this page was last modified.
135: *
136: * @return The last modification date
137: */
138: public Date getLastModified() {
139: return m_lastModified;
140: }
141:
142: /**
143: * Sets the last modification date. In general, this is only
144: * changed by the provider.
145: *
146: * @param date The date
147: */
148: public void setLastModified(Date date) {
149: m_lastModified = date;
150: }
151:
152: /**
153: * Sets the page version. In general, this is only changed
154: * by the provider.
155: *
156: * @param version The version number
157: */
158: public void setVersion(int version) {
159: m_version = version;
160: }
161:
162: /**
163: * Returns the version that this WikiPage instance represents.
164: *
165: * @return the version number of this page.
166: */
167: public int getVersion() {
168: return m_version;
169: }
170:
171: /**
172: * Returns the size of the page.
173: *
174: * @return the size of the page.
175: * @since 2.1.109
176: */
177: public long getSize() {
178: return m_fileSize;
179: }
180:
181: /**
182: * Sets the size. Typically called by the provider only.
183: *
184: * @param size The size of the page.
185: * @since 2.1.109
186: */
187: public void setSize(long size) {
188: m_fileSize = size;
189: }
190:
191: /**
192: * Returns the Acl for this page. May return <code>null</code>,
193: * in case there is no Acl defined, or it has not
194: * yet been set by {@link #setAcl(Acl)}.
195: *
196: * @return The access control list. May return null, if there is
197: * no acl.
198: */
199: public Acl getAcl() {
200: return m_accessList;
201: }
202:
203: /**
204: * Sets the Acl for this page. Note that method does <em>not</em>
205: * persist the Acl itself to back-end storage or in page markup;
206: * it merely sets the internal field that stores the Acl. To
207: * persist the Acl, callers should invoke
208: * {@link com.ecyrd.jspwiki.auth.acl.AclManager#setPermissions(WikiPage, Acl)}.
209: * @param acl The Acl to set
210: */
211: public void setAcl(Acl acl) {
212: m_accessList = acl;
213: }
214:
215: /**
216: * Sets the author of the page. Typically called only by the provider.
217: *
218: * @param author The author name.
219: */
220: public void setAuthor(String author) {
221: m_author = author;
222: }
223:
224: /**
225: * Returns author name, or null, if no author has been defined.
226: *
227: * @return Author name, or possibly null.
228: */
229: public String getAuthor() {
230: return m_author;
231: }
232:
233: /**
234: * Returns the wiki nanme for this page
235: *
236: * @return The name of the wiki.
237: */
238: public String getWiki() {
239: return m_wiki;
240: }
241:
242: /**
243: * This method will remove all metadata from the page.
244: */
245: public void invalidateMetadata() {
246: m_hasMetadata = false;
247: setAcl(null);
248: m_attributes.clear();
249: }
250:
251: private boolean m_hasMetadata = false;
252:
253: /**
254: * Returns <code>true</code> if the page has valid metadata; that is, it has been parsed.
255: * Note that this method is a kludge to support our pre-3.0 metadata system, and as such
256: * will go away with the new API.
257: *
258: * @return true, if the page has metadata.
259: */
260: public boolean hasMetadata() {
261: return m_hasMetadata;
262: }
263:
264: /**
265: * Sets the metadata flag to true. Never call.
266: */
267: public void setHasMetadata() {
268: m_hasMetadata = true;
269: }
270:
271: /**
272: * Returns a debug-suitable version of the page.
273: *
274: * @return A debug string.
275: */
276: public String toString() {
277: return "WikiPage [" + m_wiki + ":" + m_name + ",ver="
278: + m_version + ",mod=" + m_lastModified + "]";
279: }
280:
281: /**
282: * Creates a deep clone of a WikiPage. Strings are not cloned, since
283: * they're immutable. Attributes are not cloned, only the internal
284: * HashMap (so if you modify the contents of a value of an attribute,
285: * these will reflect back to everyone).
286: *
287: * @return A deep clone of the WikiPage
288: */
289: public Object clone() {
290: try {
291: WikiPage p = (WikiPage) super .clone();
292:
293: p.m_engine = m_engine;
294: p.m_name = m_name;
295: p.m_wiki = m_wiki;
296:
297: p.m_author = m_author;
298: p.m_version = m_version;
299: p.m_lastModified = m_lastModified != null ? (Date) m_lastModified
300: .clone()
301: : null;
302:
303: p.m_fileSize = m_fileSize;
304:
305: p.m_attributes.putAll(m_attributes);
306:
307: return p;
308: } catch (CloneNotSupportedException e) {
309: }
310:
311: return null;
312: }
313:
314: /**
315: * Compares a page with another. The primary sorting order
316: * is according to page name, and if they have the same name,
317: * then according to the page version.
318: *
319: * @param o The object to compare against
320: * @return -1, 0 or 1
321: */
322: public int compareTo(Object o) {
323: int res = 0;
324: if (o instanceof WikiPage) {
325: WikiPage c = (WikiPage) o;
326:
327: res = this .getName().compareTo(c.getName());
328:
329: if (res == 0)
330: res = this .getVersion() - c.getVersion();
331: }
332:
333: return res;
334: }
335:
336: /**
337: * A page is equal to another page if its name and version are equal.
338: *
339: * {@inheritDoc}
340: */
341: public boolean equals(Object o) {
342: if (o != null && o instanceof WikiPage) {
343: WikiPage oo = (WikiPage) o;
344:
345: if (oo.getName().equals(getName())) {
346: if (oo.getVersion() == getVersion()) {
347: return true;
348: }
349: }
350: }
351:
352: return false;
353: }
354:
355: /**
356: * {@inheritDoc}
357: */
358: public int hashCode() {
359: return m_name.hashCode() * m_version;
360: }
361: }
|