blob: ed7b0debd85f063e59114cebf75175112128a3b5 [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:
* Hisashi MIYASHITA - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.ai.fennec.treemanager.impl;
import java.util.ArrayList;
import org.eclipse.actf.ai.fennec.IFennecService;
import org.eclipse.actf.ai.fennec.FennecException;
import org.eclipse.actf.ai.fennec.FennecInterruptedException;
import org.eclipse.actf.ai.fennec.treemanager.IAccessKeyList;
import org.eclipse.actf.ai.fennec.treemanager.ILocation;
import org.eclipse.actf.ai.fennec.treemanager.ISoundControl;
import org.eclipse.actf.ai.fennec.treemanager.ITreeItem;
import org.eclipse.actf.ai.fennec.treemanager.ITreeManager;
import org.eclipse.actf.ai.fennec.treemanager.IVideoControl;
import org.eclipse.actf.ai.fennec.treemanager.TreeManagerException;
import org.eclipse.actf.ai.fennec.treemanager.TreeManagerInterruptedException;
import org.eclipse.actf.model.dom.dombycom.IFlashNode;
import org.eclipse.actf.util.vocab.IProposition;
import org.eclipse.actf.util.vocab.Vocabulary;
/**
* The main plugin class to be used in the desktop.
*/
public class TreeManagerImpl implements ITreeManager {
private IFennecService fennecService;
public TreeManagerImpl(IFennecService fennecService) {
this.fennecService = fennecService;
}
public int getLevel() throws TreeManagerException {
int i = 0;
ITreeItem ita = getActiveItem();
if (ita == null)
return 0;
while (true) {
ita = ita.getParent();
if (ita == null)
break;
i++;
}
return i;
}
public ITreeItem getActiveItem() throws TreeManagerException {
return fennecService.getLastTreeItem();
}
public ITreeItem[] getSiblings() throws TreeManagerException {
ITreeItem item = getActiveItem();
if (item == null)
return null;
ITreeItem parent = item.getParent();
if (parent == null) {
ITreeItem[] itas = new ITreeItem[1];
itas[0] = getActiveItem();
return itas;
}
return parent.getChildItems();
}
private void initFennecService() throws TreeManagerException {
if (fennecService.getStatus() == IFennecService.NORMAL)
return;
try {
fennecService.initialize();
} catch (FennecInterruptedException e) {
throw new TreeManagerInterruptedException(ITreeManager.UNDONE, e.getMessage(), e);
} catch (FennecException e) {
throw new TreeManagerException(ITreeManager.ERROR, e.getMessage(), e);
}
}
public int initialize() throws TreeManagerException {
initFennecService();
return ITreeManager.NOACTION;
}
private int moveUpdate(ITreeItem target, boolean update) throws TreeManagerException {
try {
return fennecService.moveUpdate(target, update);
} catch (FennecInterruptedException e) {
throw new TreeManagerInterruptedException(ITreeManager.UNDONE, "Failed to update by move.", e);
} catch (FennecException e) {
throw new TreeManagerException(ITreeManager.ERROR, "Failed to update by move.", e);
}
}
private int clickUpdate(ITreeItem target) throws TreeManagerException {
try {
return fennecService.clickUpdate(target);
} catch (FennecInterruptedException e) {
throw new TreeManagerInterruptedException(ITreeManager.UNDONE, "Failed to update by click.", e);
} catch (FennecException e) {
throw new TreeManagerException(ITreeManager.ERROR, "Failed to update by click.", e);
}
}
private int gotoRoot() throws TreeManagerException {
ITreeItem parent = getActiveItem().getParent();
if (parent == null)
return ITreeManager.NOACTION;
while (gotoParent() != ITreeManager.NOACTION)
;
return ITreeManager.MOVED | ITreeManager.LEVEL_CHANGED;
}
public int stay() throws TreeManagerException {
initFennecService();
return getActiveItem().stay();
}
public int click(boolean doClick) throws TreeManagerException {
initFennecService();
ITreeItem item = getActiveItem();
if (doClick)
item.doClick();
return clickUpdate(item);
}
public int gotoParent() throws TreeManagerException {
initFennecService();
ITreeItem parent = getActiveItem().getParent();
if (parent != null) {
int st = moveUpdate(parent, true);
if ((st & ITreeManager.MOVED) != 0)
st |= ITreeManager.LEVEL_CHANGED;
return st;
}
return ITreeManager.NOACTION;
}
public int gotoFirstChild() throws TreeManagerException {
initFennecService();
ITreeItem active = getActiveItem();
ITreeItem[] childItems = active.getChildItems();
if (childItems.length == 0)
return ITreeManager.NOACTION;
int st = moveUpdate(childItems[0], true);
if ((st & ITreeManager.MOVED) != 0)
st |= ITreeManager.LEVEL_CHANGED;
return st;
}
private int gotoLastChild() throws TreeManagerException {
initFennecService();
ITreeItem active = getActiveItem();
ITreeItem[] childItems = active.getChildItems();
if (childItems.length == 0)
return ITreeManager.NOACTION;
int st = moveUpdate(childItems[childItems.length - 1], true);
if ((st & ITreeManager.MOVED) != 0)
st |= ITreeManager.LEVEL_CHANGED;
return st;
}
private int gotoSiblingIndex(int idx) throws TreeManagerException {
initFennecService();
ITreeItem active = getActiveItem();
ITreeItem[] siblingItems = getSiblings();
if ((idx < 0) || (siblingItems.length <= idx) || (active.equals(siblingItems[idx])))
return ITreeManager.NOACTION;
int st = moveUpdate(siblingItems[idx], true);
return st;
}
private int getActiveIndex() throws TreeManagerException {
initFennecService();
return getActiveItem().getNth();
}
public int gotoStartOfSiblings() throws TreeManagerException {
return gotoSiblingIndex(0);
}
public int gotoEndOfSiblings() throws TreeManagerException {
initFennecService();
ITreeItem[] siblingItems = getSiblings();
int st = moveUpdate(siblingItems[siblingItems.length - 1], true);
return st | ITreeManager.MOVED;
}
public int gotoPreviousSibling() throws TreeManagerException {
int idx = getActiveIndex();
return gotoSiblingIndex(idx - 1);
}
public int gotoNextSibling() throws TreeManagerException {
int idx = getActiveIndex();
return gotoSiblingIndex(idx + 1);
}
public int gotoStartOfPage() throws TreeManagerException {
ITreeItem item = getCurrentRootItem();
int st;
st = moveUpdate(item, true);
return ITreeManager.NOACTION;
/*
ITreeItem[] childItems = item.getChildItems();
int st;
if ((childItems != null) && (childItems.length > 0)) {
st = moveUpdate(childItems[0], true);
} else {
st = moveUpdate(item, true);
}
if ((st & ITreeManager.MOVED) != 0)
st |= ITreeManager.LEVEL_CHANGED;
return st;*/
}
public int gotoEndOfPageForFind() throws TreeManagerException {
// TODO
int st;
this.gotoStartOfPage();
do {
st = this.gotoEndOfSiblings();
} while (this.gotoFirstChild() != ITreeManager.NOACTION);
if ((st & ITreeManager.MOVED) != 0)
st |= ITreeManager.LEVEL_CHANGED;
return st;
}
public int gotoEndOfPage() throws TreeManagerException {
// TODO
int st;
this.gotoStartOfPage();
do {
st = this.gotoEndOfSiblings();
} while (this.gotoFirstChild() != ITreeManager.NOACTION);
ITreeItem item = getActiveItem();
while (!Vocabulary.hasReadingContent().eval(item)) {
st = this.traverse(true);
item = getActiveItem();
}
if ((st & ITreeManager.MOVED) != 0)
st |= ITreeManager.LEVEL_CHANGED;
return st;
}
public int gotoPreviousLine() throws TreeManagerException {
// TODO
return ITreeManager.NOACTION;
}
public int gotoNextLine() throws TreeManagerException {
// TODO
return ITreeManager.NOACTION;
}
public int gotoStartOfLine() throws TreeManagerException {
// TODO Auto-generated method stub
return 0;
}
public int gotoEndOfLine() throws TreeManagerException {
// TODO Auto-generated method stub
return 0;
}
private int findItem(boolean back, IProposition proposition) throws TreeManagerException {
try {
ITreeItem item;
int[] pos = getActivePos();
int level = pos.length;
int rc;
if (back) {
// First, traverse to the next item in order to skip the items
// connectable with the current item.
rc = traverse(true);
item = getActiveItem();
if (proposition.eval(item)) {
rc |= ITreeManager.FOUND;
} else {
rc = fennecService.searchBackward(proposition);
}
} else {
// Likewise.
rc = traverse(false);
item = getActiveItem();
if (proposition.eval(item)) {
rc |= ITreeManager.FOUND;
} else {
rc = fennecService.searchForward(proposition);
}
}
if ((rc & ITreeManager.FOUND) == 0) {
setActivePos(pos);
return rc;
}
item = getActiveItem();
if (back) {
// Skip to the interval start.
ITreeItem siblings[] = getSiblings();
int idx = item.getNth();
int st = intervalStart(siblings, idx);
if (idx != st) {
rc |= moveUpdate(siblings[st], false);
}
item = getActiveItem();
}
if (!Vocabulary.hasReadingContent().eval(item)) {
traverse(false);
}
if (level != getLevel()) {
rc |= ITreeManager.LEVEL_CHANGED;
}
return rc;
} catch (FennecInterruptedException e) {
throw new TreeManagerInterruptedException(ITreeManager.UNDONE, "Failed to search.", e);
} catch (FennecException e) {
throw new TreeManagerException(ITreeManager.ERROR, "Failed to search.", e);
}
}
private int[] getActivePos() throws TreeManagerException {
int[] ret = new int[getLevel()];
ITreeItem current = getActiveItem();
int count = ret.length;
while (count > 0) {
ret[count - 1] = current.getNth();
count--;
current = current.getParent();
}
return ret;
}
private int setActivePos(int[] indexes) throws TreeManagerException {
gotoRoot();
ITreeItem item;
int st = ITreeManager.NOACTION;
for (int i = 0; i < indexes.length; i++) {
item = getActiveItem();
ITreeItem[] children = item.getChildItems();
int idx = indexes[i];
if ((children == null) || (idx >= children.length))
break;
st |= moveUpdate(children[idx], true);
}
return st;
}
public int findNext(IProposition proposition) throws TreeManagerException {
return findItem(false, proposition);
}
public int findPrevious(IProposition proposition) throws TreeManagerException {
return findItem(true, proposition);
}
private int traverseForward(ITreeItem active) throws TreeManagerException {
ITreeItem[] childItems = active.getChildItems();
if (childItems.length != 0) {
int st = moveUpdate(childItems[0], false);
return st;
}
int idx = active.getNth();
ITreeItem[] siblings = getSiblings();
if ((idx >= 0) && ((idx + 1) < siblings.length)) {
int st = moveUpdate(siblings[idx + 1], false);
return st;
}
for (int upCount = 1;; upCount++) {
active = getActiveItem();
ITreeItem parent = active.getParent();
if (parent == null) {
for (; upCount > 0; upCount--) {
gotoLastChild();
}
return ITreeManager.NOACTION;
}
if (moveUpdate(parent, false) == ITreeManager.NOACTION) {
throw new TreeManagerException(ITreeManager.ERROR, "Internal Error.");
}
idx = getActiveIndex();
siblings = getSiblings();
if ((idx >= 0) && ((idx + 1) < siblings.length)) {
int st = moveUpdate(siblings[idx + 1], false);
return st;
}
}
}
private int traverseBackward() throws TreeManagerException {
int idx = getActiveIndex();
if (idx <= 0) {
ITreeItem active = getActiveItem();
ITreeItem parent = active.getParent();
if (parent == null)
return ITreeManager.NOACTION;
int st = moveUpdate(parent, false);
return st;
}
ITreeItem[] siblings = getSiblings();
int st = moveUpdate(siblings[idx - 1], false);
for (;;) {
ITreeItem active = getActiveItem();
ITreeItem[] childItems = active.getChildItems();
if (childItems.length == 0)
break;
st |= moveUpdate(childItems[0], false) | ITreeManager.LEVEL_CHANGED;
siblings = getSiblings();
if (siblings.length > 1) {
st |= moveUpdate(siblings[siblings.length - 1], false);
}
}
return st;
}
private int intervalStart(ITreeItem[] siblings, int st) {
for (st = st - 1;; st--) {
if (st < 0)
return 0;
if (!Vocabulary.isConnectable().eval(siblings[st]))
return st + 1;
}
}
private int intervalEnd(ITreeItem[] siblings, int end) {
for (; end < siblings.length; end++) {
if (!Vocabulary.isConnectable().eval(siblings[end]))
return end;
}
return end - 1;
}
public int traverse(boolean back) throws TreeManagerException {
initFennecService();
ITreeItem orig = getActiveItem();
ITreeItem current = orig;
int level = getLevel();
int rc = ITreeManager.NOACTION;
if (back) {
do {
rc = traverseBackward();
current = getActiveItem();
} while ((rc != ITreeManager.NOACTION)
&& (!Vocabulary.hasReadingContent().eval(current)));
ITreeItem siblings[] = getSiblings();
int idx = current.getNth();
int st = intervalStart(siblings, idx);
if (idx != st) {
rc |= moveUpdate(siblings[st], false);
}
} else {
ITreeItem siblings[] = getSiblings();
int idx = current.getNth();
int end = intervalEnd(siblings, idx);
current = siblings[end];
do {
rc = traverseForward(current);
current = getActiveItem();
} while ((rc != ITreeManager.NOACTION)
&& (!Vocabulary.hasReadingContent().eval(current)));
}
if (!orig.equals(current)) {
// rc |= ITreeManager.MOVED;
if (level != getLevel()) {
rc |= ITreeManager.LEVEL_CHANGED;
}
}
return rc;
}
public String[] getActiveStrings() throws TreeManagerException {
initFennecService();
ArrayList al = new ArrayList();
ITreeItem[] siblings = getSiblings();
for (int i = getActiveIndex(); i < siblings.length; i++) {
ITreeItem current = siblings[i];
String str = current.getUIString();
if (str.length() > 0) {
al.add(str);
}
ITreeItem[] childItems = current.getChildItems();
if (childItems.length > 0)
break;
}
return (String[]) al.toArray(new String[0]);
}
public int gotoLeftCell() throws TreeManagerException {
// TODO Auto-generated method stub
return 0;
}
public int gotoRightCell() throws TreeManagerException {
// TODO Auto-generated method stub
return 0;
}
public int gotoUpCell() throws TreeManagerException {
// TODO Auto-generated method stub
return 0;
}
public int gotoDownCell() throws TreeManagerException {
// TODO Auto-generated method stub
return 0;
}
public int getActiveTableInfo() throws TreeManagerException {
// TODO Auto-generated method stub
return 0;
}
public int getActiveTableCellInfo() throws TreeManagerException {
// TODO Auto-generated method stub
return 0;
}
public ITreeItem getCurrentRootItem() throws TreeManagerException {
initFennecService();
ITreeItem parent, current;
current = getActiveItem();
while (true) {
parent = current.getParent();
if (parent == null)
break;
current = parent;
}
return current;
}
public ISoundControl getSoundControl() throws TreeManagerException {
initFennecService();
return fennecService.getSoundControl();
}
public IVideoControl getVideoControl() throws TreeManagerException {
initFennecService();
return fennecService.getVideoControl();
}
public IAccessKeyList getAccessKeyList() throws TreeManagerException {
initFennecService();
return fennecService.getAccessKeyList();
}
public int analyze() throws TreeManagerException {
initFennecService();
try {
return fennecService.analyze();
} catch (FennecException e) {
throw new TreeManagerException(ITreeManager.ERROR, "Failed to analyze", e);
}
}
public ILocation getCurrentLocation() throws TreeManagerException {
initFennecService();
return new LocationImpl(getActivePos());
}
public int moveToLocation(ILocation location) throws TreeManagerException {
initFennecService();
LocationImpl loc = (LocationImpl) location;
int[] pos = loc.getPos();
return setActivePos(pos);
}
public ITreeItem expandWholeTree() throws TreeManagerException {
initFennecService();
try {
return fennecService.expandWholeTree();
} catch (FennecException e) {
throw new TreeManagerException(ITreeManager.ERROR, "Failed to expand the whole tree", e);
}
}
public int skipToAnchor(String target) throws TreeManagerException {
initFennecService();
try {
return fennecService.skipToAnchor(target);
} catch (FennecException e) {
throw new TreeManagerException(ITreeManager.ERROR, "Failed to find the target in the anchors", e);
}
}
public void repairFlash() throws TreeManagerException {
initFennecService();
IFlashNode[] node = fennecService.getFlashTopNodes();
for (int i = 0; i < node.length; i++) {
node[i].repairFlash();
}
}
}