Merge branch 'master' of https://bitbucket.org/appfusions/universal-wiki-converter
diff --git a/.gitignore b/.gitignore
index 2443c87..473372b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@
sampleData/*/*Output*
output
tmp/
+archive
diff --git a/conf/converter.dokuwiki.properties b/conf/converter.dokuwiki.properties
index 3d33c8e..d8d1f8e 100644
--- a/conf/converter.dokuwiki.properties
+++ b/conf/converter.dokuwiki.properties
@@ -75,7 +75,7 @@
# Code (needs to be early so we can tokenize the contents)
DokuWiki.002.code.java-regex-tokenizer=(?s)<code>(.*?)<\/code>{replace-with}{code}$1{code}
DokuWiki.002.code-tsql.java-regex-tokenizer=(?s)\<code (tsql)\>(.*?)<\/code>{replace-with}{code:sql}$2{code}
-DokuWiki.002.code-type.java-regex-tokenizer=(?s)\<code ([^>]+?)\>(.*?)<\/code>{replace-with}{code:$1}$2{code}
+DokuWiki.002.code-type.java-regex-tokenizer=(?s)\<code ([^> ]+).*?\>(.*?)<\/code>{replace-with}{code:$1}$2{code}
DokuWiki.002.noformat.java-regex-tokenizer=(?s)%%(.*?)%%{replace-with}{noformat}$1{noformat}
# We do this after code because code blocks often have leading spaces and we
# don't want to transform a code block more than once
@@ -136,6 +136,7 @@
# Tables -- must be run before the image and link converters
DokuWiki.21.prep-colspans.class=com.atlassian.uwc.converters.dokuwiki.PrepColSpansConverter
+DokuWiki.22.prep-rowspans.class=com.atlassian.uwc.converters.dokuwiki.PrepRowSpansConverter
DokuWiki.23.table1.perl=s/\^/||/g
# Interwiki links
diff --git a/readme.txt b/readme.txt
index e0dbfee..ea8efa0 100644
--- a/readme.txt
+++ b/readme.txt
@@ -10,6 +10,3 @@
* chmod a+x *sh
* ./run_uwc_devel.sh
-For more info, please see:
-
-https://studio.plugins.atlassian.com/wiki/display/UWC/Universal+Wiki+Converter
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/DokuwikiAttachmentConverter.java b/src/com/atlassian/uwc/converters/dokuwiki/DokuwikiAttachmentConverter.java
index e10b9c2..30f2825 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/DokuwikiAttachmentConverter.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/DokuwikiAttachmentConverter.java
@@ -38,6 +38,9 @@
String dokupath = partsFinder.group(1);
String fileRelPath = createRelativePath(dokupath, relpath);
File file = new File(attdir + File.separator + fileRelPath);
+ if (!file.exists()) {
+ file = altCase(file);
+ }
candidates.add(file);
replacement = file.getName();
Matcher typeFinder = type.matcher(file.getName());
@@ -68,6 +71,25 @@
return input;
}
+ protected File altCase(File file) {
+ String name = file.getName();
+ File parent = file.getParentFile();
+ if (parent == null || !parent.exists()) {
+ log.warn("File probably does not exist: " + file.getAbsolutePath());
+ return file;
+ }
+ File[] files = parent.listFiles();
+ if (files == null) {
+ log.warn("File probably does not exist: " + file.getAbsolutePath());
+ return file;
+ }
+ for (File realFile : files) {
+ if (name.equalsIgnoreCase(realFile.getName())) return realFile;
+ }
+ log.warn("File probably does not exist: " + file.getAbsolutePath());
+ return file;
+ }
+
private String getSizeData(Matcher partsFinder) {
String hasOtherData = partsFinder.group(2);
String otherData = partsFinder.group(3);
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/DokuwikiAttachmentConverterTest.java b/src/com/atlassian/uwc/converters/dokuwiki/DokuwikiAttachmentConverterTest.java
index 13175a8..5874971 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/DokuwikiAttachmentConverterTest.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/DokuwikiAttachmentConverterTest.java
@@ -146,4 +146,13 @@
assertNotNull(actual);
assertEquals(expected, actual);
}
+
+ public void testAltCase() {
+ File file = new File("sampleData/dokuwiki/sampledokuwiki-inputbasic.txt");
+ File actual = tester.altCase(file);
+ String expected = "SampleDokuwiki-InputBasic.txt";
+ assertNotNull(actual);
+ assertEquals(expected, actual.getName());
+ assertTrue(actual.exists());
+ }
}
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/DokuwikiUserDate.java b/src/com/atlassian/uwc/converters/dokuwiki/DokuwikiUserDate.java
index 9544b6f..8c982f7 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/DokuwikiUserDate.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/DokuwikiUserDate.java
@@ -32,8 +32,7 @@
try {
changeContent = FileUtils.readTextFile(changeFile);
} catch (IOException e) {
- log.error("Could not read changes file: " + changeFilepath +". Skipping.");
- e.printStackTrace();
+ log.error("Could not read changes file: " + changeFilepath +". Skipping.", e);
return;
}
//not preserving history at this time
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverter.java b/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverter.java
index 51006c8..e84919b 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverter.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverter.java
@@ -55,8 +55,10 @@
if (target.startsWith("\\\\")) continue; //UNC link
if (target.contains("|")) {
String[] parts = target.split("\\|");
- target = parts[0];
- alias = parts[1];
+ if (parts.length > 1) {
+ target = parts[0];
+ alias = parts[1];
+ }
}
//FIXME anchors? we're not ready to transform these, so just get rid of the anchor part
if (target.contains("#")) target = target.replaceAll("#[^|]*", "");
@@ -84,8 +86,10 @@
//figure out if we've already got the space represented
String targetPart1 = target.replaceFirst(":[^:]+$", "");
boolean containsSpace = false;
- if (namespaces.containsKey(target.replaceAll(":", "/"))) {
- targetPart1 = target;
+// log.debug("targetPart1 = " + targetPart1);
+ String nsFromTarget = findNSFromTarget(namespaces, target);
+ if (nsFromTarget != null) {
+ targetPart1 = nsFromTarget;
}
if (allspaces.contains(targetPart1))
containsSpace = true;
@@ -97,8 +101,6 @@
boolean isOne = (onecolon.matcher(target)).matches();
if (!(containsSpace && isOne))
target = target.replaceFirst(":start$", "");
- if (containsSpace) //remove the space from the target for now
- target = target.replaceFirst("\\Q"+targetPart1+"\\E:", "");
String hierarchy = target; //save for later
//is there a meta title to be used?
// log.debug("pagepath = " + pagepath);
@@ -149,6 +151,16 @@
}
return input;
}
+
+ protected String findNSFromTarget(HashMap<String, String> namespaces, String target) {
+ target = target.replaceAll(":", "/");
+ while (!"".equals(target)) {
+ if (namespaces.containsKey(target)) { return target; }
+ if (target.contains("/")) target = target.replaceAll("[/][^/]*$", "");
+ else return null;
+ }
+ return null;
+ }
private void blogLinkReport(HashMap<String, String> namespaces,
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverterTest.java b/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverterTest.java
index b687921..ba485d4 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverterTest.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/HierarchyLinkConverterTest.java
@@ -131,15 +131,24 @@
public void testConvertWithPageByPageSpaces_2() {
tester.getProperties().setProperty("space-lala","ns/tada");
+ tester.getProperties().setProperty("space-foo","ns/tada/other");
Page page = new Page(new File(HierarchyTitleConverterTest.PAGESDIR+"/SampleDokuwiki-InputTitle.txt"));
page.setOriginalText("[[.:home]]\n" +
- "[[ns:tada]]\n");
+ "[[ns:tada]]\n" +
+ "[[ns:tada:subchild]]\n" +
+ "[[ns:tada:other:subchild]]\n" +
+ "[[ns:tada:Other:subchild]]\n" +
+ "[[ns:tada:other:sub:subsubchild]]\n");
String spacekey = "otherspace";
page.setSpacekey(spacekey);//default spacekey is 'food'
tester.convert(page);
String actual = page.getConvertedText();
String expected = "[" + spacekey + ":Home]\n" + //this one users the current home
- "[lala:Tada]\n"; //this one uses the mapping (drink points to food)
+ "[lala:Tada]\n" +
+ "[lala:Subchild]\n" +
+ "[foo:Subchild]\n" +
+ "[foo:Subchild]\n" +
+ "[foo:Subsubchild]\n"; //this one uses the mapping (drink points to food)
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 dc911c6..74a3455 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/HierarchyTarget.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/HierarchyTarget.java
@@ -141,7 +141,7 @@
return full.replaceAll("\\Q"+ignorable + "\\E", "");
}
- protected String getMetaFilename(String path, String filetype) {
+ public String getMetaFilename(String path, String filetype) {
String ignorable = getProperties().getProperty("filepath-hierarchy-ignorable-ancestors", null);
if (ignorable == null) {
return null;
@@ -166,5 +166,5 @@
log.debug("HierarchyTarget: relative path = " + path);
return path;
}
-
+
}
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/PrepColSpansConverter.java b/src/com/atlassian/uwc/converters/dokuwiki/PrepColSpansConverter.java
index f0f339b..79a22a1 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/PrepColSpansConverter.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/PrepColSpansConverter.java
@@ -18,7 +18,7 @@
page.setConvertedText(converted);
}
- Pattern colspan = Pattern.compile("[|]{2,}");
+ Pattern colspan = Pattern.compile("[|^]{2,}");
protected String prep(String input) {
input = removeEmptyColspanLines(input);
Matcher spanFinder = colspan.matcher(input);
@@ -28,7 +28,7 @@
found = true;
String spans = spanFinder.group();
int spanlength = spans.length();
- String replacement = DELIM +TOKENKEY+spanlength+DELIM +"|";
+ String replacement = DELIM +TOKENKEY+spanlength+DELIM +spans.substring(0, 1);
replacement = RegexUtil.handleEscapesInReplacement(replacement);
spanFinder.appendReplacement(sb, replacement);
}
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/PrepColSpansConverterTest.java b/src/com/atlassian/uwc/converters/dokuwiki/PrepColSpansConverterTest.java
index e8af0bc..866defe 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/PrepColSpansConverterTest.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/PrepColSpansConverterTest.java
@@ -17,10 +17,10 @@
public void testPrep() {
String input, expected, actual;
input = "^ Header ^ Header ^ Header ^ Header ^ Header ^ Header ^\n" +
- "^ Header | 2 | 3 | 4 | 5 | 6 |^\n" +
+ "^ Header | 2 | 3 | 4 | 5 | 6 |\n" +
"^ Header | next colspans |||||\n";
expected ="^ Header ^ Header ^ Header ^ Header ^ Header ^ Header ^\n" +
- "^ Header | 2 | 3 | 4 | 5 | 6 |^\n" +
+ "^ Header | 2 | 3 | 4 | 5 | 6 |\n" +
"^ Header | next colspans ::UWCTOKENCOLSPANS:5::|\n";
actual = tester.prep(input);
assertNotNull(actual);
@@ -100,4 +100,17 @@
assertNotNull(actual);
assertEquals(expected, actual);
}
+
+ public void testPrepHeader() {
+ String input, expected, actual;
+ input = "^ h1 ^^^^^^ \n" +
+ "^ a1 ^ a2 ^ a3 ^ a4 ^ a5 ^ a6 ^\n" +
+ "| r1 | r2 | r3 | r4 |r5 |r6 |\n";
+ expected ="^ h1 ::UWCTOKENCOLSPANS:6::^ \n" +
+ "^ a1 ^ a2 ^ a3 ^ a4 ^ a5 ^ a6 ^\n" +
+ "| r1 | r2 | r3 | r4 |r5 |r6 |\n";
+ actual = tester.prep(input);
+ assertNotNull(actual);
+ assertEquals(expected, actual);
+ }
}
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/PrepRowSpansConverter.java b/src/com/atlassian/uwc/converters/dokuwiki/PrepRowSpansConverter.java
new file mode 100644
index 0000000..783bf99
--- /dev/null
+++ b/src/com/atlassian/uwc/converters/dokuwiki/PrepRowSpansConverter.java
@@ -0,0 +1,128 @@
+package com.atlassian.uwc.converters.dokuwiki;
+
+import java.util.HashMap;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.atlassian.uwc.converters.BaseConverter;
+import com.atlassian.uwc.converters.tikiwiki.RegexUtil;
+import com.atlassian.uwc.ui.Page;
+
+public class PrepRowSpansConverter extends BaseConverter {
+
+
+ public static final String TOKENKEY = "UWCTOKENROWSPANS:";
+ private static final String DELIM = "::";
+ @Override
+ public void convert(Page page) {
+ String input = page.getOriginalText();
+ String converted = prep(input);
+ page.setConvertedText(converted);
+ }
+
+ Pattern rowspan = Pattern.compile("(?<=^|\n)[|^](.*?):::(.*?)((\n(?=\\s*[^|^]))|$)", Pattern.DOTALL);
+ protected String prep(String input) {
+ Matcher rowspanFinder = rowspan.matcher(input);
+ StringBuffer sb = new StringBuffer();
+ boolean found = false;
+ while (rowspanFinder.find()) {
+ found = true;
+ String table = rowspanFinder.group();
+ //remove everything before the last table
+ String pre = "";
+ if (needToTrim(table)) {
+ String parts[] = trimTable(table);
+ if (parts.length > 1) {
+ pre = parts[0];
+ table = parts[1];
+ }
+ }
+ //how many columns
+ int numcols = getNumCols(table);
+ //Look for a cell without the signal. Does the one following have it?
+ for (int i = 0; i < numcols; i++) {
+ //for each :::, if the one above is not :::, put the token?
+ table = handleColumn(i, table);
+ }
+ table = RegexUtil.handleEscapesInReplacement(pre + table);
+ rowspanFinder.appendReplacement(sb, table);
+ }
+ if (found) {
+ rowspanFinder.appendTail(sb);
+ return sb.toString();
+ }
+ return input;
+ }
+
+ Pattern moreThanOneTable = Pattern.compile("[|^]\n([^|^]|\n).*?[|^]", Pattern.DOTALL);
+ protected boolean needToTrim(String input) {
+ Matcher finder = moreThanOneTable.matcher(input);
+ return finder.find();
+ }
+
+ Pattern lastTable = Pattern.compile("^(.*?(?:(?:\n|[^|^])\n))([|^].*)", Pattern.DOTALL);
+ protected String[] trimTable(String input) {
+ Matcher lastFinder = lastTable.matcher(input);
+ if (lastFinder.find()) {
+ return new String[] {lastFinder.group(1),lastFinder.group(2)};
+ }
+ return new String[] {input};
+ }
+
+ String cellstring = "[|^][^|^]*";
+ Pattern cell = Pattern.compile(cellstring);
+ protected String handleColumn(int i, String input) {
+ String pre = "(?<=^|\n)";
+ while (i-- > 0) { pre += cellstring;}
+ Pattern p = Pattern.compile(pre+"("+cellstring+")");
+ Matcher colFinder = p.matcher(input);
+ int lastrow = -1;
+ int length = 0;
+ TreeMap<Integer, String> additions = new TreeMap<Integer, String>();
+ while (colFinder.find()) {
+ String cellcontents = colFinder.group(1);
+ if (!cellcontents.contains(":::")) {
+ if (length > 0) {
+ additions.put(lastrow, DELIM + TOKENKEY + (length+1) + DELIM);
+ length = 0;
+ }
+ lastrow = colFinder.end();
+ }
+ else {
+ length++;
+ }
+ }
+ if (length > 0) {
+ additions.put(lastrow, DELIM + TOKENKEY + (length+1) + DELIM);
+ }
+ Set<Integer> keySet = additions.keySet();
+ Vector<Integer> keys = new Vector<Integer>(keySet);
+ if (keys.isEmpty()) return input;
+ String output = "";
+ int first = 0, last = 0;
+ for (int index = 0; index < keys.size(); index ++ ) {
+ last = keys.get(index);
+ String part = input.substring(first, last);
+ output += part + additions.get(last);
+ first = last;
+ }
+ output += input.substring(last);
+ return output;
+ }
+
+ Pattern line = Pattern.compile("^[^\n]+", Pattern.MULTILINE);
+ protected int getNumCols(String input) {
+ Matcher lineFinder = line.matcher(input);
+ while (lineFinder.find()) {
+ String firstline = lineFinder.group();
+ if (firstline.contains(PrepColSpansConverter.TOKENKEY)) continue;
+ String[] cols = firstline.split("[|^]");
+ return cols.length - 1;
+ }
+ return 0;
+ }
+
+}
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/PrepRowSpansConverterTest.java b/src/com/atlassian/uwc/converters/dokuwiki/PrepRowSpansConverterTest.java
new file mode 100644
index 0000000..ead11eb
--- /dev/null
+++ b/src/com/atlassian/uwc/converters/dokuwiki/PrepRowSpansConverterTest.java
@@ -0,0 +1,265 @@
+package com.atlassian.uwc.converters.dokuwiki;
+
+import junit.framework.TestCase;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+
+public class PrepRowSpansConverterTest extends TestCase {
+
+ PrepRowSpansConverter tester = null;
+ Logger log = Logger.getLogger(this.getClass());
+ protected void setUp() throws Exception {
+ tester = new PrepRowSpansConverter();
+ PropertyConfigurator.configure("log4j.properties");
+ }
+
+ public void testPrep_MultiRow() {
+ String input, expected, actual;
+ input = "^ 1 ^ 2 ^ 1 ^ 2 ^\n" +
+ "| a | b | a | b |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "^ 1 ^ 2 ^ 3 ^ 4 ^\n" +
+ "| a | b | c | d |\n" +
+ "| ::: |b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: |b | ::: | d |\n" +
+ "";
+ expected ="^ 1 ^ 2 ^ 1 ^ 2 ^\n" +
+ "| a ::UWCTOKENROWSPANS:4::| b | a ::UWCTOKENROWSPANS:4::| b |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "^ 1 ^ 2 ^ 3 ^ 4 ^\n" +
+ "| a ::UWCTOKENROWSPANS:4::| b | c ::UWCTOKENROWSPANS:4::| d |\n" +
+ "| ::: |b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: |b | ::: | d |\n" +
+ "";
+ actual = tester.prep(input);
+ assertNotNull(actual);
+ assertEquals(expected, actual);
+ }
+
+ public void testPrep_MultiRow_b() {
+ String input, expected, actual;
+ input = "^ 1 ^ 2 ^ 1 ^ 2 ^\n" +
+ "| a | b | a | b |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "^ 1 ^ 2 ^ 3 ^ 4 ^\n" +
+ "| a | b | c | d |\n" +
+ "| ::: |b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: |b | c | d |\n" +
+ "no longer a table";
+ expected ="^ 1 ^ 2 ^ 1 ^ 2 ^\n" +
+ "| a ::UWCTOKENROWSPANS:4::| b | a ::UWCTOKENROWSPANS:4::| b |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "^ 1 ^ 2 ^ 3 ^ 4 ^\n" +
+ "| a ::UWCTOKENROWSPANS:4::| b | c ::UWCTOKENROWSPANS:3::| d |\n" +
+ "| ::: |b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: |b | c | d |\n" +
+ "no longer a table";
+ actual = tester.prep(input);
+ assertNotNull(actual);
+ assertEquals(expected, actual);
+ }
+
+ public void testGetNumCols() {
+ String input;
+ int expected, actual;
+ input = "^ 1 ^ 2 ^ 1 ^ 2 ^\n" +
+ "| a | b | a | b |\n" +
+ "| ::: | b | ::: | d |\n";
+ expected = 4;
+ actual = tester.getNumCols(input);
+ assertNotNull(actual);
+ assertEquals(expected, actual);
+ }
+
+
+ public void testGetNumCols_WithColspan() {
+ String input;
+ int expected, actual;
+ input = "^ h1 ::UWCTOKENCOLSPANS:6::^\n" +
+ "^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^\n" +
+ "| Trala | abc.def.ghu.jkl.edu | D:\\Path\\TO\\Some\\Place_tada\\asd | D:\\Path\\TO\\Some\\Place_tada\\asd[mmyyyy].txt | asd.asd.asd.org | Asdlkj_askjda_BD |\n" +
+ "| ::: | foo-1234-bar.abc.def.org:0986 | ::: | D:\\AppLogFiles\\BindingLogs_[yyyy-mm].txt | ::: | ::: |\n" +
+ "| Lala | a.b.c.d.e | D:\\Apps\\INT\\Do\\ComparioXMLSite_es\\Web | D:\\AppLogFiles\\ComparioXmlSite.xml[mmyyyy].txt | sqlcompariopreview.internet.conseur.org | Compario_ES_ES |\n" +
+ "";
+ expected = 6;
+ actual = tester.getNumCols(input);
+ assertNotNull(actual);
+ assertEquals(expected, actual);
+ }
+
+ public void testHandleColumn_0() {
+ String input, expected, actual;
+ input = "^ 1 ^ 2 ^ 1 ^ 2 ^\n" +
+ "| a | b | a | b |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "^ 1 ^ 2 ^ 3 ^ 4 ^\n" +
+ "| a | b | c | d |\n" +
+ "| ::: |b | ::: | d |\n";
+ expected = "^ 1 ^ 2 ^ 1 ^ 2 ^\n" +
+ "| a ::UWCTOKENROWSPANS:4::| b | a | b |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "^ 1 ^ 2 ^ 3 ^ 4 ^\n" +
+ "| a ::UWCTOKENROWSPANS:2::| b | c | d |\n" +
+ "| ::: |b | ::: | d |\n";
+ actual = tester.handleColumn(0, input);
+ assertNotNull(actual);
+ assertEquals(expected, actual);
+ }
+
+ public void testHandleColumn_2() {
+ String input, expected, actual;
+ input = "^ 1 ^ 2 ^ 1 ^ 2 ^\n" +
+ "| a | b | a | b |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "^ 1 ^ 2 ^ 3 ^ 4 ^\n" +
+ "| a | b | c | d |\n" +
+ "| ::: |b | ::: | d |\n";
+ expected = "^ 1 ^ 2 ^ 1 ^ 2 ^\n" +
+ "| a | b | a ::UWCTOKENROWSPANS:4::| b |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "| ::: | b | ::: | d |\n" +
+ "^ 1 ^ 2 ^ 3 ^ 4 ^\n" +
+ "| a | b | c ::UWCTOKENROWSPANS:2::| d |\n" +
+ "| ::: |b | ::: | d |\n";
+ actual = tester.handleColumn(2, input);
+ assertNotNull(actual);
+ assertEquals(expected, actual);
+ }
+
+ public void testExample() {
+ String input, expected, actual;
+ input = "^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^\n" +
+ "^ r1c1 | r1c2 | r1c3| r1c4 | r1c5 | r1c6 |\n" +
+ "^ ::: | r2c2 | r2c3| c4 | c5 | c6 |\n" +
+ "^ ::: | c2 | c3|c4| c5|c6 |\n" +
+ "^ ::: | c2 | c3|c4| c5|c6 |\n" +
+ "^ Health page | c2 ::UWCTOKENCOLSPANS:5::|\n" +
+ "";
+ expected = "^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^\n" +
+ "^ r1c1 ::UWCTOKENROWSPANS:4::| r1c2 | r1c3| r1c4 | r1c5 | r1c6 |\n" +
+ "^ ::: | r2c2 | r2c3| c4 | c5 | c6 |\n" +
+ "^ ::: | c2 | c3|c4| c5|c6 |\n" +
+ "^ ::: | c2 | c3|c4| c5|c6 |\n" +
+ "^ Health page | c2 ::UWCTOKENCOLSPANS:5::|\n";
+ actual = tester.prep(input);
+ assertNotNull(actual);
+ assertEquals(expected, actual);
+ }
+
+ public void testExample2() {
+ String input, expected, actual;
+ input = "^ h1 ::UWCTOKENCOLSPANS:6::^\n" +
+ "^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^\n" +
+ "| Trala | abc.def.ghu.jkl.edu | D:\\Path\\TO\\Some\\Place_tada\\asd | D:\\Path\\TO\\Some\\Place_tada\\asd[mmyyyy].txt | asd.asd.asd.org | Asdlkj_askjda_BD |\n" +
+ "| ::: | foo-1234-bar.abc.def.org:0986 | ::: | D:\\AppLogFiles\\BindingLogs_[yyyy-mm].txt | ::: | ::: |\n" +
+ "| Lala | a.b.c.d.e | D:\\Apps\\INT\\Do\\ComparioXMLSite_es\\Web | D:\\AppLogFiles\\ComparioXmlSite.xml[mmyyyy].txt | sqlcompariopreview.internet.conseur.org | Compario_ES_ES |\n" +
+ "";
+ expected = "^ h1 ::UWCTOKENCOLSPANS:6::^\n" +
+ "^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^\n" +
+ "| Trala ::UWCTOKENROWSPANS:2::| abc.def.ghu.jkl.edu | D:\\Path\\TO\\Some\\Place_tada\\asd ::UWCTOKENROWSPANS:2::| D:\\Path\\TO\\Some\\Place_tada\\asd[mmyyyy].txt | asd.asd.asd.org ::UWCTOKENROWSPANS:2::| Asdlkj_askjda_BD ::UWCTOKENROWSPANS:2::|\n" +
+ "| ::: | foo-1234-bar.abc.def.org:0986 | ::: | D:\\AppLogFiles\\BindingLogs_[yyyy-mm].txt | ::: | ::: |\n" +
+ "| Lala | a.b.c.d.e | D:\\Apps\\INT\\Do\\ComparioXMLSite_es\\Web | D:\\AppLogFiles\\ComparioXmlSite.xml[mmyyyy].txt | sqlcompariopreview.internet.conseur.org | Compario_ES_ES |\n" +
+ "";
+ actual = tester.prep(input);
+ assertNotNull(actual);
+ assertEquals(expected, actual);
+ }
+
+ public void testExample3() {
+ String input, expected, actual;
+ input = "Given the following:\n" +
+ "\n" +
+ "^ 1 | 2 |\n" +
+ "^ 1 | 2 |\n" +
+ "^ 1 | 2 |\n" +
+ "\n" +
+ "tralala:\n" +
+ "\n" +
+ "^ 1 ^ 2 ^ 3 ^ 4 ^\n" +
+ "| a | b | c | !!! |\n" +
+ "| a | b | c |::: |\n" +
+ "| a | b | c | end |\n" +
+ "";
+ expected = "Given the following:\n" +
+ "\n" +
+ "^ 1 | 2 |\n" +
+ "^ 1 | 2 |\n" +
+ "^ 1 | 2 |\n" +
+ "\n" +
+ "tralala:\n" +
+ "\n" +
+ "^ 1 ^ 2 ^ 3 ^ 4 ^\n" +
+ "| a | b | c | !!! ::UWCTOKENROWSPANS:2::|\n" +
+ "| a | b | c |::: |\n" +
+ "| a | b | c | end |\n" +
+ "";
+ actual = tester.prep(input);
+ assertNotNull(actual);
+ assertEquals(expected, actual);
+ }
+
+ public void testTrimTable() {
+ String input, expected, actual;
+ input = "^ 1 | 2 |\n" +
+ "^ 1 | 2 |\n" +
+ "^ 1 | 2 |\n" +
+ "\n" +
+ "tralala:\n" +
+ "\n" +
+ "^ 1 ^ 2 ^ 3 ^ 4 ^\n" +
+ "| a | b | c | !!! ::UWCTOKENROWSPANS:2::|\n" +
+ "| a | b | c |::: |\n" +
+ "| a | b | c | end |\n";
+ expected = "^ 1 ^ 2 ^ 3 ^ 4 ^\n" +
+ "| a | b | c | !!! ::UWCTOKENROWSPANS:2::|\n" +
+ "| a | b | c |::: |\n" +
+ "| a | b | c | end |\n";
+ actual = tester.trimTable(input)[1];
+ assertNotNull(actual);
+ assertEquals(expected, actual);
+ }
+
+ public void testNeedToTrim() {
+ String input, expected, actual;
+ input = "^ 1 | 2 |\n" +
+ "^ 1 | 2 |\n" +
+ "^ 1 | 2 |\n" +
+ "\n" +
+ "tralala:\n" +
+ "\n" +
+ "^ 1 ^ 2 ^ 3 ^ 4 ^\n" +
+ "| a | b | c | !!!|\n" +
+ "| a | b | c |::: |\n" +
+ "| a | b | c | end |\n";
+
+ assertTrue(tester.needToTrim(input));
+
+ input = "tralala:\n" +
+ "\n" +
+ "^ 1 ^ 2 ^ 3 ^ 4 ^\n" +
+ "| a | b | c | !!!|\n" +
+ "| a | b | c |::: |\n" +
+ "| a | b | c | end |\n";
+ assertFalse(tester.needToTrim(input));
+ }
+}
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/SpaceConverter.java b/src/com/atlassian/uwc/converters/dokuwiki/SpaceConverter.java
index 1d22fed..f3b306d 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/SpaceConverter.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/SpaceConverter.java
@@ -43,7 +43,7 @@
//remove deepest portion of the path
tmppath = removeDeepest(tmppath);
}
-
+ log.debug("spacekey set to: " + page.getSpacekey());
}
static Pattern filetype = Pattern.compile("[.]\\w+$");
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverter.java b/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverter.java
index a99dceb..76ec28f 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverter.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverter.java
@@ -19,10 +19,10 @@
String input = page.getOriginalText();
String tmpconverted = convertColspans(input);
if (!(page instanceof VersionPage) && !input.equals(tmpconverted))
- log.debug("Colspans detected: " + page.getName());
+ log.debug("Colspans detected: '" + page.getName() + "' in space: " + page.getSpacekey());
String converted = convertRowspans(tmpconverted);
if (!(page instanceof VersionPage) && !tmpconverted.equals(converted))
- log.debug("Rowspans detected: " + page.getName());
+ log.debug("Rowspans detected: '" + page.getName() + "' in space: " + page.getSpacekey());
page.setConvertedText(converted);
}
@@ -61,185 +61,48 @@
}
return input;
}
-
- Pattern table = Pattern.compile("<table>(.*?)</table>", Pattern.DOTALL);
+
+ Pattern uwctokenrowspan = Pattern.compile("::" + PrepRowSpansConverter.TOKENKEY + "(\\d+)::");
Pattern rowspan = Pattern.compile(":::");
- Pattern tablerow = Pattern.compile("<tr>(.*?)</tr>", Pattern.DOTALL);
- Pattern tdWithColspan = Pattern.compile("<t([dh])(?: colspan='(\\d+)')?>(.*?)</t[dh]>", Pattern.DOTALL);
protected String convertRowspans(String input) {
- Matcher tableFinder = table.matcher(input);
+ Matcher tdFinder = td.matcher(input);
StringBuffer sb = new StringBuffer();
boolean found = false;
- while (tableFinder.find()) {
- Vector<Integer> rowindeces = new Vector<Integer>();
- Vector<Integer> colindeces = new Vector<Integer>();
- Vector<Integer> rowvals = new Vector<Integer>();
- Vector<Integer> colclear = new Vector<Integer>();
+ while (tdFinder.find()) {
found = true;
- String tableContents = tableFinder.group(1);
- Matcher rowspanFinder = rowspan.matcher(tableContents);
- if (!rowspanFinder.find()) continue;
-
- int rowspanVal = 1; //the value of the rowspan attribute
- int lastrow = 0;
- int rowspancount = 0;
-
- Matcher rowFinder = tablerow.matcher(tableContents);
- StringBuffer rowsb = new StringBuffer();
- boolean rowfound = false;
- boolean noteindex = true;
-
- boolean clearrow = false;
- while (rowFinder.find()) {
- int lastcol = -1;
- rowfound = true;
- boolean newrow = true;
-
- String rowcontents = rowFinder.group(1);
- Matcher tdFinder = tdWithColspan.matcher(rowcontents);
- StringBuffer tdsb = new StringBuffer();
- boolean tdfound = false;
- boolean rowspanfoundLast = true;
- boolean rowspanfoundCurrent = true;
- int rowspancountThisRow = 0;
- int currentColOffset = 0;
- while (tdFinder.find()) {
- tdfound = true;
- lastcol++;
- String cell = tdFinder.group(3);
- String colspanOffset = tdFinder.group(2);
-
- rowspanFinder = rowspan.matcher(cell);
- rowspanfoundLast = rowspanfoundCurrent;
- rowspanfoundCurrent = rowspanFinder.find();
- if (!rowspanfoundCurrent) { //no rowspan
- colclear.add(lastcol+currentColOffset);
- }
- else { //found a rowspan!
- tdFinder.appendReplacement(tdsb, ""); //remove the ::: cells
- if (newrow && clearrow && rowspanVal > 1) {
- rowspancount++;
- fillRowSpanVals(rowindeces, rowvals, rowspanVal);
- rowspanVal = currentColOffset+1;
- colindeces.add(lastcol); //note the index of the current cell
- rowindeces.add(lastrow-1);//note the index of the previous row
- noteindex = false;
- }
- rowspanVal++;
-
- if (noteindex || !newrow) {
- rowspancount++;
- rowspancountThisRow++;
- colindeces.add(lastcol); //note the index of the current cell
- rowindeces.add(lastrow-1);//note the index of the previous row
- noteindex = false;
- if (!newrow && rowspancountThisRow > 0) rowspanVal--;
- colclear.removeAllElements();
- }
- else if (!rowspanfoundLast) {
- noteindex = true;
- rowvals.add(rowspanVal);
- rowspanVal=currentColOffset+1;
- }
-
- newrow = false;
- }
- if (colspanOffset != null)
- currentColOffset += (Integer.parseInt(colspanOffset));
- }
- if (tdfound) {
- tdFinder.appendTail(tdsb);
- rowcontents = "<tr>"+tdsb.toString()+"</tr>";
- }
- else
- rowcontents = "<tr>" + rowcontents + "</tr>";
-
-
- String replacement = rowcontents;
- replacement = RegexUtil.handleEscapesInReplacement(replacement);
- rowFinder.appendReplacement(rowsb, replacement);
- lastrow++;
- boolean tmpclear = true;
- for (int i = 0; i < lastcol-1; i++) {
- if (!colclear.contains(i+currentColOffset)) tmpclear = false;
- }
- clearrow = tmpclear;
- colclear.removeAllElements();
+ String type = tdFinder.group(1);
+ String row = tdFinder.group(2);
+ Matcher rowspanFinder = rowspan.matcher(row);
+ if (rowspanFinder.find()) {
+ tdFinder.appendReplacement(sb, "");
+ continue;
}
- if (rowfound) {
- fillRowSpanVals(rowindeces, rowvals, rowspanVal);
- rowspanVal=1;
- rowFinder.appendTail(rowsb);
- tableContents = rowsb.toString();
+
+ Matcher uwctokenFinder = uwctokenrowspan.matcher(row);
+ boolean found2 = false;
+ String len = "";
+ StringBuffer sb2 = new StringBuffer();
+ while (uwctokenFinder.find()) {
+ found2 = true;
+ len = uwctokenFinder.group(1);
+ String rep2= RegexUtil.handleEscapesInReplacement("");
+ uwctokenFinder.appendReplacement(sb2, rep2);
}
-
- rowFinder = tablerow.matcher(tableContents);
- rowsb = new StringBuffer();
- rowfound = false;
- int currentrow = 0;
- int index = 0;
- while (rowFinder.find()) {
- rowfound = true;
- String rowcontents = rowFinder.group(1);
-
- if (index >= rowspancount) break;
- int rowindex = rowindeces.get(index);
- int colindex = colindeces.get(index);
- int rowval = rowvals.get(index);
- if (currentrow == rowindex) {
- Matcher tdFinder = td.matcher(rowcontents);
- StringBuffer tdsb = new StringBuffer();
- boolean tdfound = false;
-
- int currentcell = 0;
- while (tdFinder.find()) {
- tdfound = true;
- String type = tdFinder.group(1);
- if (currentcell == colindex) {
- String newcell = "<t"+type+" rowspan='"+rowval+"'>"+tdFinder.group(2)+"</t"+type+">";
- tdFinder.appendReplacement(tdsb, newcell); //replace the rowspan cell
- index++;
- if (index < rowspancount) { //get these now in case we have more rowspans in the same row
- colindex = colindeces.get(index);
- rowval = rowvals.get(index);
- }
- }
- currentcell++;
- }
- if (tdfound) {
- tdFinder.appendTail(tdsb);
- rowcontents = tdsb.toString();
- }
- }
-
- String replacement = "<tr>"+rowcontents+"</tr>";
- replacement = RegexUtil.handleEscapesInReplacement(replacement);
- rowFinder.appendReplacement(rowsb, replacement);
- currentrow++;
+ if (found2) {
+ uwctokenFinder.appendTail(sb2);
+ row = sb2.toString();
}
- if (rowfound) {
- rowFinder.appendTail(rowsb);
- tableContents = rowsb.toString();
- }
-
- String replacement = "<table>" + tableContents + "</table>";
+ else continue;
+ String replacement = "<t"+type+" rowspan='"+len+"'>"+row+"</t"+type+">";
replacement = RegexUtil.handleEscapesInReplacement(replacement);
- tableFinder.appendReplacement(sb, replacement);
+ tdFinder.appendReplacement(sb, replacement);
}
if (found) {
- tableFinder.appendTail(sb);
+ tdFinder.appendTail(sb);
return sb.toString();
}
return input;
}
- public void fillRowSpanVals(Vector<Integer> indeces, Vector<Integer> vals, int val) {
- vals.add(val);
- int last = indeces.get(vals.size()-1);
- while (indeces.size() > vals.size()) {
- if (indeces.get(vals.size()-1) == last)
- vals.add(val);
- else break;
- }
- }
+
}
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverterTest.java b/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverterTest.java
index e0e472a..b233331 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverterTest.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverterTest.java
@@ -130,7 +130,7 @@
"<th><p> Head 6 </p></th>\n" +
"</tr>\n" +
"<tr>\n" +
- "<th><p> Row 1 </p></th>\n" +
+ "<th><p> Row 1 ::UWCTOKENROWSPANS:4::</p></th>\n" +
"<td> Row 2 </td>\n" +
"<td> Row 3 </td>\n" +
"<td> Row 4 </td>\n" +
@@ -233,7 +233,7 @@
"</tr>\n" +
"<tr>\n" +
"<td><p> Row 4 Col 1 </p></td>\n" +
- "<td><p> this cell spans vertically </p></td>\n" +
+ "<td><p> this cell spans vertically ::UWCTOKENROWSPANS:3::</p></td>\n" +
"<td><p> Row 4 Col 3 </p></td>\n" +
"</tr>\n" +
"<tr>\n" +
@@ -255,7 +255,7 @@
"<td><p> Row 8 some colspan (note the double pipe) ::UWCTOKENCOLSPANS:3::</p></td>\n" +
"</tr>\n" +
"<tr>\n" +
- "<td><p> Row 9 Col 1 </p></td>\n" +
+ "<td><p> Row 9 Col 1 ::UWCTOKENROWSPANS:3::</p></td>\n" +
"<td><p> Row 9 Col 2 </p></td>\n" +
"<td><p> Row 9 Col 3 </p></td>\n" +
"</tr>\n" +
@@ -360,7 +360,7 @@
"</tr>\n" +
"<tr>\n" +
"<td><p> Row 4 Col 1 </p></td>\n" +
- "<td><p> this cell spans vertically </p></td>\n" +
+ "<td><p> this cell spans vertically ::UWCTOKENROWSPANS:3::</p></td>\n" +
"<td><p> Row 4 Col 3 </p></td>\n" +
"</tr>\n" +
"<tr>\n" +
@@ -384,7 +384,7 @@
"<td><p> Row 8 Col 3</p></td>\n" +
"</tr>\n" +
"<tr>\n" +
- "<td><p> Row 9 Col 1 </p></td>\n" +
+ "<td><p> Row 9 Col 1 ::UWCTOKENROWSPANS:3::</p></td>\n" +
"<td><p> Row 9 Col 2 </p></td>\n" +
"<td><p> Row 9 Col 3 </p></td>\n" +
"</tr>\n" +
@@ -481,8 +481,8 @@
"</tr>\n" +
"<tr>\n" +
"<td><p> Row 1 Col 1 </p></td>\n" +
- "<td><p> Row 1 Col 2 </p></td>\n" +
- "<td><p> Row 1 Col 3 </p></td>\n" +
+ "<td><p> Row 1 Col 2 ::UWCTOKENROWSPANS:4::</p></td>\n" +
+ "<td><p> Row 1 Col 3 ::UWCTOKENROWSPANS:3::</p></td>\n" +
"</tr>\n" +
"<tr>\n" +
"<td><p> Row 2 Col 1 </p></td>\n" +
@@ -559,7 +559,7 @@
"</tr>\n" +
"<tr>\n" +
"<td><p> Row 4 Col 1 </p></td>\n" +
- "<td><p> this cell spans vertically </p></td>\n" +
+ "<td><p> this cell spans vertically ::UWCTOKENROWSPANS:3::</p></td>\n" +
"<td><p> Row 4 Col 3 </p></td>\n" +
"</tr>\n" +
"<tr>\n" +
@@ -581,7 +581,7 @@
"<td><p> Row 8 some colspan (note the double pipe) ::UWCTOKENCOLSPANS:3::</p></td>\n" +
"</tr>\n" +
"<tr>\n" +
- "<td><p> Row 9 Col 1 </p></td>\n" +
+ "<td><p> Row 9 Col 1 ::UWCTOKENROWSPANS:3::</p></td>\n" +
"<td><p> Row 9 Col 2 </p></td>\n" +
"<td><p> Row 9 Col 3 </p></td>\n" +
"</tr>\n" +
@@ -605,8 +605,8 @@
"</tr>\n" +
"<tr>\n" +
"<td><p> Row 1 Col 1 </p></td>\n" +
- "<td><p> Row 1 Col 2 </p></td>\n" +
- "<td><p> Row 1 Col 3 </p></td>\n" +
+ "<td><p> Row 1 Col 2 ::UWCTOKENROWSPANS:4::</p></td>\n" +
+ "<td><p> Row 1 Col 3 ::UWCTOKENROWSPANS:3::</p></td>\n" +
"</tr>\n" +
"<tr>\n" +
"<td><p> Row 2 Col 1 </p></td>\n" +
@@ -727,9 +727,9 @@
"<th><p> h4 </p></th>\n" +
"</tr>\n" +
"<tr>\n" +
- "<td><p> foo </p></td>\n" +
+ "<td><p> foo ::UWCTOKENROWSPANS:2::</p></td>\n" +
"<td><p> bar </p></td>\n" +
- "<td><p> baz </p></td>\n" +
+ "<td><p> baz ::UWCTOKENROWSPANS:2::</p></td>\n" +
"<td><p> tralala </p></td>\n" +
"</tr>\n" +
"<tr>\n" +
@@ -783,12 +783,12 @@
"<th><p> h6 </p></th>\n" +
"</tr>\n" +
"<tr>\n" +
- "<td><p> thin </p></td>\n" +
+ "<td><p> thin ::UWCTOKENROWSPANS:2::</p></td>\n" +
"<td><p> man </p></td>\n" +
- "<td><p> starring </p></td>\n" +
+ "<td><p> starring ::UWCTOKENROWSPANS:2::</p></td>\n" +
"<td><p> myrna </p></td>\n" +
- "<td><p> loy </p></td>\n" +
- "<td><p> tralalala </p></td>\n" +
+ "<td><p> loy ::UWCTOKENROWSPANS:2::</p></td>\n" +
+ "<td><p> tralalala ::UWCTOKENROWSPANS:2::</p></td>\n" +
"</tr>\n" +
"<tr>\n" +
"<td><p> ::: </p></td>\n" +
@@ -799,12 +799,12 @@
"<td><p> ::: </p></td>\n" +
"</tr>\n" +
"<tr>\n" +
- "<td><p> foo </p></td>\n" +
+ "<td><p> foo ::UWCTOKENROWSPANS:2::</p></td>\n" +
"<td><p> bar </p></td>\n" +
- "<td><p> arg</p></td>\n" +
+ "<td><p> arg::UWCTOKENROWSPANS:2::</p></td>\n" +
"<td><p> this </p></td>\n" +
- "<td><p> is </p></td>\n" +
- "<td><p> annoying </p></td>\n" +
+ "<td><p> is ::UWCTOKENROWSPANS:2::</p></td>\n" +
+ "<td><p> annoying ::UWCTOKENROWSPANS:2::</p></td>\n" +
"</tr>\n" +
"<tr>\n" +
"<td><p> ::: </p></td>\n" +
@@ -815,12 +815,12 @@
"<td><p> ::: </p></td>\n" +
"</tr>\n" +
"<tr>\n" +
- "<td><p> 1 </p></td>\n" +
+ "<td><p> 1 ::UWCTOKENROWSPANS:2::</p></td>\n" +
"<td><p> 2 </p></td>\n" +
- "<td><p> 3 </p></td>\n" +
+ "<td><p> 3 ::UWCTOKENROWSPANS:2::</p></td>\n" +
"<td><p> 4 </p></td>\n" +
- "<td><p> 5 </p></td>\n" +
- "<td><p> 6 </p></td>\n" +
+ "<td><p> 5 ::UWCTOKENROWSPANS:2::</p></td>\n" +
+ "<td><p> 6 ::UWCTOKENROWSPANS:2::</p></td>\n" +
"</tr>\n" +
"<tr>\n" +
"<td><p> ::: </p></td>\n" +
@@ -897,5 +897,230 @@
assertNotNull(actual);
assertEquals(expected, actual);
}
+
+ public void testConvertColSpansWithHeader() {
+ String input, expected, actual;
+ input = "<table><tbody>\n" +
+ "<tr>\n" +
+ "<th><p> Head 1 ::UWCTOKENCOLSPANS:6:: </p></th>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<th><p> Row 1 </p></th>\n" +
+ "<td> Row 2 </td>\n" +
+ "<td> Row 3 </td>\n" +
+ "<td> Row 4 </td>\n" +
+ "<td> Row 5 </td>\n" +
+ "<td> Row 6 </td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<th><p> ::: </p></th>\n" +
+ "<td><p> Row 2 </p></td>\n" +
+ "<td><p> Row 3 </p></td>\n" +
+ "<td><p> Row 4 </p></td>\n" +
+ "<td><p> Row 5 </p></td>\n" +
+ "<td><p> Row 6 </p></td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<th><p> ::: </p></th>\n" +
+ "<td><p> </p></td>\n" +
+ "<td><p> </p></td>\n" +
+ "<td><p> </p></td>\n" +
+ "<td><p> </p></td>\n" +
+ "<td> Item 6 </td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<th><p> ::: </p></th>\n" +
+ "<td><p> </p></td>\n" +
+ "<td><p> </p></td>\n" +
+ "<td><p> </p></td>\n" +
+ "<td><p> </p></td>\n" +
+ "<td> Last 6 </td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<th><p> Header </p></th>\n" +
+ "<td><p> Colspan Here ::UWCTOKENCOLSPANS:5::</p></td>\n" +
+ "</tr>\n" +
+ "</tbody></table>\n" +
+ "";
+ expected = "<table><tbody>\n" +
+ "<tr>\n" +
+ "<th colspan='6'><p> Head 1 </p></th>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<th><p> Row 1 </p></th>\n" +
+ "<td> Row 2 </td>\n" +
+ "<td> Row 3 </td>\n" +
+ "<td> Row 4 </td>\n" +
+ "<td> Row 5 </td>\n" +
+ "<td> Row 6 </td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<th><p> ::: </p></th>\n" +
+ "<td><p> Row 2 </p></td>\n" +
+ "<td><p> Row 3 </p></td>\n" +
+ "<td><p> Row 4 </p></td>\n" +
+ "<td><p> Row 5 </p></td>\n" +
+ "<td><p> Row 6 </p></td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<th><p> ::: </p></th>\n" +
+ "<td><p> </p></td>\n" +
+ "<td><p> </p></td>\n" +
+ "<td><p> </p></td>\n" +
+ "<td><p> </p></td>\n" +
+ "<td> Item 6 </td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<th><p> ::: </p></th>\n" +
+ "<td><p> </p></td>\n" +
+ "<td><p> </p></td>\n" +
+ "<td><p> </p></td>\n" +
+ "<td><p> </p></td>\n" +
+ "<td> Last 6 </td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<th><p> Header </p></th>\n" +
+ "<td colspan='5'><p> Colspan Here </p></td>\n" +
+ "</tr>\n" +
+ "</tbody></table>\n" +
+ "";
+ actual = tester.convertColspans(input);
+ assertNotNull(actual);
+ assertEquals(expected, actual);
+ }
+
+
+ public void testConvertMoreRowSpanTroubles() {
+ String input, expected, actual;
+ input = "<table><tbody>\n" +
+ "<tr>\n" +
+ "<th><p> HEADER ::UWCTOKENCOLSPANS:6::</p></th>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<th><p> h1 </p></th>\n" +
+ "<th><p> h2 </p></th>\n" +
+ "<th><p> h3 </p></th>\n" +
+ "<th><p> h4 </p></th>\n" +
+ "<th><p> h5 </p></th>\n" +
+ "<th><p> h6 </p></th>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<td><p> r1c1 ::UWCTOKENROWSPANS:3::</p></td>\n" +
+ "<td><p> r1c2 </p></td>\n" +
+ "<td><p> r1c3 ::UWCTOKENROWSPANS:3::</p></td>\n" +
+ "<td><p> r1c4 </p></td>\n" +
+ "<td><p> r1c5 ::UWCTOKENROWSPANS:3::</p></td>\n" +
+ "<td><p> r1c6 ::UWCTOKENROWSPANS:3::</p></td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "<td><p> r2c2 </p></td>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "<td><p> r2c4 </p></td>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "<td><p> r3c2 </p></td>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "<td><p>r3c4</p></td>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<td><p> r4c1 ::UWCTOKENROWSPANS:3::</p></td>\n" +
+ "<td><p> r4c2 </p></td>\n" +
+ "<td><p> r4c3 ::UWCTOKENROWSPANS:3::</p></td>\n" +
+ "<td><p> r4c4 </p></td>\n" +
+ "<td><p> r4c5 ::UWCTOKENROWSPANS:3::</p></td>\n" +
+ "<td><p> r4c6 ::UWCTOKENROWSPANS:3::</p></td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "<td><p> r2c2 </p></td>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "<td><p> r2c4 </p></td>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "<td><p> r3c2 </p></td>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "<td><p>r3c4</p></td>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "<td><p> ::: </p></td>\n" +
+ "</tr>\n" +
+ "</table>\n" +
+ "";
+ expected = "<table><tbody>\n" +
+ "<tr>\n" +
+ "<th colspan='6'><p> HEADER </p></th>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<th><p> h1 </p></th>\n" +
+ "<th><p> h2 </p></th>\n" +
+ "<th><p> h3 </p></th>\n" +
+ "<th><p> h4 </p></th>\n" +
+ "<th><p> h5 </p></th>\n" +
+ "<th><p> h6 </p></th>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<td rowspan='3'><p> r1c1 </p></td>\n" +
+ "<td><p> r1c2 </p></td>\n" +
+ "<td rowspan='3'><p> r1c3 </p></td>\n" +
+ "<td><p> r1c4 </p></td>\n" +
+ "<td rowspan='3'><p> r1c5 </p></td>\n" +
+ "<td rowspan='3'><p> r1c6 </p></td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "\n" +
+ "<td><p> r2c2 </p></td>\n" +
+ "\n" +
+ "<td><p> r2c4 </p></td>\n" +
+ "\n" +
+ "\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "\n" +
+ "<td><p> r3c2 </p></td>\n" +
+ "\n" +
+ "<td><p>r3c4</p></td>\n" +
+ "\n" +
+ "\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "<td rowspan='3'><p> r4c1 </p></td>\n" +
+ "<td><p> r4c2 </p></td>\n" +
+ "<td rowspan='3'><p> r4c3 </p></td>\n" +
+ "<td><p> r4c4 </p></td>\n" +
+ "<td rowspan='3'><p> r4c5 </p></td>\n" +
+ "<td rowspan='3'><p> r4c6 </p></td>\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "\n" +
+ "<td><p> r2c2 </p></td>\n" +
+ "\n" +
+ "<td><p> r2c4 </p></td>\n" +
+ "\n" +
+ "\n" +
+ "</tr>\n" +
+ "<tr>\n" +
+ "\n" +
+ "<td><p> r3c2 </p></td>\n" +
+ "\n" +
+ "<td><p>r3c4</p></td>\n" +
+ "\n" +
+ "\n" +
+ "</tr>\n" +
+ "</table>\n";
+ Page page = new Page(null);
+ page.setOriginalText(input);
+ tester.convert(page);
+ actual = page.getConvertedText();
+ assertNotNull(actual);
+ assertEquals(expected, actual);
+ }
}
diff --git a/src/com/atlassian/uwc/hierarchies/ContentHierarchyTest.java b/src/com/atlassian/uwc/hierarchies/ContentHierarchyTest.java
index 71564f6..9095c8f 100644
--- a/src/com/atlassian/uwc/hierarchies/ContentHierarchyTest.java
+++ b/src/com/atlassian/uwc/hierarchies/ContentHierarchyTest.java
@@ -4,9 +4,8 @@
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
+import java.util.Collection;
import java.util.Properties;
-import java.util.Set;
import java.util.Vector;
import junit.framework.TestCase;
@@ -49,13 +48,13 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> children1 = actual.getChildren();
+ Collection<HierarchyNode> children1 = actual.getChildren();
assertEquals(1, children1.size());
Vector<HierarchyNode> nodes1 = new Vector<HierarchyNode>();
nodes1.addAll(children1);
assertTrue((nodes1.get(0)).getName().equals("Plants"));
- Set<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
+ Collection<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
assertEquals(2, children2.size());
Vector<HierarchyNode> nodes2 = new Vector<HierarchyNode>();
nodes2.addAll(children2);
@@ -74,7 +73,7 @@
treenode = nodes2.get(1);
}
- Set<HierarchyNode> treechildren = treenode.getChildren();
+ Collection<HierarchyNode> treechildren = treenode.getChildren();
assertEquals(2, treechildren.size());
Vector<HierarchyNode> trees = new Vector<HierarchyNode>();
trees.addAll(treechildren);
@@ -83,7 +82,7 @@
assertTrue((trees.get(1)).getName().equals("Chestnut") ||
(trees.get(1)).getName().equals("Pine"));
- Set<HierarchyNode> flowerchildren = flowernode.getChildren();
+ Collection<HierarchyNode> flowerchildren = flowernode.getChildren();
assertEquals(3, flowerchildren.size());
Vector<HierarchyNode> flowers = new Vector<HierarchyNode>();
flowers.addAll(flowerchildren);
@@ -128,19 +127,19 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> home = actual.getChildren();
+ Collection<HierarchyNode> home = actual.getChildren();
assertEquals(1, home.size());
Vector<HierarchyNode> nodes0 = new Vector<HierarchyNode>();
nodes0.addAll(home);
assertTrue((nodes0.get(0)).getName().equals("Home"));
- Set<HierarchyNode> children1 = nodes0.get(0).getChildren();
+ Collection<HierarchyNode> children1 = nodes0.get(0).getChildren();
assertEquals(1, children1.size());
Vector<HierarchyNode> nodes1 = new Vector<HierarchyNode>();
nodes1.addAll(children1);
assertTrue((nodes1.get(0)).getName().equals("Plants"));
- Set<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
+ Collection<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
assertEquals(2, children2.size());
Vector<HierarchyNode> nodes2 = new Vector<HierarchyNode>();
nodes2.addAll(children2);
@@ -159,7 +158,7 @@
treenode = nodes2.get(1);
}
- Set<HierarchyNode> treechildren = treenode.getChildren();
+ Collection<HierarchyNode> treechildren = treenode.getChildren();
assertEquals(2, treechildren.size());
Vector<HierarchyNode> trees = new Vector<HierarchyNode>();
trees.addAll(treechildren);
@@ -168,7 +167,7 @@
assertTrue((trees.get(1)).getName().equals("Chestnut") ||
(trees.get(1)).getName().equals("Pine"));
- Set<HierarchyNode> flowerchildren = flowernode.getChildren();
+ Collection<HierarchyNode> flowerchildren = flowernode.getChildren();
assertEquals(3, flowerchildren.size());
Vector<HierarchyNode> flowers = new Vector<HierarchyNode>();
flowers.addAll(flowerchildren);
@@ -208,13 +207,13 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> children1 = actual.getChildren();
+ Collection<HierarchyNode> children1 = actual.getChildren();
assertEquals(1, children1.size());
Vector<HierarchyNode> nodes1 = new Vector<HierarchyNode>();
nodes1.addAll(children1);
assertTrue((nodes1.get(0)).getName().equals("Plants"));
- Set<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
+ Collection<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
assertEquals(3, children2.size());
Vector<HierarchyNode> nodes2 = new Vector<HierarchyNode>();
nodes2.addAll(children2);
@@ -232,7 +231,7 @@
if (node.getName().equals("Plants_Nuts")) nutnode = node;
}
- Set<HierarchyNode> treechildren = treenode.getChildren();
+ Collection<HierarchyNode> treechildren = treenode.getChildren();
assertEquals(2, treechildren.size());
Vector<HierarchyNode> trees = new Vector<HierarchyNode>();
trees.addAll(treechildren);
@@ -241,7 +240,7 @@
assertTrue((trees.get(1)).getName().equals("Plants_Trees_Chestnut") ||
(trees.get(1)).getName().equals("Plants_Trees_Pine"));
- Set<HierarchyNode> flowerchildren = flowernode.getChildren();
+ Collection<HierarchyNode> flowerchildren = flowernode.getChildren();
assertEquals(3, flowerchildren.size());
Vector<HierarchyNode> flowers = new Vector<HierarchyNode>();
flowers.addAll(flowerchildren);
@@ -255,7 +254,7 @@
(flowers.get(2)).getName().equals("Plants_Flowers_Daisy") ||
(flowers.get(2)).getName().equals("Plants_Flowers_Orchid"));
- Set<HierarchyNode> nutchildren = nutnode.getChildren();
+ Collection<HierarchyNode> nutchildren = nutnode.getChildren();
assertEquals(2, nutchildren.size());
Vector<HierarchyNode> nuts = new Vector<HierarchyNode>();
nuts.addAll(nutchildren);
@@ -296,13 +295,13 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> children1 = actual.getChildren();
+ Collection<HierarchyNode> children1 = actual.getChildren();
assertEquals(1, children1.size());
Vector<HierarchyNode> nodes1 = new Vector<HierarchyNode>();
nodes1.addAll(children1);
assertTrue((nodes1.get(0)).getName().equals("Plants"));
- Set<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
+ Collection<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
assertEquals(3, children2.size());
Vector<HierarchyNode> nodes2 = new Vector<HierarchyNode>();
nodes2.addAll(children2);
@@ -320,7 +319,7 @@
if (node.getName().equals("Nuts")) nutnode = node;
}
- Set<HierarchyNode> treechildren = treenode.getChildren();
+ Collection<HierarchyNode> treechildren = treenode.getChildren();
assertEquals(2, treechildren.size());
Vector<HierarchyNode> trees = new Vector<HierarchyNode>();
trees.addAll(treechildren);
@@ -329,7 +328,7 @@
assertTrue((trees.get(1)).getName().equals("Chestnut") ||
(trees.get(1)).getName().equals("Pine"));
- Set<HierarchyNode> flowerchildren = flowernode.getChildren();
+ Collection<HierarchyNode> flowerchildren = flowernode.getChildren();
assertEquals(3, flowerchildren.size());
Vector<HierarchyNode> flowers = new Vector<HierarchyNode>();
flowers.addAll(flowerchildren);
@@ -343,7 +342,7 @@
(flowers.get(2)).getName().equals("Daisy") ||
(flowers.get(2)).getName().equals("Orchid"));
- Set<HierarchyNode> nutchildren = nutnode.getChildren();
+ Collection<HierarchyNode> nutchildren = nutnode.getChildren();
assertEquals(2, nutchildren.size());
Vector<HierarchyNode> nuts = new Vector<HierarchyNode>();
nuts.addAll(nutchildren);
@@ -376,13 +375,13 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> children1 = actual.getChildren();
+ Collection<HierarchyNode> children1 = actual.getChildren();
assertEquals(1, children1.size());
Vector<HierarchyNode> nodes1 = new Vector<HierarchyNode>();
nodes1.addAll(children1);
assertTrue((nodes1.get(0)).getName().equals("Plants"));
- Set<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
+ Collection<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
assertEquals(2, children2.size());
Vector<HierarchyNode> nodes2 = new Vector<HierarchyNode>();
nodes2.addAll(children2);
@@ -397,7 +396,7 @@
if (node.getName().equals("Plants Nuts")) nutnode = node;
}
- Set<HierarchyNode> flowerchildren = flowernode.getChildren();
+ Collection<HierarchyNode> flowerchildren = flowernode.getChildren();
assertEquals(2, flowerchildren.size());
Vector<HierarchyNode> flowers = new Vector<HierarchyNode>();
flowers.addAll(flowerchildren);
@@ -406,7 +405,7 @@
assertTrue((flowers.get(1)).getName().equals("Plants Flowers Rose") ||
(flowers.get(1)).getName().equals("Plants Flowers Orchid"));
- Set<HierarchyNode> nutchildren = nutnode.getChildren();
+ Collection<HierarchyNode> nutchildren = nutnode.getChildren();
assertEquals(1, nutchildren.size());
Vector<HierarchyNode> nuts = new Vector<HierarchyNode>();
nuts.addAll(nutchildren);
@@ -447,13 +446,13 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> children1 = actual.getChildren();
+ Collection<HierarchyNode> children1 = actual.getChildren();
assertEquals(1, children1.size());
Vector<HierarchyNode> nodes1 = new Vector<HierarchyNode>();
nodes1.addAll(children1);
assertTrue((nodes1.get(0)).getName().equals("Plants"));
- Set<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
+ Collection<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
assertEquals(1, children2.size());
Vector<HierarchyNode> nodes2 = new Vector<HierarchyNode>();
nodes2.addAll(children2);
@@ -461,7 +460,7 @@
HierarchyNode treenode = nodes2.get(0);
- Set<HierarchyNode> treechildren = treenode.getChildren();
+ Collection<HierarchyNode> treechildren = treenode.getChildren();
assertEquals(5, treechildren.size());
Vector<HierarchyNode> trees = new Vector<HierarchyNode>();
trees.addAll(treechildren);
@@ -518,19 +517,19 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> home = actual.getChildren();
+ Collection<HierarchyNode> home = actual.getChildren();
assertEquals(1, home.size());
Vector<HierarchyNode> nodes0 = new Vector<HierarchyNode>();
nodes0.addAll(home);
assertTrue((nodes0.get(0)).getName().equals("Home"));
- Set<HierarchyNode> children1 = nodes0.get(0).getChildren();
+ Collection<HierarchyNode> children1 = nodes0.get(0).getChildren();
assertEquals(1, children1.size());
Vector<HierarchyNode> nodes1 = new Vector<HierarchyNode>();
nodes1.addAll(children1);
assertTrue((nodes1.get(0)).getName().equals("Plants"));
- Set<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
+ Collection<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
assertEquals(1, children2.size());
Vector<HierarchyNode> nodes2 = new Vector<HierarchyNode>();
nodes2.addAll(children2);
@@ -538,7 +537,7 @@
HierarchyNode treenode = nodes2.get(0);
- Set<HierarchyNode> treechildren = treenode.getChildren();
+ Collection<HierarchyNode> treechildren = treenode.getChildren();
assertEquals(5, treechildren.size());
Vector<HierarchyNode> trees = new Vector<HierarchyNode>();
trees.addAll(treechildren);
@@ -593,7 +592,7 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> children1 = actual.getChildren();
+ Collection<HierarchyNode> children1 = actual.getChildren();
assertEquals(1, children1.size());
Vector<HierarchyNode> nodes1 = new Vector<HierarchyNode>();
nodes1.addAll(children1);
@@ -631,13 +630,13 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> children1 = actual.getChildren();
+ Collection<HierarchyNode> children1 = actual.getChildren();
assertEquals(1, children1.size());
Vector<HierarchyNode> nodes1 = new Vector<HierarchyNode>();
nodes1.addAll(children1);
assertTrue((nodes1.get(0)).getName().equals("Plants"));
- Set<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
+ Collection<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
assertEquals(1, children2.size());
Vector<HierarchyNode> nodes2 = new Vector<HierarchyNode>();
nodes2.addAll(children2);
@@ -645,7 +644,7 @@
HierarchyNode treenode = nodes2.get(0);
- Set<HierarchyNode> treechildren = treenode.getChildren();
+ Collection<HierarchyNode> treechildren = treenode.getChildren();
assertEquals(5, treechildren.size());
Vector<HierarchyNode> trees = new Vector<HierarchyNode>();
trees.addAll(treechildren);
@@ -808,13 +807,13 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> children1 = actual.getChildren();
+ Collection<HierarchyNode> children1 = actual.getChildren();
assertEquals(1, children1.size());
Vector<HierarchyNode> nodes1 = new Vector<HierarchyNode>();
nodes1.addAll(children1);
assertTrue((nodes1.get(0)).getName().equals("TestPage"));
- Set<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
+ Collection<HierarchyNode> children2 = (nodes1.get(0)).getChildren();
assertEquals(3, children2.size());
Vector<HierarchyNode> nodes2 = new Vector<HierarchyNode>();
nodes2.addAll(children2);
@@ -824,7 +823,7 @@
HierarchyNode parent0node = nodes2.get(2);
- Set<HierarchyNode> p0children = parent0node.getChildren();
+ Collection<HierarchyNode> p0children = parent0node.getChildren();
assertEquals(2, p0children.size());
Vector<HierarchyNode> p0 = new Vector<HierarchyNode>();
p0.addAll(p0children);
diff --git a/src/com/atlassian/uwc/hierarchies/DocDirectoryHierarchyTest.java b/src/com/atlassian/uwc/hierarchies/DocDirectoryHierarchyTest.java
index adb7d14..bb09e8d 100644
--- a/src/com/atlassian/uwc/hierarchies/DocDirectoryHierarchyTest.java
+++ b/src/com/atlassian/uwc/hierarchies/DocDirectoryHierarchyTest.java
@@ -1,8 +1,8 @@
package com.atlassian.uwc.hierarchies;
import java.io.File;
+import java.util.Collection;
import java.util.Properties;
-import java.util.Set;
import java.util.Vector;
import junit.framework.TestCase;
@@ -10,7 +10,6 @@
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
-import com.atlassian.uwc.filters.NoSvnFilter;
import com.atlassian.uwc.ui.Page;
public class DocDirectoryHierarchyTest extends TestCase {
@@ -49,7 +48,7 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> children1 = actual.getChildren();
+ Collection<HierarchyNode> children1 = actual.getChildren();
assertEquals(1, children1.size());
Vector<HierarchyNode> nodes1 = new Vector<HierarchyNode>();
nodes1.addAll(children1);
@@ -60,7 +59,7 @@
File file = (File) object;
assertTrue("test.txt".equals(file.getName()));
- Set<HierarchyNode> children2 = nodes1.get(0).getChildren();
+ Collection<HierarchyNode> children2 = nodes1.get(0).getChildren();
assertEquals(3, children2.size());
Vector<HierarchyNode> nodes2 = new Vector<HierarchyNode>();
nodes2.addAll(children2);
@@ -76,7 +75,7 @@
assertTrue("test1.txt".equals(filea.getName())||
"test2.txt".equals(filea.getName())
);
- Set<HierarchyNode> children3 = node.getChildren();
+ Collection<HierarchyNode> children3 = node.getChildren();
assertEquals(1, children3.size());
Vector<HierarchyNode> nodes3 = new Vector<HierarchyNode>();
nodes3.addAll(children3);
@@ -123,7 +122,7 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> children1 = actual.getChildren();
+ Collection<HierarchyNode> children1 = actual.getChildren();
assertEquals(1, children1.size());
Vector<HierarchyNode> nodes1 = new Vector<HierarchyNode>();
nodes1.addAll(children1);
@@ -152,7 +151,7 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> children1 = actual.getChildren();
+ Collection<HierarchyNode> children1 = actual.getChildren();
assertEquals(1, children1.size());
Vector<HierarchyNode> nodes1 = new Vector<HierarchyNode>();
nodes1.addAll(children1);
@@ -183,7 +182,7 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> children1 = actual.getChildren();
+ Collection<HierarchyNode> children1 = actual.getChildren();
assertEquals(1, children1.size());
Vector<HierarchyNode> nodes1 = new Vector<HierarchyNode>();
nodes1.addAll(children1);
@@ -194,7 +193,7 @@
File file = (File) object;
assertTrue("test.txt".equals(file.getName()));
- Set<HierarchyNode> children2 = nodes1.get(0).getChildren();
+ Collection<HierarchyNode> children2 = nodes1.get(0).getChildren();
assertEquals(2, children2.size());
Vector<HierarchyNode> nodes2 = new Vector<HierarchyNode>();
nodes2.addAll(children2);
diff --git a/src/com/atlassian/uwc/hierarchies/DokuwikiHierarchy.java b/src/com/atlassian/uwc/hierarchies/DokuwikiHierarchy.java
index 512c1d1..7479af6 100644
--- a/src/com/atlassian/uwc/hierarchies/DokuwikiHierarchy.java
+++ b/src/com/atlassian/uwc/hierarchies/DokuwikiHierarchy.java
@@ -2,6 +2,7 @@
import java.io.File;
import java.util.Collection;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
@@ -9,10 +10,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import sun.tools.tree.AddExpression;
-
import com.atlassian.uwc.converters.dokuwiki.HierarchyTitleConverter;
-import com.atlassian.uwc.converters.tikiwiki.RegexUtil;
import com.atlassian.uwc.filters.NoSvnFilter;
import com.atlassian.uwc.ui.Page;
@@ -21,20 +19,35 @@
int newpagescount = 0;
public HierarchyNode buildHierarchy(Collection<Page> pages) {
+// getRootNode().setChildrenComparator(dokuComparator());
+ getRootNode().childrenAsList(true);
log.debug("Number of hierarchy pages: " + pages.size());
//run the filepath hierarchy first -
HierarchyNode node = super.buildHierarchy(pages);
+// log.debug("filepath hierarchy tree:");
+// printTree(node);
//move spacekeys
- node = handleSpacekeyBranchWithProp(node);
- //handle start pages
- node = handleHomePages(node, true);
+// node = handleSpacekeyBranchWithProp(node);
//handle spacekeys not with a property, but with page.getSpacekey setting
node = handleSpacekeyBranchWithPage(node);
+// log.debug("branching by spacekey:");
+// printTree(node);
+ //handle start pages
+ node = handleHomePages(node, true);
+// log.debug("merging home pages:");
+// printTree(node);
//fix collisions
node = fixCollisions(node);
+// log.debug("fix collisions:");
+// printTree(node);
+ //fix broken branches
+ node = mergeBrokenNodes(node);
+// log.debug("merge broken nodes:");
+// printTree(node);
//fix titles
node = fixTitles(node);
+// log.debug("fix titles:");
//attach images - old attachment handling. Idea is to put the attachments in the
//new confluence page corresponding with the media directory for that namespace
//but this doesn't work if the media dir doesn't correspond to an existing pages namespace
@@ -53,10 +66,12 @@
}
+
+
private HierarchyNode handleSpacekeyBranchWithProp(HierarchyNode node) {
String spacekey = getProperties().getProperty("spacekey");
if (spacekey != null && !"".equals(spacekey)) {
- Set<HierarchyNode> top = node.getChildren();
+ Collection<HierarchyNode> top = node.getChildren();
for (Iterator iter = top.iterator(); iter.hasNext();) {
HierarchyNode topnode = (HierarchyNode) iter.next();
if (topnode.getName().toLowerCase().equals(spacekey.toLowerCase())) {
@@ -70,7 +85,7 @@
}
private HierarchyNode handleSpacekeyBranchWithPage(HierarchyNode root) {
- Set<HierarchyNode> top = root.getChildren();
+ Collection<HierarchyNode> top = root.getChildren();
Vector<HierarchyNode> ordered = new Vector<HierarchyNode>(top);
for (HierarchyNode topnode : ordered) {
root = handleSpacekeyBranchTop(root, topnode);
@@ -85,27 +100,8 @@
else if (node.getPage().getSpacekey() != null) {
String spacekey = node.getPage().getSpacekey();
node = setAncestorsBySpacekey(root, node, spacekey);
- if (node.getParent() == null) {
- Set<HierarchyNode> top = root.getChildren();
- Vector<HierarchyNode> ordered = new Vector<HierarchyNode>(top);
- for (HierarchyNode topnode : ordered) {
- if (topnode.getPage() == null) {
- log.debug("NULL! (Skipping) topnode.getName() = " + topnode.getName());
- continue;
- }
- if (spacekey.equals(topnode.getPage().getSpacekey())) {
- Set<HierarchyNode> children = topnode.getChildren();
- log.debug("Moving topnode: " + topnode.getPage().getName());
- topnode.setParent(null); //since we have to use iter.remove instead of node.removeChild(topnode)
- for (HierarchyNode child : children) {
- root.addChild(child);
- }
- break;
- }
- }
- }
}
- Set<HierarchyNode> nextSet = node.getChildren();
+ Collection<HierarchyNode> nextSet = node.getChildren();
Vector<HierarchyNode> ordered = new Vector<HierarchyNode>(nextSet);
for (HierarchyNode next : ordered) {
root = handleSpacekeyBranchTop(root, next);
@@ -138,17 +134,56 @@
}
else if (!parent.getPage().getSpacekey().equals(spacekey)) {
log.debug("...parent.getPage().getSpacekey: " + parent.getPage().getSpacekey() + "... and spacekey: " + spacekey);
- log.debug("Copying branch to new parent because of spacekey: " + node.getName());
-
- copyBranch(node, spacekey, parent);
-
+ HierarchyNode branch = hasSpaceBranchAlready(parent, spacekey);
+ if (branch != null) {
+ log.debug("Moving node ('"+node.getName()+"') to existing branch ('"+branch.getName()+"') because of spacekey: " + spacekey);
+ moveBranch(node, parent, branch);
+ }
+ else {
+ log.debug("Copying branch to new parent because of spacekey: " + node.getName());
+ copyBranch(node, spacekey, parent);
+ }
+// log.debug("Printing the whole tree after copy/move");
+// printTree(root);
}
return node;
}
+ private HierarchyNode hasSpaceBranchAlready(HierarchyNode parent, String spacekey) {
+ HierarchyNode current = parent;
+ int level = 0;
+ while (current.getPage() != null) {
+ current = current.getParent();
+ for (HierarchyNode child : current.getChildren()) {
+ String childspace = (child.getPage() == null)?"":child.getPage().getSpacekey();
+ if (childspace.equalsIgnoreCase(spacekey)) {
+ HierarchyNode depthNode = child;
+ while (level-- > 0) {
+ if (depthNode.getChildren().size()>0) {
+ Vector<HierarchyNode> onenode = new Vector<HierarchyNode>(depthNode.getChildren());
+ depthNode = onenode.firstElement();
+ }
+ }
+ return depthNode;
+ }
+ }
+ level++;
+ }
+ return null;
+ }
+
+
+ private void moveBranch(HierarchyNode node, HierarchyNode parent, HierarchyNode branch) {
+ log.debug("node: " + node.getName() + " parent: " + parent.getName() + " branch: " + branch.getName());
+ parent.removeChild(node);
+ branch.addChild(node);
+ }
+
+
public void copyBranch(HierarchyNode node, String spacekey,
HierarchyNode parent) {
+ log.debug("node: " + node.getName() + " parent: " + parent.getName());
HierarchyNode newparent = new HierarchyNode();
newparent.setName(parent.getName());
Page newparentpage = createPage(parent.getName());
@@ -158,15 +193,19 @@
if (parent.getPage().getConvertedText() != null)
newparentpage.setConvertedText(parent.getPage().getConvertedText());
newparent.setPage(newparentpage);
- parent.removeChild(node);
+ HierarchyNode gparent = parent.getParent();
+ if (!parent.removeChild(node)) {
+// log.debug("tree for parent: " + parent.getName());
+// printTree(parent);
+ }
newparent.addChild(node);
- parent.getParent().addChild(newparent);
- if (parent.getParent().getName() == null) return;
- copyBranch(newparent, spacekey, parent.getParent());
+ gparent.addChild(newparent);
+ if (gparent.getName() == null) return;
+ copyBranch(newparent, spacekey, gparent);
}
private void setTopNodeBranch(HierarchyNode root, Iterator topiter, HierarchyNode nexttopnode) {
- Set<HierarchyNode> children = nexttopnode.getChildren();
+ Collection<HierarchyNode> children = nexttopnode.getChildren();
topiter.remove(); //Only allowed way to remove from an iterator.
nexttopnode.setParent(null); //since we have to use iter.remove instead of node.removeChild(topnode)
for (HierarchyNode child : children) {
@@ -175,7 +214,7 @@
}
private HierarchyNode handleHomePages(HierarchyNode node, boolean top) {
- Set<HierarchyNode> children = node.getChildren();
+ Collection<HierarchyNode> children = node.getChildren();
for (Iterator iter = children.iterator(); iter.hasNext();) {
HierarchyNode child = (HierarchyNode) iter.next();
String name = child.getName();
@@ -201,17 +240,19 @@
private HierarchyNode fixCollisions(HierarchyNode node) {
- Set<HierarchyNode> children = node.getChildren();
- for (Iterator iter = children.iterator(); iter.hasNext();) {
- HierarchyNode child = (HierarchyNode) iter.next();
+ Collection<HierarchyNode> children = node.getChildren();
+ Vector<HierarchyNode> childrenV = new Vector<HierarchyNode>(children);
+ for (int i = 0; i < childrenV.size(); i++) {
+ HierarchyNode child = (HierarchyNode) childrenV.get(i);
Vector<String> collisions = getCollisionsForThisNode(child);
- for (String name : collisions) {
+ for (int j = 0; j < collisions.size(); j++) {
+ String name = collisions.get(j);
String eqname = equalize(name);
String childname = equalize(child.getName());
if (childname.equals(eqname)) {
log.debug("Examining collisions candidate: '" + eqname + "' for this child: '" + childname + "'");
- String parent = child.getParent().getName();
+ String parent = getParentTitle(child);
log.debug("parent = " + parent);
if (parent == null) continue;
String newname = parent + " " + child.getName();
@@ -224,7 +265,114 @@
}
return node;
}
+
+ private static int numericCollisionCounter = 2;
+ private HierarchyNode mergeBrokenNodes(HierarchyNode node) {
+
+ Collection<HierarchyNode> children = node.getChildren();
+ Vector<HierarchyNode> childrenV = new Vector<HierarchyNode>(children);
+ for (int i = 0; i < childrenV.size(); i++) {
+ HierarchyNode child = (HierarchyNode) childrenV.get(i);
+ log.debug("Merging child: '" + child.getName()+"'");
+ HierarchyNode parent = child.getParent();
+ if (child.getPage() != null && child.getPage().getFile() != null) {
+ Collection<HierarchyNode> siblingsSet = parent.getChildren();
+ Vector<HierarchyNode> siblings = new Vector<HierarchyNode>();
+ for (HierarchyNode s : siblingsSet) {
+ if (!s.equals(child)) {
+ siblings.add(s);
+ }
+ }
+// log.debug("sibling size: " + siblings.size());
+ for (int j = 0; j < siblings.size(); j++) {
+ HierarchyNode sibling = siblings.get(j);
+// log.debug("all siblings: " + sibling.getName());
+ if (sibling.getPage() == null || sibling.getPage().getFile() == null) {
+ if (compareNodes(child, sibling)) {
+ mergeTwoNodes(child, sibling, parent);
+ }
+ }
+ else if (child.getName().equalsIgnoreCase(sibling.getName())) {
+ String newname = sibling.getName() + " " + numericCollisionCounter++;
+ log.debug("Found conflicting node. Changing name to: '"+ newname + "'");
+ sibling.setName(newname);
+ sibling.getPage().setName(newname);
+ }
+ }
+ }
+// log.debug("***v");
+ child = mergeBrokenNodes(child);
+ }
+ return node;
+ }
+
+
+ protected void mergeTwoNodes(HierarchyNode first, HierarchyNode second,
+ HierarchyNode parent) {
+ log.debug("Merging second node (sibling): '" + second.getName()+"'");
+ for (HierarchyNode gchild : second.getChildren()) {
+// log.debug("adding child: " + gchild.getName());
+ first.addChild(gchild);
+ }
+ if (parent != null) {
+ if (!parent.removeChild(second)) {
+// log.debug("parent tree");
+// printTree(parent);
+ }
+ }
+// log.debug("child tree");
+// printTreeOneLevel(first);
+ }
+
+
+ /**
+ * Uses the filepath of the first node to compare names with the second node.
+ * Note, these nodes should already be at the same depth and have the same parent before
+ * calling this method.
+ * @param first should have a page with a file object
+ * @param second must have node name, but doesn't need page
+ * @return if they are the same node
+ */
+ protected boolean compareNodes(HierarchyNode first, HierarchyNode second) {
+ String filename = first.getPage().getFile().getName();
+ filename = filename.replaceFirst("\\.txt$", "");
+ boolean samenode = equalize(second.getName()).equals(equalize(filename));
+ if (samenode) {
+ log.debug("first node name: " + first.getName() + " and full file path: " + first.getPage().getFile().getAbsolutePath());
+ log.debug("filename of first node: " + filename + " and equalized: " + equalize(filename));
+ log.debug("second node name: " + second.getName() + " and equalized: " + equalize(second.getName()));
+ log.debug("first spacekey " + first.getPage().getSpacekey() + " ... second spacekey " + ((second.getPage()!=null)?second.getPage().getSpacekey():"null"));
+ }
+ return samenode;
+ }
+
+ protected String getParentTitle(HierarchyNode child) {
+ String basename = child.getParent().getName();
+ //unchanged source is set in the engine.
+ //if it's null, we created the parent in the hierarchy, so we need to review the title
+ if (child.getParent().getPage() != null && child.getParent().getPage().getUnchangedSource() != null)
+ return child.getParent().getPage().getName();
+ log.debug("Attempting to identify meta name for parent title.");
+ HierarchyNode gparent = child.getParent().getParent();
+ if (gparent == null) return basename;
+ Collection<HierarchyNode> siblingsSet = gparent.getChildren();
+ Vector<HierarchyNode> siblings = new Vector<HierarchyNode>(siblingsSet);
+ for (int i = 0; i < siblings.size(); i++) {
+ HierarchyNode sibling = (HierarchyNode) siblings.get(i);
+ if (sibling.getPage() != null && sibling.getPage().getFile() != null) {
+// log.debug("Examining sibling: "+ sibling.getName());
+ String filename = sibling.getPage().getFile().getName();
+ filename = filename.replaceFirst("\\.txt$", "");
+ if (equalize(basename).equals(equalize(filename))) {
+ log.debug("returning sibling name: " + sibling.getName());
+ return sibling.getName();
+ }
+ }
+ }
+ return basename;
+ }
+
public Vector<String> getCollisionsForThisNode(HierarchyNode node) {
String spacekey = (node.getPage() != null && node.getPage().getSpacekey() != null)?
node.getPage().getSpacekey() :
@@ -235,12 +383,12 @@
protected Vector<String> getCollisionsCandidates(String spacekey) {
Properties props = getProperties();
Vector<String> candidates = new Vector<String>();
- log.debug("Looking for collisions candidates for spacekey: " + spacekey);
+// log.debug("Looking for collisions candidates for spacekey: " + spacekey);
for (Iterator iter = props.keySet().iterator();iter.hasNext();) {
String key = (String) iter.next();
if (key.toLowerCase().startsWith("collision-titles-"+spacekey.toLowerCase())) {
String namesraw = props.getProperty(key, "");
- log.debug("Found collisions data: " + namesraw);
+// log.debug("Found collisions data: " + namesraw);
if ("".equals(namesraw)) continue;
String[] names = namesraw.split(",");
for (String name : names) {
@@ -249,12 +397,12 @@
}
}
}
- log.debug("candidates size? " + candidates.size());
+// log.debug("candidates size? " + candidates.size());
return candidates;
}
private HierarchyNode attachAllImages(HierarchyNode node, Vector<File> attdirs, boolean top) {
- Set<HierarchyNode> children = node.getChildren();
+ Collection<HierarchyNode> children = node.getChildren();
for (Iterator iter = children.iterator(); iter.hasNext();) {
HierarchyNode child = (HierarchyNode) iter.next();
String name = getOrigChildName(child);
@@ -322,13 +470,14 @@
}
private Page createPage(String name) {
- Page page = new Page(null);
- page.setName(name);
- page.setOriginalText("");
- page.setConvertedText("");
- page.setPath(name);
- newpagescount++;
- return page;
+ log.debug("Creating page in hierarchy for: " + name);
+ Page page = new Page(null);
+ page.setName(name);
+ page.setOriginalText("");
+ page.setConvertedText("");
+ page.setPath(name);
+ newpagescount++;
+ return page;
}
NoSvnFilter svnfilter = new NoSvnFilter();
@@ -356,7 +505,7 @@
HierarchyTitleConverter titleConverter = new HierarchyTitleConverter();
//nodes without pages probably will need this
private HierarchyNode fixTitles(HierarchyNode node) {
- Set<HierarchyNode> children = node.getChildren();
+ Collection<HierarchyNode> children = node.getChildren();
for (Iterator iter = children.iterator(); iter.hasNext();) {
HierarchyNode child = (HierarchyNode) iter.next();
if (child.getPage() == null)
@@ -378,32 +527,45 @@
private int count;
@Override
protected void buildRelationships(Page page, HierarchyNode root) {
+ log.debug("Building Relationship for page: " + page.getName() + " -> " + page.getFile().getName());
currentpage = page;
combineHomepageNodes = false;
currentParent = null;
super.buildRelationships(page, root);
if (combineHomepageNodes) {
- combineHomepages(page);
+ combineHomepages();
}
- log.debug("++count: "+(count++) +", completed building relationship for page: " + page.getName());
+ log.debug("++count: "+(count++) +", completed building relationship for page: " + page.getName() + " -> " + page.getFile().getName());
}
- public void combineHomepages(Page page) {
- Set<HierarchyNode> children = currentParent.getChildren();
+ public void combineHomepages() {
+ Collection<HierarchyNode> children = currentParent.getChildren();
Vector<HierarchyNode> all = new Vector<HierarchyNode>(children);
HierarchyNode first = null, second = null;
- for (HierarchyNode node : all) {
- if (node.getName().equalsIgnoreCase(page.getName())) {
- if (first == null) first = node;
- else second = node;
+ for (int i = 0; i < all.size()-1 && all.size() > 1; i++) {
+ first = all.get(i);
+ second = all.get(i+1);
+ if (first == null || second == null) continue;
+ log.debug ("first = " + first.getName() + " second = " + second.getName());
+ if ((first.getPage() == null || first.getPage().getFile() == null)) {
+ if (second.getPage() != null && second.getPage().getFile() != null) {
+ HierarchyNode tmp = first;
+ first = second;
+ second = tmp;
+ log.debug ("first = " + first.getName() + " second = " + second.getName());
+ }
+ else continue;
}
- }
- if (first.getPage() == null) {
- combineHomepages(first, second, page);
- }
- else {
- combineHomepages(second, first, page);
+ if (compareNodes(first, second)) {
+
+ if (first.getPage() == null) {
+ combineHomepages(first, second, second.getPage());
+ }
+ else {
+ combineHomepages(second, first, first.getPage());
+ }
+ }
}
}
@@ -411,7 +573,7 @@
Page page) {
if (noChildrenNode.getPage() == null) return;//indicates this isn't the right scenario to combine
if (noChildrenNode.getChildren().size() > 0) {
- log.error("Combining Homepages - noChildrenNode has children!: " + noChildrenNode.getName());
+ mergeTwoNodes(noChildrenNode, nullPageNode, noChildrenNode.getParent());
return;
}
log.debug("Combining: " + page.getName());
@@ -428,6 +590,7 @@
if (parent.getPage() == null && currentpage.getName().equalsIgnoreCase(childname)) {
combineHomepageNodes = true;
currentParent = parent;
+ log.debug("-> (dokuwikihierarchy check) false");
return false;
}
return hasRel;
@@ -442,11 +605,21 @@
printTree(node.getChildren(), "");
}
- private void printTree(Set<HierarchyNode> children, String delim) {
+ private void printTree(Collection<HierarchyNode> children, String delim) {
for (HierarchyNode child : children) {
- String newdelim = delim + " ";
- log.debug("PRINTTREE: " + newdelim + child.getName());
+ String newdelim = delim + " .";
+ String childdata = child.getName();
+// if (child.getPage() != null && child.getPage().getFile() != null)
+// childdata += " -> " + child.getPage().getFile().getAbsolutePath();
+ log.debug("PRINTTREE: " + newdelim + childdata);
printTree(child.getChildren(), newdelim);
}
}
+
+ private void printTreeOneLevel(HierarchyNode node) {
+ Collection<HierarchyNode> children = node.getChildren();
+ for (HierarchyNode child : children) {
+ log.debug("PRINTTREE: " + child.getName());
+ }
+ }
}
diff --git a/src/com/atlassian/uwc/hierarchies/DokuwikiHierarchyTest.java b/src/com/atlassian/uwc/hierarchies/DokuwikiHierarchyTest.java
index d53f184..e46f49c 100644
--- a/src/com/atlassian/uwc/hierarchies/DokuwikiHierarchyTest.java
+++ b/src/com/atlassian/uwc/hierarchies/DokuwikiHierarchyTest.java
@@ -56,7 +56,7 @@
assertNull(root.getParent());
assertNotNull(root.getChildren());
- Set<HierarchyNode> top = root.getChildren();
+ Collection<HierarchyNode> top = root.getChildren();
assertEquals(5, top.size());
Vector<HierarchyNode> nodes0 = new Vector<HierarchyNode>();
nodes0.addAll(top);
@@ -142,7 +142,7 @@
assertNull(root.getParent());
assertNotNull(root.getChildren());
- Set<HierarchyNode> top = root.getChildren();
+ Collection<HierarchyNode> top = root.getChildren();
assertEquals(5, top.size());
Vector<HierarchyNode> nodes0 = new Vector<HierarchyNode>();
nodes0.addAll(top);
@@ -188,7 +188,7 @@
assertNull(root.getParent());
assertNotNull(root.getChildren());
- Set<HierarchyNode> top = root.getChildren();
+ Collection<HierarchyNode> top = root.getChildren();
assertEquals(5, top.size());
Vector<HierarchyNode> nodes0 = new Vector<HierarchyNode>();
nodes0.addAll(top);
@@ -257,7 +257,7 @@
assertNull(root.getParent());
assertNotNull(root.getChildren());
- Set<HierarchyNode> top = root.getChildren();
+ Collection<HierarchyNode> top = root.getChildren();
assertEquals(3, top.size());
Vector<HierarchyNode> nodes0 = new Vector<HierarchyNode>();
nodes0.addAll(top);
@@ -336,7 +336,7 @@
// assertNull(root.getParent());
// assertNotNull(root.getChildren());
//
-// Set<HierarchyNode> top = root.getChildren();
+// Collection<HierarchyNode> top = root.getChildren();
// assertEquals(6, top.size());
// Vector<HierarchyNode> nodes0 = new Vector<HierarchyNode>();
// nodes0.addAll(top);
@@ -426,7 +426,7 @@
assertNull(root.getParent());
assertNotNull(root.getChildren());
- Set<HierarchyNode> top = root.getChildren();
+ Collection<HierarchyNode> top = root.getChildren();
assertEquals(5, top.size());
Vector<HierarchyNode> nodes0 = new Vector<HierarchyNode>();
nodes0.addAll(top);
@@ -479,7 +479,7 @@
assertNull(root.getParent());
assertNotNull(root.getChildren());
- Set<HierarchyNode> top = root.getChildren();
+ Collection<HierarchyNode> top = root.getChildren();
assertEquals(2, top.size());
Vector<HierarchyNode> nodes0 = new Vector<HierarchyNode>();
nodes0.addAll(top);
@@ -558,7 +558,7 @@
assertNull(root.getParent());
assertNotNull(root.getChildren());
- Set<HierarchyNode> top = root.getChildren();
+ Collection<HierarchyNode> top = root.getChildren();
assertEquals(2, top.size());
Vector<HierarchyNode> nodes0 = new Vector<HierarchyNode>();
nodes0.addAll(top);
diff --git a/src/com/atlassian/uwc/hierarchies/FilenameHierarchyTest.java b/src/com/atlassian/uwc/hierarchies/FilenameHierarchyTest.java
index 859b438..86cc4e8 100644
--- a/src/com/atlassian/uwc/hierarchies/FilenameHierarchyTest.java
+++ b/src/com/atlassian/uwc/hierarchies/FilenameHierarchyTest.java
@@ -1,9 +1,8 @@
package com.atlassian.uwc.hierarchies;
import java.io.File;
-import java.util.Comparator;
+import java.util.Collection;
import java.util.Properties;
-import java.util.Set;
import java.util.Vector;
import junit.framework.TestCase;
@@ -39,7 +38,7 @@
HierarchyNode actual = tester.buildHierarchy(pages);
assertNotNull(actual);
- Set<HierarchyNode> nodes = actual.getChildren();
+ Collection<HierarchyNode> nodes = actual.getChildren();
assertNotNull(nodes);
assertEquals(1, nodes.size());
for (HierarchyNode root : nodes) {
@@ -62,7 +61,7 @@
HierarchyNode actual = tester.buildHierarchy(pages);
assertNotNull(actual);
- Set<HierarchyNode> nodes = actual.getChildren();
+ Collection<HierarchyNode> nodes = actual.getChildren();
assertNotNull(nodes);
assertEquals(1, nodes.size());
for (HierarchyNode root : nodes) {
@@ -89,7 +88,7 @@
HierarchyNode actual = tester.buildHierarchy(pages);
assertNotNull(actual);
- Set<HierarchyNode> nodes = actual.getChildren();
+ Collection<HierarchyNode> nodes = actual.getChildren();
assertNotNull(nodes);
assertEquals(1, nodes.size());
for (HierarchyNode root : nodes) {
@@ -122,7 +121,7 @@
HierarchyNode actual = tester.buildHierarchy(pages);
assertNotNull(actual);
- Set<HierarchyNode> nodes = actual.getChildren();
+ Collection<HierarchyNode> nodes = actual.getChildren();
assertNotNull(nodes);
assertEquals(1, nodes.size());
for (HierarchyNode root : nodes) {
@@ -244,7 +243,7 @@
pages.add(page);
}
- private Vector<HierarchyNode> asVector(Set<HierarchyNode> children) {
+ private Vector<HierarchyNode> asVector(Collection<HierarchyNode> children) {
Vector<HierarchyNode> nodes = new Vector<HierarchyNode>();
nodes.addAll(children);
return nodes;
diff --git a/src/com/atlassian/uwc/hierarchies/FilepathHierarchy.java b/src/com/atlassian/uwc/hierarchies/FilepathHierarchy.java
index 6102e31..95a840e 100644
--- a/src/com/atlassian/uwc/hierarchies/FilepathHierarchy.java
+++ b/src/com/atlassian/uwc/hierarchies/FilepathHierarchy.java
@@ -173,7 +173,7 @@
log.debug("...... checking parent '" + parent.getName() + "' has relationship with '" + childname + "'");
boolean relationship = false;
- Set<HierarchyNode> children = parent.getChildren();
+ Collection<HierarchyNode> children = parent.getChildren();
if (children == null || children.isEmpty()) {
log.debug("...... -> parent has no children");
return false;
@@ -226,7 +226,7 @@
*/
protected HierarchyNode getChildNode(HierarchyNode parent, String childname) {
log.debug("...... Getting child node with name: " + childname);
- Set<HierarchyNode> children = parent.getChildren();
+ Collection<HierarchyNode> children = (Collection<HierarchyNode>) parent.getChildren();
if (children == null || children.isEmpty()) {
log.debug("...... -> parent has no children. Returning null.");
return null;
diff --git a/src/com/atlassian/uwc/hierarchies/FilepathHierarchyTest.java b/src/com/atlassian/uwc/hierarchies/FilepathHierarchyTest.java
index 7214176..9ef0f54 100644
--- a/src/com/atlassian/uwc/hierarchies/FilepathHierarchyTest.java
+++ b/src/com/atlassian/uwc/hierarchies/FilepathHierarchyTest.java
@@ -5,7 +5,6 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
-import java.util.Set;
import java.util.Vector;
import junit.framework.TestCase;
@@ -13,7 +12,6 @@
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
-import com.atlassian.uwc.converters.jotspot.TitleConverter;
import com.atlassian.uwc.filters.NoSvnFilter;
import com.atlassian.uwc.ui.Page;
@@ -80,7 +78,7 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> level1ChildSet = actual.getChildren();
+ Collection<HierarchyNode> level1ChildSet = actual.getChildren();
assertEquals(2, level1ChildSet.size());
Vector<HierarchyNode> level1Children = new Vector<HierarchyNode>();
level1Children.addAll(level1ChildSet);
@@ -127,7 +125,7 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> level1ChildSet = actual.getChildren();
+ Collection<HierarchyNode> level1ChildSet = actual.getChildren();
assertEquals(2, level1ChildSet.size());
Vector<HierarchyNode> level1Children = new Vector<HierarchyNode>();
level1Children.addAll(level1ChildSet);
@@ -175,7 +173,7 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> level1ChildSet = actual.getChildren();
+ Collection<HierarchyNode> level1ChildSet = actual.getChildren();
assertEquals(2, level1ChildSet.size());
Vector<HierarchyNode> level1Children = new Vector<HierarchyNode>();
level1Children.addAll(level1ChildSet);
@@ -600,7 +598,7 @@
HierarchyNode root = tester.buildHierarchy(pages);
assertNotNull(root);
assertEquals(6, root.countDescendants());
- Set<HierarchyNode> level1 = root.getChildren();
+ Collection<HierarchyNode> level1 = root.getChildren();
assertNotNull(level1);
assertEquals(2, level1.size());
for (HierarchyNode lvl1Node : level1) {
@@ -611,7 +609,7 @@
else if ("Drink.txt".equals(lvl1Node.getName())) fail("Still have Drink node");
else if ("Comestibles".equals(lvl1Node.getName())) {
assertEquals(3, lvl1Node.countDescendants());
- Set<HierarchyNode> level2 = lvl1Node.getChildren();
+ Collection<HierarchyNode> level2 = lvl1Node.getChildren();
assertNotNull(level2);
assertEquals(2, level2.size());
for (HierarchyNode lvl2Node : level2) {
@@ -622,7 +620,7 @@
}
else if ("Liquid".equals(lvl1Node.getName())) {
assertEquals(2, lvl1Node.countDescendants());
- Set<HierarchyNode> level2 = lvl1Node.getChildren();
+ Collection<HierarchyNode> level2 = lvl1Node.getChildren();
assertNotNull(level2);
assertEquals(1, level2.size());
for (HierarchyNode lvl2Node : level2) {
@@ -648,19 +646,19 @@
HierarchyNode root = tester.buildHierarchy(pages);
assertNotNull(root);
assertEquals(6, root.countDescendants());
- Set<HierarchyNode> level1 = root.getChildren();
+ Collection<HierarchyNode> level1 = root.getChildren();
assertNotNull(level1);
assertEquals(1, level1.size());
for (HierarchyNode lvl1Node : level1) {
assertNotNull(lvl1Node);
if (lvl1Node.getName().endsWith("_subpages")) fail("Still have subpages dir node.");
assertEquals(5, lvl1Node.countDescendants());
- Set<HierarchyNode> level2 = lvl1Node.getChildren();
+ Collection<HierarchyNode> level2 = lvl1Node.getChildren();
assertNotNull(level2);
assertEquals(1, level2.size());
for (HierarchyNode lvl2Node : level2) {
if (lvl2Node.getName().endsWith("_subpages")) fail("Still have subpages dir node.");
- Set<HierarchyNode> level3 = lvl2Node.getChildren();
+ Collection<HierarchyNode> level3 = lvl2Node.getChildren();
assertNotNull(level3);
assertEquals(3, level3.size());
}
@@ -701,7 +699,7 @@
assertNull(actual.getParent());
assertNotNull(actual.getChildren());
- Set<HierarchyNode> level1ChildSet = actual.getChildren();
+ Collection<HierarchyNode> level1ChildSet = actual.getChildren();
assertEquals(1, level1ChildSet.size());
assertEquals("sampleData.txt", level1ChildSet.iterator().next().getName());
@@ -771,7 +769,7 @@
HierarchyNode rootnode = tester.buildHierarchy(pages);
assertNull(rootnode.getPage());
- Set<HierarchyNode> actualrootnodeSet = rootnode.getChildren();
+ Collection<HierarchyNode> actualrootnodeSet = rootnode.getChildren();
HierarchyNode actualRootNode = null;
for (HierarchyNode next : actualrootnodeSet) {
actualRootNode = next;
@@ -781,7 +779,7 @@
assertNotNull(actualRoot);
assertEquals("Root", actualRoot.getName());
- Set<HierarchyNode> children = actualRootNode.getChildren();
+ Collection<HierarchyNode> children = actualRootNode.getChildren();
for (HierarchyNode childnode : children) {
Page childpage = childnode.getPage();
assertNotNull(childpage);
diff --git a/src/com/atlassian/uwc/hierarchies/HierarchyNode.java b/src/com/atlassian/uwc/hierarchies/HierarchyNode.java
index 9b04218..154b81a 100644
--- a/src/com/atlassian/uwc/hierarchies/HierarchyNode.java
+++ b/src/com/atlassian/uwc/hierarchies/HierarchyNode.java
@@ -1,13 +1,18 @@
package com.atlassian.uwc.hierarchies;
+import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Set;
import java.util.TreeSet;
+import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.log4j.Logger;
+
import com.atlassian.uwc.ui.Page;
/**
@@ -19,9 +24,12 @@
private String name;
private Page page;
private HierarchyNode parent;
- private Set<HierarchyNode> children;
+ private Collection<HierarchyNode> children;
private static Comparator childrenComparator;
+ private static boolean childrenAsList = false;
+ Logger log = Logger.getLogger(this.getClass());
+
public HierarchyNode() {
}
@@ -62,19 +70,24 @@
*
* @param child The child to be removed. Must not be <code>null</code>.
*/
- public void removeChild(HierarchyNode child) {
+ public boolean removeChild(HierarchyNode child) {
if (child == null) {
throw new IllegalArgumentException("The parameter must not be null!");
}
- if (children != null && children.contains(child)) {
- children.remove(child);
+ if (getChildren().remove(child)) {
+ log.debug("Removed: '" + child.getName() + "' from " + this.getName());
if (children.size() == 0) {
children = null;
}
child.setParent(null);
+ return true;
+ }
+ else {
+ log.debug("Unable to remove this child: " + child.getName());
+ return false;
}
}
-
+
/**
* Returns the parent of this node.
* @return The parent of this node, or <code>null</code> if
@@ -93,9 +106,12 @@
* @return A set of child nodes, or an empty set if
* this node has no children.
*/
- public Set<HierarchyNode> getChildren() {
+ public Collection<HierarchyNode> getChildren() {
if (this.children == null) {
- if (childrenComparator == null)
+ if (childrenAsList) {
+ this.children = new Vector<HierarchyNode>();
+ }
+ else if (childrenComparator == null)
this.children = new HashSet<HierarchyNode>();
else //if you want to be able to control the child sort order
this.children = new TreeSet<HierarchyNode>(childrenComparator);
@@ -112,7 +128,7 @@
return children == null ? null : children.iterator();
}
- public void setChildren(Set<HierarchyNode> children) {
+ public void setChildren(Collection<HierarchyNode> children) {
this.children = children;
}
@@ -217,4 +233,25 @@
i++;
return i;
}
+
+// public String toString() {
+// return treeAsString(this);
+// }
+ public String treeAsString(HierarchyNode node) {
+ return treeAsString(node.getChildren(), "");
+ }
+
+ private String treeAsString(Collection<HierarchyNode> children, String delim) {
+ String msg = "";
+ for (HierarchyNode child : children) {
+ String newdelim = delim + " .";
+ msg += newdelim + child.getName() + "\n";
+ msg += treeAsString(child.getChildren(), newdelim);
+ }
+ return msg;
+ }
+
+ public static void childrenAsList(boolean aslist) {
+ childrenAsList = aslist;
+ }
}
diff --git a/src/com/atlassian/uwc/hierarchies/SmfHierarchy.java b/src/com/atlassian/uwc/hierarchies/SmfHierarchy.java
index 14fb305..d6c0058 100644
--- a/src/com/atlassian/uwc/hierarchies/SmfHierarchy.java
+++ b/src/com/atlassian/uwc/hierarchies/SmfHierarchy.java
@@ -10,7 +10,6 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;
-import java.util.Set;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -215,7 +214,7 @@
Boolean.parseBoolean(this.getProperties().getProperty(PROPKEY_COMMENTS))) {
Vector<HierarchyNode> topicNodes = getTopicNodes(root);
for (HierarchyNode topic : topicNodes) {
- Set<HierarchyNode> children = topic.getChildren();
+ Collection<HierarchyNode> children = topic.getChildren();
for (Iterator iter = children.iterator(); iter.hasNext();) {
HierarchyNode reply = (HierarchyNode) iter.next();
String comment = createComment(reply.getName());
diff --git a/src/com/atlassian/uwc/ui/ConverterEngine.java b/src/com/atlassian/uwc/ui/ConverterEngine.java
index 95bca26..ac7c1d6 100644
--- a/src/com/atlassian/uwc/ui/ConverterEngine.java
+++ b/src/com/atlassian/uwc/ui/ConverterEngine.java
@@ -67,7 +67,7 @@
* possibly some other method in the future)
*/
public class ConverterEngine implements FeedbackHandler {
-
+
/* START CONSTANTS */
private static final int NUM_REQ_CONVERTERS = 2;
@@ -93,10 +93,10 @@
private static final String DEFAULT_ATTACHMENT_UPLOAD_COMMENT = "Added by UWC, the Universal Wiki Converter";
public static final String PROPKEY_ENGINE_SAVES_TO_DISK = "engine-saves-to-disk";
private static final String PROPKEY_SPACEPERMS = "spaceperms";
-
+
/* START FIELDS */
public boolean running = false; //Methods check this to see if the conversion needs to be cancelled
-
+
/**
* used to disable check for illegal names and links.
* We want to allow users to override this so they can handle it themselves
@@ -106,48 +106,48 @@
private boolean autoDetectSpacekeys = false; //default = false
private HashSet<String> attachedFiles;//attachmentids
private HashSet<String> attachedPaths;//attachment file paths
-
- Logger log = Logger.getLogger(this.getClass());
- // this logger is used to write out totals for the UWC to a seperate file uwc-totals.log
- Logger totalsFileLog = Logger.getLogger("totalsFileLog");
- Logger attachmentLog = Logger.getLogger("attachmentsLog");
- /**
- * The string that directory separators (e.g., / on Unix and \ on Windows) are replaced
- * with in page titles.
- * This is used by DokuWikiLinkConverter too.
- */
- public static final String CONFLUENCE_SEPARATOR = " -- ";
+ Logger log = Logger.getLogger(this.getClass());
+ // this logger is used to write out totals for the UWC to a seperate file uwc-totals.log
+ Logger totalsFileLog = Logger.getLogger("totalsFileLog");
+ Logger attachmentLog = Logger.getLogger("attachmentsLog");
- protected enum HierarchyHandler {
- DEFAULT, //no hierarchy handling
- HIERARCHY_BUILDER, //hierarchyBuilder handles
- PAGENAME_HIERARCHIES//hierarchy maintained in pagename
- }
- private HierarchyHandler hierarchyHandler = HierarchyHandler.DEFAULT;
-
- /**
- * The mapping from file name extension to mime type that is used when sending
- * attachments to Confluence.
- * NOTE: static so that other files can get access to this easily.
- */
- private static MimetypesFileTypeMap mimeTypes;
+ /**
+ * The string that directory separators (e.g., / on Unix and \ on Windows) are replaced
+ * with in page titles.
+ * This is used by DokuWikiLinkConverter too.
+ */
+ public static final String CONFLUENCE_SEPARATOR = " -- ";
- /**
- * This is the location of the mime type mapping file. For details on the file format,
- * refer to the link below.
- *
- * @see javax.activation.MimetypesFileTypeMap
- */
- public final static String mimetypeFileLoc = "conf" + File.separator + "mime.types";
+ protected enum HierarchyHandler {
+ DEFAULT, //no hierarchy handling
+ HIERARCHY_BUILDER, //hierarchyBuilder handles
+ PAGENAME_HIERARCHIES//hierarchy maintained in pagename
+ }
+ private HierarchyHandler hierarchyHandler = HierarchyHandler.DEFAULT;
- /**
- * This field is set if a hierarchy builder "converter" is used. The field controls the
- * way in which pages are added/updated in Confluence. If hierarchyBuilder is <code>null</code>, all
- * pages are added as top-level pages in the selected space. Otherwise, the hierarchy builder is
- * called on to create a page hierarchy, and the engine will insert the pages correspondingly.
- */
- private HierarchyBuilder hierarchyBuilder = null;
+ /**
+ * The mapping from file name extension to mime type that is used when sending
+ * attachments to Confluence.
+ * NOTE: static so that other files can get access to this easily.
+ */
+ private static MimetypesFileTypeMap mimeTypes;
+
+ /**
+ * This is the location of the mime type mapping file. For details on the file format,
+ * refer to the link below.
+ *
+ * @see javax.activation.MimetypesFileTypeMap
+ */
+ public final static String mimetypeFileLoc = "conf" + File.separator + "mime.types";
+
+ /**
+ * This field is set if a hierarchy builder "converter" is used. The field controls the
+ * way in which pages are added/updated in Confluence. If hierarchyBuilder is <code>null</code>, all
+ * pages are added as top-level pages in the selected space. Otherwise, the hierarchy builder is
+ * called on to create a page hierarchy, and the engine will insert the pages correspondingly.
+ */
+ private HierarchyBuilder hierarchyBuilder = null;
private UWCUserSettings settings;
private State state;
private Properties miscProperties = new Properties(); //instantiate this here - UWC-293
@@ -165,72 +165,72 @@
private int newNodes;
- HashMap<String, Converter> converterCacheMap = new HashMap<String, Converter>();
+ HashMap<String, Converter> converterCacheMap = new HashMap<String, Converter>();
private long startTotalConvertTime;
-
+
//Error handlers
private ConverterErrors errors = new ConverterErrors();
private boolean hadConverterErrors;
private HashMap<String, String> homepages = new HashMap<String, String>();
/* START CONSTRUCTORS */
-
- /**
- * This default constructor initializes the mime types.
- */
- public ConverterEngine() {
- try {
- mimeTypes = new MimetypesFileTypeMap(new FileInputStream(mimetypeFileLoc));
- } catch (FileNotFoundException e) {
- String note = "Couldn't load mime types!";
- log.error(note, e);
- this.errors.addError(Feedback.BAD_SETTINGS_FILE, note, false);
- }
- totalsFileLog.setAdditivity(false);
- }
-
- /* START METHODS */
- /**
- * converts the files with the converterstrings, and hooks any feedback into the given ui
- * @param inputPages pages from the filesystem to be converted
- * @param converterStrings list of converters as strings which will be run on the pages
- * @param sendToConfluence true if the pages should be uploaded to confluence
- * @param wikitype The wiki type that's being converted into Confluence, ex: Mediawiki
- */
- public void convert(List<File> inputPages, List<String> converterStrings, UWCUserSettings settings) {
- //setup
- this.running = true;
+ /**
+ * This default constructor initializes the mime types.
+ */
+ public ConverterEngine() {
+ try {
+ mimeTypes = new MimetypesFileTypeMap(new FileInputStream(mimetypeFileLoc));
+ } catch (FileNotFoundException e) {
+ String note = "Couldn't load mime types!";
+ log.error(note, e);
+ this.errors.addError(Feedback.BAD_SETTINGS_FILE, note, false);
+ }
+ totalsFileLog.setAdditivity(false);
+ }
+
+ /* START METHODS */
+
+ /**
+ * converts the files with the converterstrings, and hooks any feedback into the given ui
+ * @param inputPages pages from the filesystem to be converted
+ * @param converterStrings list of converters as strings which will be run on the pages
+ * @param sendToConfluence true if the pages should be uploaded to confluence
+ * @param wikitype The wiki type that's being converted into Confluence, ex: Mediawiki
+ */
+ public void convert(List<File> inputPages, List<String> converterStrings, UWCUserSettings settings) {
+ //setup
+ this.running = true;
resetFeedback();
resetErrorHandlers();
resetHierarchy();
-
+
//settings
boolean sendToConfluence = Boolean.parseBoolean(settings.getSendToConfluence());
- this.settings = settings;
- if (!this.running) {
- this.feedback = Feedback.CANCELLED;
- return;
- }
-
- //convert
+ this.settings = settings;
+ if (!this.running) {
+ this.feedback = Feedback.CANCELLED;
+ return;
+ }
+
+ //convert
convert(inputPages, converterStrings, sendToConfluence, settings.getPattern());
-
+
//cleanup
if (this.feedback == Feedback.NONE)
this.feedback = Feedback.OK;
this.running = false;
- }
-
- /**
- * cancels the conversion
- */
- public void cancel() {
+ }
+
+ /**
+ * cancels the conversion
+ */
+ public void cancel() {
String message = "Engine - Sending Cancel Signal";
- log.debug(message);
+ log.debug(message);
this.state.updateNote(message);
- this.running = false;
- }
+ this.running = false;
+ }
/**
* gets a new State object.
@@ -245,12 +245,12 @@
//inputPages includes directories which are counted as 1 object in the inputPages list, and
//converterStrings includes non-converter properties. So, for now we'll use a default value to set up
//the state.
-// int steps =
-// getNumberOfSteps(
-// inputPages,
-// converterStrings,
-// Boolean.parseBoolean(settings.getSendToConfluence())
-// );
+ // int steps =
+ // getNumberOfSteps(
+ // inputPages,
+ // converterStrings,
+ // Boolean.parseBoolean(settings.getSendToConfluence())
+ // );
return getState(settings);
}
@@ -296,7 +296,7 @@
private int getNumberOfSteps(int pages, int converters, boolean sendToConfluence) {
return getNumberOfSteps(pages, converters, converters, sendToConfluence);
}
-
+
/**
* Counts the number of steps needed to do an entire conversion from start to finish.
* Used with progress monitor
@@ -323,16 +323,16 @@
private int getNumberOfSteps(int files, int pages, int properties, int converters, boolean sendToConfluence) {
int numReqConverters = isIllegalHandlingEnabled()?NUM_REQ_CONVERTERS:0;
int steps =
- properties + //1. initialize converters (handles both converter and non-converter properties)
- files + //2. create page objects (uses the original list of chosen file objects)
- (converters * pages) + //3. convert the files (uses the number of page objects)
- (numReqConverters) + //4. create required converters (2, right now)
- (numReqConverters * pages) + //5. convert with required converters (2, right now)
- pages + //6. save the files
- (sendToConfluence?pages:0); //7. upload pages if sendToConfluence
+ properties + //1. initialize converters (handles both converter and non-converter properties)
+ files + //2. create page objects (uses the original list of chosen file objects)
+ (converters * pages) + //3. convert the files (uses the number of page objects)
+ (numReqConverters) + //4. create required converters (2, right now)
+ (numReqConverters * pages) + //5. convert with required converters (2, right now)
+ pages + //6. save the files
+ (sendToConfluence?pages:0); //7. upload pages if sendToConfluence
return steps;
}
-
+
/**
* converts the given pages using the given converterStrings, and sends the pages
* to Confluence, if sendToConfluence is true.
@@ -345,148 +345,182 @@
}
/**
- * converts the given pages not filtered out with the given filterPattern
- * using the given converterStrings, and sends the pages to Confluence,
- * if sendToConfluence is true
- * @param pages
- * @param converterStrings
- * @param sendToConfluence
- * @param filterPattern ignores files with this filter pattern
- */
- public void convert(List<File> pages, List<String> converterStrings, boolean sendToConfluence, String filterPattern) {
- log.info("Starting conversion.");
-
- initConversion();
-
- //create converters
- ArrayList<Converter> converters = createConverters(converterStrings);
+ * converts the given pages not filtered out with the given filterPattern
+ * using the given converterStrings, and sends the pages to Confluence,
+ * if sendToConfluence is true
+ * @param pages
+ * @param converterStrings
+ * @param sendToConfluence
+ * @param filterPattern ignores files with this filter pattern
+ */
+ public void convert(List<File> pages, List<String> converterStrings, boolean sendToConfluence, String filterPattern) {
+ log.info("Starting conversion.");
- //create page objects - Recurse through directories, adding all files
- FileFilter filter = createFilter(filterPattern);
- List<Page> allPages = createPages(filter, pages);
-
- //fix progressbar max, which is dependent on the previous two lists
- int steps = getNumberOfSteps(pages.size(), allPages.size(), converterStrings.size(), converters.size(), sendToConfluence);
- this.state.updateMax(steps);
-
-
- //convert the files
- if (convertPages(allPages, converters)) {
- //in case converting the pages disqualified some pages, we need to break if there are no pages left
- if (allPages.size() < 1) {
- String message = "All pages submitted were disqualified for various reasons. Could not complete conversion.";
+ initConversion();
+
+ //create converters
+ ArrayList<Converter> converters = createConverters(converterStrings);
+
+ //create page objects - Recurse through directories, adding all files
+ FileFilter filter = createFilter(filterPattern);
+ List<Page> allPages = createPages(filter, pages);
+
+ //fix progressbar max, which is dependent on the previous two lists
+ int steps = getNumberOfSteps(pages.size(), allPages.size(), converterStrings.size(), converters.size(), sendToConfluence);
+ this.state.updateMax(steps);
+
+
+ //convert the files
+ if (convertPages(allPages, converters)) {
+ //in case converting the pages disqualified some pages, we need to break if there are no pages left
+ if (allPages.size() < 1) {
+ String message = "All pages submitted were disqualified for various reasons. Could not complete conversion.";
log.warn(message);
this.errors.addError(Feedback.CONVERTER_ERROR, message, true);
this.state.updateMax(this.state.getStep()); //complete progress bar, prematurely
return;
- }
- //in case converting the pages disqualified some pages, we need to recompute progressbarmax
- steps = getNumberOfSteps(pages.size(), allPages.size(), converterStrings.size(), converters.size(), sendToConfluence);
- if (steps != this.state.getMax()) this.state.updateMax(steps);
-
- // do final required conversions. This step is seperate, due to state saving issues
- convertWithRequiredConverters(allPages);
+ }
+ //in case converting the pages disqualified some pages, we need to recompute progressbarmax
+ steps = getNumberOfSteps(pages.size(), allPages.size(), converterStrings.size(), converters.size(), sendToConfluence);
+ if (steps != this.state.getMax()) this.state.updateMax(steps);
- //save pages if engine-saves-to-disk property is true. Useful for debugging.
- //We are making this opt-in because users that don't need it will get a speed boost with fewer disk calls
- if (Boolean.parseBoolean(this.miscProperties.getProperty(PROPKEY_ENGINE_SAVES_TO_DISK, "false")))
- savePages(allPages, filterPattern);
- else log.debug("Engine Saves To Disk setting turned off.");
-
+ // do final required conversions. This step is seperate, due to state saving issues
+ convertWithRequiredConverters(allPages);
+
+ //save pages if engine-saves-to-disk property is true. Useful for debugging.
+ //We are making this opt-in because users that don't need it will get a speed boost with fewer disk calls
+ if (Boolean.parseBoolean(this.miscProperties.getProperty(PROPKEY_ENGINE_SAVES_TO_DISK, "false")))
+ savePages(allPages, filterPattern);
+ else log.debug("Engine Saves To Disk setting turned off.");
+
//handling page histories and not sorting on create
if (isHandlingPageHistories() &&
!(isPageHistorySortOnCreate())) {
allPages = sortByHistory(allPages);
}
-
- //upload pages, if the user approves
- if (sendToConfluence && this.running) {
- if (hierarchyHandler == HierarchyHandler.HIERARCHY_BUILDER && hierarchyBuilder != null) {
- //tell the hierarchy builder about the page histories framework
- //do this here so that we're sure the page histories properties are set
- if (hierarchyBuilder.getProperties() != null) {
- hierarchyBuilder.getProperties().setProperty("switch."+NONCONVERTERTYPE_PAGEHISTORYPRESERVATION, isHandlingPageHistories()+"");
- if (getPageHistorySuffix() != null)
- hierarchyBuilder.getProperties().setProperty("suffix."+NONCONVERTERTYPE_PAGEHISTORYPRESERVATION, getPageHistorySuffix());
+
+ if (hierarchyHandler == HierarchyHandler.HIERARCHY_BUILDER && hierarchyBuilder != null) {
+ //tell the hierarchy builder about the page histories framework
+ //do this here so that we're sure the page histories properties are set
+ if (hierarchyBuilder.getProperties() != null) {
+ hierarchyBuilder.getProperties().setProperty("switch."+NONCONVERTERTYPE_PAGEHISTORYPRESERVATION, isHandlingPageHistories()+"");
+ if (getPageHistorySuffix() != null)
+ hierarchyBuilder.getProperties().setProperty("suffix."+NONCONVERTERTYPE_PAGEHISTORYPRESERVATION, getPageHistorySuffix());
+ }
+ //tell the hierarchy some other information
+ if (hierarchyBuilder.getProperties() != null) {
+ hierarchyBuilder.getProperties().setProperty("spacekey", settings.getSpace());
+ }
+ //build the hierarchy
+ HierarchyNode root = hierarchyBuilder.buildHierarchy(allPages);
+ int currenttotal = root.countDescendants()-1; //-1 for the null root;
+ log.debug("number of nodes in the hierarchy = " + root.countDescendants());
+ //upload pages, if the user approves
+ if (sendToConfluence && this.running) { //check here so that hierarchy can impact collisions without upload
+ if (Boolean.parseBoolean(this.miscProperties.getProperty("onlyorphans", "false"))) {
+ log.debug("Orphan attachments only.");
+ noteAttachments(root);
+ }
+ else {
+ writeHierarchy(root, currenttotal, settings.getSpace());
}
- //tell the hierarchy some other information
- if (hierarchyBuilder.getProperties() != null) {
- hierarchyBuilder.getProperties().setProperty("spacekey", settings.getSpace());
- }
- //build the hierarchy
- HierarchyNode root = hierarchyBuilder.buildHierarchy(allPages);
- int currenttotal = allPages.size();
- if (hierarchyBuilder.getProperties().containsKey("newpagecount"))
- currenttotal = Integer.parseInt(hierarchyBuilder.getProperties().getProperty("newpagescount"));
- writeHierarchy(root, currenttotal, settings.getSpace());
handleOrphanAttachments();
- } else { //no hierarchy - just write the pages
+ }
+ else if (!sendToConfluence){
+ log.debug("Send To Confluence setting turned off. --> Not uploading pages.");
+ }
+ } else { //no hierarchy
+ if (sendToConfluence && this.running) {//check here so that hierarchy can impact collisions without upload
writePages(allPages, settings.getSpace());
handleOrphanAttachments();
}
- //check for namespace collisions and emit errors if found
- //(after hierarchy has had a chance to make changes)
- listCollisions(allPages);
+ else if (!sendToConfluence){
+ log.debug("Send To Confluence setting turned off. --> Not uploading pages.");
+ }
+ }
+ //check for namespace collisions and emit errors if found
+ //(after hierarchy has had a chance to make changes)
+ listCollisions(allPages);
+ clearAttachedFileList();
+ }
+ log.info("Conversion Complete");
+ }
+
+ private void noteAttachments(HierarchyNode root) {
+ if (root.getPage() != null) {
+ log.debug("ORPHANDEBUG node: " + root.getPage().getName());
+ for (Attachment attachment : root.getPage().getAllAttachmentData()) {
+ alreadyAttached(root.getPage(), attachment.getFile());
+ if (root.getPage().getAncestors() != null) {
+ for (VersionPage ancestor : root.getPage().getAncestors()) {
+ for (Attachment ancAtt : ancestor.getAllAttachmentData()) {
+ log.debug("VERSION ORPHANDEBUG: " + ancestor.getName() + ": " + ancAtt.getFile().getName());
+ alreadyAttached(ancestor, ancAtt.getFile());
+ }
+ }
+ }
}
- else if (!sendToConfluence){
- log.debug("Send To Confluence setting turned off. --> Not uploading pages.");
+ }
+ if (!root.getChildren().isEmpty()) {
+ for (HierarchyNode child : root.getChildren()) {
+ noteAttachments(child);
}
- }
- log.info("Conversion Complete");
- }
+ }
+
+ }
protected boolean isPageHistorySortOnCreate() {
return Boolean.parseBoolean(this.miscProperties.getProperty("page-history-sortoncreate", "true"));
}
- /**
- * handle any cleanup
- */
- protected void initConversion() {
+ /**
+ * handle any cleanup
+ */
+ protected void initConversion() {
this.miscProperties.clear();
}
/**
- * Instantiate all the converterStrings
- *
- * @param converterStrings a list of converter strings of the form "key=value"
- * @return a list of converters
- */
- public ArrayList<Converter> createConverters(List<String> converterStrings) {
- return createConverters(converterStrings, true);
- }
- public ArrayList<Converter> createConverters(List<String> converterStrings, boolean runningState) {
- String message = "Initializing Converters...";
+ * Instantiate all the converterStrings
+ *
+ * @param converterStrings a list of converter strings of the form "key=value"
+ * @return a list of converters
+ */
+ public ArrayList<Converter> createConverters(List<String> converterStrings) {
+ return createConverters(converterStrings, true);
+ }
+ public ArrayList<Converter> createConverters(List<String> converterStrings, boolean runningState) {
+ String message = "Initializing Converters...";
if (runningState) this.state.updateNote(message);
log.info(message);
-
- new DefaultXmlEvents().clearAll(); //everytime this method is called, have a clean slate of events
-
- ArrayList<Converter> converters = new ArrayList<Converter>();
- this.numNonConverterProperties = 0;
- for (String converterStr : converterStrings) {
- if (runningState) this.state.updateProgress();
- if (runningState && !this.running) {
- this.feedback = Feedback.CANCELLED;
- return null;
- }
- Converter converter;
- if (isNonConverterProperty(converterStr)) {
- this.numNonConverterProperties++;
- handleNonConverterProperty(converterStr);
- continue;
- }
- converter = getConverterFromString(converterStr);
- if (converter == null) {
- continue;
- }
- converters.add(converter);
- }
- if (runningState) addDefaultMiscProperties();
-
- return converters;
- }
+
+ new DefaultXmlEvents().clearAll(); //everytime this method is called, have a clean slate of events
+
+ ArrayList<Converter> converters = new ArrayList<Converter>();
+ this.numNonConverterProperties = 0;
+ for (String converterStr : converterStrings) {
+ if (runningState) this.state.updateProgress();
+ if (runningState && !this.running) {
+ this.feedback = Feedback.CANCELLED;
+ return null;
+ }
+ Converter converter;
+ if (isNonConverterProperty(converterStr)) {
+ this.numNonConverterProperties++;
+ handleNonConverterProperty(converterStr);
+ continue;
+ }
+ converter = getConverterFromString(converterStr);
+ if (converter == null) {
+ continue;
+ }
+ converters.add(converter);
+ }
+ if (runningState) addDefaultMiscProperties();
+
+ return converters;
+ }
/**
* coverts pages with required converters
@@ -504,33 +538,33 @@
converters = createOneConverter(illegallinksConvStr);
convertPages(pages, converters, "Checking for links to illegal pagenames.");
}
- }
-
- /**
- * converts the list of pages with the given converter
- * @param pages list of pages to be converted
- * @param useUI set this to false if you do not want the associated GUI elements
- * to be updated. This is useful for unit testing.
- */
- protected void convertWithRequiredConverters(List<Page> pages, boolean useUI) {
- //XXX used only by the junit tests
-
- //create pagename converter and convert with it
+ }
+
+ /**
+ * converts the list of pages with the given converter
+ * @param pages list of pages to be converted
+ * @param useUI set this to false if you do not want the associated GUI elements
+ * to be updated. This is useful for unit testing.
+ */
+ protected void convertWithRequiredConverters(List<Page> pages, boolean useUI) {
+ //XXX used only by the junit tests
+
+ //create pagename converter and convert with it
String pagenameConvStr = REQUIRED_CONVERTER_ILLEGAL_NAMES;
ArrayList<Converter> converters = createOneConverter(pagenameConvStr);
- convertPages(pages, converters, "Checking for illegal pagenames.");
-
- //get the state hashtable
- IllegalPageNameConverter pagenameConverter = (IllegalPageNameConverter) converters.remove(0);
- HashSet<String> illegalNames = pagenameConverter.getIllegalPagenames();
-
- //create linkname converter and convert with it
+ convertPages(pages, converters, "Checking for illegal pagenames.");
+
+ //get the state hashtable
+ IllegalPageNameConverter pagenameConverter = (IllegalPageNameConverter) converters.remove(0);
+ HashSet<String> illegalNames = pagenameConverter.getIllegalPagenames();
+
+ //create linkname converter and convert with it
String illegallinksConvStr = REQUIRED_CONVERTER_ILLEGAL_LINKS;
- converters = createOneConverter(illegallinksConvStr);
- IllegalLinkNameConverter linknameConverter = (IllegalLinkNameConverter) converters.get(0);
- linknameConverter.setIllegalPagenames(illegalNames);
- convertPages(pages, converters, "Checking for links to illegal pagenames.");
- }
+ converters = createOneConverter(illegallinksConvStr);
+ IllegalLinkNameConverter linknameConverter = (IllegalLinkNameConverter) converters.get(0);
+ linknameConverter.setIllegalPagenames(illegalNames);
+ convertPages(pages, converters, "Checking for links to illegal pagenames.");
+ }
/**
* creates the arraylist of converters when only one converter is needed
@@ -544,267 +578,270 @@
ArrayList<Converter> converters = createConverters(converterStrings);
return converters;
}
-
+
/**
- * Instantiates a converter from a correctly formatted String.
- * <p/>
- * Note: This method is now only called once per converter -- first all converters
- * are created, then all pages, then all converters are run on all pages.
- *
- * @param converterStr A string of the form "name.keyword=parameters". The
- * keyword is used to create the correct type of converter, and the parameters
- * are then passed to the converter. Finally, the "name.keyword" part is set as
- * the key in the converter, mainly for debugging purposes.
- * @return converter or null if no converter can be parsed/instantiated
- */
- public Converter getConverterFromString(String converterStr) {
- Converter converter;
- int equalLoc = converterStr.indexOf("=");
- String key = converterStr.substring(0, equalLoc);
- String value = converterStr.substring(equalLoc + 1);
- try {
- if (key.indexOf(CONVERTERTYPE_CLASS) >= 0) {
- converter = getConverterClassFromCache(value);
- } else if (key.indexOf(CONVERTERTYPE_PERL) >= 0) {
- converter = PerlConverter.getPerlConverter(value);
- converter.setValue(value);
- } else if (key.indexOf(CONVERTERTYPE_JAVAREGEXTOKEN) >= 0) {
- converter = JavaRegexAndTokenizerConverter.getConverter(value);
- converter.setValue(value);
- } else if (key.indexOf(CONVERTERTYPE_JAVAREGEX) >= 0) {
- converter = JavaRegexConverter.getConverter(value);
- converter.setValue(value);
- } else if (key.indexOf(CONVERTERTYPE_TWIKICLEANER) >= 0) {
- //converter = getConverterClassFromCache(value);
- converter = TWikiRegexConverterCleanerWrapper.getTWikiRegexConverterCleanerWrapper(value);
- converter.setValue(value);
- } else {
- String note = "Converter ignored -- name pattern not recognized: " + key;
+ * Instantiates a converter from a correctly formatted String.
+ * <p/>
+ * Note: This method is now only called once per converter -- first all converters
+ * are created, then all pages, then all converters are run on all pages.
+ *
+ * @param converterStr A string of the form "name.keyword=parameters". The
+ * keyword is used to create the correct type of converter, and the parameters
+ * are then passed to the converter. Finally, the "name.keyword" part is set as
+ * the key in the converter, mainly for debugging purposes.
+ * @return converter or null if no converter can be parsed/instantiated
+ */
+ public Converter getConverterFromString(String converterStr) {
+ Converter converter;
+ int equalLoc = converterStr.indexOf("=");
+ String key = converterStr.substring(0, equalLoc);
+ String value = converterStr.substring(equalLoc + 1);
+ try {
+ if (key.indexOf(CONVERTERTYPE_CLASS) >= 0) {
+ converter = getConverterClassFromCache(value);
+ } else if (key.indexOf(CONVERTERTYPE_PERL) >= 0) {
+ converter = PerlConverter.getPerlConverter(value);
+ converter.setValue(value);
+ } else if (key.indexOf(CONVERTERTYPE_JAVAREGEXTOKEN) >= 0) {
+ converter = JavaRegexAndTokenizerConverter.getConverter(value);
+ converter.setValue(value);
+ } else if (key.indexOf(CONVERTERTYPE_JAVAREGEX) >= 0) {
+ converter = JavaRegexConverter.getConverter(value);
+ converter.setValue(value);
+ } else if (key.indexOf(CONVERTERTYPE_TWIKICLEANER) >= 0) {
+ //converter = getConverterClassFromCache(value);
+ converter = TWikiRegexConverterCleanerWrapper.getTWikiRegexConverterCleanerWrapper(value);
+ converter.setValue(value);
+ } else {
+ String note = "Converter ignored -- name pattern not recognized: " + key;
this.errors.addError(Feedback.BAD_PROPERTY, note, true);
log.error(note);
- return null;
- }
- converter.setProperties(this.miscProperties);
- if (converter instanceof RequiresEngineConverter) {
- ((RequiresEngineConverter) converter).setEngine(this);
- }
- } catch (ClassNotFoundException e) {
- this.errors.addError(Feedback.BAD_CONVERTER_CLASS, "Converter ignored -- the Java class " + value + " was not found", true);
- return null;
- } catch (IllegalAccessException e) {
- this.errors.addError(Feedback.BAD_CONVERTER_CLASS, "Converter ignored -- there was a problem creating a converter object", true);
- return null;
- } catch (InstantiationException e) {
- this.errors.addError(Feedback.BAD_CONVERTER_CLASS, "Converter ignored -- there was a problem creating the Java class " + value, true);
- return null;
- } catch (ClassCastException e) {
- this.errors.addError(Feedback.BAD_CONVERTER_CLASS, "Converter ignored -- the Java class " + value +
- " must implement the " + Converter.class.getName() + " interface!", true);
- return null;
- }
- converter.setKey(key);
- return converter;
- }
-
- /**
- * handles necessary state changes for expected properties
- * that were set in the converter properties file.
- * expected nonconverter properties include hierarchy builder properties
- * and page history preservation properties
- * @param converterStr should be a line from the converter properties file
- * Example:
- * MyWiki.0001.someproperty.somepropertytype=setting
- * <br/>
- * where somepropertytype is an expected property type:
- * <br/>
- * NONCONVERTERTYPE_HIERARCHYBUILDER or NONCONVERTERTYPE_PAGEHISTORYPRESERVATION
- * or NONCONVERTERTYPE_ILLEGALHANDLING
- * or NONCONVERTERTYPE_AUTODETECTSPACEKEYS
- * or NONCONVERTERTYPE_FILTERS
- * or NONCONVERTERTYPE_MISCPROPERTIES
- */
- protected void handleNonConverterProperty(String converterStr) {
- int equalLoc = converterStr.indexOf("=");
- String key = converterStr.substring(0, equalLoc);
- String value = converterStr.substring(equalLoc + 1);
- String parent = "";
- try {
- if (key.indexOf(NONCONVERTERTYPE_HIERARCHYBUILDER) >= 0) {
- if (isHierarchySwitch(key))
- setHierarchyHandler(value);
- else {
- parent = HierarchyBuilder.class.getName();
- Class c;
- c = Class.forName(value);
- HierarchyBuilder hierarchy = (HierarchyBuilder) c.newInstance();
- hierarchyBuilder = hierarchy;
- this.hierarchyBuilder.setProperties(this.miscProperties);
- }
- }
- else if (key.endsWith(NONCONVERTERTYPE_PAGEHISTORYPRESERVATION)) {
- handlePageHistoryProperty(key, value);
- }
- else if (key.endsWith(NONCONVERTERTYPE_ILLEGALHANDLING)) {
- handleIllegalHandling(key, value);
- }
- else if (key.endsWith(NONCONVERTERTYPE_AUTODETECTSPACEKEYS)) {
- handleAutoDetectSpacekeys(key, value);
- }
- else if (key.endsWith(NONCONVERTERTYPE_MISCPROPERTIES)) {
- handleMiscellaneousProperties(key, value);
- }
- else if (key.endsWith(NONCONVERTERTYPE_FILTERS)) {
- parent = FileFilter.class.getName();
- handleFilters(key, value);
- }
- else if (key.endsWith(NONCONVERTERTYPE_XMLEVENT)) {
- handleXmlEvents(key, value);
- }
- } catch (ClassNotFoundException e) {
- String message = "Property ignored -- the Java class " + value + " was not found";
- log.error(message);
- this.errors.addError(Feedback.BAD_PROPERTY, message, true);
- } catch (IllegalAccessException e) {
- String message = "Property ignored -- there was a problem creating the Java class: " + value +
- ".\n" +
- "Note: A necessary method's permissions were too restrictive. Check the constructor. ";
- log.error(message);
- this.errors.addError(Feedback.BAD_PROPERTY, message, true);
- } catch (InstantiationException e) {
- String message = "Property ignored -- there was a problem creating the Java class " + value +
- ".\n" +
- "Note: The class cannot be instantiated as it is abstract or is an interface.";
- log.error(message);
- this.errors.addError(Feedback.BAD_PROPERTY, message, true);
- } catch (ClassCastException e) {
- String message = "Property ignored -- the Java class " + value +
- " must implement the " + parent + " interface!";
- log.error(message);
- this.errors.addError(Feedback.BAD_PROPERTY, message, true);
- } catch (IllegalArgumentException e) {
- String message = "Property ignored -- property value was not in expected format.";
- log.error(message);
- this.errors.addError(Feedback.BAD_PROPERTY, message, true);
- }
- }
-
- /**
- * at long last making some performance enhancements
- * here we are creating an object cache which should help a bit
- *
- * @param key A string representing the converter (actually the part after the
- * equals sign of the converter string).
- * @return
- * @throws ClassNotFoundException
- * @throws IllegalAccessException
- * @throws InstantiationException
- */
- private Converter getConverterClassFromCache(String key) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
- Converter converter = converterCacheMap.get(key);
- if (converter == null) {
- Class c = Class.forName(key);
- converter = (Converter) c.newInstance();
- converterCacheMap.put(key, converter);
- }
- return converter;
- }
-
- /**
- * creates file filter.
- * If we have no filter values, returns null.
- * If we have at least one filter value, uses the FilterChain class
- * to create FileFilter that will handle all of the filter requirements.
- * There are two types of supported filters: Class filters, and endswith filters.
- * Class filters are fully resolved class names for classes that implement FileFilter.
- * Endswith filters are text strings that the end of the filename must conform to.
- * If there are more than one filter invoked, the following will be used to resolve
- * which files to accept: Only pages that all class filters accept as long as
- * any endswith filter accepts as well will be included. (Class filters are ANDed.
- * Endswith filters are ORed.) Example: If you had two endswiths, and a class: ".txt",
- * ".xml", and NoSvnFilter, then .txt and .xml files that the NoSvnFilter accepts
- * will be included.
- * @return FileFilter or null
- */
- protected FileFilter createFilter(final String pattern) {
- Set<String> values = getFilterValues();
- if (pattern != null && !"".equals(pattern))
- values.add(pattern);
-
- if (values.isEmpty()) return null;
-
- FilterChain chain = new FilterChain(values, this.miscProperties);
- return chain.getFilter();
- }
-
- /**
- * Creates PageForXmlRpcOld objects for all the files in inputPages.
- *
- * @param filter file filter to be used to filter input pages, or null, if no such filter should be used
- * @param inputPages A list of files and directories that Pages should be created for.
- * @return A list of PageForXmlRpcOld objects for all files matching the pattern in the settings.
- */
- protected List<Page> createPages(FileFilter filter, List<File> inputPages) {
- String message = "Initializing Pages...";
- this.state.updateNote(message);
- log.info(message);
-
- List<Page> allPages = new LinkedList<Page>();
-
- for (File fileOrDir : inputPages) {
- this.state.updateProgress();
- List<Page> pages = recurse(fileOrDir, filter);
- setupPages(fileOrDir, pages);
- allPages.addAll(pages);
- }
-
- if (isHandlingPageHistories() && isPageHistorySortOnCreate()) {
- return sortByHistory(allPages);
- }
- return allPages;
- }
+ return null;
+ }
+ converter.setProperties(this.miscProperties);
+ if (converter instanceof RequiresEngineConverter) {
+ ((RequiresEngineConverter) converter).setEngine(this);
+ }
+ } catch (ClassNotFoundException e) {
+ this.errors.addError(Feedback.BAD_CONVERTER_CLASS, "Converter ignored -- the Java class " + value + " was not found", true);
+ return null;
+ } catch (IllegalAccessException e) {
+ this.errors.addError(Feedback.BAD_CONVERTER_CLASS, "Converter ignored -- there was a problem creating a converter object", true);
+ return null;
+ } catch (InstantiationException e) {
+ this.errors.addError(Feedback.BAD_CONVERTER_CLASS, "Converter ignored -- there was a problem creating the Java class " + value, true);
+ return null;
+ } catch (ClassCastException e) {
+ this.errors.addError(Feedback.BAD_CONVERTER_CLASS, "Converter ignored -- the Java class " + value +
+ " must implement the " + Converter.class.getName() + " interface!", true);
+ return null;
+ }
+ converter.setKey(key);
+ return converter;
+ }
/**
- * Recurses through a directory structure and adds all files in it matching the filter.
- * Called by createPages.
- *
- * @param fileOrDir A directory or file. Must not be <code>null</code>.
- * @param filter the filter to use when selecting files
- * @return A list with PageForXmlRpcOld objects for all the matching files in the directory and its subdirectories
- */
- private List<Page> recurse(File fileOrDir, FileFilter filter) {
- assert fileOrDir != null;
- List<Page> result = new LinkedList<Page>();
- if (fileOrDir.isFile()) { //it's a file AND
- if (filter == null || filter.accept(fileOrDir)) { //there's no filter OR the filter accepts the file
- PageSplitter splitter = getPageSplitter();
- if (splitter == null)
- result.add(new Page(fileOrDir));
- else
- result.addAll(splitter.split(fileOrDir));
- }
- else
- log.debug("Filtering out filename: " + fileOrDir.getName());
- } else if (fileOrDir.isDirectory()) {
- File[] files = fileOrDir.listFiles(filter);
- for (File file : files) {
- result.addAll(recurse(file, filter));
- }
- }
- else { //some other problem
- String message = "Could not find file: '" +
- fileOrDir.getAbsolutePath() +
- "'.\n" +
- "Check existence and permissions.";
+ * handles necessary state changes for expected properties
+ * that were set in the converter properties file.
+ * expected nonconverter properties include hierarchy builder properties
+ * and page history preservation properties
+ * @param converterStr should be a line from the converter properties file
+ * Example:
+ * MyWiki.0001.someproperty.somepropertytype=setting
+ * <br/>
+ * where somepropertytype is an expected property type:
+ * <br/>
+ * NONCONVERTERTYPE_HIERARCHYBUILDER or NONCONVERTERTYPE_PAGEHISTORYPRESERVATION
+ * or NONCONVERTERTYPE_ILLEGALHANDLING
+ * or NONCONVERTERTYPE_AUTODETECTSPACEKEYS
+ * or NONCONVERTERTYPE_FILTERS
+ * or NONCONVERTERTYPE_MISCPROPERTIES
+ */
+ protected void handleNonConverterProperty(String converterStr) {
+ int equalLoc = converterStr.indexOf("=");
+ String key = converterStr.substring(0, equalLoc);
+ String value = converterStr.substring(equalLoc + 1);
+ String parent = "";
+ try {
+ if (key.indexOf(NONCONVERTERTYPE_HIERARCHYBUILDER) >= 0) {
+ if (isHierarchySwitch(key))
+ setHierarchyHandler(value);
+ else {
+ parent = HierarchyBuilder.class.getName();
+ Class c;
+ c = Class.forName(value);
+ HierarchyBuilder hierarchy = (HierarchyBuilder) c.newInstance();
+ hierarchyBuilder = hierarchy;
+ this.hierarchyBuilder.setProperties(this.miscProperties);
+ }
+ }
+ else if (key.endsWith(NONCONVERTERTYPE_PAGEHISTORYPRESERVATION)) {
+ handlePageHistoryProperty(key, value);
+ }
+ else if (key.endsWith(NONCONVERTERTYPE_ILLEGALHANDLING)) {
+ handleIllegalHandling(key, value);
+ }
+ else if (key.endsWith(NONCONVERTERTYPE_AUTODETECTSPACEKEYS)) {
+ handleAutoDetectSpacekeys(key, value);
+ }
+ else if (key.endsWith(NONCONVERTERTYPE_MISCPROPERTIES)) {
+ handleMiscellaneousProperties(key, value);
+ }
+ else if (key.endsWith(NONCONVERTERTYPE_FILTERS)) {
+ parent = FileFilter.class.getName();
+ handleFilters(key, value);
+ }
+ else if (key.endsWith(NONCONVERTERTYPE_XMLEVENT)) {
+ handleXmlEvents(key, value);
+ }
+ } catch (ClassNotFoundException e) {
+ String message = "Property ignored -- the Java class " + value + " was not found";
+ log.error(message);
+ this.errors.addError(Feedback.BAD_PROPERTY, message, true);
+ } catch (IllegalAccessException e) {
+ String message = "Property ignored -- there was a problem creating the Java class: " + value +
+ ".\n" +
+ "Note: A necessary method's permissions were too restrictive. Check the constructor. ";
+ log.error(message);
+ this.errors.addError(Feedback.BAD_PROPERTY, message, true);
+ } catch (InstantiationException e) {
+ String message = "Property ignored -- there was a problem creating the Java class " + value +
+ ".\n" +
+ "Note: The class cannot be instantiated as it is abstract or is an interface.";
+ log.error(message);
+ this.errors.addError(Feedback.BAD_PROPERTY, message, true);
+ } catch (ClassCastException e) {
+ String message = "Property ignored -- the Java class " + value +
+ " must implement the " + parent + " interface!";
+ log.error(message);
+ this.errors.addError(Feedback.BAD_PROPERTY, message, true);
+ } catch (IllegalArgumentException e) {
+ String message = "Property ignored -- property value was not in expected format.";
+ log.error(message);
+ this.errors.addError(Feedback.BAD_PROPERTY, message, true);
+ }
+ }
+
+ /**
+ * at long last making some performance enhancements
+ * here we are creating an object cache which should help a bit
+ *
+ * @param key A string representing the converter (actually the part after the
+ * equals sign of the converter string).
+ * @return
+ * @throws ClassNotFoundException
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ */
+ private Converter getConverterClassFromCache(String key) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+ Converter converter = converterCacheMap.get(key);
+ if (converter == null) {
+ Class c = Class.forName(key);
+ converter = (Converter) c.newInstance();
+ converterCacheMap.put(key, converter);
+ }
+ return converter;
+ }
+
+ /**
+ * creates file filter.
+ * If we have no filter values, returns null.
+ * If we have at least one filter value, uses the FilterChain class
+ * to create FileFilter that will handle all of the filter requirements.
+ * There are two types of supported filters: Class filters, and endswith filters.
+ * Class filters are fully resolved class names for classes that implement FileFilter.
+ * Endswith filters are text strings that the end of the filename must conform to.
+ * If there are more than one filter invoked, the following will be used to resolve
+ * which files to accept: Only pages that all class filters accept as long as
+ * any endswith filter accepts as well will be included. (Class filters are ANDed.
+ * Endswith filters are ORed.) Example: If you had two endswiths, and a class: ".txt",
+ * ".xml", and NoSvnFilter, then .txt and .xml files that the NoSvnFilter accepts
+ * will be included.
+ * @return FileFilter or null
+ */
+ protected FileFilter createFilter(final String pattern) {
+ Set<String> values = getFilterValues();
+ if (pattern != null && !"".equals(pattern))
+ values.add(pattern);
+
+ if (values.isEmpty()) return null;
+
+ FilterChain chain = new FilterChain(values, this.miscProperties);
+ return chain.getFilter();
+ }
+
+ /**
+ * Creates PageForXmlRpcOld objects for all the files in inputPages.
+ *
+ * @param filter file filter to be used to filter input pages, or null, if no such filter should be used
+ * @param inputPages A list of files and directories that Pages should be created for.
+ * @return A list of PageForXmlRpcOld objects for all files matching the pattern in the settings.
+ */
+ protected List<Page> createPages(FileFilter filter, List<File> inputPages) {
+ String message = "Initializing Pages...";
+ this.state.updateNote(message);
+ log.info(message);
+
+ List<Page> allPages = new LinkedList<Page>();
+
+ for (File fileOrDir : inputPages) {
+ this.state.updateProgress();
+ List<Page> pages = recurse(fileOrDir, filter);
+ setupPages(fileOrDir, pages);
+ allPages.addAll(pages);
+ }
+
+ log.debug("Number of page inputs (all): " + allPages.size());
+ if (isHandlingPageHistories() && isPageHistorySortOnCreate()) {
+ List<Page> sorted = sortByHistory(allPages);
+ log.debug("Number of page inputs (sorted): " + sorted.size());
+ return sorted;
+ }
+ return allPages;
+ }
+
+ /**
+ * Recurses through a directory structure and adds all files in it matching the filter.
+ * Called by createPages.
+ *
+ * @param fileOrDir A directory or file. Must not be <code>null</code>.
+ * @param filter the filter to use when selecting files
+ * @return A list with PageForXmlRpcOld objects for all the matching files in the directory and its subdirectories
+ */
+ private List<Page> recurse(File fileOrDir, FileFilter filter) {
+ assert fileOrDir != null;
+ List<Page> result = new LinkedList<Page>();
+ if (fileOrDir.isFile()) { //it's a file AND
+ if (filter == null || filter.accept(fileOrDir)) { //there's no filter OR the filter accepts the file
+ PageSplitter splitter = getPageSplitter();
+ if (splitter == null)
+ result.add(new Page(fileOrDir));
+ else
+ result.addAll(splitter.split(fileOrDir));
+ }
+ else
+ log.debug("Filtering out filename: " + fileOrDir.getName());
+ } else if (fileOrDir.isDirectory()) {
+ File[] files = fileOrDir.listFiles(filter);
+ for (File file : files) {
+ result.addAll(recurse(file, filter));
+ }
+ }
+ else { //some other problem
+ String message = "Could not find file: '" +
+ fileOrDir.getAbsolutePath() +
+ "'.\n" +
+ "Check existence and permissions.";
log.warn(message);
this.errors.addError(Feedback.BAD_FILE, message, true);
- }
- return result;
- }
+ }
+ return result;
+ }
- private PageSplitter getPageSplitter() {
- String classname = this.miscProperties.getProperty("pagesplitter", null);
- if (classname == null) return null;
- Class c;
+ private PageSplitter getPageSplitter() {
+ String classname = this.miscProperties.getProperty("pagesplitter", null);
+ if (classname == null) return null;
+ Class c;
try {
c = Class.forName(classname);
} catch (ClassNotFoundException e) {
@@ -823,29 +860,30 @@
}
/**
- * Set the names of the pages and performs any other setup needed. Called by recurse().
- * If the user selected a directory and this file is inside it, the base directory's
- * path is removed and the rest is used as the page name.
- * <p/>
- * Any directory separators are replaced with the constant CONFLUENCE_SEPARATOR.
- *
- * @param baseDir The directory that the top-level documents are in
- * @param pages A list of pages to set up
- */
- protected void setupPages(File baseDir, List<Page> pages) {
- String basepath = baseDir.getParentFile().getPath() + File.separator;
- int baselength = basepath.length();
+ * Set the names of the pages and performs any other setup needed. Called by recurse().
+ * If the user selected a directory and this file is inside it, the base directory's
+ * path is removed and the rest is used as the page name.
+ * <p/>
+ * Any directory separators are replaced with the constant CONFLUENCE_SEPARATOR.
+ *
+ * @param baseDir The directory that the top-level documents are in
+ * @param pages A list of pages to set up
+ */
+ protected void setupPages(File baseDir, List<Page> pages) {
+ String basepath = baseDir.getParentFile().getPath() + File.separator;
+ int baselength = basepath.length();
- for (Page page : pages) {
- String pagePath = page.getFile().getPath();
- String pageName = getPagename(pagePath.substring(baselength));
- //Strip the file name from the path.
- String path = getPath(pagePath);
- page.setPath(path);
- page.setName(pageName);
- if (isHandlingPageHistoriesFromFilename()) preserveHistory(page, pageName);
- }
- }
+ for (Page page : pages) {
+ String pagePath = page.getFile().getPath();
+ String pageName = getPagename(pagePath.substring(baselength));
+ log.debug("New page: " + pageName + " -> " + pagePath);
+ //Strip the file name from the path.
+ String path = getPath(pagePath);
+ page.setPath(path);
+ page.setName(pageName);
+ if (isHandlingPageHistoriesFromFilename()) preserveHistory(page, pageName);
+ }
+ }
/**
* figures out path var for Page based on complete path to page's file
@@ -855,77 +893,77 @@
private String getPath(String pagePath) {
int fileNameStart = pagePath.lastIndexOf(File.separator);
if (fileNameStart >= 0) {
- pagePath = pagePath.substring(0, fileNameStart);
+ pagePath = pagePath.substring(0, fileNameStart);
} else {
- pagePath = "";
+ pagePath = "";
}
return pagePath;
}
- /**
- * uses the filename to set the version and name of the given page
- * so that the history is preserved in the conversion. Note:
- * uses the pageHistorySuffix which is set by the handlePageHistoryProperty
- * method
- * @param page object that will be changed to reflect pagename and version of given filename
- * @param filename should use the pageHistorySuffix to indicate version and pagename:
- * <br/>
- * if pageHistorySuffix is -#.txt
- * <br/>
- * then filename should be something like: pagename-2.txt
- * @return Page with changed name and version
- * Will return passed page with no changes if:
- * <ul>
- * <li>suffix is null</li>
- * <li> suffix has no numerical indicator (#)</li>
- * </ul>
- */
- protected Page preserveHistory(Page page, String filename) {
- if (loadOnAncestors()) {
- addAncestors(page);
- if (!page.getAncestors().isEmpty()) {
- page.setVersion(page.getLatestVersion()+1);
- log.debug("Current page version: " + page.getVersion());
- }
- return page;
- }
- return identifyHistoryOnePage(page, filename);
+ /**
+ * uses the filename to set the version and name of the given page
+ * so that the history is preserved in the conversion. Note:
+ * uses the pageHistorySuffix which is set by the handlePageHistoryProperty
+ * method
+ * @param page object that will be changed to reflect pagename and version of given filename
+ * @param filename should use the pageHistorySuffix to indicate version and pagename:
+ * <br/>
+ * if pageHistorySuffix is -#.txt
+ * <br/>
+ * then filename should be something like: pagename-2.txt
+ * @return Page with changed name and version
+ * Will return passed page with no changes if:
+ * <ul>
+ * <li>suffix is null</li>
+ * <li> suffix has no numerical indicator (#)</li>
+ * </ul>
+ */
+ protected Page preserveHistory(Page page, String filename) {
+ if (loadOnAncestors()) {
+ addAncestors(page);
+ if (!page.getAncestors().isEmpty()) {
+ page.setVersion(page.getLatestVersion()+1);
+ log.debug("Current page version: " + page.getVersion());
+ }
+ return page;
+ }
+ return identifyHistoryOnePage(page, filename);
}
public Page identifyHistoryOnePage(Page page, String filename) {
//get suffix
String suffix = getPageHistorySuffix();
- if (suffix == null) {
- log.error("Error attempting to preserve history: Page history suffix is Null.");
- return page;
- }
- //create regex for filename based on the suffix
- Matcher hashFinder = hashPattern.matcher(suffix);
- String suffixReplaceRegex = "";
- if (hashFinder.find()) {
- suffixReplaceRegex = hashFinder.replaceAll("(\\\\d+)");
- suffixReplaceRegex = "(.*)" + suffixReplaceRegex;
- }
- else {
- log.error("Error attempting to preserve history: Suffix is invalid. Must contain '#'.");
- return page;
- }
- //get the version and name
- Pattern suffixReplacePattern = Pattern.compile(suffixReplaceRegex);
- Matcher suffixReplacer = suffixReplacePattern.matcher(filename);
- if (suffixReplacer.find()) {
- String pagename = suffixReplacer.group(1);
- String versionString = suffixReplacer.group(2);
- page.setName(pagename); //set name before version so latestversion data is properly set in Page
- if (Boolean.parseBoolean(this.miscProperties.getProperty("page-history-sortwithtimestamp", "false")))
- page.setTimestamp(new Date(Long.parseLong(versionString)*1000));
- else
- page.setVersion(Integer.parseInt(versionString));
- }
- return page;
+ if (suffix == null) {
+ log.error("Error attempting to preserve history: Page history suffix is Null.");
+ return page;
+ }
+ //create regex for filename based on the suffix
+ Matcher hashFinder = hashPattern.matcher(suffix);
+ String suffixReplaceRegex = "";
+ if (hashFinder.find()) {
+ suffixReplaceRegex = hashFinder.replaceAll("(\\\\d+)");
+ suffixReplaceRegex = "(.*)" + suffixReplaceRegex;
+ }
+ else {
+ log.error("Error attempting to preserve history: Suffix is invalid. Must contain '#'.");
+ return page;
+ }
+ //get the version and name
+ Pattern suffixReplacePattern = Pattern.compile(suffixReplaceRegex);
+ Matcher suffixReplacer = suffixReplacePattern.matcher(filename);
+ if (suffixReplacer.find()) {
+ String pagename = suffixReplacer.group(1);
+ String versionString = suffixReplacer.group(2);
+ page.setName(pagename); //set name before version so latestversion data is properly set in Page
+ if (Boolean.parseBoolean(this.miscProperties.getProperty("page-history-sortwithtimestamp", "false")))
+ page.setTimestamp(new Date(Long.parseLong(versionString)*1000));
+ else
+ page.setVersion(Integer.parseInt(versionString));
+ }
+ return page;
}
-
- /* Page History Load on Ancestors methods - START */
+
+ /* Page History Load on Ancestors methods - START */
private boolean loadOnAncestors() {
return Boolean.parseBoolean(this.miscProperties.getProperty("page-history-load-as-ancestors", "false"));
}
@@ -967,9 +1005,21 @@
}
page.setSortWithTimestamp(true); //affects sorting of collections of pages (including hierarchies)
}
-
+ if (this.miscProperties.containsKey("page-history-maxversions")) { //useful for debugging
+ String maxString = this.miscProperties.getProperty("page-history-maxversions", null);
+ int max = Integer.parseInt(maxString);
+ if (max <= page.getAncestors().size()) {
+ log.debug("number of ancestors: " + page.getAncestors().size());
+ int actmax = page.getAncestors().size();
+ for (int i = actmax-1; i >=max; i--) {
+ page.getAncestors().remove(i);
+ }
+ log.debug("after limiting, number of ancestors: " + page.getAncestors().size());
+ }
+ }
+
}
-
+
protected String getPageRelativePath(Page page) {
String ignorable = this.miscProperties.getProperty("filepath-hierarchy-ignorable-ancestors", "");
String full = page.getPath();
@@ -977,7 +1027,7 @@
return full.replaceAll("\\Q"+ignorable + "\\E", "");
}
/* Page History Load on Ancestors methods - END */
-
+
/**
* gets the pagename given the pagepath
@@ -988,14 +1038,14 @@
String pageName = "";
if (hierarchyHandler == HierarchyHandler.DEFAULT ||
hierarchyHandler == HierarchyHandler.HIERARCHY_BUILDER) {
- pageName = pagePath.substring(pagePath.lastIndexOf(File.separator) + 1);
+ pageName = pagePath.substring(pagePath.lastIndexOf(File.separator) + 1);
} else if (hierarchyHandler == HierarchyHandler.PAGENAME_HIERARCHIES) {
String quotedSeparator = Pattern.quote(File.separator);
pageName = pagePath.replaceAll(quotedSeparator, CONFLUENCE_SEPARATOR);
}
return pageName;
}
-
+
/**
* converts the given pages with the given converts
* @param pages
@@ -1005,7 +1055,7 @@
protected boolean convertPages(List pages, List<Converter> converters) {
return convertPages(pages, converters, "Converting pages...");
}
-
+
/**
* converts the given pages with the given converters
* @param pages
@@ -1017,49 +1067,48 @@
boolean result = true;
this.state.updateNote(note);
log.info(note);
-
+
this.startTotalConvertTime = (new Date()).getTime();
-
//go through each page
for (Iterator<Page> iter = pages.iterator(); iter.hasNext();) {
if (!this.running) {
this.feedback = Feedback.CANCELLED;
return false;
}
-
+
Page page = iter.next();
//some bookkeeping
long startTimeStamp = conversionBookkeepingNextPage(page);
- //get the file's contents
-
+ //get the file's contents
+
if (page.getOriginalText() == null || "".equals(page.getOriginalText())) {
- File file = getFileContents(page);
- if (file == null) {
- iter.remove(); //get rid of this page from the iterator.
- continue;
- }
+ File file = getFileContents(page);
+ if (file == null) {
+ iter.remove(); //get rid of this page from the iterator.
+ continue;
+ }
} //else we used a PageSplitter to set the original text, so we can go straight to conversion
-
- //convert the page
- convertPage(converters, page);
- //more bookkeeping
- conversionBookkeepingEndThisPage(startTimeStamp);
- if (!this.running) {
- this.feedback = Feedback.CANCELLED;
- return false;
- }
- if (page.getAncestors() != null && !page.getAncestors().isEmpty()) {
- convertPages(page.getAncestors(), converters);
- }
- }
+
+ //convert the page
+ convertPage(converters, page);
+ //more bookkeeping
+ conversionBookkeepingEndThisPage(startTimeStamp);
+ if (!this.running) {
+ this.feedback = Feedback.CANCELLED;
+ return false;
+ }
+ if (page.getAncestors() != null && !page.getAncestors().isEmpty()) {
+ convertPages(page.getAncestors(), converters);
+ }
+ }
//still more bookkeeping
conversionBookkeepingEndAll(pages, converters);
return result;
-
+
}
-
+
/**
* make some log entries about the time it took to convert a page
* @param startTimeStamp
@@ -1082,11 +1131,11 @@
String baseMessage = "::: total time to convert files: "+ totalTimeToConvert+ " seconds.";
log.info(baseMessage);
String message = baseMessage +
- "For " +
- pages.size() +
- " pages and using " +
- converters.size() +
- " converters.";
+ "For " +
+ pages.size() +
+ " pages and using " +
+ converters.size() +
+ " converters.";
totalsFileLog.info(message);
}
@@ -1119,25 +1168,25 @@
file = new File(path);
}
else {
- log.warn("No file was set for page " + page.getName() + ". Skipping page.");
- return null;
+ log.warn("No file was set for page " + page.getName() + ". Skipping page.");
+ return null;
}
}
else if (page.getOriginalText() == null){
- try {
- String pageContents = "";
- if (isGzip() && page instanceof VersionPage) {
- pageContents = getGzipText(file);
- }
- else pageContents = getAsciiText(file);
- page.setOriginalText(pageContents);
- } catch (IOException e) {
- String message = "Could not read file " + file.getAbsolutePath() + ".\n" +
- "Check existence and permissions.";
- log.error(message);
+ try {
+ String pageContents = "";
+ if (isGzip() && page instanceof VersionPage) {
+ pageContents = getGzipText(file);
+ }
+ else pageContents = getAsciiText(file);
+ page.setOriginalText(pageContents);
+ } catch (IOException e) {
+ String message = "Could not read file " + file.getAbsolutePath() + ".\n" +
+ "Check existence and permissions.";
+ log.error(message);
this.errors.addError(Feedback.BAD_FILE, message, true);
- return null;
- }
+ return null;
+ }
// Save the true source since the original will get modified in convert.
page.setUnchangedSource(page.getOriginalText());
@@ -1157,7 +1206,7 @@
}
public String getAsciiText(File file) throws IOException,
- UnsupportedEncodingException {
+ UnsupportedEncodingException {
String pageContents;
if (changingEncoding()) {
String encoding = getEncoding();
@@ -1183,7 +1232,7 @@
private String getEncoding() {
if (this.miscProperties != null)
- return this.miscProperties.getProperty("encoding", "utf-8");
+ return this.miscProperties.getProperty("encoding", "utf-8");
return "utf-8";
}
@@ -1198,98 +1247,96 @@
page.setConvertedText(page.getOriginalText()); //in case empty converter list
for (Converter converter : converters) {
- try {
- this.state.updateProgress();
- if (this.settings != null) {
- converter.setAttachmentDirectory(this.settings.getAttachmentDirectory());
- }
- else {
- //for backwards compatibility with v2
- ConfluenceSettingsForm confSettings = UWCForm2.getInstance().getConfluenceSettingsForm();
- converter.setAttachmentDirectory(confSettings.getAttachmentDirectory());
- }
- converter.convert(page);
- // Need to reset originalText here because each converted expects
- // to start with the result of previous conversions.
- page.setOriginalText(page.getConvertedText());
- } catch (Exception e) {
- String note = "Exception thrown by converter " + converter.getKey() +
- " on page " + page.getName() + ". Continuing with next converter.";
- log.error(note, e);
+ try {
+ this.state.updateProgress();
+ if (this.settings != null) {
+ converter.setAttachmentDirectory(this.settings.getAttachmentDirectory());
+ }
+ else {
+ //for backwards compatibility with v2
+ ConfluenceSettingsForm confSettings = UWCForm2.getInstance().getConfluenceSettingsForm();
+ converter.setAttachmentDirectory(confSettings.getAttachmentDirectory());
+ }
+ converter.convert(page);
+ // Need to reset originalText here because each converted expects
+ // to start with the result of previous conversions.
+ page.setOriginalText(page.getConvertedText());
+ } catch (Exception e) {
+ String note = "Exception thrown by converter " + converter.getKey() +
+ " on page " + page.getName() + ". Continuing with next converter.";
+ log.error(note, e);
this.errors.addError(Feedback.CONVERTER_ERROR, note, true);
- }
- if (converter.getErrors().hasErrors()) {
- this.hadConverterErrors = true;
- this.state.updateNote(converter.getErrors().getFeedbackWindowErrorMessages());
- }
+ }
+ if (converter.getErrors().hasErrors()) {
+ this.hadConverterErrors = true;
+ this.state.updateNote(converter.getErrors().getFeedbackWindowErrorMessages());
+ }
}
-
+
return page;
}
- /**
- * Write pages to disk. They are saved to the directory output/output below the
- * current working directory.
- *
- * @param pages The pages to save
- * @param pattern This file name extension is appended
- * to each page name to create the file name.
- */
- private void savePages(List<Page> pages, String pattern) {
- String message = "Saving Pages to Filesystem";
+ /**
+ * Write pages to disk. They are saved to the directory output/output below the
+ * current working directory.
+ *
+ * @param pages The pages to save
+ * @param pattern This file name extension is appended
+ * to each page name to create the file name.
+ */
+ private void savePages(List<Page> pages, String pattern) {
+ String message = "Saving Pages to Filesystem";
this.state.updateNote(message);
log.info(message);
-
- FileUtils.createOutputDirIfNeeded();
-
- String outputDirName = UWCGuiModel.getOutputDir();
- log.debug("Output Directory = " + outputDirName);
- File outputDir = new File(outputDirName);
- if (!outputDir.exists() && !outputDir.mkdir()) {
- String dirfailMessage = "Directory creation failed for directory " + outputDirName;
- log.error(Feedback.BAD_OUTPUT_DIR + ": " + dirfailMessage);
+ FileUtils.createOutputDirIfNeeded();
+
+ String outputDirName = UWCGuiModel.getOutputDir();
+ log.debug("Output Directory = " + outputDirName);
+
+ File outputDir = new File(outputDirName);
+ if (!outputDir.exists() && !outputDir.mkdir()) {
+ String dirfailMessage = "Directory creation failed for directory " + outputDirName;
+ log.error(Feedback.BAD_OUTPUT_DIR + ": " + dirfailMessage);
this.errors.addError(Feedback.BAD_OUTPUT_DIR, dirfailMessage, true);
- }
-
- for (Page page : pages) {
- if (!this.running) {
- this.feedback = Feedback.CANCELLED;
- return;
- }
- this.state.updateProgress();
- String outputFileLoc = outputDirName + File.separator + page.getName() + pattern;
- FileUtils.writeFile(page.getConvertedText(), outputFileLoc);
- }
- }
-
- protected Vector listCollisions(List<Page> pages) {
- Vector<String> collisions = new Vector<String>();
- //check to see if "off" property is present
- if (this.miscProperties != null &&
- this.miscProperties.containsKey("list-collisions") &&
- !Boolean.parseBoolean(this.miscProperties.getProperty("list-collisions"))) {
- log.debug("Namespace Collisions Feature turned off.");
- return collisions;
- }
- //sort
- Vector<Page> sorted = new Vector<Page>();
- sorted.addAll(pages);
- AsciiVersionComparator version = new AsciiVersionComparator();
- Collections.sort(sorted, version);
- //look for collisions
- Page last = new Page(null);
- last.setName("");
- last.setPath("");
- for (int i = 1; i < sorted.size(); i++) {
+ }
+
+ for (Page page : pages) {
+ if (!this.running) {
+ this.feedback = Feedback.CANCELLED;
+ return;
+ }
+ this.state.updateProgress();
+ String outputFileLoc = outputDirName + File.separator + page.getName() + pattern;
+ FileUtils.writeFile(page.getConvertedText(), outputFileLoc);
+ }
+ }
+
+ protected Vector listCollisions(List<Page> pages) {
+ Vector<String> collisions = new Vector<String>();
+ //check to see if "off" property is present
+ if (this.miscProperties != null &&
+ this.miscProperties.containsKey("list-collisions") &&
+ !Boolean.parseBoolean(this.miscProperties.getProperty("list-collisions"))) {
+ log.debug("Namespace Collisions Feature turned off.");
+ return collisions;
+ }
+ //sort
+ Vector<Page> sorted = new Vector<Page>();
+ sorted.addAll(pages);
+ AsciiVersionComparator version = new AsciiVersionComparator();
+ Collections.sort(sorted, version);
+ //look for collisions
+ Page last = new Page(null);
+ last.setName("");
+ last.setPath("");
+ for (int i = 1; i < sorted.size(); i++) {
Page page1 = (Page) sorted.get(i-1);
Page page2 = (Page) sorted.get(i);
log.debug("Checking for collisions: " + page1.getName() + " and " + page2.getName());
String collision = "";
//if each page lower cased is the same
- if (getCollisionComparisonString(page1).equals(getCollisionComparisonString(page2))
- && page1.getVersion() == page2.getVersion() //and same page history version
- ) {
+ if (colliding(page1, page2)) {
if (getCollisionComparisonString(page1).equals(getCollisionComparisonString(last))) { //already have one for this name
String latestPath = getPagePath(page2);
String current = collisions.remove(collisions.size()-1);
@@ -1297,7 +1344,7 @@
}
else { //starting here
collision = getPagePath(page1) + page1.getName() + ", " +
- getPagePath(page2) + page2.getName();
+ getPagePath(page2) + page2.getName();
}
collisions.add(collision);
last = page1;
@@ -1308,8 +1355,29 @@
this.log.error(error);
}
}
- return collisions;
- }
+ return collisions;
+ }
+
+ protected boolean colliding(Page page1, Page page2) {
+ boolean name = getCollisionComparisonString(page1).equals(getCollisionComparisonString(page2));
+ boolean version = page1.getVersion() == page2.getVersion();
+
+ boolean space = false;
+ if (page1.getSpacekey() != null) {
+ space = page1.getSpacekey().equals(page2.getSpacekey());
+ }
+ else if (page2.getSpacekey() != null) {
+ space = page2.getSpacekey().equals(page1.getSpacekey());
+ }
+ else if (page1.getSpacekey() == null && page2.getSpacekey() == null)
+ space = true;
+
+ boolean path = !getPagePath(page1).equals(getPagePath(page2));
+ return name
+ && version //and same page history version
+ && space// and same space
+ && path; // but not the same path
+ }
/**
* @param page
@@ -1331,68 +1399,77 @@
private String getPagePath(Page page) {
return (page.getPath().endsWith(File.separator)?
page.getPath():
- page.getPath()+File.separator);
+ page.getPath()+File.separator);
}
-
- /**
- * Writes the pages to Confluence. If the process takes more than three seconds,
- * a progress monitor will be displayed so that the user can see that something is
- * indeed happening.
- *
- * @param pages The pages to output.
- * @param spacekey space to which the pages will be written
- */
- protected void writePages(List pages, String spacekey) {
- String note = "Uploading Pages to Confluence...";
- this.state.updateNote(note);
- log.info(note);
-
- int numUploaded = 0;
- List<Page> casted = (List<Page>) pages;
- // at last, write the pages to Confluence!
- for (Page page : casted) {
- this.state.updateProgress();
- if (!this.running) {
- this.feedback = Feedback.CANCELLED;
- return;
- }
- if (sendPage(page, null, this.settings) == null) continue;
- numUploaded++;
- if ((numUploaded % 10) == 0) {
- String message = "Uploaded " + numUploaded +
- " out of " + pages.size() +
- " page"+ (numUploaded==1?"":"s") +
- ".";
- this.state.updateNote(message);
- log.info(message);
- }
- }
-
- String message = "Uploaded " + numUploaded +
- " out of " + pages.size() +
- " page"+ (numUploaded==1?"":"s") +
- ".";
- this.state.updateNote(message);
- log.info(message);
-
- //attachedFiles is cleared so that if we do another conversion
- //without closing the UWC, it won't think the attachment has already been
- //attached
- this.attachedFiles = null;
- this.attachedPaths = null;
- }
+ /**
+ * Writes the pages to Confluence. If the process takes more than three seconds,
+ * a progress monitor will be displayed so that the user can see that something is
+ * indeed happening.
+ *
+ * @param pages The pages to output.
+ * @param spacekey space to which the pages will be written
+ */
+ protected void writePages(List pages, String spacekey) {
+ writePages(pages, spacekey, true);
+ }
+ protected void writePages(List pages, String spacekey, boolean logging) {
+ if (logging) {
+ String note = "Uploading Pages to Confluence...";
+ this.state.updateNote(note);
+ log.info(note);
+ }
- Pattern uploadedPattern = Pattern.compile("Attachment Uploaded: (.*)");
+ int numUploaded = 0;
+ List<Page> casted = (List<Page>) pages;
+ // at last, write the pages to Confluence!
+ for (Page page : casted) {
+ this.state.updateProgress();
+ if (!this.running) {
+ this.feedback = Feedback.CANCELLED;
+ return;
+ }
+ if (sendPage(page, null, this.settings) == null) continue;
+ numUploaded++;
+ if (logging && (numUploaded % 10) == 0) {
+ String message = "Uploaded " + numUploaded +
+ " out of " + pages.size() +
+ " page"+ (numUploaded==1?"":"s") +
+ ".";
+ this.state.updateNote(message);
+ log.info(message);
+ }
+ }
+
+ if (logging) {
+ String message = "Uploaded " + numUploaded +
+ " out of " + pages.size() +
+ " page"+ (numUploaded==1?"":"s") +
+ ".";
+ this.state.updateNote(message);
+ log.info(message);
+ }
+ }
+
+ protected void clearAttachedFileList() {
+ //attachedFiles is cleared so that if we do another conversion
+ //without closing the UWC, it won't think the attachment has already been
+ //attached
+ log.debug("Clearing Attached Filelist for next run.");
+ this.attachedFiles = null;
+ this.attachedPaths = null;
+ }
+
+ Pattern uploadedPattern = Pattern.compile("Attachment Uploaded: (.*)");
public void handleOrphanAttachments() {
if (this.settings.getUploadOrphanAttachments().equalsIgnoreCase("true"))
- {
+ {
if (this.miscProperties.containsKey("attachments-uploaded-file")) {
identifyPreviouslyAttachedPaths(this.miscProperties.getProperty("attachments-uploaded-file"));
}
- ArrayList <File> orphanAttachments=findOrphanAttachments(this.settings.getAttachmentDirectory());
- uploadOrphanAttachments(orphanAttachments);
- }
+ ArrayList <File> orphanAttachments=findOrphanAttachments(this.settings.getAttachmentDirectory());
+ uploadOrphanAttachments(orphanAttachments);
+ }
}
protected void identifyPreviouslyAttachedPaths(String uploadedpath) {
@@ -1413,124 +1490,124 @@
}
}
}
-
+
//for unit testing purposes
protected void addAttachedPath(String path) {
if (this.attachedPaths == null) this.attachedPaths = new HashSet<String>();
this.attachedPaths.add(path);
}
-
+
//for unit testing purposes
protected void clearAttachedPath() {
this.attachedPaths = null;
}
-
- /******
- * to find all orphan attachment files
- * @param dirName
- * @return
- */
- protected ArrayList<File> findOrphanAttachments(String dirName)
- {
- ArrayList<File> orphanAttachments=new ArrayList<File>();
- File directory=new File(dirName);
- for (File file : directory.listFiles()) {
- if (file.isDirectory())
- orphanAttachments.addAll(findOrphanAttachments(file.getAbsolutePath()));
- else if (file.isFile())
- {
- if (orphanAlreadyAttached(file))
- continue;
- log.debug("Found orphan attachment: " + file.getAbsolutePath());
- orphanAttachments.add(file);
- }
- }
-
- return orphanAttachments;
-
-
- }
- /**
- * to upload the orphan attachment files to wiki.
- */
- protected void uploadOrphanAttachments(ArrayList<File> orphanAttachments)
- {
- if (orphanAttachments == null || orphanAttachments.size() == 0)
- return;
-
- Hashtable pageTable = new Hashtable();
- pageTable.put("content", "");
- pageTable.put("title", ORPHAN_ATTACHMENTS_PAGE_TITLE);
-
- //create ConfluenceServerSettings object
- ConfluenceServerSettings confSettings = new ConfluenceServerSettings();
- confSettings.login = settings.getLogin();
- confSettings.password = settings.getPassword();
- confSettings.url = settings.getUrl();
- confSettings.spaceKey = settings.getSpace();
- confSettings.truststore = settings.getTruststore();
- confSettings.trustpass = settings.getTrustpass();
- confSettings.trustallcerts = settings.getTrustall();
-
- RemoteWikiBroker broker = RemoteWikiBroker.getInstance();
- //check for problems with settings
- checkConfluenceSettings(confSettings);
- //send page
- String pageId = sendPage(broker, pageTable, confSettings);
-
- int total=orphanAttachments.size();
- int count=0;
- for (File file : orphanAttachments) {
- sendAttachment(file, broker, pageId, confSettings);
- count++;
- if ((count % 10) == 0) {
- String message = "Uploaded " + count +
- " out of " + total + " orphan attachments.";
- this.state.updateNote(message);
- log.info(message);
- }
- }
-
- String message = "Uploaded " + total + " orphan attachments.";
+
+ /******
+ * to find all orphan attachment files
+ * @param dirName
+ * @return
+ */
+ protected ArrayList<File> findOrphanAttachments(String dirName)
+ {
+ ArrayList<File> orphanAttachments=new ArrayList<File>();
+ File directory=new File(dirName);
+ for (File file : directory.listFiles()) {
+ if (file.isDirectory())
+ orphanAttachments.addAll(findOrphanAttachments(file.getAbsolutePath()));
+ else if (file.isFile())
+ {
+ if (orphanAlreadyAttached(file))
+ continue;
+ log.debug("Found orphan attachment: " + file.getAbsolutePath());
+ orphanAttachments.add(file);
+ }
+ }
+
+ return orphanAttachments;
+
+
+ }
+ /**
+ * to upload the orphan attachment files to wiki.
+ */
+ protected void uploadOrphanAttachments(ArrayList<File> orphanAttachments)
+ {
+ if (orphanAttachments == null || orphanAttachments.size() == 0)
+ return;
+
+ Hashtable pageTable = new Hashtable();
+ pageTable.put("content", "");
+ pageTable.put("title", ORPHAN_ATTACHMENTS_PAGE_TITLE);
+
+ //create ConfluenceServerSettings object
+ ConfluenceServerSettings confSettings = new ConfluenceServerSettings();
+ confSettings.login = settings.getLogin();
+ confSettings.password = settings.getPassword();
+ confSettings.url = settings.getUrl();
+ confSettings.spaceKey = settings.getSpace();
+ confSettings.truststore = settings.getTruststore();
+ confSettings.trustpass = settings.getTrustpass();
+ confSettings.trustallcerts = settings.getTrustall();
+
+ RemoteWikiBroker broker = RemoteWikiBroker.getInstance();
+ //check for problems with settings
+ checkConfluenceSettings(confSettings);
+ //send page
+ String pageId = sendPage(broker, pageTable, confSettings);
+
+ int total=orphanAttachments.size();
+ int count=0;
+ for (File file : orphanAttachments) {
+ sendAttachment(file, broker, pageId, confSettings);
+ count++;
+ if ((count % 10) == 0) {
+ String message = "Uploaded " + count +
+ " out of " + total + " orphan attachments.";
+ this.state.updateNote(message);
+ log.info(message);
+ }
+ }
+
+ String message = "Uploaded " + total + " orphan attachments.";
this.state.updateNote(message);
log.info(message);
-
- }
-
- /****
- * send an attachment file to wiki.
- *
- * @param file
- * @param broker
- * @param pageId
- * @param confSettings
- * @return the attachment object we sent. used by junit tests
- */
- protected AttachmentForXmlRpc sendAttachment(File file, RemoteWikiBroker broker, String pageId, ConfluenceServerSettings confSettings) {
- return sendAttachment(new Attachment(file), broker, pageId, confSettings);
- }
- protected AttachmentForXmlRpc sendAttachment(Attachment attachment, RemoteWikiBroker broker, String pageId, ConfluenceServerSettings confSettings)
- {
- File file = attachment.getFile();
- AttachmentForXmlRpc attachmentRpc = new AttachmentForXmlRpc();
- if (tooBig(file) || doesNotExist(file))
- return null;
- attachmentRpc.setFileName(attachment.getName());
- attachmentRpc.setFileLocation(file.getAbsolutePath());
- attachmentRpc.setContentType(determineContentType(file)); //XXX Note: if the filename is different from the file, the content type determining might be foiled
- attachmentRpc.setComment(attachment.getComment() == null?getAttachmentUploadComment():attachment.getComment());
- String errorMessage = "Couldn't send attachmentRpc " +
- file.getAbsolutePath() + ". Skipping attachmentRpc.";
- if (usingWebdav()) {
- String webdavPath = getWebdavPath();
- sendAttachmentWebdav(broker, pageId, confSettings, attachmentRpc, webdavPath, errorMessage);
- }
- else
- sendAttachmentRemoteAPI(broker, pageId, confSettings, attachmentRpc, errorMessage);
- attachmentLog.info("Attachment Uploaded: " + file.getAbsolutePath());
- return attachmentRpc;//for junit tests
- }
+
+ }
+
+ /****
+ * send an attachment file to wiki.
+ *
+ * @param file
+ * @param broker
+ * @param pageId
+ * @param confSettings
+ * @return the attachment object we sent. used by junit tests
+ */
+ protected AttachmentForXmlRpc sendAttachment(File file, RemoteWikiBroker broker, String pageId, ConfluenceServerSettings confSettings) {
+ return sendAttachment(new Attachment(file), broker, pageId, confSettings);
+ }
+ protected AttachmentForXmlRpc sendAttachment(Attachment attachment, RemoteWikiBroker broker, String pageId, ConfluenceServerSettings confSettings)
+ {
+ File file = attachment.getFile();
+ AttachmentForXmlRpc attachmentRpc = new AttachmentForXmlRpc();
+ if (tooBig(file) || doesNotExist(file))
+ return null;
+ attachmentRpc.setFileName(attachment.getName());
+ attachmentRpc.setFileLocation(file.getAbsolutePath());
+ attachmentRpc.setContentType(determineContentType(file)); //XXX Note: if the filename is different from the file, the content type determining might be foiled
+ attachmentRpc.setComment(attachment.getComment() == null?getAttachmentUploadComment():attachment.getComment());
+ String errorMessage = "Couldn't send attachmentRpc " +
+ file.getAbsolutePath() + ". Skipping attachmentRpc.";
+ if (usingWebdav()) {
+ String webdavPath = getWebdavPath();
+ sendAttachmentWebdav(broker, pageId, confSettings, attachmentRpc, webdavPath, errorMessage);
+ }
+ else
+ sendAttachmentRemoteAPI(broker, pageId, confSettings, attachmentRpc, errorMessage);
+ attachmentLog.info("Attachment Uploaded: " + file.getAbsolutePath());
+ return attachmentRpc;//for junit tests
+ }
private String getAttachmentUploadComment() {
if (this.miscProperties != null &&
@@ -1560,144 +1637,144 @@
}
private void sendAttachmentWebdav(RemoteWikiBroker broker, String pageId,
- ConfluenceServerSettings confSettings,
- AttachmentForXmlRpc attachment, String basepath,
- String errorMessage) {
+ ConfluenceServerSettings confSettings,
+ AttachmentForXmlRpc attachment, String basepath,
+ String errorMessage) {
try {
Map pagesByIdMap = broker.getAllServerPagesMapById(confSettings, confSettings.spaceKey);
String webdavPath = broker.getWebDAVPagePath(confSettings.url, confSettings.spaceKey, pageId, pagesByIdMap, basepath);
broker.sendFileViaWebDAV(attachment.getFileLocation(), webdavPath, confSettings.login, confSettings.password);
} catch (IOException e) {
- log.error(Feedback.BAD_FILE + ": " + errorMessage, e);
- this.errors.addError(Feedback.BAD_FILE, errorMessage, true);
- } catch (XmlRpcException e) {
- log.error(Feedback.REMOTE_API_ERROR + ": " + errorMessage, e);
- this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
- if (Pattern.matches(".*?You do not have the permissions.*", e.getMessage())) {
- String noPermissionsError = "User '" + confSettings.login +
- "' " +
- "does not have permission to attach files to space '" +
- confSettings.spaceKey +
- "'.";
- log.debug(Feedback.USER_NOT_PERMITTED + ": " + noPermissionsError);
- this.errors.addError(Feedback.USER_NOT_PERMITTED, noPermissionsError, true);
- }
- }
-
+ log.error(Feedback.BAD_FILE + ": " + errorMessage, e);
+ this.errors.addError(Feedback.BAD_FILE, errorMessage, true);
+ } catch (XmlRpcException e) {
+ log.error(Feedback.REMOTE_API_ERROR + ": " + errorMessage, e);
+ this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
+ if (Pattern.matches(".*?You do not have the permissions.*", e.getMessage())) {
+ String noPermissionsError = "User '" + confSettings.login +
+ "' " +
+ "does not have permission to attach files to space '" +
+ confSettings.spaceKey +
+ "'.";
+ log.debug(Feedback.USER_NOT_PERMITTED + ": " + noPermissionsError);
+ this.errors.addError(Feedback.USER_NOT_PERMITTED, noPermissionsError, true);
+ }
+ }
+
}
private void sendAttachmentRemoteAPI(RemoteWikiBroker broker, String pageId, ConfluenceServerSettings confSettings, AttachmentForXmlRpc attachment, String errorMessage) {
try {
- broker.storeAttachment(confSettings, pageId, attachment);
- } catch (IOException e) {
- log.error(Feedback.BAD_FILE + ": " + errorMessage, e);
- this.errors.addError(Feedback.BAD_FILE, errorMessage, true);
- } catch (XmlRpcException e) {
- log.error(Feedback.REMOTE_API_ERROR + ": " + errorMessage, e);
- this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
- if (Pattern.matches(".*?You do not have the permissions.*", e.getMessage())) {
- String noPermissionsError = "User '" + confSettings.login +
- "' " +
- "does not have permission to attach files to space '" +
- confSettings.spaceKey +
- "'.";
- log.debug(Feedback.USER_NOT_PERMITTED + ": " + noPermissionsError);
- this.errors.addError(Feedback.USER_NOT_PERMITTED, noPermissionsError, true);
- }
- }
+ broker.storeAttachment(confSettings, pageId, attachment);
+ } catch (IOException e) {
+ log.error(Feedback.BAD_FILE + ": " + errorMessage, e);
+ this.errors.addError(Feedback.BAD_FILE, errorMessage, true);
+ } catch (XmlRpcException e) {
+ log.error(Feedback.REMOTE_API_ERROR + ": " + errorMessage, e);
+ this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
+ if (Pattern.matches(".*?You do not have the permissions.*", e.getMessage())) {
+ String noPermissionsError = "User '" + confSettings.login +
+ "' " +
+ "does not have permission to attach files to space '" +
+ confSettings.spaceKey +
+ "'.";
+ log.debug(Feedback.USER_NOT_PERMITTED + ": " + noPermissionsError);
+ this.errors.addError(Feedback.USER_NOT_PERMITTED, noPermissionsError, true);
+ }
+ }
}
- /**
- * Writes a hierarchy of pages to Confluence. The empty nodes (those with page=null) will
- * not be written if there already exists a page in Confluence. If there is no page at the
- * corresponding place in Confluence, an empty page will be created.
- *
- * Like writePages(), this method will show a progress bar if the hierarchy takes more than
- * a few seconds to send to Confluence.
- *
- * @param root The root of the hierarchy. Note: The root node itself will <strong>NOT</strong> be
- * added to Confluence. All it's children will be added as top-level pages in the space.
- * @param maxProgress used by logging and status messages
- * @param spacekey space to which the pages will be written
- */
- protected void writeHierarchy(HierarchyNode root, int maxProgress, String spacekey) {
- String message = "Uploading Pages to Confluence...";
+ /**
+ * Writes a hierarchy of pages to Confluence. The empty nodes (those with page=null) will
+ * not be written if there already exists a page in Confluence. If there is no page at the
+ * corresponding place in Confluence, an empty page will be created.
+ *
+ * Like writePages(), this method will show a progress bar if the hierarchy takes more than
+ * a few seconds to send to Confluence.
+ *
+ * @param root The root of the hierarchy. Note: The root node itself will <strong>NOT</strong> be
+ * added to Confluence. All it's children will be added as top-level pages in the space.
+ * @param maxProgress used by logging and status messages
+ * @param spacekey space to which the pages will be written
+ */
+ protected void writeHierarchy(HierarchyNode root, int maxProgress, String spacekey) {
+ String message = "Uploading Pages to Confluence...";
this.state.updateNote(message);
log.info(message);
-
- int progressNum = 0;
- this.newNodes = 0; //this has to be a field, because we're already returning something;
- // at last write the pages to Confluence!
- for (HierarchyNode topLevelPage : root.getChildren()) {
- log.debug("writeHierarchy: toplevelpage = " + topLevelPage.getName());
- log.debug("number of children this toplevelpage has = " + topLevelPage.getChildren().size());
- progressNum = writeHierarchy(topLevelPage, null, progressNum, maxProgress, spacekey);
- if (!this.running) {
- this.feedback = Feedback.CANCELLED;
- return;
- }
- }
- }
- /**
- * This is the recursive part of <code>writeHierarchy</code>. Don't call this directly!
- * Call writeHierarchy(root) instead.
- *
- * @param node The current node in the hierarchy
- * @param parentId The Confluence "page ID" of the parent page
- * @param progress The number of pages that have been converted so far
- * (used to keep the progress monitor updated)
- * @param spacekey space to which the pages will be written
- * @return The number of pages converted after this node and all its descendants have been added.
- */
- private int writeHierarchy(
- HierarchyNode node,
- String parentId,
- int progress,
- int maxProgress,
- String spacekey) {
- if (!this.running) {
- this.feedback = Feedback.CANCELLED;
- return progress;
- }
- // First upload the page contained in this node
- Page page = node.getPage();
- // create missing nodes - like a directory that didn't have a corresponding page
- if (page == null) {
- // This node is a "placeholder" because there are pages further down the hierarchy but
- // for some reason this node was not included in the conversion. Create an empty page.
- // Note that this page will only be sent to Confluence if there was no page in place before.
- page = new Page(null);
- page.setName(node.getName());
- page.setOriginalText("");
- page.setConvertedText("");
- page.setPath(node.getName()); //needed by auto-detect spacekeys feature
+ int progressNum = 0;
+ this.newNodes = 0; //this has to be a field, because we're already returning something;
+ // at last write the pages to Confluence!
+ for (HierarchyNode topLevelPage : root.getChildren()) {
+ log.debug("writeHierarchy: toplevelpage = " + topLevelPage.getName());
+ log.debug("number of children this toplevelpage has = " + topLevelPage.getChildren().size());
+ progressNum = writeHierarchy(topLevelPage, null, progressNum, maxProgress, spacekey);
+ if (!this.running) {
+ this.feedback = Feedback.CANCELLED;
+ return;
+ }
+ }
+ }
- String message = "Page '" + page.getName() + "' does not exist. Creating it now.";
+ /**
+ * This is the recursive part of <code>writeHierarchy</code>. Don't call this directly!
+ * Call writeHierarchy(root) instead.
+ *
+ * @param node The current node in the hierarchy
+ * @param parentId The Confluence "page ID" of the parent page
+ * @param progress The number of pages that have been converted so far
+ * (used to keep the progress monitor updated)
+ * @param spacekey space to which the pages will be written
+ * @return The number of pages converted after this node and all its descendants have been added.
+ */
+ private int writeHierarchy(
+ HierarchyNode node,
+ String parentId,
+ int progress,
+ int maxProgress,
+ String spacekey) {
+ if (!this.running) {
+ this.feedback = Feedback.CANCELLED;
+ return progress;
+ }
+ // First upload the page contained in this node
+ Page page = node.getPage();
+ // create missing nodes - like a directory that didn't have a corresponding page
+ if (page == null) {
+ // This node is a "placeholder" because there are pages further down the hierarchy but
+ // for some reason this node was not included in the conversion. Create an empty page.
+ // Note that this page will only be sent to Confluence if there was no page in place before.
+ page = new Page(null);
+ page.setName(node.getName());
+ page.setOriginalText("");
+ page.setConvertedText("");
+ page.setPath(node.getName()); //needed by auto-detect spacekeys feature
+
+ String message = "Page '" + page.getName() + "' does not exist. Creating it now.";
log.info(message);
this.state.updateNote(message);
-
- this.newNodes++;
- this.state.updateMax(this.state.getMax() + 1);
- }
-
- //upload the page
- String myId = sendPage(page, parentId, this.settings);
-
- //some bookkeeping
- progress++;
- logProgressMessage(progress, maxProgress);
-
- // Then recursively upload all the node's descendants
- for (HierarchyNode child : node.getChildren()) {
- progress = writeHierarchy(child, myId, progress, maxProgress, spacekey);
- if (!this.running) {
- this.feedback = Feedback.CANCELLED;
- return progress;
- }
- }
-
- return progress;
- }
+
+ this.newNodes++;
+ this.state.updateMax(this.state.getMax() + 1);
+ }
+
+ //upload the page
+ String myId = sendPage(page, parentId, this.settings);
+
+ //some bookkeeping
+ progress++;
+ logProgressMessage(progress, maxProgress);
+
+ // Then recursively upload all the node's descendants
+ for (HierarchyNode child : node.getChildren()) {
+ progress = writeHierarchy(child, myId, progress, maxProgress, spacekey);
+ if (!this.running) {
+ this.feedback = Feedback.CANCELLED;
+ return progress;
+ }
+ }
+
+ return progress;
+ }
/**
* sends upload progress messages to the feedback window and the log
@@ -1706,63 +1783,63 @@
*/
private void logProgressMessage(int current, int max) {
this.state.updateProgress();
- String message = "Uploaded " + current + " out of " + (max + this.newNodes) + " pages.";
-
- //more visible note if current is divisible by 10 or last page
- if ((current % 10) == 0 || current == (max + this.newNodes)) {
- this.state.updateNote(message);
- log.info(message);
- }
- else { //less visible note for everything else
- log.debug(message);
- }
+ String message = "Uploaded " + current + " out of " + (max + this.newNodes) + " pages.";
+
+ //more visible note if current is divisible by 10 or last page
+ if ((current % 10) == 0 || current == (max + this.newNodes)) {
+ this.state.updateNote(message);
+ log.info(message);
+ }
+ else { //less visible note for everything else
+ log.debug(message);
+ }
}
- /**
- * sends page, using settings from the given settings
- * @param page
- * @param parentId
- * @return page id
- * @throws IllegalArgumentException if a confluenceSetting is invalid
- */
- protected String sendPage(Page page, String parentId, UWCUserSettings settings) {
- //write current page
- //XXX why are we setting these up every page. Most of these are global.
- //XXX If we set these up earlier in the process, we could do the checkConfluenceSettings call
- //(currently in the next sendPage) earlier in the process as well
- ConfluenceServerSettings confSettings = getConfluenceServerSettings(settings);
-
- //check to see if we've assigned a space to the page
- if (page.getSpacekey() != null && !"".equals(page.getSpacekey())) {
- confSettings.spaceKey = page.getSpacekey();
- String[] spacedata = page.getSpaceData(page.getSpacekey());
- String spacename = (spacedata == null || spacedata.length < 1)?page.getSpacekey():spacedata[0];
- String spacedesc = (spacedata == null || spacedata.length < 2)?"":spacedata[1];
- if (!createSpace(confSettings, spacename, spacedesc, page.isPersonalSpace(), page.getPersonalSpaceUsername())) {
- log.warn("Could not create space '" + confSettings.spaceKey + "' assigned to page '" + page.getName() + "'. " +
- "Using default space from settings.");
- confSettings.spaceKey = settings.getSpace();
- }
- } // check to see if we're automatically detecting spaces based on the file system
- else if (isAutoDetectingSpacekeys()) {
- confSettings.spaceKey = determineSpaceKey(page);
- if ("".equals(confSettings.spaceKey) || confSettings.spaceKey == null) {
- String error = "Could not find spacekeys. Note: the auto-detect spacekeys" +
- " framework is being used. You must choose directories not individual files" +
- " for conversion.\nCannot upload files to Confluence. Exiting.";
- log.error(error);
- this.errors.addError(Feedback.BAD_SPACE, error, true);
- this.state.updateProgress(this.state.getMax());
- this.running = false;
- return "";
- }
- if (!createSpace(confSettings)) return null;
- } //else otherwise use the default (settings based) spacekey
-
- return sendPage(page, parentId, confSettings);
- }
+ /**
+ * sends page, using settings from the given settings
+ * @param page
+ * @param parentId
+ * @return page id
+ * @throws IllegalArgumentException if a confluenceSetting is invalid
+ */
+ protected String sendPage(Page page, String parentId, UWCUserSettings settings) {
+ //write current page
+ //XXX why are we setting these up every page. Most of these are global.
+ //XXX If we set these up earlier in the process, we could do the checkConfluenceSettings call
+ //(currently in the next sendPage) earlier in the process as well
+ ConfluenceServerSettings confSettings = getConfluenceServerSettings(settings);
- Pattern spacepermPattern = Pattern.compile("[{]groupname[}](.*?)[{]permissions[}](.*)");
+ //check to see if we've assigned a space to the page
+ if (page.getSpacekey() != null && !"".equals(page.getSpacekey())) {
+ confSettings.spaceKey = page.getSpacekey();
+ String[] spacedata = page.getSpaceData(page.getSpacekey());
+ String spacename = (spacedata == null || spacedata.length < 1)?page.getSpacekey():spacedata[0];
+ String spacedesc = (spacedata == null || spacedata.length < 2)?"":spacedata[1];
+ if (!createSpace(confSettings, spacename, spacedesc, page.isPersonalSpace(), page.getPersonalSpaceUsername())) {
+ log.warn("Could not create space '" + confSettings.spaceKey + "' assigned to page '" + page.getName() + "'. " +
+ "Using default space from settings.");
+ confSettings.spaceKey = settings.getSpace();
+ }
+ } // check to see if we're automatically detecting spaces based on the file system
+ else if (isAutoDetectingSpacekeys()) {
+ confSettings.spaceKey = determineSpaceKey(page);
+ if ("".equals(confSettings.spaceKey) || confSettings.spaceKey == null) {
+ String error = "Could not find spacekeys. Note: the auto-detect spacekeys" +
+ " framework is being used. You must choose directories not individual files" +
+ " for conversion.\nCannot upload files to Confluence. Exiting.";
+ log.error(error);
+ this.errors.addError(Feedback.BAD_SPACE, error, true);
+ this.state.updateProgress(this.state.getMax());
+ this.running = false;
+ return "";
+ }
+ if (!createSpace(confSettings)) return null;
+ } //else otherwise use the default (settings based) spacekey
+
+ return sendPage(page, parentId, confSettings);
+ }
+
+ Pattern spacepermPattern = Pattern.compile("[{]groupname[}](.*?)[{]permissions[}](.*)");
private void updateSpacePermissions(ConfluenceServerSettings confSettings) {
if (!this.miscProperties.containsKey(PROPKEY_SPACEPERMS)) return;
@@ -1794,8 +1871,8 @@
String message = "Could not update permissions ('"+allperms+"') for groupname: '" + groupname +"'";
getErrors().addError(Feedback.REMOTE_API_ERROR,
message,
- true);
- log.error(message,e);
+ true);
+ log.error(message,e);
}
}
}
@@ -1803,90 +1880,90 @@
public ConfluenceServerSettings getConfluenceServerSettings(
UWCUserSettings settings) {
ConfluenceServerSettings confSettings = new ConfluenceServerSettings();
- confSettings.login = settings.getLogin();
- confSettings.password = settings.getPassword();
- confSettings.url = settings.getUrl();
- confSettings.spaceKey = settings.getSpace();
- confSettings.truststore = settings.getTruststore();
- confSettings.trustpass = settings.getTrustpass();
- confSettings.trustallcerts = settings.getTrustall();
+ confSettings.login = settings.getLogin();
+ confSettings.password = settings.getPassword();
+ confSettings.url = settings.getUrl();
+ confSettings.spaceKey = settings.getSpace();
+ confSettings.truststore = settings.getTruststore();
+ confSettings.trustpass = settings.getTrustpass();
+ confSettings.trustallcerts = settings.getTrustall();
return confSettings;
}
-
- /**
- * creates a space for the spacekey in the given settings, if it
- * doesn't already exist
- * @param confSettings
- * @return false if space could not be created
- */
- protected boolean createSpace(ConfluenceServerSettings confSettings) {
- String spaceName = confSettings.spaceKey;
- String description = "This space was auto-generated by the UWC.";
- return createSpace(confSettings, spaceName, description, false, null);
- }
- /**
- * creates a space for the spacekey in the given settings, if it doesn't already exist
- * @param confSettings
- * @param name name of space to be created. will not be used, if space already exists
- * @param description description of space to be created. will not be used if space already exists
- * @param isPersonalSpace true if space is personal space
- * @param personalSpaceUsername should be non-null if isPersonalSpace is true. If this condition is not
- * maintained, will use spacekey in confSettings instead
- * @return false if space could not be created
- */
- protected boolean createSpace(ConfluenceServerSettings confSettings, String name, String description,
- boolean isPersonalSpace, String personalSpaceUsername) {
- String spacekey = confSettings.spaceKey;
- RemoteWikiBroker broker = RemoteWikiBroker.getInstance();
- SpaceForXmlRpc space = broker.createSpace(spacekey, name, description);
- if (isPersonalSpace) {
- space.setType(SpaceType.PERSONAL);
- space.setUsername(personalSpaceUsername);
- }
- try {
- // Conf 2.x will throw an exception if the space doesn't exist.
- SpaceForXmlRpc space2 = broker.getSpace(confSettings, spacekey);
- // Conf 3.x will not throw an exception but will return null
- if (space2 == null) { //Confluence 3.x
- String note = "Creating space with spacekey '" + spacekey + "' and name: " + name;
+ /**
+ * creates a space for the spacekey in the given settings, if it
+ * doesn't already exist
+ * @param confSettings
+ * @return false if space could not be created
+ */
+ protected boolean createSpace(ConfluenceServerSettings confSettings) {
+ String spaceName = confSettings.spaceKey;
+ String description = "This space was auto-generated by the UWC.";
+ return createSpace(confSettings, spaceName, description, false, null);
+ }
+ /**
+ * creates a space for the spacekey in the given settings, if it doesn't already exist
+ * @param confSettings
+ * @param name name of space to be created. will not be used, if space already exists
+ * @param description description of space to be created. will not be used if space already exists
+ * @param isPersonalSpace true if space is personal space
+ * @param personalSpaceUsername should be non-null if isPersonalSpace is true. If this condition is not
+ * maintained, will use spacekey in confSettings instead
+ * @return false if space could not be created
+ */
+ protected boolean createSpace(ConfluenceServerSettings confSettings, String name, String description,
+ boolean isPersonalSpace, String personalSpaceUsername) {
+ String spacekey = confSettings.spaceKey;
+ RemoteWikiBroker broker = RemoteWikiBroker.getInstance();
+ SpaceForXmlRpc space = broker.createSpace(spacekey, name, description);
+ if (isPersonalSpace) {
+ space.setType(SpaceType.PERSONAL);
+ space.setUsername(personalSpaceUsername);
+ }
+
+ try {
+ // Conf 2.x will throw an exception if the space doesn't exist.
+ SpaceForXmlRpc space2 = broker.getSpace(confSettings, spacekey);
+ // Conf 3.x will not throw an exception but will return null
+ if (space2 == null) { //Confluence 3.x
+ String note = "Creating space with spacekey '" + spacekey + "' and name: " + name;
log.info(note);
- this.state.updateNote(note);
- try {
- broker.addSpace(confSettings, space);
- //at some point in Confluence 4.x, the Home page stopped being set to Home, so let's prestore the homepage id
- Vector newspacepages = broker.getAllServerPageSummaries(confSettings, space.getSpaceKey());
- PageForXmlRpc newhome = (PageForXmlRpc) newspacepages.get(0); //should only be one at this point
- this.homepages.put(space.getSpaceKey(), newhome.getId());
- //check to see if we're setting any permissions
- updateSpacePermissions(confSettings);
- } catch (Exception e) {
- getErrors().addError(Feedback.BAD_LOGIN,
- "Could not create space: " + spacekey +
- " with login: " + confSettings.login +
- ". That login may not have permission to create spaces.",
- true);
- e.printStackTrace();
- return false;
- }
- }
- } catch (Exception e) { //Confluence 2.x
- try { //exception! So, try adding the space
- String note = "Creating space with spacekey '" + spacekey + "' and name: " + name;
+ this.state.updateNote(note);
+ try {
+ broker.addSpace(confSettings, space);
+ //at some point in Confluence 4.x, the Home page stopped being set to Home, so let's prestore the homepage id
+ Vector newspacepages = broker.getAllServerPageSummaries(confSettings, space.getSpaceKey());
+ PageForXmlRpc newhome = (PageForXmlRpc) newspacepages.get(0); //should only be one at this point
+ this.homepages.put(space.getSpaceKey(), newhome.getId());
+ //check to see if we're setting any permissions
+ updateSpacePermissions(confSettings);
+ } catch (Exception e) {
+ getErrors().addError(Feedback.BAD_LOGIN,
+ "Could not create space: " + spacekey +
+ " with login: " + confSettings.login +
+ ". That login may not have permission to create spaces.",
+ true);
+ e.printStackTrace();
+ return false;
+ }
+ }
+ } catch (Exception e) { //Confluence 2.x
+ try { //exception! So, try adding the space
+ String note = "Creating space with spacekey '" + spacekey + "' and name: " + name;
log.info(note);
- this.state.updateNote(note);
- broker.addSpace(confSettings, space);
- } catch (Exception e1) { //something bad happened.
- getErrors().addError(Feedback.BAD_LOGIN,
- "Could not create space: " + spacekey +
- " with login: " + confSettings.login +
- ". That login may not have permission to create spaces.",
- true);
- e1.printStackTrace();
- return false;
- }
- }
- return true;
+ this.state.updateNote(note);
+ broker.addSpace(confSettings, space);
+ } catch (Exception e1) { //something bad happened.
+ getErrors().addError(Feedback.BAD_LOGIN,
+ "Could not create space: " + spacekey +
+ " with login: " + confSettings.login +
+ ". That login may not have permission to create spaces.",
+ true);
+ e1.printStackTrace();
+ return false;
+ }
+ }
+ return true;
}
/**
@@ -1940,7 +2017,7 @@
newPage = broker.storeNewOrUpdatePage(confSettings, confSettings.spaceKey, brokerPage);
if (newPage == null || newPage.getPageParams() == null) {
String message = "Unknown problem occured while sending page '" + pageTable.get("title") +
- "'. See atlassian-confluence.log for more details.";
+ "'. See atlassian-confluence.log for more details.";
log.error(message);
getErrors().addError(Feedback.REMOTE_API_ERROR, message, true);
return null;
@@ -1948,12 +2025,13 @@
} catch (Exception e) {
getErrors().addError(Feedback.REMOTE_API_ERROR,
"The Remote API threw an exception when it tried to upload page: \"" +
- pageTable.get("title") +
- "\".", true);
+ pageTable.get("title") +
+ "\".", true);
e.printStackTrace();
return null;
- }
-
+ }
+ log.debug("Page URL: " + newPage.getUrl());
+
//move the page if necessary and you can
log.debug("Identifying parent location for page...");
String parentid = null;
@@ -1975,22 +2053,22 @@
this.homepages.put(confSettings.spaceKey, "-1");
}
}
-
+
}
if (parentid != null) {
log.debug("Attempting to set parent to: " + parentid);
try {
broker.movePage(confSettings, newPage.getId(), parentid, RemoteWikiBroker.Position.APPEND);
} catch (Exception e) {
- log.debug("Could not move page " + pageTable.get("title") + "\n" + e.getMessage() + "\n" +
- e.getStackTrace()); //could be because Confluence is earlier than 2.9
+ log.error("Could not move page " + pageTable.get("title") + "\n" + e.getMessage() + "\n" +
+ e.getStackTrace()); //could be because Confluence is earlier than 2.9
}
}
-
- return newPage.getId();
-
+
+ return newPage.getId();
+
}
-
+
/*********
* to send a blog table which has all the attributes for a blog to wiki
* @param broker
@@ -2006,7 +2084,7 @@
newPage = broker.storeBlog(confSettings, confSettings.spaceKey, brokerPage);
if (newPage == null || newPage.getblogParams() == null) {
String message = "Unknown problem occured while sending page '" + pageTable.get("title") +
- "'. See atlassian-confluence.log for more details.";
+ "'. See atlassian-confluence.log for more details.";
log.error(message);
getErrors().addError(Feedback.REMOTE_API_ERROR, message, true);
return null;
@@ -2014,77 +2092,82 @@
} catch (Exception e) {
getErrors().addError(Feedback.REMOTE_API_ERROR,
"The Remote API threw an exception when it tried to upload page: \"" +
- pageTable.get("title") +
- "\".", true);
+ pageTable.get("title") +
+ "\".", true);
e.printStackTrace();
return null;
}
- return newPage.getId();
+ log.debug("Page URL: " + newPage.getUrl());
+ return newPage.getId();
}
-
-
+
+
protected void checkConfluenceSettings(ConfluenceServerSettings confSettings)
{
//check for problems with settings
- Feedback testConnectionFeedback = TestSettingsListener.getConnectionFeedback(confSettings, isAutoDetectingSpacekeys());
- if (testConnectionFeedback != Feedback.OK) {
- String message = TestSettingsListener.getConnectionFeedbackMessage(confSettings, isAutoDetectingSpacekeys());
- log.error(message);
- this.state.updateNote(message);
- throw new IllegalArgumentException(message);
- }
-// log.info(TestSettingsListener.SUCCESS_MESSAGE_LONG); //this is getting called for every page
-
+ Feedback testConnectionFeedback = TestSettingsListener.getConnectionFeedback(confSettings, isAutoDetectingSpacekeys());
+ if (testConnectionFeedback != Feedback.OK) {
+ String message = TestSettingsListener.getConnectionFeedbackMessage(confSettings, isAutoDetectingSpacekeys());
+ log.error(message);
+ this.state.updateNote(message);
+ throw new IllegalArgumentException(message);
+ }
+ // log.info(TestSettingsListener.SUCCESS_MESSAGE_LONG); //this is getting called for every page
+
}
/**
- * sends page using the given settings
- * @param page
- * @param parentId
- * @param confSettings
- * @return page id the confluence page id for the page being stored. Used if
- * page is new.
- */
- protected String sendPage(Page page, String parentId, ConfluenceServerSettings confSettings) {
- //create wiki broker
- RemoteWikiBroker broker = RemoteWikiBroker.getInstance();
- //update page content to be xhtml
- if (Boolean.parseBoolean(this.miscProperties.getProperty("engine-markuptoxhtml", "true"))) {
- page = pageContentToXhtml(broker, confSettings, page);
- } else {
- log.debug("Engine: markup to xhtml property set to false");
- }
- //create page that broker can use
- Hashtable pageTable = createPageTable(page, parentId);
- //check for problems with settings
- checkConfluenceSettings(confSettings); //XXX Why are we doing this for every page? 'cause we seem to create the confSettings on a page by page basis?
- //write ancestors, if any, first
- if (page.getAncestors() != null && !page.getAncestors().isEmpty()) {
- pageTable = handleAncestors(page, confSettings, pageTable);
- }
- //send page
- String id = null;
- if (page.isBlog()) {
- log.debug("Attempting to send blog: " + page.getName() + " to space: " + confSettings.spaceKey);
- id = sendBlog(broker, pageTable, confSettings);
- } else {
- log.debug("Attempting to send page: " + page.getName() + " to space: " + confSettings.spaceKey);
- id = sendPage(broker, pageTable, confSettings);
- }
- if (id == null) return null;
- //send attachments
- sendAttachments(page, broker, id, confSettings);
- //send labels
- sendLabels(page, broker, id, confSettings);
- //send comments
- sendComments(page, broker, id, confSettings);
- //set author
- log.debug("Page Version: " + page.getVersion());
- sendAuthor(page, broker, id, confSettings);
- //set timestamp
- sendTimestamp(page, broker, id, confSettings);
- //return the page id
- return id;
- }
+ * sends page using the given settings
+ * @param page
+ * @param parentId
+ * @param confSettings
+ * @return page id the confluence page id for the page being stored. Used if
+ * page is new.
+ */
+ protected String sendPage(Page page, String parentId, ConfluenceServerSettings confSettings) {
+ //create wiki broker
+ RemoteWikiBroker broker = RemoteWikiBroker.getInstance();
+ //update page content to be xhtml
+ if (Boolean.parseBoolean(this.miscProperties.getProperty("engine-markuptoxhtml", "true"))) {
+ page = pageContentToXhtml(broker, confSettings, page);
+ } else {
+ log.debug("Engine: markup to xhtml property set to false");
+ }
+ //create page that broker can use
+ Hashtable pageTable = createPageTable(page, parentId);
+ //check for problems with settings
+ checkConfluenceSettings(confSettings); //XXX Why are we doing this for every page? 'cause we seem to create the confSettings on a page by page basis?
+ //write ancestors, if any, first
+ if (page.getAncestors() != null && !page.getAncestors().isEmpty()) {
+ pageTable = handleAncestors(page, confSettings, pageTable);
+ }
+ //send page
+ String id = null;
+ if (!(page instanceof VersionPage) && page.getFile() != null) {
+ log.debug("Original Filepath: " + page.getFile().getAbsolutePath());
+ }
+ String tmpspacekey = (page.getSpacekey()!=null)?page.getSpacekey():confSettings.spaceKey;
+ if (page.isBlog()) {
+ log.debug("Attempting to send blog: " + page.getName() + " to space: " + tmpspacekey);
+ id = sendBlog(broker, pageTable, confSettings);
+ } else {
+ log.debug("Attempting to send page: " + page.getName() + " to space: " + tmpspacekey);
+ id = sendPage(broker, pageTable, confSettings);
+ }
+ if (id == null) return null;
+ //send attachments
+ sendAttachments(page, broker, id, confSettings);
+ //send labels
+ sendLabels(page, broker, id, confSettings);
+ //send comments
+ sendComments(page, broker, id, confSettings);
+ //set author
+ log.debug("Page Version: " + page.getVersion());
+ sendAuthor(page, broker, id, confSettings);
+ //set timestamp
+ sendTimestamp(page, broker, id, confSettings);
+ //return the page id
+ return id;
+ }
private Hashtable handleAncestors(Page page,
ConfluenceServerSettings confSettings, Hashtable pageTable) {
@@ -2095,16 +2178,17 @@
enforceBlogId(page, page.getAncestors(), blogid);
pageTable.put("id", blogid);
}
- writePages(page.getAncestors(), settings.getSpace());
+ if (page.getAncestors() != null) log.info("Number of ancestors for page '"+page.getName()+"': " + page.getAncestors().size());
+ writePages(page.getAncestors(), settings.getSpace(), false);
return pageTable;
}
-
- private void enforceBlogId(Page page, Vector<VersionPage> pages,
+
+ private void enforceBlogId(Page page, Vector<VersionPage> pages,
String blogid) {
- page.setId(blogid);
- for (VersionPage anc : pages) {
- anc.setId(blogid);
- }
+ page.setId(blogid);
+ for (VersionPage anc : pages) {
+ anc.setId(blogid);
+ }
}
private void enforceAncestorTitleAndKey(Vector<VersionPage> pages,
@@ -2114,22 +2198,22 @@
page.setSpacekey(spacekey);
page.setIsBlog(isBlog);
}
-
+
}
public String markupToXhtml(String markup) {
- RemoteWikiBroker broker = RemoteWikiBroker.getInstance();
- ConfluenceServerSettings confSettings = getConfluenceServerSettings(this.settings);
- try {
+ RemoteWikiBroker broker = RemoteWikiBroker.getInstance();
+ ConfluenceServerSettings confSettings = getConfluenceServerSettings(this.settings);
+ try {
return getContentAsXhtmlFormat(broker, confSettings, markup);
- } catch (Exception e) {
- String errorMessage = "Could not transform wiki content from markup to xhtml.";
- log.error(Feedback.REMOTE_API_ERROR + ": " + errorMessage);
- this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
- return null;
- }
- }
-
+ } catch (Exception e) {
+ String errorMessage = "Could not transform wiki content from markup to xhtml.";
+ log.error(Feedback.REMOTE_API_ERROR + ": " + errorMessage);
+ this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
+ return null;
+ }
+ }
+
private Page pageContentToXhtml(RemoteWikiBroker broker,
ConfluenceServerSettings confSettings, Page page) {
try {
@@ -2138,132 +2222,132 @@
} catch (Exception e) {
String errorMessage = "Could not transform wiki content in page: '"+page.getName()+
"' from markup to xhtml.";
- log.error(Feedback.REMOTE_API_ERROR + ": " + errorMessage);
- this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
+ log.error(Feedback.REMOTE_API_ERROR + ": " + errorMessage);
+ this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
}
return page;
}
/**
- * creates a parameter table with the given page and parentId.
- * @param page
- * @param parentId
- * @return table with Remote API page parameters
- */
- private Hashtable createPageTable(Page page, String parentId) {
- Hashtable table = new Hashtable();
- table.put("content", page.getConvertedText());
- table.put("title", page.getName());
- if (parentId != null && !parentId.equals("null")) table.put("parentId", parentId);
- if (page.getVersion() > 0) table.put("version", page.getVersion() + "");
- if (page.isBlog() && page.getId() != null) table.put("id", page.getId());
- return table;
+ * creates a parameter table with the given page and parentId.
+ * @param page
+ * @param parentId
+ * @return table with Remote API page parameters
+ */
+ private Hashtable createPageTable(Page page, String parentId) {
+ Hashtable table = new Hashtable();
+ table.put("content", page.getConvertedText());
+ table.put("title", page.getName());
+ if (parentId != null && !parentId.equals("null")) table.put("parentId", parentId);
+ if (page.getVersion() > 0) table.put("version", page.getVersion() + "");
+ if (page.isBlog() && page.getId() != null) table.put("id", page.getId());
+ return table;
}
- /**
- * checks the given page for valid attachments,
- * and sends them to Confluence using the rwb and the given pageId string as the
- * page to be attached to.
- *
- * @param page given page object that might have attachments
- * @param broker XML-RPC broker which will communicate with Confluence
- * @param pageId the page the Confluence will attach the attachment to
- * @param confSettings the confluence user settings needed by the broker to connect to Confluence
- */
- private void sendAttachments(Page page, RemoteWikiBroker broker, String pageId, ConfluenceServerSettings confSettings) {
- log.debug("Examining attachments for page: " + page.getName());
+ /**
+ * checks the given page for valid attachments,
+ * and sends them to Confluence using the rwb and the given pageId string as the
+ * page to be attached to.
+ *
+ * @param page given page object that might have attachments
+ * @param broker XML-RPC broker which will communicate with Confluence
+ * @param pageId the page the Confluence will attach the attachment to
+ * @param confSettings the confluence user settings needed by the broker to connect to Confluence
+ */
+ private void sendAttachments(Page page, RemoteWikiBroker broker, String pageId, ConfluenceServerSettings confSettings) {
+ log.debug("Examining attachments for page: " + page.getName());
// Send the attachments
- for (Attachment attachment : page.getAllAttachmentData()) {
- if (alreadyAttached(page, attachment.getFile()))
- continue;
- sendAttachment(attachment, broker, pageId, confSettings);
- }
+ for (Attachment attachment : page.getAllAttachmentData()) {
+ if (alreadyAttached(page, attachment.getFile()))
+ continue;
+ sendAttachment(attachment, broker, pageId, confSettings);
+ }
}
-
- protected void sendLabels(Page page, RemoteWikiBroker broker, String pageId, ConfluenceServerSettings confSettings) {
- log.debug("Examining labels for page: " + page.getName());
- //check to see if we're sending labels for this version of the page
+
+ protected void sendLabels(Page page, RemoteWikiBroker broker, String pageId, ConfluenceServerSettings confSettings) {
+ log.debug("Examining labels for page: " + page.getName());
+ //check to see if we're sending labels for this version of the page
if (badVersionForSendingLabels(page)) return;
- String labels = page.getLabelsAsString();
- log.debug("Sending Labels: " + labels);
- if (labels == null)
- return;
- try {
- broker.addLabels(confSettings, labels, pageId);
- } catch (Exception e) {
- String errorMessage = "Could not add labels '" + labels + "' to page '" + page.getName() +"'";
- log.error(Feedback.REMOTE_API_ERROR + ": " + errorMessage);
- this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
- }
- }
+ String labels = page.getLabelsAsString();
+ log.debug("Sending Labels: " + labels);
+ if (labels == null)
+ return;
+ try {
+ broker.addLabels(confSettings, labels, pageId);
+ } catch (Exception e) {
+ String errorMessage = "Could not add labels '" + labels + "' to page '" + page.getName() +"'";
+ log.error(Feedback.REMOTE_API_ERROR + ": " + errorMessage);
+ this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
+ }
+ }
private boolean badVersionForSendingLabels(Page page) {
int version = page.getVersion();
- int latest = Page.getLatestVersion(page.getName());
- boolean history = isHandlingPageHistories();
- String allVersionsProp = (String) this.miscProperties.get("page-history-allversionlabels");
- boolean allVersions = (allVersionsProp != null) && Boolean.parseBoolean(allVersionsProp);
+ int latest = Page.getLatestVersion(page.getName());
+ boolean history = isHandlingPageHistories();
+ String allVersionsProp = (String) this.miscProperties.get("page-history-allversionlabels");
+ boolean allVersions = (allVersionsProp != null) && Boolean.parseBoolean(allVersionsProp);
return history && !allVersions && version != latest;
}
-
- /**
- * adds page comments to a page in confluence
- * @param page given page object that might have comments
- * @param broker XML-RPC broker which will communicate with Confluence
- * @param pageId the page id for the given page
- * @param confSettings the confluence user settings needed by the broker to connect to Confluence
- */
- protected void sendComments(Page page, RemoteWikiBroker broker, String pageId, ConfluenceServerSettings confSettings) {
- if (page.hasComments()) {
- log.debug("Sending comments for page: " + page.getName());
- try {
- for (Comment comment : page.getAllCommentData()) {
- if (comment == null) {
- log.error("Comment was null! SKIPPING");
- this.errors.addError(Feedback.CONVERTER_ERROR, "Comment should not be null!", true);
- continue;
- }
- //create page that broker can use
- CommentForXmlRpc brokerComment = new CommentForXmlRpc();
- brokerComment.setPageId(pageId);
- String commentcontent = comment.text;
- if (!comment.isXhtml()) {
+
+ /**
+ * adds page comments to a page in confluence
+ * @param page given page object that might have comments
+ * @param broker XML-RPC broker which will communicate with Confluence
+ * @param pageId the page id for the given page
+ * @param confSettings the confluence user settings needed by the broker to connect to Confluence
+ */
+ protected void sendComments(Page page, RemoteWikiBroker broker, String pageId, ConfluenceServerSettings confSettings) {
+ if (page.hasComments()) {
+ log.debug("Sending comments for page: " + page.getName());
+ try {
+ for (Comment comment : page.getAllCommentData()) {
+ if (comment == null) {
+ log.error("Comment was null! SKIPPING");
+ this.errors.addError(Feedback.CONVERTER_ERROR, "Comment should not be null!", true);
+ continue;
+ }
+ //create page that broker can use
+ CommentForXmlRpc brokerComment = new CommentForXmlRpc();
+ brokerComment.setPageId(pageId);
+ String commentcontent = comment.text;
+ if (!comment.isXhtml()) {
commentcontent = getContentAsXhtmlFormat(broker, confSettings, comment.text);
}
- brokerComment.setContent(commentcontent);
- //upload comment
- CommentForXmlRpc uploadedComment = broker.addComment(confSettings, brokerComment);
- if (comment.hasCreator()) {
- boolean usersMustExist = false;
+ brokerComment.setContent(commentcontent);
+ //upload comment
+ CommentForXmlRpc uploadedComment = broker.addComment(confSettings, brokerComment);
+ if (comment.hasCreator()) {
+ boolean usersMustExist = false;
broker.setCreator(confSettings, comment.creator, uploadedComment.getId(), usersMustExist);
broker.setLastModifier(confSettings, comment.creator, uploadedComment.getId(), usersMustExist);
- }
- if (comment.hasTimestamp()) {
- broker.setCreateDate(confSettings, comment.timestamp, uploadedComment.getId());
- broker.setLastModifiedDate(confSettings, comment.timestamp, uploadedComment.getId());
- }
- }
- } catch (Exception e) {
- String errorMessage = null;
- if (e.getMessage() == null) {
- log.error("Problem with comments!", e);
- return;
- }
- else if (e.getMessage().contains("NotPermittedException")) {
- errorMessage = "User is not permitted to add comments to page: " + page.getName() + "'";
- }
- else if (e.getMessage().contains("does not exist")) {
- errorMessage = "Cannot add comments to the page because it does not exist: " + page.getName();
- }
- else {
- errorMessage = "Could not send comments to page '" + page.getName() +"'";
- }
- log.error(Feedback.REMOTE_API_ERROR + ": " + errorMessage);
- this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
- }
- }
-// else log.debug("Page has no comments."); //DELETE
- }
+ }
+ if (comment.hasTimestamp()) {
+ broker.setCreateDate(confSettings, comment.timestamp, uploadedComment.getId());
+ broker.setLastModifiedDate(confSettings, comment.timestamp, uploadedComment.getId());
+ }
+ }
+ } catch (Exception e) {
+ String errorMessage = null;
+ if (e.getMessage() == null) {
+ log.error("Problem with comments!", e);
+ return;
+ }
+ else if (e.getMessage().contains("NotPermittedException")) {
+ errorMessage = "User is not permitted to add comments to page: " + page.getName() + "'";
+ }
+ else if (e.getMessage().contains("does not exist")) {
+ errorMessage = "Cannot add comments to the page because it does not exist: " + page.getName();
+ }
+ else {
+ errorMessage = "Could not send comments to page '" + page.getName() +"'";
+ }
+ log.error(Feedback.REMOTE_API_ERROR + ": " + errorMessage);
+ this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
+ }
+ }
+ // else log.debug("Page has no comments."); //DELETE
+ }
public String getContentAsXhtmlFormat(RemoteWikiBroker broker, ConfluenceServerSettings confSettings, String text) throws XmlRpcException, IOException {
return broker.convertWikiToStorageFormat(confSettings, text);
@@ -2283,12 +2367,12 @@
} catch (Exception e) {
String errorMessage = Feedback.REMOTE_API_ERROR + ": Problem setting creator or last modifier data.";
log.error(errorMessage);
- this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
+ this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
e.printStackTrace();
}
}
}
-
+
private void sendTimestamp(Page page, RemoteWikiBroker broker, String id, ConfluenceServerSettings confSettings) {
if (page.getTimestamp() != null) {
log.debug("Sending timestamp data: " + page.getTimestamp());
@@ -2299,7 +2383,7 @@
timezone = timezone.trim();
dateFormat.setTimeZone(TimeZone.getTimeZone(timezone));
}
- String timestamp = dateFormat.format(page.getTimestamp());
+ String timestamp = dateFormat.format(page.getTimestamp());
if (page.getVersion() == 1) { //only set the creator if its the first version
broker.setCreateDate(confSettings, timestamp, id);
@@ -2309,18 +2393,18 @@
} catch (Exception e) {
String errorMessage = Feedback.REMOTE_API_ERROR + ": Problem setting create or last modified date.";
log.error(errorMessage);
- this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
+ this.errors.addError(Feedback.REMOTE_API_ERROR, errorMessage, true);
e.printStackTrace();
}
}
}
-
- /**
- * @param file
- * @return true if the given file does not exist on the filesystem.
- */
- protected boolean doesNotExist(File file) {
+
+ /**
+ * @param file
+ * @return true if the given file does not exist on the filesystem.
+ */
+ protected boolean doesNotExist(File file) {
boolean doesNotExist = !file.exists();
if (doesNotExist)
log.warn("File '" + file.getPath() + "' does not exist: Skipping");
@@ -2328,16 +2412,16 @@
}
/**
- * @param file
- * @return true if file size is too big
- */
- protected boolean tooBig(File file) {
-
- if (!file.exists()) return false;
+ * @param file
+ * @return true if file size is too big
+ */
+ protected boolean tooBig(File file) {
+
+ if (!file.exists()) return false;
int length = (int) file.length();
-
+
String maxString = getMaxAttachmentSizeString();
-
+
int maxBytes = getAsBytes(maxString);
if (maxBytes < 0) return false;
boolean tooBig = length > maxBytes;
@@ -2361,83 +2445,83 @@
}
/**
- * @param fileLocation location of properties file
+ * @param fileLocation location of properties file
* @return a Properties object containing confluence settings
- */
- protected Properties loadProperties(String fileLocation) {
- /* most of this code grabbed from ConfluenceSettingsForm.populateConfluenceSettings*/
- Properties properties = new Properties();
- File confSettings = new File(fileLocation);
- if (confSettings.exists()) {
- // load properties file
- FileInputStream fis;
- try {
- fis = new FileInputStream(fileLocation);
+ */
+ protected Properties loadProperties(String fileLocation) {
+ /* most of this code grabbed from ConfluenceSettingsForm.populateConfluenceSettings*/
+ Properties properties = new Properties();
+ File confSettings = new File(fileLocation);
+ if (confSettings.exists()) {
+ // load properties file
+ FileInputStream fis;
+ try {
+ fis = new FileInputStream(fileLocation);
properties.load(fis);
- fis.close();
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return properties;
- }
-
- /**
- * calculates the number of bytes the given maxString represents
- * @param maxString file size described as a String.
- * Example: 5B, 5K, 5M, 5G, etc.
- * @return as Bytes.
- * Respectively: 5, 5120, 5242880, 5368709120
- */
- protected int getAsBytes(String maxString) {
- String maxRegex = "^(\\d+)(\\D)";
- if (maxString == null || "".equals(maxString))
- return -1;
-
- int power, num = 0;
- String numString, unitString = null;
- if (Pattern.matches("^\\d+$", maxString)) {
- unitString = "B";
- numString = maxString;
- }
- else {
- numString = maxString.replaceFirst(maxRegex, "$1");
- unitString = maxString.replaceFirst(maxRegex, "$2");
- }
- try {
- num = Integer.parseInt(numString);
- } catch (NumberFormatException e) {
- String message = PROP_ATTACHMENT_SIZE_MAX + " setting is malformed.\n" +
- "Setting must be formatted like so: [number][unit], where unit is\n" +
- "one of the following: B, K, M, G. No max attachment size set.";
- log.error(message);
- return -1;
- }
- unitString = unitString.toUpperCase();
- char unit = unitString.toCharArray()[0]; //first char in that string
-
- switch (unit) {
- case ('B'): power = 0;break;
- case ('K'): power = 1;break;
- case ('M'): power = 2;break;
- case ('G'): power = 3;break;
- default: return -1;
+ fis.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
-
+ return properties;
+ }
+
+ /**
+ * calculates the number of bytes the given maxString represents
+ * @param maxString file size described as a String.
+ * Example: 5B, 5K, 5M, 5G, etc.
+ * @return as Bytes.
+ * Respectively: 5, 5120, 5242880, 5368709120
+ */
+ protected int getAsBytes(String maxString) {
+ String maxRegex = "^(\\d+)(\\D)";
+ if (maxString == null || "".equals(maxString))
+ return -1;
+
+ int power, num = 0;
+ String numString, unitString = null;
+ if (Pattern.matches("^\\d+$", maxString)) {
+ unitString = "B";
+ numString = maxString;
+ }
+ else {
+ numString = maxString.replaceFirst(maxRegex, "$1");
+ unitString = maxString.replaceFirst(maxRegex, "$2");
+ }
+ try {
+ num = Integer.parseInt(numString);
+ } catch (NumberFormatException e) {
+ String message = PROP_ATTACHMENT_SIZE_MAX + " setting is malformed.\n" +
+ "Setting must be formatted like so: [number][unit], where unit is\n" +
+ "one of the following: B, K, M, G. No max attachment size set.";
+ log.error(message);
+ return -1;
+ }
+ unitString = unitString.toUpperCase();
+ char unit = unitString.toCharArray()[0]; //first char in that string
+
+ switch (unit) {
+ case ('B'): power = 0;break;
+ case ('K'): power = 1;break;
+ case ('M'): power = 2;break;
+ case ('G'): power = 3;break;
+ default: return -1;
+ }
+
int multiplier = (int) Math.pow(1024, power);
int value = num * multiplier;
return value;
}
/**
- * @param page
- * @param file
- * @return true if a particular page already has a particular
- * file attached.
- */
- protected boolean alreadyAttached(Page page, File file) {
+ * @param page
+ * @param file
+ * @return true if a particular page already has a particular
+ * file attached.
+ */
+ protected boolean alreadyAttached(Page page, File file) {
String pagename = page.getName();
String filename = file.getName();
boolean isblog = page.isBlog();
@@ -2446,167 +2530,167 @@
if (attachedFiles == null)
attachedFiles = new HashSet<String>();
boolean attached = attachedFiles.contains(attachmentId);
-
+
if (!attached) {
attachedFiles.add(attachmentId);
if (attachedPaths == null) attachedPaths = new HashSet<String>();
attachedPaths.add(file.getAbsolutePath()); //used with orphan upload checking
}
else log.debug("Attachment " + filename + " is already attached: Skipping.");
-
+
return attached;
}
-
- /**
- * to check if the file has been attached with any pages.
- * @param fileName
- * @return
- */
- protected boolean alreadyAttached(String fileName) {
- if (this.attachedFiles == null || this.attachedFiles.isEmpty())
- return false;
- Iterator <String>it=attachedFiles.iterator();
- while (it.hasNext())
- {
- String item=it.next();
- int index=item.lastIndexOf(fileName);
- if (index < 0)
- continue;
- if (item.length() - index == fileName.length())
- return true;
- }
- return false;
-
- }
-
- protected boolean orphanAlreadyAttached(File file) {
- if (this.attachedPaths == null) return false;
- return (this.attachedPaths.contains(file.getAbsolutePath()));
- }
- /**
- * This method determines the mime type of a file. It uses the file
- * conf/mime.types to map from the file name extension
- * to a mime type. The mime type file should be read into the
- * mimeTypes field before this method is called.
- *
- * @param file The file object
- * @return the mime type of the file.
- */
- public static String determineContentType(File file) {
- if (mimeTypes != null) {
- return mimeTypes.getContentType(file);
- }
- //else assume it's an image
- String filename = file.getName();
- int extensionStart = filename.lastIndexOf(".");
- if (extensionStart >= 0) {
- String extension = filename.substring(extensionStart + 1);
- return "image/" + extension;
- }
- // Hmm... No extension. Assume it's a text file.
- return "text/plain";
- }
-
- Pattern switchPattern = Pattern.compile("switch");
- Pattern suffixPattern = Pattern.compile("suffix");
- private boolean handlingPageHistories = false;
+ /**
+ * to check if the file has been attached with any pages.
+ * @param fileName
+ * @return
+ */
+// protected boolean alreadyAttached(String fileName) {
+// if (this.attachedFiles == null || this.attachedFiles.isEmpty())
+// return false;
+// Iterator <String>it=attachedFiles.iterator();
+// while (it.hasNext())
+// {
+// String item=it.next();
+// int index=item.lastIndexOf(fileName);
+// if (index < 0)
+// continue;
+// if (item.length() - index == fileName.length())
+// return true;
+// }
+// return false;
+//
+// }
+
+ protected boolean orphanAlreadyAttached(File file) {
+ if (this.attachedPaths == null) return false;
+ return (this.attachedPaths.contains(file.getAbsolutePath()));
+ }
+
+ /**
+ * This method determines the mime type of a file. It uses the file
+ * conf/mime.types to map from the file name extension
+ * to a mime type. The mime type file should be read into the
+ * mimeTypes field before this method is called.
+ *
+ * @param file The file object
+ * @return the mime type of the file.
+ */
+ public static String determineContentType(File file) {
+ if (mimeTypes != null) {
+ return mimeTypes.getContentType(file);
+ }
+ //else assume it's an image
+ String filename = file.getName();
+ int extensionStart = filename.lastIndexOf(".");
+ if (extensionStart >= 0) {
+ String extension = filename.substring(extensionStart + 1);
+ return "image/" + extension;
+ }
+ // Hmm... No extension. Assume it's a text file.
+ return "text/plain";
+ }
+
+ Pattern switchPattern = Pattern.compile("switch");
+ Pattern suffixPattern = Pattern.compile("suffix");
+ private boolean handlingPageHistories = false;
private String pageHistorySuffix = null;
-
- /**
- * set the page history state to reflect the page history property
- * and associated value that are passed as arguments
- * @param key
- * @param value
- */
- protected void handlePageHistoryProperty(String key, String value) {
- Matcher switchFinder = switchPattern.matcher(key);
- if (switchFinder.find()) {
- //the default should be false, so it's ok to just parse the string.
- this.handlingPageHistories = Boolean.parseBoolean(value);
- return;
- }
- Matcher suffixFinder = suffixPattern.matcher(key);
- if (suffixFinder.find()) {
- setPageHistorySuffix(value);
- return;
- }
- }
-
- protected void handleIllegalHandling(String key, String value) {
- boolean enabled = false; //default, confluence 4 doesn't appear to need this
- value = value.trim();
- if ("false".equals(value))
- enabled = false;
- illegalHandlingEnabled = enabled;
- }
-
- protected void handleAutoDetectSpacekeys(String key, String value) {
- boolean enabled = false; //default
- value = value.trim();
- if ("true".equals(value)) {
- enabled = true;
- }
- autoDetectSpacekeys = enabled;
- }
-
- Pattern miscPropsPattern = Pattern.compile("" +
- "\\w+\\.\\d+\\.([^.]+)\\.property"
- );
- protected Properties handleMiscellaneousProperties(String key, String value) {
- Matcher miscKeyFinder = miscPropsPattern.matcher(key);
- if (miscKeyFinder.matches()) {
- String misckey = miscKeyFinder.group(1);
- if (this.miscProperties == null)
- this.miscProperties = new Properties();
- this.miscProperties.put(misckey, value);
- log.debug("Miscellaneous Property set: " + misckey + "=" + value);
- return this.miscProperties;
- }
- String error = "Miscellaneous property was detected, " +
- "but key was invalid. Could not instantiate property: " +
- key + "=" + value;
+
+ /**
+ * set the page history state to reflect the page history property
+ * and associated value that are passed as arguments
+ * @param key
+ * @param value
+ */
+ protected void handlePageHistoryProperty(String key, String value) {
+ Matcher switchFinder = switchPattern.matcher(key);
+ if (switchFinder.find()) {
+ //the default should be false, so it's ok to just parse the string.
+ this.handlingPageHistories = Boolean.parseBoolean(value);
+ return;
+ }
+ Matcher suffixFinder = suffixPattern.matcher(key);
+ if (suffixFinder.find()) {
+ setPageHistorySuffix(value);
+ return;
+ }
+ }
+
+ protected void handleIllegalHandling(String key, String value) {
+ boolean enabled = false; //default, confluence 4 doesn't appear to need this
+ value = value.trim();
+ if ("false".equals(value))
+ enabled = false;
+ illegalHandlingEnabled = enabled;
+ }
+
+ protected void handleAutoDetectSpacekeys(String key, String value) {
+ boolean enabled = false; //default
+ value = value.trim();
+ if ("true".equals(value)) {
+ enabled = true;
+ }
+ autoDetectSpacekeys = enabled;
+ }
+
+ Pattern miscPropsPattern = Pattern.compile("" +
+ "\\w+\\.\\d+\\.([^.]+)\\.property"
+ );
+ protected Properties handleMiscellaneousProperties(String key, String value) {
+ Matcher miscKeyFinder = miscPropsPattern.matcher(key);
+ if (miscKeyFinder.matches()) {
+ String misckey = miscKeyFinder.group(1);
+ if (this.miscProperties == null)
+ this.miscProperties = new Properties();
+ this.miscProperties.put(misckey, value);
+ log.debug("Miscellaneous Property set: " + misckey + "=" + value);
+ return this.miscProperties;
+ }
+ String error = "Miscellaneous property was detected, " +
+ "but key was invalid. Could not instantiate property: " +
+ key + "=" + value;
log.error(error);
this.errors.addError(Feedback.BAD_PROPERTY, error, true);
return this.miscProperties;
- }
-
- private void addDefaultMiscProperties() {
- handleMiscellaneousProperties("Testing.1234.spacekey.property", this.settings.getSpace());
- }
-
- protected void handleFilters(String key, String value) throws InstantiationException, IllegalAccessException {
- log.debug("filter property = " + value);
- getFilterValues().add(value);
- }
+ }
+
+ private void addDefaultMiscProperties() {
+ handleMiscellaneousProperties("Testing.1234.spacekey.property", this.settings.getSpace());
+ }
+
+ protected void handleFilters(String key, String value) throws InstantiationException, IllegalAccessException {
+ log.debug("filter property = " + value);
+ getFilterValues().add(value);
+ }
private Set<String> getFilterValues() {
if (this.filterValues == null)
this.filterValues = new HashSet<String>();
return this.filterValues;
}
-
- /**
- * sets up .xmlevent properties
- * @param key must end in .xmlevent
- * @param value must follow this format:
- * <tt>
- * {tag}tagname{class}classname
- * </tt>
- * where tagname is the xml tag to associate the event with (b, for bold)
- * and classname is the parser that will manage the events for that tag.
- * tagname can contain a comma-delimited list of tags. For example:
- * {tag}h1, h2, h3{class}com.example.HeaderParser
- */
- private void handleXmlEvents(String key, String value) {
- String tag = getXmlEventTag(value);
- String classname = getXmlEventClassname(value);
- String[] tags = tag.split(",");
- for (String onetag : tags) {
- onetag = onetag.trim();
+
+ /**
+ * sets up .xmlevent properties
+ * @param key must end in .xmlevent
+ * @param value must follow this format:
+ * <tt>
+ * {tag}tagname{class}classname
+ * </tt>
+ * where tagname is the xml tag to associate the event with (b, for bold)
+ * and classname is the parser that will manage the events for that tag.
+ * tagname can contain a comma-delimited list of tags. For example:
+ * {tag}h1, h2, h3{class}com.example.HeaderParser
+ */
+ private void handleXmlEvents(String key, String value) {
+ String tag = getXmlEventTag(value);
+ String classname = getXmlEventClassname(value);
+ String[] tags = tag.split(",");
+ for (String onetag : tags) {
+ onetag = onetag.trim();
addOneXmlEvent(onetag, classname);
}
- }
+ }
/**
* adds one xml event object to the events handler, such that the classname becomes
@@ -2618,8 +2702,8 @@
*/
private void addOneXmlEvent(String tag, String classname) {
if (this.miscProperties.containsKey("xmlevents")) {
- Class eventsClass;
- String xmleventsclass = this.miscProperties.getProperty("xmlevents");
+ Class eventsClass;
+ String xmleventsclass = this.miscProperties.getProperty("xmlevents");
try {
eventsClass = Class.forName(xmleventsclass);
} catch (ClassNotFoundException e) {
@@ -2629,7 +2713,7 @@
this.miscProperties.remove("xmlevents");
eventsClass = DefaultXmlEvents.class; //try setting the DefaultXmlEvents
}
- XmlEvents events = null;
+ XmlEvents events = null;
try {
events = (XmlEvents) eventsClass.newInstance();
events.addEvent(tag, classname); //call the custom events class
@@ -2641,13 +2725,13 @@
this.miscProperties.remove("xmlevents");
//continue to DefaultXmlEvents.addEvent below
}
- }
+ }
new DefaultXmlEvents().addEvent(tag, classname);
}
-
- Pattern xmleventClassPattern = Pattern.compile("" +
- "\\{class\\}(.*)");
- protected String getXmlEventClassname(String value) {
+
+ Pattern xmleventClassPattern = Pattern.compile("" +
+ "\\{class\\}(.*)");
+ protected String getXmlEventClassname(String value) {
Matcher finder = xmleventClassPattern.matcher(value);
if (finder.find()) {
return finder.group(1);
@@ -2655,8 +2739,8 @@
throw new IllegalArgumentException(XMLEVENT_PROP_ERROR);
}
- Pattern xmleventTagPattern = Pattern.compile("" +
- "\\{tag\\}([^}]+)\\{class\\}");
+ Pattern xmleventTagPattern = Pattern.compile("" +
+ "\\{tag\\}([^}]+)\\{class\\}");
protected String getXmlEventTag(String value) {
Matcher finder = xmleventTagPattern.matcher(value);
if (finder.find()) {
@@ -2666,79 +2750,79 @@
}
/**
- * @param key
- * @return true if the given key is the switch to turn on the
- * Hierarchy framework
- */
- protected boolean isHierarchySwitch(String key) {
- Matcher switchFinder = switchPattern.matcher(key);
- return switchFinder.find();
- }
-
- /**
- * determines if the given string represents an allowed
- * non converter property: (hierarchy builder, page history preserver,
- * illegalname handler, autodetect spacekeys)
- * @param input represents an entire converter/property string. For example:
- * <br/>
- * Wiki.0011.somefilename.propertytype=something
- * @return true if it's an expected/allowed non converter property
- */
- public boolean isNonConverterProperty(String input) {
- String converterTypes =
- "(" +
- "(" +
- NONCONVERTERTYPE_HIERARCHYBUILDER +
- ")" +
- "|" +
- "(" +
- NONCONVERTERTYPE_PAGEHISTORYPRESERVATION +
- ")" +
- "|" +
- "(" +
- NONCONVERTERTYPE_ILLEGALHANDLING +
+ * @param key
+ * @return true if the given key is the switch to turn on the
+ * Hierarchy framework
+ */
+ protected boolean isHierarchySwitch(String key) {
+ Matcher switchFinder = switchPattern.matcher(key);
+ return switchFinder.find();
+ }
+
+ /**
+ * determines if the given string represents an allowed
+ * non converter property: (hierarchy builder, page history preserver,
+ * illegalname handler, autodetect spacekeys)
+ * @param input represents an entire converter/property string. For example:
+ * <br/>
+ * Wiki.0011.somefilename.propertytype=something
+ * @return true if it's an expected/allowed non converter property
+ */
+ public boolean isNonConverterProperty(String input) {
+ String converterTypes =
+ "(" +
+ "(" +
+ NONCONVERTERTYPE_HIERARCHYBUILDER +
+ ")" +
+ "|" +
+ "(" +
+ NONCONVERTERTYPE_PAGEHISTORYPRESERVATION +
")" +
- "|" +
- "(" +
- NONCONVERTERTYPE_AUTODETECTSPACEKEYS +
+ "|" +
+ "(" +
+ NONCONVERTERTYPE_ILLEGALHANDLING +
+ ")" +
+ "|" +
+ "(" +
+ NONCONVERTERTYPE_AUTODETECTSPACEKEYS +
")" +
"|" +
"(" +
- NONCONVERTERTYPE_FILTERS +
+ NONCONVERTERTYPE_FILTERS +
")" +
"|" +
"(" +
- NONCONVERTERTYPE_MISCPROPERTIES +
+ NONCONVERTERTYPE_MISCPROPERTIES +
")" +
"|" +
"(" +
- NONCONVERTERTYPE_XMLEVENT +
+ NONCONVERTERTYPE_XMLEVENT +
")" +
- ")";
- String converterPattern = "[-\\w\\d.]+?" + converterTypes + "=" + ".*";
- return input.matches(converterPattern);
- }
- /**
- * @return true if the converter should handle page histories
- */
- public boolean isHandlingPageHistories() {
- return this.handlingPageHistories;
- }
-
- /**
- * @return true if the converter should handle page histories
- */
- public boolean isHandlingPageHistoriesFromFilename() {
- return this.handlingPageHistories && this.pageHistorySuffix != null;
- }
-
- /**
- * @return the current page history suffix
- */
- public String getPageHistorySuffix() {
- return this.pageHistorySuffix;
- }
-
+ ")";
+ String converterPattern = "[-\\w\\d.]+?" + converterTypes + "=" + ".*";
+ return input.matches(converterPattern);
+ }
+ /**
+ * @return true if the converter should handle page histories
+ */
+ public boolean isHandlingPageHistories() {
+ return this.handlingPageHistories;
+ }
+
+ /**
+ * @return true if the converter should handle page histories
+ */
+ public boolean isHandlingPageHistoriesFromFilename() {
+ return this.handlingPageHistories && this.pageHistorySuffix != null;
+ }
+
+ /**
+ * @return the current page history suffix
+ */
+ public String getPageHistorySuffix() {
+ return this.pageHistorySuffix;
+ }
+
/**
* sorts the given list of pages.
* Note: sorting will take into account page name
@@ -2748,10 +2832,16 @@
*/
protected List<Page> sortByHistory(List<Page> pages) {
this.state.updateNote("Sorting Pages by Page History");
+ log.debug("num of pages: " + pages.size());
List<Page> sortedPages = new ArrayList<Page>();
Set<Page> sorted = new TreeSet<Page>();
sorted.addAll(pages); //sort them and get rid of non-unique pages
sortedPages.addAll(sorted); //turn them back into a list
+ if (log.isDebugEnabled()) {
+ for (Page page : sorted) {
+ log.debug("Sorted pages: " + page.getFile().getName());
+ }
+ }
return sortedPages;
}
@@ -2792,7 +2882,7 @@
protected HierarchyHandler getHierarchyHandler() {
return hierarchyHandler;
}
-
+
/**
* sets how the hierarchy framework is to be used.
* @param input "UseBuilder", "UsePagenames", or "Default".
@@ -2817,7 +2907,7 @@
public void resetFeedback() {
this.feedback = Feedback.NONE;
}
-
+
/**
* clears state relating to the error handling
*/
@@ -2825,7 +2915,7 @@
this.errors.clear();
this.hadConverterErrors = false;
}
-
+
/**
* clears state relating to the hierarchy framework
*/
@@ -2833,21 +2923,21 @@
this.hierarchyBuilder = null;
this.hierarchyHandler = HierarchyHandler.DEFAULT;
}
-
+
/**
* @return object contains information relating to errors triggered during the conversion
*/
public ConverterErrors getErrors() {
return this.errors;
}
-
+
/**
* @return true if the conversion has generated errors
*/
public boolean hadConverterErrors() {
return this.hadConverterErrors;
}
-
+
/**
* setter
* @param running
@@ -2855,7 +2945,7 @@
protected void setRunning(boolean running) {
this.running = running; //used in junit
}
-
+
/**
* setter
* @param settings
@@ -2864,7 +2954,7 @@
this.settings = settings; //used in junit
}
-
+
/**
* @return true if the illegal handling (names and links) should occur.
* false if it should be disabled
@@ -2872,22 +2962,22 @@
public boolean isIllegalHandlingEnabled() {
return illegalHandlingEnabled;
}
-
+
public boolean isAutoDetectingSpacekeys() {
return autoDetectSpacekeys;
}
-
+
public class AsciiVersionComparator implements Comparator {
- public int compare(Object a, Object b) {
- Page pa = (Page) a;
- Page pb = (Page) b;
- String sa = pa.getName().toLowerCase();
- String sb = pb.getName().toLowerCase();
- int ascii = sa.compareTo(sb);
- int sav = pa.getVersion();
- int sbv = pb.getVersion();
- int version = sbv - sav;
- return ascii - version;
- }
+ public int compare(Object a, Object b) {
+ Page pa = (Page) a;
+ Page pb = (Page) b;
+ String sa = pa.getName().toLowerCase();
+ String sb = pb.getName().toLowerCase();
+ int ascii = sa.compareTo(sb);
+ int sav = pa.getVersion();
+ int sbv = pb.getVersion();
+ int version = sbv - sav;
+ return ascii - version;
+ }
}
}
diff --git a/src/com/atlassian/uwc/ui/Page.java b/src/com/atlassian/uwc/ui/Page.java
index 9a62b1d..b509a10 100644
--- a/src/com/atlassian/uwc/ui/Page.java
+++ b/src/com/atlassian/uwc/ui/Page.java
@@ -164,7 +164,14 @@
if (compareValue == 0) {
if (!sortWithTimestamp) compareValue = versionA - versionB;
}
+ //if these are the same, double check file path in case the filename is the same
+ if (compareValue == 0) {
+ String pathA = this.path;
+ String pathB = b.getPath();
+ compareValue = pathA.compareTo(pathB);
+ }
+ //NOTE: If we return 0, only one of these objects will win in a Set that is sorted with this method.
return compareValue;
}