/*
* #!
* Ontopia Navigator
* #-
* Copyright (C) 2001 - 2013 The Ontopia Project
* #-
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* !#
*/
package net.ontopia.topicmaps.nav2.portlets.pojos;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.io.Writer;
import java.io.IOException;
import net.ontopia.utils.StringUtils;
import net.ontopia.utils.StringifierIF;
import net.ontopia.utils.OntopiaRuntimeException;
import net.ontopia.infoset.core.LocatorIF;
import net.ontopia.topicmaps.core.TopicIF;
import net.ontopia.topicmaps.core.TopicMapIF;
import net.ontopia.topicmaps.utils.TopicStringifiers;
import net.ontopia.topicmaps.query.core.QueryResultIF;
import net.ontopia.topicmaps.query.core.QueryProcessorIF;
import net.ontopia.topicmaps.query.core.InvalidQueryException;
import net.ontopia.topicmaps.query.utils.QueryUtils;
/**
* PUBLIC: This component can render wiki formatting a la MediaWiki
* into HTML.
*/
public class Wiki {
public static void render(String text, Writer out, TopicMapIF topicmap,
Map params) throws IOException {
out.write("<p>");
int old = 0;
for (int ix = 0; ix < text.length(); ix++) {
String output = null;
int end = ix;
if (text.charAt(ix) == '\n') {
if (ix+1 == text.length()) {
output = "";
end = ix;
} else if (text.charAt(ix+1) == '\n') {
output = "</p><p>";
end = ix + 1;
} else if (text.charAt(ix+1) == '\r' && text.charAt(ix+2) == '\n') {
output = "</p><p>";
end = ix + 2;
} else if (text.charAt(ix+1) == '*') {
int pos = findNextDoubleNewline(text, ix+1, out);
output = makeList(text.substring(ix+1, pos));
end = pos + 1;
}
} else if (text.charAt(ix) == '=') {
int pos = text.indexOf('=', ix + 1);
output = "<h2>" + text.substring(ix+1, pos) + "</h2>";
end = pos;
} else if (text.charAt(ix) == '<') {
if (text.substring(ix, ix+5).equals("<pre>")) {
int pos = text.indexOf("</pre>", ix + 1);
output = "<pre>" + escape(text.substring(ix + 5, pos)) + "</pre>";
end = pos + 6;
} else if (text.substring(ix, ix+7).equals("<tolog>")) {
int pos = text.indexOf("</tolog>", ix + 1);
String query = text.substring(ix+7, pos);
output = runQuery(query, topicmap, params);
end = pos + 7; // ?
}
} else if (text.charAt(ix) == '\'') {
int length = 0;
String gi = null;
if (text.substring(ix, ix+3).equals("'''")) {
length = 3;
gi = "b";
} else if (text.substring(ix, ix+2).equals("''")) {
length = 2;
gi = "i";
}
if (gi != null) {
int pos = text.indexOf("''" + (length == 3 ? "'" : ""), ix + length);
output = "<" + gi + ">" + text.substring(ix + length, pos) + "</" + gi + ">";
end = pos + length - 1;
}
} else if (text.charAt(ix) == '[') {
int pos = text.indexOf(']', ix);
String name = text.substring(ix + 1, pos);
TopicIF topic = getTopic(name, topicmap);
output = getString(topic, params);
end = pos;
}
if (output != null) {
out.write(text.substring(old, ix));
out.write(output);
ix = end;
old = end + 1;
}
}
out.write(escape(text.substring(old)));
out.write("</p>");
}
private static String escape(String str) {
str = StringUtils.replace(str, "<", "<");
str = StringUtils.replace(str, ">", ">");
return str;
}
private static String makeList(String rawlist) {
return "<ul>\n" + StringUtils.replace(rawlist, "*", "<li>") + "</ul>";
}
private static int findNextDoubleNewline(String text, int ix, Writer out)
throws IOException {
for (; ix < text.length(); ix++) {
if (text.charAt(ix) == '\n') {
int start = ix++;
while (text.charAt(ix) == ' ' || text.charAt(ix) == '\r')
ix++;
if (text.charAt(ix) == '\n')
return start;
}
}
return ix - 2;
}
private static String debug(char ch) {
if (ch == ' ')
return "SPACE";
if (ch == '\n')
return "NEWLINE";
if (ch == '\r')
return "CR";
return "" + ch + " (" + ((int) ch) + ")";
}
private static String runQuery(String query, TopicMapIF topicmap, Map params) {
try {
StringBuilder out = new StringBuilder();
out.append("<table>\n");
QueryProcessorIF proc = QueryUtils.getQueryProcessor(topicmap);
QueryResultIF result = proc.execute(query, params);
out.append("<tr>");
for (int ix = 0; ix < result.getWidth(); ix++)
out.append("<th>" + result.getColumnName(ix));
while (result.next()) {
out.append("<tr>");
for (int ix = 0; ix < result.getWidth(); ix++)
out.append("<td>" + getString(result.getValue(ix), params));
}
out.append("</table>");
return out.toString();
} catch (InvalidQueryException e) {
throw new OntopiaRuntimeException(e);
}
}
private static StringifierIF strify =
TopicStringifiers.getDefaultStringifier();
private static StringifierIF linker =
new Linker();
private static String getString(Object value, Map params) {
if (value instanceof TopicIF) {
TopicIF topic = (TopicIF) value;
StringifierIF l = (StringifierIF) params.get("linker");
if (l == null)
l = linker;
return l.toString(topic);
} else
return value.toString();
}
private static TopicIF getTopic(String name, TopicMapIF topicmap) {
try {
Map params = new HashMap();
params.put("value", name);
String query = "select $TOPIC from topic-name($TOPIC, $TN), " +
"value($TN, %value%)?";
QueryProcessorIF proc = QueryUtils.getQueryProcessor(topicmap);
QueryResultIF result = proc.execute(query, params);
if (result.next()) {
return (TopicIF) result.getValue(0);
} else
return null;
} catch (InvalidQueryException e) {
throw new OntopiaRuntimeException(e);
}
}
static class Linker implements StringifierIF {
public String toString(Object o) {
TopicIF topic = (TopicIF) o;
return "<a href=\"topic.jsp?id=" + getId(topic) +
"\">" + strify.toString(topic) + "</a>";
}
private String getId(TopicIF topic) {
String base = topic.getTopicMap().getStore().getBaseAddress().getAddress();
Iterator it = topic.getItemIdentifiers().iterator();
while (it.hasNext()) {
LocatorIF loc = (LocatorIF) it.next();
String addr = loc.getAddress();
if (addr.startsWith(base))
return addr.substring(base.length() + 1);
}
return topic.getObjectId();
}
}
}