| /******************************************************************************* |
| * 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(); |
| } |
| } |
| } |