Dokuwiki - Improve links with collision handling, Instiki - New converter module
diff --git a/conf/converter.instiki.properties b/conf/converter.instiki.properties
new file mode 100644
index 0000000..8fccd06
--- /dev/null
+++ b/conf/converter.instiki.properties
@@ -0,0 +1,5 @@
+## NOTE: Intended to works with xhtml export

+# Don't allow the engine to run the transformation - we already have xhtml

+Instiki.0002.engine-markuptoxhtml.property=false

+Instiki.0100.justbody.java-regex=^(?s)(?:.*?)<body>(.*?)</body>.*${replace-with}$1

+Instiki.0200.title.class=com.atlassian.uwc.converters.instiki.TitleConverter

diff --git a/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverter.java b/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverter.java
index e8accdb..e1e06c3 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverter.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverter.java
@@ -89,7 +89,7 @@
 					target = target.replaceFirst("^.*:", ""); //remove everything to the last colon
 				else //title was set with metadata
 					target = metatitle;
-				target = HierarchyTitleConverter.casify(target); //foo_bar becomes Foo Bar
+				target = HierarchyTitleConverter.fixTitle(target); //foo_bar becomes Foo Bar
 				//fix collisions
 				String linkSpacekey = currentSpacekey;
 				targetPart1 = targetPart1.replaceAll(":", File.separator);
@@ -98,7 +98,7 @@
 					linkSpacekey = namespaces.get(targetPart1); 
 				}
 				if (containsSpace) linkSpacekey = targetPart1;
-//				target = fixCollisions(target, hierarchy, linkSpacekey);//collisions handling has to happen elsewhere?
+				target = fixCollisions(target, hierarchy, linkSpacekey, metaFilename);
 				//underscores to spaces
 				target = target.replaceAll("_", " ");
 				log.debug("link target = " + target);
@@ -122,7 +122,6 @@
 	}
 	
 	
-	Pattern metaFile = Pattern.compile("([\\\\/])([^\\\\/]+)(\\.meta)$");
 	protected String getTargetMetaFilename(String target, String metaFilename, boolean isOne) {
 		target=target.replaceAll(":+", File.separator);
 		if (!target.startsWith(File.separator)) target = File.separator + target;
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverterTest.java b/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverterTest.java
index 79fc7e7..bdb30fb 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverterTest.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverterTest.java
@@ -65,8 +65,8 @@
 				"[food:Water]\n" + 
 				"[Food|food:Start]\n" + 
 				"[food:Baklava]\n" + 
-				"[food:Fruit]\n" + 
-				"[food:Fruit Apple]\n" + 
+				"[food:Food Fruit]\n" + 
+				"[food:Food Fruit Apple]\n" + 
 				"[food:Pie]\n" + 
 				"[food:Pie Apple]\n" + 
 				"[food:Pie Fruit]\n" + 
@@ -154,11 +154,17 @@
 		assertEquals(expected, actual);
 	}
 	
