View Javadoc

1   package net.sf.statcvs.pages.xml;
2   
3   import java.util.ArrayList;
4   import java.util.Collections;
5   import java.util.HashMap;
6   import java.util.HashSet;
7   import java.util.Iterator;
8   import java.util.List;
9   import java.util.Set;
10  
11  import net.sf.statcvs.model.Commit;
12  import net.sf.statcvs.model.Revision;
13  import net.sf.statcvs.model.SymbolicName;
14  import net.sf.statcvs.renderer.FileCollectionFormatter;
15  
16  import org.jdom.CDATA;
17  import org.jdom.Element;
18  
19  /**
20   * This is a mere copy of the CommitListFormatter class with dfew minor changes done
21   * Class for formatting a list of commits as XML.
22   *
23   * @author Anja Jentzsch
24   * @author Richard Cyganiak (richard@cyganiak.de)
25   * @version $Id: CommitListXml.java,v 1.4 2008/04/02 11:52:02 benoitx Exp $
26   */
27  public class CommitListXml {
28      private final List commits;
29      private final List tags;
30      private final HashMap commitHashMap = new HashMap();
31  
32      /**
33       * Creates a new instance for the list of commits.
34       * @param commits A list of {@link Commit} objects
35       */
36      public CommitListXml(final List commits, final List tags, final boolean withPermalinks) {
37          this(commits, tags, Integer.MAX_VALUE, withPermalinks);
38      }
39  
40      /**
41       * Creates a new instance for the list of commits.
42       * @param commits A list of {@link Commit} objects
43       * @param max maximum number of commits for the log; if there
44       * are more, only the most recent will be used
45       */
46      public CommitListXml(final List commit, final List tags, final int max, final boolean withPermalinks) {
47          this.commits = new ArrayList(commit);
48          this.tags = tags;
49          Collections.reverse(this.commits);
50      }
51  
52      public Element renderCommitList(final List commitList) {
53          if (commitList.isEmpty()) {
54              return null;
55          }
56          int id = commitList.size();
57          final Element lg = new Element(XmlTags.TAG_COMMIT_LIST);
58          final Iterator commitIt = commitList.iterator();
59          Commit nextCommit = commitIt.hasNext() ? (Commit) commitIt.next() : null;
60          final Iterator tagIt = this.tags.iterator();
61          SymbolicName nextTag = tagIt.hasNext() ? (SymbolicName) tagIt.next() : null;
62          while (nextCommit != null) {
63              Element log = null;
64              if (nextTag == null || nextCommit.getDate().getTime() > nextTag.getDate().getTime()) {
65                  log = renderCommit(nextCommit, id);
66                  nextCommit = commitIt.hasNext() ? (Commit) commitIt.next() : null;
67                  id--;
68              } else {
69                  nextTag = tagIt.hasNext() ? (SymbolicName) tagIt.next() : null;
70              }
71              lg.addContent(log);
72          }
73          return lg;
74      }
75  
76      private Element renderCommit(final Commit commit, final int id) {
77          final Element cmt = new Element(XmlTags.TAG_COMMIT);
78  
79          cmt.setAttribute("date", getDate(commit));
80          cmt.setAttribute("author", getAuthor(commit));
81          cmt.setAttribute("loc_change", getLinesOfCode(commit));
82          final String revision = getRevisionNumber(commit);
83          if (revision != null) {
84              cmt.setAttribute("revision", revision);
85          }
86          final Element comment = new Element(XmlTags.TAG_COMMENT);
87          final CDATA theActualComment = new CDATA(commit.getComment());
88          comment.addContent(theActualComment);
89          cmt.addContent(comment);
90          cmt.addContent(getAffectedFiles(commit));
91  
92          return cmt;
93      }
94  
95      private String getRevisionNumber(final Commit commit) {
96          final Set rev = new HashSet();
97          for (final Iterator it = commit.getRevisions().iterator(); it.hasNext();) {
98              rev.add(((Revision) it.next()).getRevisionNumber());
99          }
100         if (rev.size() == 1) {
101             return (String) rev.iterator().next();
102         } else {
103             return null;
104         }
105     }
106 
107     private String getDate(final Commit commit) {
108         return XML.getDateAndTime(commit.getDate());
109     }
110 
111     private String getAuthor(final Commit commit) {
112         return XML.getAuthorLink(commit.getAuthor());
113     }
114 
115     private String getLinesOfCode(final Commit commit) {
116         final Iterator it = commit.getRevisions().iterator();
117         int locSum = 0;
118         while (it.hasNext()) {
119             final Revision each = (Revision) it.next();
120             locSum += each.getNewLines();
121             saveRevision(each);
122         }
123         return Integer.toString(locSum);
124     }
125 
126     private void saveRevision(final Revision revision) {
127         commitHashMap.put(revision.getFile().getFilenameWithPath(), revision);
128     }
129 
130     private Element getAffectedFiles(final Commit commit) {
131         final Element result = new Element(XmlTags.TAG_FILES_AFFECTED);
132         final FileCollectionFormatter formatter = new FileCollectionFormatter(commit.getAffectedFiles());
133         final Iterator it = formatter.getDirectories().iterator();
134         while (it.hasNext()) {
135             final String directory = (String) it.next();
136             final Iterator files = formatter.getFiles(directory).iterator();
137             final StringBuffer fileList = new StringBuffer();
138             while (files.hasNext()) {
139                 final Element File = new Element(XmlTags.TAG_FILE);
140                 if (fileList.length() > 0) {
141                     fileList.append(",\n");
142                 }
143                 final String file = (String) files.next();
144                 final Element path = new Element(XmlTags.TAG_PATH).setText(directory + file);
145                 File.addContent(path);
146                 final Revision revision = (Revision) commitHashMap.get(directory + file);
147                 if (revision.isInitialRevision()) {
148                     final int linesAdded = revision.getLines();
149                     File.setAttribute("action", "new");
150                     if (linesAdded > 0) {
151                         File.addContent(new Element(XmlTags.TAG_LOC_ADDED).setText(Integer.toString(linesAdded)));
152                     }
153                 } else if (revision.isDead()) {
154                     File.setAttribute("action", "deleted");
155                 } else {
156                     final int delta = revision.getLinesDelta();
157                     final int linesAdded = revision.getReplacedLines() + ((delta > 0) ? delta : 0);
158                     final int linesRemoved = revision.getReplacedLines() - ((delta < 0) ? delta : 0);
159                     if (linesAdded > 0) {
160                         File.setAttribute("action", "changed");
161                         File.addContent(new Element(XmlTags.TAG_LOC_ADDED).setText(Integer.toString(linesAdded)));
162                         if (linesRemoved > 0) {
163                             File.addContent(new Element(XmlTags.TAG_LOC_REMOVED).setText(Integer.toString(linesRemoved)));
164                         }
165                     } else if (linesRemoved > 0) {
166                         File.setAttribute("action", "changed");
167                         File.addContent(new Element(XmlTags.TAG_LOC_ADDED).setText("0"));
168                         File.addContent(new Element(XmlTags.TAG_LOC_REMOVED).setText(Integer.toString(linesRemoved)));
169                     } else { // linesAdded == linesRemoved == 0
170                         // should be binary file or keyword subst change
171                         File.setAttribute("action", "binary file or keyword subst change");
172                     }
173                 }
174                 result.addContent(File);
175             }
176         }
177         return result;
178     }
179 }