001: /**
002: * @copyright
003: * ====================================================================
004: * Copyright (c) 2003-2005 CollabNet. All rights reserved.
005: *
006: * This software is licensed as described in the file COPYING, which
007: * you should have received as part of this distribution. The terms
008: * are also available at http://subversion.tigris.org/license-1.html.
009: * If newer versions of this license are posted there, you may use a
010: * newer version instead, at your option.
011: *
012: * This software consists of voluntary contributions made by many
013: * individuals. For exact contribution history, see the revision
014: * history and logs, available at http://subversion.tigris.org/.
015: * ====================================================================
016: * @endcopyright
017: */package org.tigris.subversion.javahl;
018:
019: import java.util.Date;
020:
021: /**
022: * Subversion status API.
023: * This describes the status of one subversion item (file or directory) in
024: * the working copy. Will be returned by SVNClient.status or
025: * SVNClient.singleStatus
026: * @author Patrick Mayweg
027: * @author Cédric Chabanois
028: * <a href="mailto:cchabanois@ifrance.com">cchabanois@ifrance.com</a>
029: */
030: public class Status {
031: /**
032: * the url for accessing the item
033: */
034: private String url;
035: /**
036: * the path in the working copy
037: */
038: private String path;
039: /**
040: * kind of the item (file, directory or unknonw)
041: */
042: private int nodeKind;
043: /**
044: * the base revision of the working copy
045: */
046: private long revision;
047: /**
048: * the last revision the item was changed before base
049: */
050: private long lastChangedRevision;
051: /**
052: * the last date the item was changed before base (represented in
053: * microseconds since the epoch)
054: */
055: private long lastChangedDate;
056: /**
057: * the last author of the last change before base
058: */
059: private String lastCommitAuthor;
060: /**
061: * the file or directory status (See StatusKind)
062: */
063: private int textStatus;
064: /**
065: * the status of the properties (See StatusKind)
066: */
067: private int propStatus;
068: /**
069: * flag is this item is locked locally by subversion
070: * (running or aborted operation)
071: */
072: private boolean locked;
073: /**
074: * has this item be copied from another item
075: */
076: private boolean copied;
077: /**
078: * has the url of the item be switch
079: */
080: private boolean switched;
081: /**
082: * the file or directory status of base (See StatusKind)
083: */
084: private int repositoryTextStatus;
085: /**
086: * the status of the properties base (See StatusKind)
087: */
088: private int repositoryPropStatus;
089: /**
090: * if there is a conflict, the filename of the new version
091: * from the repository
092: */
093: private String conflictNew;
094: /**
095: * if there is a conflict, the filename of the common base version
096: * from the repository
097: */
098: private String conflictOld;
099: /**
100: * if there is a conflict, the filename of the former working copy
101: * version
102: */
103: private String conflictWorking;
104: /**
105: * if copied, the url of the copy source
106: */
107: private String urlCopiedFrom;
108: /**
109: * if copied, the revision number of the copy source
110: */
111: private long revisionCopiedFrom;
112: /**
113: * @since 1.2
114: * token specified for the lock (null if not locked)
115: */
116: private String lockToken;
117: /**
118: * @since 1.2
119: * owner of the lock (null if not locked)
120: */
121: private String lockOwner;
122: /**
123: * @since 1.2
124: * comment specified for the lock (null if not locked)
125: */
126: private String lockComment;
127: /**
128: * @since 1.2
129: * date of the creation of the lock (represented in microseconds
130: * since the epoch)
131: */
132: private long lockCreationDate;
133: /**
134: * @since 1.2
135: * the lock in the repository
136: */
137: private Lock reposLock;
138: /**
139: * @since 1.3
140: * Set to the youngest committed revision, or {@link
141: * Revision#SVN_INVALID_REVNUM} if not out of date.
142: */
143: private long reposLastCmtRevision = Revision.SVN_INVALID_REVNUM;
144: /**
145: * @since 1.3
146: * Set to the most recent commit date, or 0 if not out of date.
147: */
148: private long reposLastCmtDate = 0;
149: /**
150: * @since 1.3
151: * Set to the node kind of the youngest commit, or {@link
152: * NodeKind#none} if not out of date.
153: */
154: private int reposKind = NodeKind.none;
155: /**
156: * @since 1.3
157: * Set to the user name of the youngest commit, or
158: * <code>null</code> if not out of date.
159: */
160: private String reposLastCmtAuthor;
161:
162: /**
163: * this constructor should only called from JNI code
164: * @param path the file system path of item
165: * @param url the url of the item
166: * @param nodeKind kind of item (directory, file or unknown
167: * @param revision the revision number of the base
168: * @param lastChangedRevision the last revision this item was changed
169: * @param lastChangedDate the last date this item was changed
170: * @param lastCommitAuthor the author of the last change
171: * @param textStatus the file or directory status (See
172: * StatusKind)
173: * @param propStatus the property status (See StatusKind)
174: * @param repositoryTextStatus the file or directory status of the base
175: * @param repositoryPropStatus the property status of the base
176: * @param locked if the item is locked (running or aborted
177: * operation)
178: * @param copied if the item is copy
179: * @param conflictOld in case of conflict, the file name of the
180: * the common base version
181: * @param conflictNew in case of conflict, the file name of new
182: * repository version
183: * @param conflictWorking in case of conflict, the file name of the
184: * former working copy version
185: * @param urlCopiedFrom if copied, the url of the copy source
186: * @param revisionCopiedFrom if copied, the revision number of the copy
187: * source
188: * @param switched flag if the node has been switched in the
189: * path
190: * @param lockToken the token for the current lock if any
191: * @param lockOwner the owner of the current lock is any
192: * @param lockComment the comment of the current lock if any
193: * @param lockCreationDate the date, the lock was created if any
194: * @param reposLock the lock as stored in the repository if
195: * any
196: * @param reposLastCmtRevision the youngest revision, if out of date
197: * @param reposLastCmtDate the last commit date, if out of date
198: * @param reposKind the kind of the youngest revision, if
199: * out of date
200: * @param reposLastCmtAuthor the author of the last commit, if out of
201: * date
202: */
203: public Status(String path, String url, int nodeKind, long revision,
204: long lastChangedRevision, long lastChangedDate,
205: String lastCommitAuthor, int textStatus, int propStatus,
206: int repositoryTextStatus, int repositoryPropStatus,
207: boolean locked, boolean copied, String conflictOld,
208: String conflictNew, String conflictWorking,
209: String urlCopiedFrom, long revisionCopiedFrom,
210: boolean switched, String lockToken, String lockOwner,
211: String lockComment, long lockCreationDate, Lock reposLock,
212: long reposLastCmtRevision, long reposLastCmtDate,
213: int reposKind, String reposLastCmtAuthor) {
214: this .path = path;
215: this .url = url;
216: this .nodeKind = nodeKind;
217: this .revision = revision;
218: this .lastChangedRevision = lastChangedRevision;
219: this .lastChangedDate = lastChangedDate;
220: this .lastCommitAuthor = lastCommitAuthor;
221: this .textStatus = textStatus;
222: this .propStatus = propStatus;
223: this .locked = locked;
224: this .copied = copied;
225: this .repositoryTextStatus = repositoryTextStatus;
226: this .repositoryPropStatus = repositoryPropStatus;
227: this .conflictOld = conflictOld;
228: this .conflictNew = conflictNew;
229: this .conflictWorking = conflictWorking;
230: this .urlCopiedFrom = urlCopiedFrom;
231: this .revisionCopiedFrom = revisionCopiedFrom;
232: this .switched = switched;
233: this .lockToken = lockToken;
234: this .lockOwner = lockOwner;
235: this .lockComment = lockComment;
236: this .lockCreationDate = lockCreationDate;
237: this .reposLock = reposLock;
238: this .reposLastCmtRevision = reposLastCmtRevision;
239: this .reposLastCmtDate = reposLastCmtDate;
240: this .reposKind = reposKind;
241: this .reposLastCmtAuthor = reposLastCmtAuthor;
242: }
243:
244: /**
245: * Returns the file system path of the item
246: * @return path of status entry
247: */
248: public String getPath() {
249: return path;
250: }
251:
252: /**
253: * Returns the revision as a Revision object
254: * @return revision if versioned, otherwise SVN_INVALID_REVNUM
255: */
256: public Revision.Number getRevision() {
257: return Revision.createNumber(revision);
258: }
259:
260: /**
261: * Returns the revision as a long integer
262: * @return revision if versioned, otherwise SVN_INVALID_REVNUM
263: */
264: public long getRevisionNumber() {
265: return revision;
266: }
267:
268: /**
269: * Returns the last date the item was changed or null
270: * @return the last time the item was changed.
271: * or null if not available
272: */
273: public Date getLastChangedDate() {
274: return microsecondsToDate(lastChangedDate);
275: }
276:
277: /**
278: * Returns the author of the last changed or null
279: * @return name of author if versioned, null otherwise
280: */
281: public String getLastCommitAuthor() {
282: return lastCommitAuthor;
283: }
284:
285: /**
286: * Returns the status of the item (See StatusKind)
287: * @return file status property enum of the "textual" component.
288: */
289: public int getTextStatus() {
290: return textStatus;
291: }
292:
293: /**
294: * Returns the status of the item as text.
295: * @return english text
296: */
297: public String getTextStatusDescription() {
298: return Kind.getDescription(textStatus);
299: }
300:
301: /**
302: * Returns the status of the properties (See Status Kind)
303: * @return file status property enum of the "property" component.
304: */
305: public int getPropStatus() {
306: return propStatus;
307: }
308:
309: /**
310: * Returns the status of the properties as text
311: * @return english text
312: */
313: public String getPropStatusDescription() {
314: return Kind.getDescription(propStatus);
315: }
316:
317: /**
318: * Returns the status of the item in the repository (See StatusKind)
319: * @return file status property enum of the "textual" component in the
320: * repository.
321: */
322: public int getRepositoryTextStatus() {
323: return repositoryTextStatus;
324: }
325:
326: /**
327: * Returns test status of the properties in the repository (See StatusKind)
328: * @return file status property enum of the "property" component im the
329: * repository.
330: */
331: public int getRepositoryPropStatus() {
332: return repositoryPropStatus;
333: }
334:
335: /**
336: * Returns if the item is locked (running or aborted subversion operation)
337: * @return true if locked
338: */
339: public boolean isLocked() {
340: return locked;
341: }
342:
343: /**
344: * Returns if the item has been copied
345: * @return true if copied
346: */
347: public boolean isCopied() {
348: return copied;
349: }
350:
351: /**
352: * Returns in case of conflict, the filename of the most recent repository
353: * version
354: * @return the filename of the most recent repository version
355: */
356: public String getConflictNew() {
357: return conflictNew;
358: }
359:
360: /**
361: * Returns in case of conflict, the filename of the common base version
362: * @return the filename of the common base version
363: */
364: public String getConflictOld() {
365: return conflictOld;
366: }
367:
368: /**
369: * Returns in case of conflict, the filename of the former working copy
370: * version
371: * @return the filename of the former working copy version
372: */
373: public String getConflictWorking() {
374: return conflictWorking;
375: }
376:
377: /**
378: * Returns the URI to where the item might exist in the
379: * repository. We say "might" because the item might exist in
380: * your working copy, but have been deleted from the repository.
381: * Or it might exist in the repository, but your working copy
382: * might not yet contain it (because the WC is not up to date).
383: * @return URI in repository, or <code>null</code> if the item
384: * exists in neither the repository nor the WC.
385: */
386: public String getUrl() {
387: return url;
388: }
389:
390: /**
391: * Returns the last revision the file was changed as a Revision object
392: * @return last changed revision
393: */
394: public Revision.Number getLastChangedRevision() {
395: return Revision.createNumber(lastChangedRevision);
396: }
397:
398: /**
399: * Returns the last revision the file was changed as a long integer
400: * @return last changed revision
401: */
402: public long getLastChangedRevisionNumber() {
403: return lastChangedRevision;
404: }
405:
406: /**
407: * Returns the kind of the node (file, directory or unknown, see NodeKind)
408: * @return the node kind
409: */
410: public int getNodeKind() {
411: return nodeKind;
412: }
413:
414: /**
415: * Returns if copied the copy source url or null
416: * @return the source url
417: */
418: public String getUrlCopiedFrom() {
419: return urlCopiedFrom;
420: }
421:
422: /**
423: * Returns if copied the source revision as a Revision object
424: * @return the source revision
425: */
426: public Revision.Number getRevisionCopiedFrom() {
427: return Revision.createNumber(revisionCopiedFrom);
428: }
429:
430: /**
431: * Returns if copied the source revision as s long integer
432: * @return the source revision
433: */
434: public long getRevisionCopiedFromNumber() {
435: return revisionCopiedFrom;
436: }
437:
438: /**
439: * Returns if the repository url has been switched
440: * @return is the item has been switched
441: */
442: public boolean isSwitched() {
443: return switched;
444: }
445:
446: /**
447: * Returns if is managed by svn (added, normal, modified ...)
448: * @return if managed by svn
449: */
450: public boolean isManaged() {
451: int status = getTextStatus();
452: return (status != Status.Kind.unversioned
453: && status != Status.Kind.none && status != Status.Kind.ignored);
454: }
455:
456: /**
457: * Returns if the resource has a remote counter-part
458: * @return has version in repository
459: */
460: public boolean hasRemote() {
461: return (isManaged() && getTextStatus() != Status.Kind.added);
462: }
463:
464: /**
465: * Returns if the resource just has been added
466: * @return if added
467: */
468: public boolean isAdded() {
469: return getTextStatus() == Status.Kind.added;
470: }
471:
472: /**
473: * Returns if the resource is schedules for delete
474: * @return if deleted
475: */
476: public boolean isDeleted() {
477: return getTextStatus() == Status.Kind.deleted;
478: }
479:
480: /**
481: * Returns if the resource has been merged
482: * @return if merged
483: */
484: public boolean isMerged() {
485: return getTextStatus() == Status.Kind.merged;
486: }
487:
488: /**
489: * Returns if the resource is ignored by svn (only returned if noIgnore
490: * is set on SVNClient.list)
491: * @return if ignore
492: */
493: public boolean isIgnored() {
494: return getTextStatus() == Status.Kind.ignored;
495: }
496:
497: /**
498: * Returns if the resource itself is modified
499: * @return if modified
500: */
501: public boolean isModified() {
502: return getTextStatus() == Status.Kind.modified;
503: }
504:
505: /**
506: * Returns the lock token
507: * @return the lock token
508: * @since 1.2
509: */
510: public String getLockToken() {
511: return lockToken;
512: }
513:
514: /**
515: * Returns the lock owner
516: * @return the lock owner
517: * @since 1.2
518: */
519: public String getLockOwner() {
520: return lockOwner;
521: }
522:
523: /**
524: * Returns the lock comment
525: * @return the lock comment
526: * @since 1.2
527: */
528: public String getLockComment() {
529: return lockComment;
530: }
531:
532: /**
533: * Returns the lock creation date
534: * @return the lock creation date
535: * @since 1.2
536: */
537: public Date getLockCreationDate() {
538: return microsecondsToDate(lockCreationDate);
539: }
540:
541: /**
542: * Returns the lock as in the repository
543: * @return the lock as in the repository
544: * @since 1.2
545: */
546: public Lock getReposLock() {
547: return reposLock;
548: }
549:
550: /**
551: * @return The last committed revision, or {@link
552: * Revision#SVN_INVALID_REVNUM} if up to date.
553: * @since 1.3
554: */
555: public Revision.Number getReposLastCmtRevision() {
556: return Revision.createNumber(reposLastCmtRevision);
557: }
558:
559: /**
560: * @return The last committed revision as a long integer, or
561: * <code>-1</code> if up to date.
562: * @since 1.3
563: */
564: public long getReposLastCmtRevisionNumber() {
565: return reposLastCmtRevision;
566: }
567:
568: /**
569: * @return The last committed date, or <code>null</code> if up to
570: * date.
571: * @since 1.3
572: */
573: public Date getReposLastCmtDate() {
574: return microsecondsToDate(reposLastCmtDate);
575: }
576:
577: /**
578: * @return The node kind (e.g. file, directory, etc.), or
579: * <code>null</code> if up to date.
580: * @since 1.3
581: */
582: public int getReposKind() {
583: return reposKind;
584: }
585:
586: /**
587: * @return The author of the last commit, or <code>null</code> if
588: * up to date.
589: * @since 1.3
590: */
591: public String getReposLastCmtAuthor() {
592: return reposLastCmtAuthor;
593: }
594:
595: /**
596: * class for kind status of the item or its properties
597: * the constants are defined in the interface StatusKind for building
598: * reasons
599: */
600: public static final class Kind implements StatusKind {
601: /**
602: * Returns the textual representation of the status
603: * @param kind of status
604: * @return english status
605: */
606: public static final String getDescription(int kind) {
607: switch (kind) {
608: case StatusKind.none:
609: return "non-svn";
610: case StatusKind.normal:
611: return "normal";
612: case StatusKind.added:
613: return "added";
614: case StatusKind.missing:
615: return "missing";
616: case StatusKind.deleted:
617: return "deleted";
618: case StatusKind.replaced:
619: return "replaced";
620: case StatusKind.modified:
621: return "modified";
622: case StatusKind.merged:
623: return "merged";
624: case StatusKind.conflicted:
625: return "conflicted";
626: case StatusKind.ignored:
627: return "ignored";
628: case StatusKind.incomplete:
629: return "incomplete";
630: case StatusKind.external:
631: return "external";
632: case StatusKind.unversioned:
633: default:
634: return "unversioned";
635: }
636: }
637: }
638:
639: /**
640: * Converts microseconds since the epoch to a Date object.
641: *
642: * @param micros Microseconds since the epoch.
643: * @return A Date object, or <code>null</code> if
644: * <code>micros</code> was zero.
645: */
646: private static Date microsecondsToDate(long micros) {
647: return (micros == 0 ? null : new Date(micros / 1000));
648: }
649: }
|