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.vfs;
020:
021: import java.util.ArrayList;
022: import java.util.Iterator;
023: import java.util.List;
024:
025: import org.openharmonise.vfs.event.*;
026: import org.openharmonise.vfs.status.*;
027:
028: /**
029: * A versionable virtual file, to go with a versionable virtual file
030: * System.
031: *
032: * @author Matthew Large
033: * @version $Revision: 1.1 $
034: *
035: */
036: public class VersionedVirtualFile extends VirtualFile {
037:
038: /**
039: * Path to the pending version of this virtual file. Null if there is no pending verion.
040: */
041: private String m_sPendingVersionPath = null;
042:
043: /**
044: * List of paths to historical versions of this virtual file.
045: */
046: private ArrayList m_aHistoricalVersionPaths = new ArrayList();
047:
048: /**
049: * true if the list of historical version paths has been populated.
050: */
051: private boolean m_bHistoryPopulated = false;
052:
053: /**
054: * Path to the live version of this virtual file. Null if there is no live version.
055: */
056: private String m_sLiveVersionPath = null;
057:
058: /**
059: * Constructs a Virtual File.
060: *
061: * @param sFullPath FullPath of the file
062: */
063: public VersionedVirtualFile(String sFullPath) {
064: super ();
065: this .setFullPath(sFullPath);
066: this .setVersionable(true);
067: }
068:
069: /**
070: * Checks if the list of paths for historical versions of this virtual
071: * file has been populated.
072: *
073: * @return true if the list of historical paths is populated
074: */
075: public boolean isHistoryPopulated() {
076: return this .m_bHistoryPopulated;
077: }
078:
079: /**
080: * Constructs a Virtual File.
081: */
082: public VersionedVirtualFile() {
083: super ();
084: this .setVersionable(true);
085: }
086:
087: /**
088: * Checks to see if this has a pending version associated to it.
089: * Will return false if this is not a versionable, live VirtualFile.
090: *
091: * @return true if this has a pending version associated to it
092: */
093: public boolean hasPendingVersion() {
094: return this .m_sPendingVersionPath != null;
095: }
096:
097: /**
098: * Gets the path of the pending VirtualFile associated with this one.
099: * Will return null if this is not a versionable, live in VirtualFile.
100: *
101: * @return Checked out VirtualFile, null if there isn't one
102: */
103: public String getPendingVersionPath() {
104: if (this .m_sPendingVersionPath != null) {
105: ((VersionedVirtualFile) this .m_vfs.getVirtualFile(
106: this .m_sPendingVersionPath).getResource())
107: .setLiveVersionPath(this .getFullPath());
108: ((VersionedVirtualFile) this .m_vfs.getVirtualFile(
109: this .m_sPendingVersionPath).getResource())
110: .setState(VirtualFile.STATE_PENDING);
111: }
112: return this .m_sPendingVersionPath;
113: }
114:
115: /**
116: * Sets the path to the pending version of this virtual file.
117: *
118: * @param sPath Full path to the pending version
119: */
120: protected void setPendingVersionPath(String sPath) {
121: this .m_sPendingVersionPath = sPath;
122: }
123:
124: /**
125: * Sets the path to the live version of this virtual file.
126: *
127: * @param sPath Full path to the live version
128: */
129: protected void setLiveVersionPath(String sPath) {
130: this .m_sLiveVersionPath = sPath;
131: }
132:
133: /**
134: * Returns that full path to the live version of this virtual file.
135: *
136: * @return Full path to live version
137: */
138: public String getLiveVersionPath() {
139: return this .m_sLiveVersionPath;
140: }
141:
142: /**
143: * Returns the logical path of this virtual file. If the virtual file
144: * is new or a live version then its own path will be returned. If the
145: * virtual file is a pending or historical version the path of its live
146: * version will be returned.
147: *
148: * @return Full logical path
149: */
150: public String getLogicalPath() {
151: if (this .getState() == VirtualFile.STATE_PENDING) {
152: if (this .getLiveVersionPath() != null) {
153: return this .getLiveVersionPath();
154: } else {
155: return this .getFullPath();
156: }
157: } else if (this .getState() == VirtualFile.STATE_HISTORICAL) {
158: return this .getLiveVersionPath();
159: } else {
160: return this .getFullPath();
161: }
162: }
163:
164: /**
165: * Gets the paths of the historical VirtualFiles associated with this one.
166: * Will return an empty List if this is not a versionable, live in VirtualFile.
167: *
168: * @return List of virtual files that are the historical versions of this one. List will be empty if there are none
169: */
170: public List getHistoricalVersions() {
171: if (!this .m_bHistoryPopulated) {
172: ((AbstractVersioningVFS) this .m_vfs)
173: .fullyPopulateFileHistory(this );
174: }
175: Iterator iterator = this .m_aHistoricalVersionPaths.iterator();
176: while (iterator.hasNext()) {
177: String element = ((String) iterator.next());
178: if (element != null) {
179: VersionedVirtualFile vfHistorical = (VersionedVirtualFile) this .m_vfs
180: .getVirtualFile(element).getResource();
181: vfHistorical.setLiveVersionPath(this .getFullPath());
182: vfHistorical.setState(VirtualFile.STATE_HISTORICAL);
183: }
184: }
185: return (List) this .m_aHistoricalVersionPaths.clone();
186: }
187:
188: /**
189: * Sets that the list of historical versions of this virtual file
190: * has been populated.
191: *
192: * @param bHistoryPopulated true to set that the list of historical versions has been populated
193: */
194: protected void setHistoryPopulated(boolean bHistoryPopulated) {
195: this .m_bHistoryPopulated = bHistoryPopulated;
196: }
197:
198: /**
199: * Adds a path to a historical version.
200: *
201: * @param sPath Path to historical version
202: */
203: protected void addHistoricalVersion(String sPath) {
204: if (!this .m_aHistoricalVersionPaths.contains(sPath)) {
205: this .m_aHistoricalVersionPaths.add(sPath);
206: }
207: }
208:
209: /**
210: * Removes a path to a historical version.
211: *
212: * @param sPath Path to historical version
213: */
214: protected void removeHistoricalVersion(String sPath) {
215: this .m_aHistoricalVersionPaths.remove(sPath);
216: }
217:
218: /**
219: * Makes this VirtualFile the current pending VirtualFile for its associated
220: * live VirtualFile. Will return false if this is not a historical VirtualFile.
221: *
222: * @return true if the method was successful
223: */
224: public StatusData reactivate() {
225: VFSStatus retnStatus = new VFSStatus();
226: retnStatus.setMethodName(VirtualFile.METHOD_CHECKOUT);
227:
228: StatusData vfsStatus = ((AbstractVersioningVFS) this .m_vfs)
229: .reactivateVersion(this .getFullPath());
230: retnStatus.addStatusData(vfsStatus);
231:
232: return retnStatus;
233: }
234:
235: /**
236: * Creates a pending VirtualFile associated to this VirtualFile.
237: * Will return false if this is not a versionable, live in VirtualFile or
238: * if there is already a pending version.
239: *
240: * @return true if the method was successful
241: */
242: public StatusData checkout() {
243: VFSStatus retnStatus = new VFSStatus();
244: retnStatus.setMethodName(VirtualFile.METHOD_CHECKOUT);
245:
246: VirtualFile vfLive = this .m_vfs.getVirtualFile(
247: this .getLiveVersionPath()).getResource();
248: StatusData vfsStatus = ((AbstractVersioningVFS) this .m_vfs)
249: .checkoutVirtualFile(this .getFullPath());
250: retnStatus.addStatusData(vfsStatus);
251: this .m_vfs.getVirtualFile(vfLive.getFilePath()).getResource()
252: .fireVirtualFileEvent(
253: VirtualFileEvent.FILE_MEMBERS_CHANGED);
254:
255: return retnStatus;
256: }
257:
258: /**
259: * Unchecks out this VirtualFile, removing it from the system.
260: * Will return false if this is not a pending VirtualFile.
261: *
262: * @return true if the method was successful
263: */
264: public StatusData uncheckout() {
265: return null;
266: }
267:
268: /**
269: * Checks this VirtualFile back in. Making it the current live VirtualFile.
270: * Will return false if this is not a pending VirtualFile.
271: *
272: * @return true if the method was successful
273: */
274: public StatusData checkin() {
275: VFSStatus retnStatus = new VFSStatus();
276: retnStatus.setMethodName(VirtualFile.METHOD_CHECKIN);
277:
278: VirtualFile vfLogicalFile = null;
279: if (this .getLiveVersionPath() != null) {
280: vfLogicalFile = this .m_vfs.getVirtualFile(
281: this .getLiveVersionPath()).getResource();
282: } else {
283: vfLogicalFile = this ;
284: }
285:
286: StatusData vfsStatus = ((AbstractVersioningVFS) this .m_vfs)
287: .checkinVirtualFile(this .getFullPath());
288: retnStatus.addStatusData(vfsStatus);
289:
290: if (retnStatus.isOK()) {
291: this .fireVirtualFileEvent(VirtualFileEvent.FILE_CHECKED_IN);
292: if (vfLogicalFile != null) {
293: this .setState(VirtualFile.STATE_LIVE);
294: this .m_vfs.getVirtualFile(vfLogicalFile.getFilePath())
295: .getResource().fireVirtualFileEvent(
296: VirtualFileEvent.FILE_MEMBERS_CHANGED);
297: } else {
298: this .setState(VirtualFile.STATE_LIVE);
299: this .m_vfs.getVirtualFile(this .getFilePath())
300: .getResource().fireVirtualFileEvent(
301: VirtualFileEvent.FILE_MEMBERS_CHANGED);
302: }
303: }
304:
305: return retnStatus;
306: }
307:
308: /**
309: * Tags the current version of the file.
310: *
311: * @param sTag Tag to apply to the file
312: */
313: public StatusData tag(String sTag) {
314: VFSStatus retnStatus = new VFSStatus();
315: retnStatus.setMethodName(VirtualFile.METHOD_TAG);
316:
317: StatusData vfsStatus = ((AbstractVersioningVFS) this .m_vfs)
318: .tagVirtualFile(this .getFullPath(), sTag);
319: retnStatus.addStatusData(vfsStatus);
320:
321: return retnStatus;
322: }
323:
324: /**
325: * Deletes this virtual file.
326: *
327: * @return true if the method was successful
328: */
329: public StatusData delete() {
330: VFSStatus retnStatus = new VFSStatus();
331: retnStatus.setMethodName(VirtualFile.METHOD_DELETE);
332:
333: VersionedVirtualFile vfLiveFile = null;
334: VirtualFile vfParent = null;
335: if (this .getState().equals(VirtualFile.STATE_PENDING)
336: && this .m_sLiveVersionPath != null) {
337: vfParent = this .m_vfs.getVirtualFile(
338: this .m_vfs.getVirtualFile(this .m_sLiveVersionPath)
339: .getResource().getFilePath()).getResource();
340: vfLiveFile = (VersionedVirtualFile) this .m_vfs
341: .getVirtualFile(m_sLiveVersionPath).getResource();
342: } else {
343: vfParent = this .m_vfs.getVirtualFile(
344: this .m_vfs.getParentPath(this .getFullPath()))
345: .getResource();
346: }
347:
348: StatusData vfsStatus = this.m_vfs.deleteVirtualFile(this
349: .getFullPath());
350: retnStatus.addStatusData(vfsStatus);
351:
352: if (retnStatus.isOK()) {
353: this.fireVirtualFileEvent(VirtualFileEvent.FILE_DELETED);
354: if (this.getState().equals(VirtualFile.STATE_PENDING)
355: && this.m_sLiveVersionPath != null) {
356: vfLiveFile.setPendingVersionPath(null);
357: }
358: vfParent.removeChild(this.getFullPath());
359: vfParent
360: .fireVirtualFileEvent(VirtualFileEvent.FILE_MEMBERS_CHANGED);
361: }
362:
363: return retnStatus;
364: }
365:
366: }
|