-	public void testConvertWithAnotherSpacekey() {
-		fail();
-	}
-	
 	public void testConvertWithCollision() {
-		fail();
+		tester.getProperties().setProperty("collision-titles-xyz", "Harumph BAr");
+		String input, expected, actual;
+		input = "[[.:foo]]\n" +
+				"[[:foo:bar]]\n";
+		expected = "[xyz:Foo Tralala]\n" +
+				"[xyz:Foo Tralala Harumph BAr]\n";
+		tester.getProperties().setProperty("filepath-hierarchy-ignorable-ancestors", "/Users/laura/Code/Git/uwc/sampleData/dokuwiki/junit_resources/pages");
+		String pretendthispagepath = "/Users/laura/Code/Git/uwc/sampleData/dokuwiki/junit_resources/pages/test.txt";
+		actual = tester.convertLink(input, "", "xyz", pretendthispagepath);
+		assertNotNull(actual);
+		assertEquals(expected, actual);
 	}
 }
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/HierarchyTarget.java b/src/com/atlassian/uwc/converters/dokuwiki/HierarchyTarget.java
index 5ceecfb..e96631b 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/HierarchyTarget.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/HierarchyTarget.java
@@ -8,11 +8,17 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.log4j.Logger;
+
 import com.atlassian.uwc.converters.BaseConverter;
 import com.atlassian.uwc.ui.Page;
 
 public abstract class HierarchyTarget extends BaseConverter {
 	Pattern space = Pattern.compile("space-([^-]*)");
+	protected Pattern metaFile = Pattern.compile("([\\\\/])([^\\\\/]+)(\\.meta)$");
+	
+	Logger log = Logger.getLogger(this.getClass());
+	
 	protected Vector<String> getSpaces() {
 		Properties props = getProperties();
 		Vector<String> spaces = new Vector<String>();
@@ -43,16 +49,31 @@
 		return directories;
 	}
 	protected String fixCollisions(String target, String hierarchy, String linkSpacekey) {
+		return fixCollisions(target, hierarchy, linkSpacekey, null);
+	}
+	protected String fixCollisions(String target, String hierarchy, String linkSpacekey, String targetMetaFilename) {
 		Vector<String> collisionsCandidates = getCollisionsCandidates(linkSpacekey);
 		target = HierarchyTitleConverter.casify(target);
 		if (collisionsCandidates.contains(target)) {
 			String parentsRaw = hierarchy.replaceFirst("\\Q" + target + "\\E.*$", "");
 			String[] parents = parentsRaw.split(":");
+			if (parents.length < 2) return target;
 			boolean again = false;
-			for (int i = parents.length-1;i>=0;i--) {
+			for (int i = parents.length-2;i>=0;i--) {
 				String parent = parents[i];
+				log.debug("HT: parent = '" + parent + "', targetMetaFilename:'" + targetMetaFilename + "'");
 				if (parent.toLowerCase().equals(target.toLowerCase())) continue;
 				if ("".equals(parent)) continue;
+				if (targetMetaFilename != null) {
+					Matcher metaFinder = metaFile.matcher(targetMetaFilename);
+					if (metaFinder.find()) {
+						String parentMetaFilename = metaFinder.replaceFirst(".meta");
+						log.debug("HT: parentMetaFilename: '" +  parentMetaFilename + "'");
+						String tmpparent = HierarchyTitleConverter.getMetaTitle(parentMetaFilename);
+						log.debug("HT: tmpparent: '" +  tmpparent + "'");
+						if (tmpparent != null && !"".equals(tmpparent)) parent = tmpparent;
+					}
+				}
 				parent = HierarchyTitleConverter.fixTitle(parent);
 				//how many parents do we need? if the parent is a collision, we need its parent
 				if (collisionsCandidates.contains(parent)) again = true;
diff --git a/src/com/atlassian/uwc/converters/instiki/TitleConverter.java b/src/com/atlassian/uwc/converters/instiki/TitleConverter.java
new file mode 100644
index 0000000..c18cd4e
--- /dev/null
+++ b/src/com/atlassian/uwc/converters/instiki/TitleConverter.java
@@ -0,0 +1,22 @@
+package com.atlassian.uwc.converters.instiki;
+
+import org.apache.log4j.Logger;
+
+import com.atlassian.uwc.converters.IllegalNameConverter;
+import com.atlassian.uwc.converters.dokuwiki.HierarchyTitleConverter;
+import com.atlassian.uwc.ui.Page;
+
+public class TitleConverter extends IllegalNameConverter {
+
+	Logger log = Logger.getLogger(this.getClass());
+	@Override
+	public void convert(Page page) {
+		String input = page.getName();
+		String converted = decodeUrl(input);
+		converted = converted.replaceFirst("[.]xhtml$", "");
+		converted = HierarchyTitleConverter.casify(converted);
+		log.debug("Page title: " + converted);
+		page.setName(converted);
+	}
+
+}
diff --git a/src/com/atlassian/uwc/converters/instiki/TitleConverterTest.java b/src/com/atlassian/uwc/converters/instiki/TitleConverterTest.java
new file mode 100644
index 0000000..9937d20
--- /dev/null
+++ b/src/com/atlassian/uwc/converters/instiki/TitleConverterTest.java
@@ -0,0 +1,43 @@
+package com.atlassian.uwc.converters.instiki;
+
+import junit.framework.TestCase;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+
+import com.atlassian.uwc.ui.Page;
+
+public class TitleConverterTest extends TestCase {
+
+	TitleConverter tester = null;
+	Logger log = Logger.getLogger(this.getClass());
+	Page page = new Page(null);
+	protected void setUp() throws Exception {
+		tester = new TitleConverter();
+		PropertyConfigurator.configure("log4j.properties");
+	}
+
+	
+	public void testTitleHandling() {
+		String input, expected, actual;
+		input = "foo+bar.xhtml";
+		page.setName(input);
+		tester.convert(page);
+		expected = "Foo Bar";
+		actual = page.getName();
+		assertNotNull(actual);
+		assertEquals(expected, actual);
+		
+	}
+	
+	public void testTitleURIEncoding() {
+		String input, expected, actual;
+		input = "foo+bar%3F.xhtml";
+		page.setName(input);
+		tester.convert(page);
+		expected = "Foo Bar?";
+		actual = page.getName();
+		assertNotNull(actual);
+		assertEquals(expected, actual);
+	}
+}