blob: df229b6db0fd138aa4e8db72ae0c29c99ae3092a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 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:
* Daisuke SATO - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.model.dom.dombycom.impl.html;
import java.util.HashSet;
import org.eclipse.actf.model.dom.dombycom.INodeEx;
import org.eclipse.actf.model.dom.dombycom.impl.Helper;
import org.eclipse.actf.model.dom.dombycom.impl.html.ElementImpl.InputType;
import org.eclipse.actf.util.vocab.AbstractTerms;
import org.eclipse.actf.util.vocab.IEvalTarget;
import org.eclipse.actf.util.vocab.Vocabulary;
import org.eclipse.actf.util.win32.comclutch.ComPlugin;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
@SuppressWarnings("nls")
public class HTMLTerms extends AbstractTerms {
// ADDED BY KOBAYASHI ( ////////////////////////////////
//
@Override
public boolean isAlterable(IEvalTarget target) {
return isImage(target);
}
private static HTMLTerms instance;
private static HashSet<String> headingTags;
private static HashSet<String> listItemTags;
private static HashSet<String> blockTags;
private static HashSet<String> listTopTags;
static {
headingTags = new HashSet<String>();
headingTags.add("H1".intern());
headingTags.add("H2".intern());
headingTags.add("H3".intern());
headingTags.add("H4".intern());
headingTags.add("H5".intern());
headingTags.add("H6".intern());
listItemTags = new HashSet<String>();
listItemTags.add("LI".intern());
listItemTags.add("DT".intern());
listTopTags = new HashSet<String>();
listTopTags.add("UL".intern());
listTopTags.add("OL".intern());
listTopTags.add("DL".intern());
blockTags = new HashSet<String>();
blockTags.add("H1".intern());
blockTags.add("H2".intern());
blockTags.add("H3".intern());
blockTags.add("H4".intern());
blockTags.add("H5".intern());
blockTags.add("H6".intern());
blockTags.add("B".intern());
blockTags.add("STRONG".intern());
blockTags.add("DIV".intern());
blockTags.add("SPAN".intern());
blockTags.add("P".intern());
blockTags.add("FONT".intern());
}
public static HTMLTerms getInstance() {
if (instance == null) {
instance = new HTMLTerms();
}
return instance;
}
@Override
public boolean isValidNode(IEvalTarget target) {
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
String name = element.getLocalName();
if ("HEAD".equals(name) || "MAP".equals(name))
return false;
}
return true;
}
@Override
public boolean isVisibleNode(IEvalTarget target) {
return true;
}
@Override
public boolean isMultilineEdit(IEvalTarget target) {
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
String name = element.getLocalName();
if ("TEXTAREA".equals(name)) {
return true;
}
} else if (target instanceof TextImpl) {
TextImpl text = (TextImpl) target;
Node parent = text.getParentNode();
if (parent instanceof IEvalTarget) {
return isMultilineEdit((IEvalTarget) parent);
}
}
return false;
}
@Override
public boolean isSelectOption(IEvalTarget target) {
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
String name = element.getLocalName();
if ("OPTION".equals(name)) {
return true;
}
} else if (target instanceof TextImpl) {
TextImpl text = (TextImpl) target;
Node parent = text.getParentNode();
if (parent instanceof IEvalTarget) {
return isSelectOption((IEvalTarget) parent);
}
}
return false;
}
@Override
public boolean isInputable(IEvalTarget target) {
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
String name = element.getLocalName();
if ("INPUT".equals(name)) {
InputType type = element.getInputType();
if (type == null)
return false;
return type.isEdit() || type.isPassword() || type.isFileEdit()
|| type.isCheckBox() || type.isRadio();
} else if ("TEXTAREA".equals(name)) {
return true;
}
} else if (target instanceof TextImpl) {
TextImpl text = (TextImpl) target;
Node parent = text.getParentNode();
if (parent instanceof IEvalTarget) {
return Vocabulary.isInputable().eval((IEvalTarget) parent);
}
}
return false;
}
@Override
public boolean isCombobox(IEvalTarget target) {
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
String name = element.getLocalName();
if ("SELECT".equals(name)) {
return true;
}
} else if (target instanceof TextImpl) {
TextImpl text = (TextImpl) target;
Node parent = text.getParentNode();
if (parent instanceof IEvalTarget) {
return Vocabulary.isSelectable().eval((IEvalTarget) parent);
}
}
return false;
}
@Override
public boolean isMultiSelectable(IEvalTarget target) {
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
String name = element.getLocalName();
if ("SELECT".equals(name)) {
return (Boolean) Helper.get(element.getINode(), "multiple");
}
} else if (target instanceof TextImpl) {
TextImpl text = (TextImpl) target;
Node parent = text.getParentNode();
if (parent instanceof IEvalTarget) {
return Vocabulary.isMultiSelectable()
.eval((IEvalTarget) parent);
}
}
return false;
}
@Override
public boolean isClickable(IEvalTarget target) {
if (target instanceof TextImpl) {
TextImpl text = (TextImpl) target;
Node parent = text.getParentNode();
if (parent instanceof IEvalTarget) {
return Vocabulary.isClickable().eval((IEvalTarget) parent);
}
}
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
String name = element.getLocalName();
String href = (String) Helper.get(element.getINode(), "href");
if (("A".equals(name) || "AREA".equals(name)) && href != null
&& href.length() > 0)
return true;
if ("BUTTON".equals(name) || "OPTION".equals(name))
return true;
if ("INPUT".equals(name)) {
InputType type = element.getInputType();
if (type != null) {
return type.isClickable();
}
}
if (Helper.hasProperty(element.getINode(), "onclick"))
return true;
}
if (target instanceof Node) {
Node node = (Node) target;
Node p = node.getParentNode();
if (p instanceof IEvalTarget)
return Vocabulary.isClickable().eval((IEvalTarget) p);
}
return false;
}
@Override
public boolean isLink(IEvalTarget target) {
if (target instanceof TextImpl) {
TextImpl text = (TextImpl) target;
Node parent = text.getParentNode();
if (parent instanceof IEvalTarget) {
return Vocabulary.isLink().eval((IEvalTarget) parent);
}
}
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
String name = element.getLocalName();
String href = (String) Helper.get(element.getINode(), "href");
if (("A".equals(name) || "AREA".equals(name)) && href != null
&& href.length() > 0)
return true;
}
if (target instanceof Node) {
Node node = (Node) target;
Node p = node.getParentNode();
if (p instanceof IEvalTarget)
return Vocabulary.isLink().eval((IEvalTarget) p);
}
return false;
}
@Override
public boolean isCheckbox(IEvalTarget target) {
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
InputType type = element.getInputType();
if (type != null)
return type.isCheckBox();
}
return false;
}
@Override
public boolean isChecked(IEvalTarget target) {
if (target instanceof ElementImpl) {
Object obj = Helper.get(((ElementImpl) target).getINode(),
"checked");
if (obj != null)
return (Boolean) obj;
}
return false;
}
@Override
public boolean isRadio(IEvalTarget target) {
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
InputType type = element.getInputType();
if (type != null)
return type.isRadio();
}
return false;
}
@Override
public boolean isTextbox(IEvalTarget target) {
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
InputType type = element.getInputType();
if (type != null)
return type.isEdit();
}
return false;
}
@Override
public boolean isPassword(IEvalTarget target) {
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
InputType type = element.getInputType();
if (type != null)
return type.isPassword();
}
return false;
}
@Override
public boolean isButton(IEvalTarget target) {
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
InputType type = element.getInputType();
if (type != null)
return type.isButton();
}
return false;
}
private boolean isInTags(IEvalTarget target, HashSet<String> tags) {
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
String name = element.getNodeName();
if (tags.contains(name.intern()))
return true;
}
return false;
}
@Override
public boolean isListTop(IEvalTarget target) {
if (isInTags(target, listTopTags)) {
if (target instanceof Element) {
Element e = (Element) target;
NodeList nl = e.getChildNodes();
int count = 0;
for (int i = 0; i < nl.getLength(); i++) {
Node n = nl.item(i);
if (n instanceof IEvalTarget && isListItem((IEvalTarget) n))
count++;
}
if (count > 1)
return true;
}
}
return false;
}
@Override
public boolean isListItem(IEvalTarget target) {
return isListItemJumpPoint(target);
}
@Override
public boolean isFileEdit(IEvalTarget target) {
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
InputType type = element.getInputType();
if (type != null)
return type.isFileEdit();
}
return false;
}
@Override
public boolean isEmbeddedObject(IEvalTarget target) {
if (target instanceof ElementImpl) {
ElementImpl element = (ElementImpl) target;
String name = element.getLocalName();
if ("EMBED".equals(name) || "OBJECT".equals(name))
return true;
}
return false;
}
@Override
public boolean isImage(IEvalTarget target) {
if (!(target instanceof ElementImpl))
return false;
ElementImpl element = (ElementImpl) target;
String name = element.getLocalName();
return "IMG".equals(name);
}
@Override
public boolean hasContent(IEvalTarget target) {
if (isMultilineEdit(target)) {
if (target instanceof Element) {
return !hasContent((IEvalTarget) ((Element) target)
.getFirstChild());
}
}
if (isInputable(target))
return true;
if (isListTop(target))
return true;
return super.hasContent(target);
}
private static final HashSet<String> reducibleElementNames = new HashSet<String>();
static {
reducibleElementNames.add("FONT".intern());
reducibleElementNames.add("BASEFONT".intern());
reducibleElementNames.add("S".intern());
reducibleElementNames.add("STRIKE".intern());
reducibleElementNames.add("U".intern());
reducibleElementNames.add("EM".intern());
reducibleElementNames.add("STRONG".intern());
reducibleElementNames.add("SPAN".intern());
reducibleElementNames.add("VAR".intern());
reducibleElementNames.add("CODE".intern());
reducibleElementNames.add("CITE".intern());
reducibleElementNames.add("ABBR".intern());
reducibleElementNames.add("ACRONYM".intern());
reducibleElementNames.add("Q".intern());
reducibleElementNames.add("B".intern());
reducibleElementNames.add("BIG".intern());
reducibleElementNames.add("I".intern());
reducibleElementNames.add("SMALL".intern());
reducibleElementNames.add("TT".intern());
reducibleElementNames.add("SUB".intern());
reducibleElementNames.add("SUP".intern());
// non official tag
reducibleElementNames.add("WBR".intern());
}
@Override
public boolean isReducible(IEvalTarget target) {
// Might it be included in the rules?
// if (Vocabulary.isClickable().eval(target)) return false;
if (!(target instanceof ElementImpl))
return false;
ElementImpl element = (ElementImpl) target;
String name = element.getLocalName().intern();
return reducibleElementNames.contains(name);
}
@Override
public boolean isVisitedLink(IEvalTarget target) {
if (!(target instanceof INodeEx))
return false;
INodeEx nex = (INodeEx) target;
String url = nex.getLinkURI();
if (url == null)
return false;
return ComPlugin.getDefault().getBrowserHistory().isVisited(url);
}
@Override
public boolean isHeadingJumpPoint(IEvalTarget target) {
return isJumpPoint(target, headingTags);
}
@Override
public boolean isListItemJumpPoint(IEvalTarget target) {
return isJumpPoint(target, listItemTags);
}
@Override
public boolean isBlockJumpPointF(IEvalTarget target) {
return isJumpPoint(target, blockTags, 3)
|| isJumpPoint2(target, headingTags, 3);
}
@Override
public boolean isBlockJumpPointB(IEvalTarget target) {
return isJumpPoint(target, blockTags, 3)
|| isJumpPoint2(target, headingTags, 3);
}
private boolean isJumpPoint(IEvalTarget target, HashSet<String> tags) {
return isJumpPoint(target, tags, 100);
}
private boolean isJumpPoint(IEvalTarget target, HashSet<String> tags,
int depth) {
if (depth <= 0)
return false;
if (target instanceof Element) {
Element element = (Element) target;
String name = element.getLocalName();
if (tags.contains(name.intern())) {
return true;
}
}
if (!(target instanceof Node))
return false;
Node node = (Node) target;
Node prev = node.getPreviousSibling();
while (prev != null) {
if (hasText(prev)) {
return false;
}
prev = prev.getPreviousSibling();
}
Node parent = node.getParentNode();
if (parent == null)
return false;
if (parent instanceof IEvalTarget) {
return isJumpPoint((IEvalTarget) parent, tags, depth - 1);
}
return false;
}
private boolean isJumpPoint2(IEvalTarget target, HashSet<String> tags,
int depth) {
if (depth <= 0)
return false;
if (target instanceof Element) {
Element element = (Element) target;
String name = element.getLocalName();
if (tags.contains(name.intern())) {
return true;
}
}
if (!(target instanceof Node))
return false;
Node node = (Node) target;
Node parent = node.getParentNode();
if (parent == null)
return false;
if (parent instanceof IEvalTarget) {
return isJumpPoint((IEvalTarget) parent, tags, depth - 1);
}
return false;
}
private boolean hasText(Node prev) {
if (prev instanceof INodeEx) {
INodeEx nex = (INodeEx) prev;
if (nex.hasChildNodes()) {
NodeList list = nex.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
Node cn = list.item(i);
if (hasText(cn))
return true;
}
} else {
if (nex.extractString().length() > 0) {
return true;
}
}
}
return false;
}
@Override
public boolean isAccessKey(char key, IEvalTarget node) {
if (!(node instanceof INodeEx))
return false;
INodeEx nex = (INodeEx) node;
char c = nex.getAccessKey();
return c == key;
}
@Override
public boolean isReachable(IEvalTarget evalTarget, Node target) {
if (!(evalTarget instanceof Node))
return false;
Node node = (Node) evalTarget;
Node a1 = searchNonReducibleAncestor(node);
if (a1 == null)
return false;
Node a2 = searchNonReducibleAncestor(target);
if (a2 == null)
return false;
if (a1.getParentNode() == null)
return false;
if (a2.getParentNode() == null)
return false;
if (!(a1.getParentNode().isSameNode(a2.getParentNode()))) {
return false;
} else {
if (a1 instanceof IEvalTarget && a2 instanceof IEvalTarget) {
IEvalTarget t1 = (IEvalTarget) a1;
IEvalTarget t2 = (IEvalTarget) a2;
if (isLink(t1) && isLink(t2)) {
return true;
}
if (isButton(t1) && isButton(t2)) {
return true;
}
}
}
Node start = node;
Node end = target;
if (end instanceof Text)
end = getPrev(end);
if (end == null)
return false;
Node next = getNext(start);
while (next != null) {
if (!(next instanceof IEvalTarget)) {
next = getNext(next);
continue;
}
if ((!Vocabulary.isReducible().eval((IEvalTarget) next)))
return false;
if (next.isSameNode(end))
break;
next = getNext(next);
}
return true;
}
private Node getPrev(Node node) {
Node prev = node.getPreviousSibling();
if (prev != null)
return prev;
return node.getParentNode();
}
private Node getNext(Node node) {
Node next = node.getNextSibling();
if (next != null)
return next;
return node.getParentNode();
}
private Node searchNonReducibleAncestor(Node node) {
Node child = null;
Node parent = node;
while (parent != null && parent instanceof IEvalTarget
&& (parent instanceof Text || isImage((IEvalTarget) parent))
|| isReducible((IEvalTarget) parent)) {
child = parent;
parent = parent.getParentNode();
}
return child;
}
}