diff src/org/tmatesoft/hg/internal/ChangelogEntryBuilder.java @ 618:7c0d2ce340b8

Refactor approach how content finds it way down to a commit revision
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 16 May 2013 19:46:13 +0200
parents dd4f6311af52
children 4e6179bde4fc
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/internal/ChangelogEntryBuilder.java	Wed May 15 20:10:09 2013 +0200
+++ b/src/org/tmatesoft/hg/internal/ChangelogEntryBuilder.java	Thu May 16 19:46:13 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 TMate Software Ltd
+ * Copyright (c) 2012-2013 TMate Software Ltd
  *  
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -16,6 +16,7 @@
  */
 package org.tmatesoft.hg.internal;
 
+import java.io.ByteArrayOutputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -23,24 +24,28 @@
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.TimeZone;
 import java.util.Map.Entry;
+import java.util.TimeZone;
 
+import org.tmatesoft.hg.core.HgIOException;
 import org.tmatesoft.hg.core.Nodeid;
+import org.tmatesoft.hg.internal.DataSerializer.DataSource;
 import org.tmatesoft.hg.util.Path;
 
 /**
- *
+ * Builds changelog entry
  * @author Artem Tikhomirov
  * @author TMate Software Ltd.
  */
-public class ChangelogEntryBuilder {
+public class ChangelogEntryBuilder implements DataSource {
 
 	private String user;
 	private List<Path> modifiedFiles;
 	private final Map<String, String> extrasMap = new LinkedHashMap<String, String>();
 	private Integer tzOffset;
 	private Long csetTime;
+	private Nodeid manifestRev;
+	private CharSequence comment;
 	
 	public ChangelogEntryBuilder user(String username) {
 		user = username;
@@ -89,6 +94,89 @@
 		return this;
 	}
 	
+	public ChangelogEntryBuilder manifest(Nodeid manifestRevision) {
+		manifestRev = manifestRevision;
+		return this;
+	}
+	
+	public ChangelogEntryBuilder comment(CharSequence commentString) {
+		comment = commentString;
+		return this;
+	}
+
+	public void serialize(DataSerializer out) throws HgIOException {
+		byte[] b = build();
+		out.write(b, 0, b.length);
+	}
+
+	public int serializeLength() {
+		return -1;
+	}
+
+	public byte[] build() {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		final int LF = '\n';
+		CharSequence extras = buildExtras();
+		CharSequence files = buildFiles();
+		byte[] manifestRevision = manifestRev.toString().getBytes();
+		byte[] username = user().getBytes(EncodingHelper.getUTF8());
+		out.write(manifestRevision, 0, manifestRevision.length);
+		out.write(LF);
+		out.write(username, 0, username.length);
+		out.write(LF);
+		final long csetDate = csetTime();
+		byte[] date = String.format("%d %d", csetDate, csetTimezone(csetDate)).getBytes();
+		out.write(date, 0, date.length);
+		if (extras.length() > 0) {
+			out.write(' ');
+			byte[] b = extras.toString().getBytes();
+			out.write(b, 0, b.length);
+		}
+		out.write(LF);
+		byte[] b = files.toString().getBytes();
+		out.write(b, 0, b.length);
+		out.write(LF);
+		out.write(LF);
+		byte[] cmt = comment.toString().getBytes(EncodingHelper.getUTF8());
+		out.write(cmt, 0, cmt.length);
+		return out.toByteArray();
+	}
+
+	private CharSequence buildExtras() {
+		StringBuilder extras = new StringBuilder();
+		for (Iterator<Entry<String, String>> it = extrasMap.entrySet().iterator(); it.hasNext();) {
+			final Entry<String, String> next = it.next();
+			extras.append(encodeExtrasPair(next.getKey()));
+			extras.append(':');
+			extras.append(encodeExtrasPair(next.getValue()));
+			if (it.hasNext()) {
+				extras.append('\00');
+			}
+		}
+		return extras;
+	}
+
+	private CharSequence buildFiles() {
+		StringBuilder files = new StringBuilder();
+		if (modifiedFiles != null) {
+			Collections.sort(modifiedFiles);
+			for (Iterator<Path> it = modifiedFiles.iterator(); it.hasNext(); ) {
+				files.append(it.next());
+				if (it.hasNext()) {
+					files.append('\n');
+				}
+			}
+		}
+		return files;
+	}
+
+	private final static CharSequence encodeExtrasPair(String s) {
+		if (s != null) {
+			return s.replace("\\", "\\\\").replace("\n", "\\n").replace("\r", "\\r").replace("\00", "\\0");
+		}
+		return s;
+	}
+
 	private long csetTime() {
 		if (csetTime != null) { 
 			return csetTime;
@@ -102,37 +190,4 @@
 		}
 		return -(TimeZone.getDefault().getOffset(time) / 1000);
 	}
-
-	public byte[] build(Nodeid manifestRevision, String comment) {
-		String f = "%s\n%s\n%d %d %s\n%s\n\n%s";
-		StringBuilder extras = new StringBuilder();
-		for (Iterator<Entry<String, String>> it = extrasMap.entrySet().iterator(); it.hasNext();) {
-			final Entry<String, String> next = it.next();
-			extras.append(encodeExtrasPair(next.getKey()));
-			extras.append(':');
-			extras.append(encodeExtrasPair(next.getValue()));
-			if (it.hasNext()) {
-				extras.append('\00');
-			}
-		}
-		StringBuilder files = new StringBuilder();
-		if (modifiedFiles != null) {
-			for (Iterator<Path> it = modifiedFiles.iterator(); it.hasNext(); ) {
-				files.append(it.next());
-				if (it.hasNext()) {
-					files.append('\n');
-				}
-			}
-		}
-		final long date = csetTime();
-		final int tz = csetTimezone(date);
-		return String.format(f, manifestRevision.toString(), user(), date, tz, extras, files, comment).getBytes();
-	}
-
-	private final static CharSequence encodeExtrasPair(String s) {
-		if (s != null) {
-			return s.replace("\\", "\\\\").replace("\n", "\\n").replace("\r", "\\r").replace("\00", "\\0");
-		}
-		return s;
-	}
 }