blob: bd62ea95e2f46fc7f5e39a01f26792219f8e11f3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2016 IBM Corporation and Others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Kentarou FUKUDA - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.visualization.internal.engines.blind.html.util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.actf.util.logging.DebugPrintUtil;
import org.eclipse.actf.util.xpath.XPathService;
import org.eclipse.actf.util.xpath.XPathServiceFactory;
import org.eclipse.actf.visualization.engines.blind.BlindVizResourceUtil;
import org.eclipse.actf.visualization.engines.blind.html.IBlindProblem;
import org.eclipse.actf.visualization.engines.blind.html.VisualizeEngine;
import org.eclipse.actf.visualization.engines.voicebrowser.IPacket;
import org.eclipse.actf.visualization.engines.voicebrowser.IPacketCollection;
import org.eclipse.actf.visualization.eval.html.HtmlTagUtil;
import org.eclipse.actf.visualization.eval.problem.HighlightTargetId;
import org.eclipse.actf.visualization.eval.problem.IProblemItem;
import org.eclipse.actf.visualization.internal.engines.blind.html.BlindProblem;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class VisualizeViewUtil {
// separated from VisualizeEngine
private static final XPathService xpathService = XPathServiceFactory.newService();
private static final String SCRIPT = "script"; //$NON-NLS-1$
private static final String NAME = "name"; //$NON-NLS-1$
private static final String TITLE = "title"; //$NON-NLS-1$
private static final String HREF = "href"; //$NON-NLS-1$
private static final String IMG = "img"; //$NON-NLS-1$
private static final String NULL_STRING = ""; //$NON-NLS-1$
private static final String BODY = "body"; //$NON-NLS-1$
private static final String STYLE = "style"; //$NON-NLS-1$
private static final String ID = "id"; //$NON-NLS-1$
private static final String DIV = "div"; //$NON-NLS-1$
private static final String INPUT = "input"; //$NON-NLS-1$
private static final String IMAGE = "image"; //$NON-NLS-1$
private static final String TYPE = "type"; //$NON-NLS-1$
private static final String ON_CLICK = "onClick"; //$NON-NLS-1$
private static final String ALT = "alt"; //$NON-NLS-1$
private static final String SRC = "src"; //$NON-NLS-1$
@SuppressWarnings("nls")
public static File prepareActions(Document result, VisualizeMapDataImpl mapData, String baseUrl,
boolean servletMode) {
Map<Node, Node> linkMap = mapData.getIntraPageLinkMap();
List<VisualizationNodeInfo> targetElementList = mapData.getNodeInfoList();
NodeList bodyEl = result.getElementsByTagName(BODY);
for (int i = 0; i < bodyEl.getLength(); i++) {
Element tmpE = (Element) bodyEl.item(i);
DocumentCleaner.removeOnMouse(tmpE);
DocumentCleaner.removeOnLoad(tmpE);
}
// TODO move to appropriate place
// to handle no body page
if (bodyEl.getLength() == 0) {
Node tmpN = result.getDocumentElement();
if (tmpN != null) {
tmpN.appendChild(result.createElement(BODY));
} else {
DebugPrintUtil.devOrDebugPrintln("VisualizeViewUtil: no doc element");
// TODO test
return null;
}
}
// div for arrow
Element div = result.createElement(DIV);
div.setAttribute(STYLE, "position:absolute;pixelLeft= 10;pixelTop=10; color:red;font-size=12pt");
div.setAttribute(ID, "test");
// bodyEl.item(bodyEl.getLength() - 1).appendChild(div);
Node tmpBody = bodyEl.item(0);
tmpBody.insertBefore(div, tmpBody.getFirstChild());
insertLinkIcon(result, linkMap, baseUrl);
// div for control_pane
insertControlPane(result);
// remove links of "map"
bodyEl = result.getElementsByTagName("map");
if (bodyEl != null) {
for (int i = 0; i < bodyEl.getLength(); i++) {
Element x = (Element) bodyEl.item(i);
x.setAttribute(ON_CLICK, "cancelMapLink(event)");
}
}
return (createScriptFile(result, targetElementList, baseUrl, servletMode));
}
@SuppressWarnings("nls")
private static void insertLinkIcon(Document doc, Map<Node, Node> linkMap, String baseUrl) {
Iterator<Node> it = linkMap.keySet().iterator();
Set<String> alreadySet = new HashSet<String>();
int id = 0;
while (it.hasNext()) {
Element lel = (Element) it.next();
Element ael = (Element) linkMap.get(lel);
Element imgel1 = doc.createElement(IMG);
String href = lel.getAttribute(HREF).substring(1);
imgel1.setAttribute(ALT, "Intra-page link: " + href);
imgel1.setAttribute(TITLE, "Intra-page link: " + href);
imgel1.setAttribute(SRC, baseUrl + "img/jump.gif");
imgel1.setAttribute(NAME, "jump" + id);
if (lel.hasChildNodes()) {
lel.insertBefore(imgel1, lel.getFirstChild());
} else {
lel.appendChild(imgel1);
}
if (!alreadySet.contains(href)) {
Element imgel2 = doc.createElement(IMG);
imgel2.setAttribute(ALT, "Intra-page link destination: " + href);
imgel2.setAttribute(TITLE, "Intra-page link destination: " + href);
imgel2.setAttribute(SRC, baseUrl + "img/dest.gif");
imgel2.setAttribute(NAME, href);
if (ael.hasChildNodes()) {
ael.insertBefore(imgel2, ael.getFirstChild());
} else {
ael.appendChild(imgel2);
}
alreadySet.add(href);
}
id++;
}
}
private static void addLandmarkImg(Document doc, Element target, String baseUrl) {
Element imgel1 = doc.createElement(IMG);
String name = target.getTagName().toLowerCase();
imgel1.setAttribute(ALT, "Landmark: " + name);
// imgel1.setAttribute(TITLE, name);
imgel1.setAttribute(SRC, baseUrl + "img/" + name + ".gif");
if (target.hasChildNodes()) {
target.insertBefore(imgel1, target.getFirstChild());
} else {
target.appendChild(imgel1);
}
}
private static void addLandmarkImg(Document doc, Element target, String baseUrl, String landmarkName) {
Element imgel1 = doc.createElement(IMG);
imgel1.setAttribute(ALT, "Landmark: " + landmarkName);
// imgel1.setAttribute(TITLE, name);
imgel1.setAttribute(SRC, baseUrl + "img/" + landmarkName + ".gif");
if (target.hasChildNodes()) {
target.insertBefore(imgel1, target.getFirstChild());
} else {
target.appendChild(imgel1);
}
}
public static void visualizeLandmark(Document doc, String baseUrl) {
// String[] landmarks = { "nav", "article", "aside" };
// NodeList tmpNl = doc.getElementsByTagName("main");
NodeList tmpNl = xpathService.evalPathForNodeList("//main|//*[@role='main']", doc);
for (int i = 0; i < tmpNl.getLength(); i++) {
Element landE = (Element) tmpNl.item(i);
addLandmarkImg(doc, landE, baseUrl, "main");
try {
Element parentE = (Element) landE.getParentNode();
Element divE = doc.createElement("div");
divE.setAttribute("class", "main");
parentE.insertBefore(divE, landE);
divE.appendChild(landE);
} catch (Exception e) {
}
}
tmpNl = xpathService.evalPathForNodeList("//article|//*[@role='article']", doc);
for (int i = 0; i < tmpNl.getLength(); i++) {
addLandmarkImg(doc, (Element) tmpNl.item(i), baseUrl, "article");
}
tmpNl = xpathService.evalPathForNodeList("//nav|//*[@role='navigation']", doc);
for (int i = 0; i < tmpNl.getLength(); i++) {
addLandmarkImg(doc, (Element) tmpNl.item(i), baseUrl, "nav");
}
tmpNl = doc.getElementsByTagName("aside");
for (int i = 0; i < tmpNl.getLength(); i++) {
addLandmarkImg(doc, (Element) tmpNl.item(i), baseUrl);
}
tmpNl = xpathService.evalPathForNodeList("//*[@role='complementary']", doc);
for (int i = 0; i < tmpNl.getLength(); i++) {
Element landE = (Element) tmpNl.item(i);
if (!"aside".equalsIgnoreCase(landE.getNodeName())) {
addLandmarkImg(doc, landE, baseUrl, "complementary");
}
}
for (String tag : new String[] { "header", "footer" }) {
tmpNl = doc.getElementsByTagName(tag);
for (int i = 0; i < tmpNl.getLength(); i++) {
Element landE = (Element) tmpNl.item(i);
if (!HtmlTagUtil.hasAncestor(landE, "article") && !HtmlTagUtil.hasAncestor(landE, "section")) {
landE.setAttribute("class", "header_footer");
addLandmarkImg(doc, landE, baseUrl);
}
}
}
tmpNl = xpathService.evalPathForNodeList("//*[@role='banner']", doc);
for (int i = 0; i < tmpNl.getLength(); i++) {
Element landE = (Element) tmpNl.item(i);
if (!"header".equalsIgnoreCase(landE.getNodeName())) {
addLandmarkImg(doc, landE, baseUrl, "banner");
}
}
tmpNl = xpathService.evalPathForNodeList("//*[@role='contentinfo']", doc);
for (int i = 0; i < tmpNl.getLength(); i++) {
Element landE = (Element) tmpNl.item(i);
if (!"footer".equalsIgnoreCase(landE.getNodeName())) {
addLandmarkImg(doc, landE, baseUrl, "contentinfo");
}
}
tmpNl = xpathService.evalPathForNodeList("//*[@role='application']", doc);
for (int i = 0; i < tmpNl.getLength(); i++) {
addLandmarkImg(doc, (Element) tmpNl.item(i), baseUrl, "application");
}
tmpNl = xpathService.evalPathForNodeList("//*[@role='search']", doc);
for (int i = 0; i < tmpNl.getLength(); i++) {
addLandmarkImg(doc, (Element) tmpNl.item(i), baseUrl, "search");
}
NodeList nl = doc.getElementsByTagName("head");
if (nl.getLength() > 0) {
Element el = (Element) nl.item(0);
Element cssE = doc.createElement("link");
cssE.setAttribute("rel", "stylesheet");
cssE.setAttribute("type", "text/css");
cssE.setAttribute("href", "img/visualization.css");
cssE.setAttribute("media", "all");
el.appendChild(cssE);
}
}
@SuppressWarnings("nls")
// TODO
private static void insertControlPane(Document result) {
NodeList bodyEl = result.getElementsByTagName(BODY);
Element div = result.createElement(DIV);
div.setAttribute(STYLE,
"position:absolute;font-size: medium; background-color: #FFFFFF; border-color: #333333 #000000 #000000; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px");
div.setAttribute(ID, "control_pane");
Element input1 = result.createElement(INPUT);
input1.setAttribute(TYPE, IMAGE);
input1.setAttribute(SRC, "img/stop.gif");
input1.setAttribute(ALT, "Stop/Move Balloon");
input1.setAttribute(ON_CLICK, "control_moving()");
div.appendChild(input1);
Element input2 = result.createElement(INPUT);
input2.setAttribute(TYPE, IMAGE);
input2.setAttribute(SRC, "img/clear.gif");
input2.setAttribute(ALT, "Clear Line");
input2.setAttribute(ON_CLICK, "clean_Line()");
Element input3 = result.createElement(INPUT);
input3.setAttribute(TYPE, IMAGE);
input3.setAttribute(SRC, "img/refresh.gif");
input3.setAttribute(ALT, "Refresh Line");
input3.setAttribute(ON_CLICK, "refresh_Jump()");
Element input4 = result.createElement(INPUT);
input4.setAttribute(TYPE, IMAGE);
input4.setAttribute(SRC, "img/draw.gif");
input4.setAttribute(ALT, "Draw All Line");
input4.setAttribute(ON_CLICK, "draw_all_Line()");
div.appendChild(input2);
div.appendChild(input3);
div.appendChild(input4);
// bodyEl.item(bodyEl.getLength() - 1).appendChild(div);
Node tmpBody = bodyEl.item(0);
tmpBody.insertBefore(div, tmpBody.getFirstChild());
}
@SuppressWarnings("nls")
private static File createScriptFile(Document result, List<VisualizationNodeInfo> elementList, String baseUrl,
boolean servletMode) {
try {
PrintWriter pw;
File valiantFile = BlindVizResourceUtil.createTempFile("variant", ".js");
pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(valiantFile), "UTF-8"));
StringBuffer sb = new StringBuffer();
sb.append("var id2time = new Array();");
sb.append("var id2comment = new Array();");
int size = elementList.size();
for (int i = 0; i < size; i++) {
VisualizationNodeInfo curInfo = elementList.get(i);
//
String comment = curInfo.getComment();
StringBuffer comment_sb = new StringBuffer();
// if (871 == curInfo.getId()) {
for (int x = 0; x < comment.length(); x++) {
if (comment.charAt(x) == '\"') {
comment_sb.append("\\");
}
if (comment.charAt(x) == '\'') {
comment_sb.append('\\');
}
comment_sb.append(comment.charAt(x));
}
sb.append("id2time['id");
sb.append(curInfo.getId());
sb.append("']=");
sb.append(curInfo.getTime());
sb.append(";");
sb.append("id2comment['id");
sb.append(curInfo.getId());
sb.append("']='");
sb.append(comment_sb.toString());
sb.append("';");
}
String tmpS = sb.toString().replaceAll("\n", NULL_STRING).replaceAll("\r", NULL_STRING);
pw.write(tmpS);
sb = new StringBuffer();
sb.append("var baloonSwitch = 1; ");
sb.append("var baseUrl = '" + baseUrl + "'; ");
sb.append("var acc_imageDir = 'img/'; ");
if (servletMode) {
sb.append("var servletMode = true; ");
} else {
sb.append("var servletMode = false; ");
}
// speed up -> sb.append("var isAlert = false; ");
sb.append("var isAlert = true; ");
pw.write(sb.toString());
pw.flush();
pw.close();
NodeList nl = result.getElementsByTagName("head");
if (nl.getLength() > 0) {
Element el = (Element) nl.item(0);
Element script = result.createElement(SCRIPT);
// script.setAttribute("src", "file:///C:/C/highlight.js");
script.setAttribute(SRC, baseUrl + valiantFile.getName());
el.appendChild(script);
Element script2 = result.createElement(SCRIPT);
// script.setAttribute("src", "file:///C:/C/highlight.js");
script2.setAttribute(SRC, baseUrl + "img/highlight.js");
el.appendChild(script2);
}
Element div = result.createElement(DIV);
div.setAttribute(STYLE,
"position:absolute;font-size: medium; background-color: #FFFFFF; border-color: #333333 #000000 #000000; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px");
div.setAttribute(ID, "balloon");
Element messageDiv = result.createElement(DIV);
messageDiv.setAttribute(ID, "message");
messageDiv.appendChild(result.createTextNode(NULL_STRING));
div.appendChild(messageDiv);
NodeList bodyNl = result.getElementsByTagName(BODY);
if (bodyNl.getLength() > 0) {
Element bodyEl = (Element) bodyNl.item(0);
bodyEl.insertBefore(div, bodyEl.getFirstChild());
}
return valiantFile;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static void visualizeError(Document doc, List<IProblemItem> problems, VisualizeMapDataImpl mapData,
String baseUrlS) {
int size = problems.size();
// TODO setNodeId might be duplicated
for (int i = 0; i < size; i++) {
BlindProblem prob = (BlindProblem) problems.get(i);
Node node = prob.getTargetNodeInResultDoc();
Integer idObj = mapData.getIdOfNode(node);
int subType = prob.getSubType();
switch (subType) {
case IBlindProblem.WRONG_ALT_AREA:
case IBlindProblem.NO_ALT_AREA:
case IBlindProblem.TOO_LESS_STRUCTURE:
case IBlindProblem.NO_SKIPTOMAIN_LINK:
break;
default:
if (idObj != null) {
int id = idObj.intValue();
prob.setNodeId(id);
}
}
VisualizationNodeInfo info = mapData.getNodeInfo(node);
if (info != null) {
if (IBlindProblem.WRONG_NBSP_ALT_IMG == prob.getSubType()) {
info.appendComment(prob.getDescription().replaceAll("&", "&amp;"));
} else {
info.appendComment(prob.getDescription());
}
} else {
if (node != null && node.getNodeType() == Node.ELEMENT_NODE) {
try {
String id = ((Element) node).getAttribute(ID);
if (id.startsWith(ID)) {
id = id.substring(2);
// info =
}
} catch (Exception e) {
//
}
}
}
switch (prob.getSubType()) {
case IBlindProblem.NO_ALT_IMG:
case IBlindProblem.WRONG_ALT_IMG:
case IBlindProblem.WRONG_NBSP_ALT_IMG:
Element el = (Element) node;
Node replacement = mapData.getReplacement(el);
if (replacement != null) {
el = (Element) replacement;
}
Element img = createErrorImageElement(node, prob, idObj, baseUrlS);
el.appendChild(img);
break;
case IBlindProblem.REDUNDANT_ALT:
int startId = -1;
int endId = -1;
try {
List<Node> nl = prob.getNodeList();
node = nl.get(1);
Integer endNodeId = mapData.getIdOfNode(node);
if (endNodeId != null) {
endId = endNodeId.intValue();
}
} catch (NullPointerException npe) {
npe.printStackTrace();
}
if (idObj != null) {
startId = idObj.intValue();
} else if (endId > -1) {
startId = endId;
}
prob.setNodeId(startId);
prob.addNodeIds(new HighlightTargetId(startId, startId));
prob.addNodeIds(new HighlightTargetId(endId, endId));
break;
case IBlindProblem.NO_DEST_LINK:
case IBlindProblem.NO_TEXT_INTRAPAGELINK:
case IBlindProblem.NO_DEST_SKIP_LINK:
case IBlindProblem.WRONG_SKIP_LINK_TEXT:
case IBlindProblem.TOOFAR_SKIPTOMAIN_LINK:
case IBlindProblem.NO_TEXT_WITH_TITLE_INTRAPAGELINK:
case IBlindProblem.INVISIBLE_INTRAPAGE_LINK:
case IBlindProblem.WRONG_SKIP_LINK_TITLE:
Element element = (Element) node;
Element image = createErrorImageElement(element, prob, idObj, baseUrlS);
element.appendChild(image);
break;
case IBlindProblem.WRONG_TEXT:
// Node node = prob.getNode();
Element image2 = createErrorImageElement(node, prob, idObj, baseUrlS);
if (node.getNodeType() == Node.ELEMENT_NODE) {
node.appendChild(image2);
} else {
node.getParentNode().insertBefore(image2, node);
}
break;
case IBlindProblem.NO_VALUE_INPUT_BUTTON:
case IBlindProblem.SEPARATE_DBCS_INPUT_VALUE:
Element image3 = createErrorImageElement(node, prob, idObj, baseUrlS);
node.getParentNode().insertBefore(image3, node);
break;
default:
}
}
}
@SuppressWarnings("nls")
private static Element createErrorImageElement(Node target, IProblemItem prob, Integer idObj, String baseUrlS) {
Element img = target.getOwnerDocument().createElement(IMG);
img.setAttribute(ALT, "error icon");
if (IBlindProblem.WRONG_NBSP_ALT_IMG == prob.getSubType()) {
img.setAttribute(TITLE, prob.getDescription().replaceAll("&", "&amp;"));
} else {
img.setAttribute(TITLE, prob.getDescription());
}
img.setAttribute("onmouseover", "updateBaloon('id" + idObj + "');");
img.setAttribute(SRC, baseUrlS + "img/" + VisualizeEngine.ERROR_ICON_NAME);
return (img);
}
@SuppressWarnings("nls")
public static Document returnTextView(Document result, IPacketCollection allPc, String baseUrl) {
NodeList bodyNl = result.getElementsByTagName(BODY);
// TODO remove second Body, script, etc.
if (bodyNl.getLength() > 0) {
Element bodyEl = (Element) bodyNl.item(0);
NodeList nl = bodyEl.getChildNodes();
int size = nl.getLength();
for (int i = size - 1; i >= 0; i--) {
bodyEl.removeChild(nl.item(i));
}
String str;
size = allPc.size();
boolean brFlag = false;
boolean insideLink = false;
for (int i = 0; i < size; i++) {
IPacket p = allPc.get(i);
if (p.getContext().isLinkTag()) {
insideLink = true;
}
str = p.getText();
if (str != null && !str.equals(NULL_STRING)) {
Element spanEl = result.createElement("span");
spanEl.appendChild(result.createTextNode(str));
bodyEl.appendChild(spanEl);
if (insideLink)
spanEl.setAttribute(STYLE, "text-decoration: underline;");
brFlag = false;
}
if (p.getContext().isLineDelimiter()) {
if (brFlag) {
/*
* Element spanEl = result.createElement("span");
* spanEl.appendChild( result.createTextNode(" SKIPPED
* ")); bodyEl.appendChild(spanEl);
*/
} else {
Element br = result.createElement("br");
bodyEl.appendChild(br);
brFlag = true;
}
}
if (!p.getContext().isLinkTag()) {
insideLink = false;
}
}
}
NodeList nl = result.getElementsByTagName("head");
if (nl.getLength() > 0) {
Element el = (Element) nl.item(0);
Element script = result.createElement(SCRIPT);
script.setAttribute(SRC, baseUrl + "img/highlight-dummy.js");
el.appendChild(script);
}
return result;
}
}