/* * ==================================================================== * Copyright (c) 2004-2012 TMate Software Ltd. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://svnkit.com/license.html * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * ==================================================================== */ package org.tmatesoft.svn.core; import java.io.Serializable; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.Map; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.internal.util.SVNDate; /** * The <b>SVNLogEntry</b> class encapsulates such per revision information as: * a revision number, the datestamp when the revision was committed, the author * of the revision, a commit log message and all paths changed in that revision. * * @version 1.3 * @author TMate Software Ltd. * @since 1.2 * @see SVNLogEntryPath * @see ISVNLogEntryHandler * @see <a target="_top" href="http://svnkit.com/kb/examples/">Examples</a> */ public class SVNLogEntry implements Serializable { private static final long serialVersionUID = 4845L; /** * This is a log entry children stop marker use by the <code>SVNKit</code> internals. Users should not * compare the log entry received in their {@link ISVNLogEntryHandler} implementations with this one. * Instead, to find the end of the log entry children sequence they should check the log entry's revision * for validity (i.e. that it is not less than <code>0</code>). * * @since 1.2.0 */ public static SVNLogEntry EMPTY_ENTRY = new SVNLogEntry(Collections.EMPTY_MAP, SVNRepository.INVALID_REVISION, null, false); private long myRevision; private Map myChangedPaths; private SVNProperties myRevisionProperties; private boolean myHasChildren; private boolean myIsSubtractiveMerge; private boolean myIsNonInheritable; /** * Constructs an <b>SVNLogEntry</b> object. * * @param changedPaths a map collection which keys are * all the paths that were changed in * <code>revision</code>, and values are * <b>SVNLogEntryPath</b> representation objects * @param revision a revision number * @param author the author of <code>revision</code> * @param date the datestamp when the revision was committed * @param message an commit log message for <code>revision</code> * @see SVNLogEntryPath */ public SVNLogEntry(Map changedPaths, long revision, String author, Date date, String message) { myRevision = revision; myRevisionProperties = new SVNProperties(); myChangedPaths = changedPaths; if (author != null) { myRevisionProperties.put(SVNRevisionProperty.AUTHOR, author); } if (date != null) { myRevisionProperties.put(SVNRevisionProperty.DATE, SVNDate.formatDate(date)); } if (message != null) { myRevisionProperties.put(SVNRevisionProperty.LOG, message); } } /** * Constructs an <b>SVNLogEntry</b> object. * * @param changedPaths a map collection which keys are * all the paths that were changed in * <code>revision</code>, and values are * <b>SVNLogEntryPath</b> representation objects * @param revision a revision number * @param revisionProperties revision properties * @param hasChildren whether this entry has children or not * @since 1.2.0 */ public SVNLogEntry(Map changedPaths, long revision, SVNProperties revisionProperties, boolean hasChildren) { myRevision = revision; myChangedPaths = changedPaths; myRevisionProperties = revisionProperties != null ? revisionProperties : new SVNProperties(); myHasChildren = hasChildren; } /** * Sets wheteher this log entry has children entries or not. * * <p/> * Note: this method is not intended for API users. * * @param hasChildren whether this entry has has children or not * @see #hasChildren() * @since 1.2.0 */ public void setHasChildren(boolean hasChildren) { myHasChildren = hasChildren; } /** * Gets a map containing all the paths that were changed in the * revision that this object represents. * * @return a <code>String</code> to {@link SVNLogEntryPath} map which keys are all the paths that * were changed in the revision and values represent information about each changed path * */ public Map<String, SVNLogEntryPath> getChangedPaths() { return myChangedPaths; } /** * Returns the author of the revision that this object represents. * * @return the author of the revision */ public String getAuthor() { return myRevisionProperties.getStringValue(SVNRevisionProperty.AUTHOR); } /** * Gets the datestamp when the revision was committed. * * @return the moment in time when the revision was committed */ public Date getDate() { String date = myRevisionProperties.getStringValue(SVNRevisionProperty.DATE); return date == null ? null : SVNDate.parseDate(date); } /** * Gets the log message attached to the revision. * * @return the commit log message */ public String getMessage() { return myRevisionProperties.getStringValue(SVNRevisionProperty.LOG); } /** * Returns the requested revision properties, which may be <span class="javakeyword">null</span> if it * would contain no revision properties. * * @return revision properties * @since 1.2.0 */ public SVNProperties getRevisionProperties() { return myRevisionProperties; } /** * Gets the number of the revision that this object represents. * * @return a revision number */ public long getRevision() { return myRevision; } /** * Calculates and returns a hash code for this object. * * @return a hash code */ public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + (int) (myRevision ^ (myRevision >>> 32)); result = PRIME * result + ((myChangedPaths == null) ? 0 : myChangedPaths.hashCode()); result = PRIME * result + ((myRevisionProperties == null) ? 0 : myRevisionProperties.hashCode()); return result; } /** * Compares this object with another one. * * @param obj an object to compare with * @return <span class="javakeyword">true</span> * if this object is the same as the <code>obj</code> * argument */ public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || getClass() != obj.getClass()) { return false; } SVNLogEntry other = (SVNLogEntry) obj; return myRevision == other.myRevision && compare(myRevisionProperties, other.myRevisionProperties) && compare(myChangedPaths, other.myChangedPaths); } /** * Gives a string representation of this oobject. * * @return a string representing this object */ public String toString() { StringBuffer result = new StringBuffer(); result.append(myRevision); for (Iterator propNames = myRevisionProperties.nameSet().iterator(); propNames.hasNext();) { String propName = (String) propNames.next(); Object propVal = myRevisionProperties.getSVNPropertyValue(propName); result.append('\n'); result.append(propName); result.append('='); result.append(propVal); } if (myChangedPaths != null && !myChangedPaths.isEmpty()) { for (Iterator paths = myChangedPaths.values().iterator(); paths.hasNext();) { result.append('\n'); SVNLogEntryPath path = (SVNLogEntryPath) paths.next(); result.append(path.toString()); } } return result.toString(); } /** * Tells whether or not this log entry has children. * * <p/> * When a log operation requests additional merge information, extra log entries may be returned as a * result of this entry. The new entries, are considered children of the original entry, and will follow it. * When the HAS_CHILDREN flag is set, the receiver should increment its stack * depth, and wait until an entry is provided with {@link SVNRepository#INVALID_REVISION} which * indicates the end of the children. * * <p/> * For log operations which do not request additional merge information, the HAS_CHILDREN flag is always * <span class="javakeyword">false</span>. * * <p/> * Also for more information see: * <a target="_top" href="http://subversion.tigris.org/merge-tracking/design.html#commutative-reporting">Subversion documentation</a> * * @return <span class="javakeyword">true</span> if this log entry has children entries due to * merge-tracking information * @since 1.2.0, new in Subversion 1.5.0 */ public boolean hasChildren() { return myHasChildren; } /** * Compares two objects. * * @param o1 the first object to compare * @param o2 the second object to compare * @return <span class="javakeyword">true</span> if either both * <code>o1</code> and <code>o2</code> are <span class="javakeyword">null</span> * or <code>o1.equals(o2)</code> returns <span class="javakeyword">true</span> */ static boolean compare(Object o1, Object o2) { if (o1 == null) { return o2 == null; } return o1.equals(o2); } public void setSubtractiveMerge(boolean substractiveMerge) { myIsSubtractiveMerge = substractiveMerge; } public boolean isSubtractiveMerge() { return myIsSubtractiveMerge; } public void setNonInheriable(boolean nonInheritable) { myIsNonInheritable = nonInheritable; } public boolean isNonInheritable() { return myIsNonInheritable; } }