示例#1
0
  /**
   * @param child
   * @param govVector
   * @param objLevel
   * @param govLevel
   * @param classindices
   * @param typeindices
   * @param classname
   * @return NULL if error occurs relating to gorInfo creation, or NULL if object is NOT to be
   *     processed. Otherwise, return a valid ClassTypeInfo object with all appropriate settings.
   */
  protected ClassTypeInfo incrementClassTypeIndices(
      Object child,
      GuiObjectVector govVector,
      int govLevel,
      int objLevel,
      Hashtable classindices,
      Hashtable typeindices,
      String classname) {
    Log.info("GCI: getting child GOR info. GOV level:" + govLevel);
    ClassTypeInfo cti = new ClassTypeInfo();
    final String TOOLTIP_SUFFIX = "TOOLTIP";
    cti.classname = classname;
    try {
      cti.gorInfo = govVector.getChildGuiObjectRecognition(govLevel);
    } catch (ArrayIndexOutOfBoundsException x) {
      Log.debug(
          "GCI: sought govLevel:"
              + govLevel
              + ", exceeds 0-based recognition path information:"
              + govVector.getPathVector());
      return null;
    }
    GuiClassData classdata = govVector.getGuiClassData();
    cti.typeclass = classdata.getMappedClassType(classname, child);

    // bypass panels that harbor tooltip(s)
    Object tooltip = null;
    String tooltipclass = null;
    String tooltipmapped = null;
    String gortypeclass = cti.gorInfo.getClassValue();
    // only perform check if we are NOT looking for a tooltip
    if ((gortypeclass == null)
        || (gortypeclass != null && !gortypeclass.toUpperCase().endsWith(TOOLTIP_SUFFIX))) {
      try {
        Log.info("GCI.incrementClassTypeIndices evaluating possible TOOLTIP container...");
        if (classdata.isToolTipContainerType(cti.typeclass)) {
          Object[] childsChildren = govVector.getChildObjects(child);
          if (childsChildren != null && childsChildren.length > 0) {
            tooltip = childsChildren[0];
            tooltipclass = cti.gorInfo.getObjectClassName(tooltip);
            try {
              if (tooltipclass.toUpperCase().endsWith(TOOLTIP_SUFFIX)) {
                Log.info("GCI.incrementClassTypeIndices bypassing active TOOLTIP class!");
                return null; // skip panel with tooltip
              }
              tooltipmapped = classdata.getMappedClassType(tooltipclass, tooltip);
              if (tooltipmapped.toUpperCase().endsWith(TOOLTIP_SUFFIX)) {
                Log.info("GCI.incrementClassTypeIndices bypassing active TOOLTIP type!");
                return null; // skip panel with tooltip
              }
            } catch (Exception x) {
              Log.debug(
                  "GCI.incrementClassTypeIndices ToolTip test IGNORING "
                      + x.getClass().getSimpleName());
            }
          }
        }
        Log.info("GCI.incrementClassTypeIndices container NOT a TOOLTIP container.");
      } catch (Exception x) {
        Log.debug(
            "GCI.incrementClassTypeIndices ToolTip Container test IGNORING "
                + x.getClass().getSimpleName());
      }
    }
    // increment class index counters for the retrieved class?
    Log.info("GCI: incrementing class indices for:" + classname);
    Integer classindex = (Integer) classindices.get(classname);
    classindex = (classindex == null) ? new Integer(1) : new Integer(classindex.intValue() + 1);
    classindices.put(classname, classindex);
    cti.classindex = classindex.intValue();
    Log.info("GCI: classindices.put(" + classname + ", " + classindex + ")");

    Integer absclassindex = (Integer) absindices.get(classname);
    absclassindex =
        (absclassindex == null) ? new Integer(1) : new Integer(absclassindex.intValue() + 1);
    absindices.put(classname, absclassindex);
    cti.absoluteclassindex = absclassindex.intValue();
    Log.info("GCI: absindices.put(" + classname + ", " + absclassindex + ")");

    // also increment the Type index counter if it is equivalent to a known type
    String gorClassType = cti.gorInfo.getClassValue();
    Log.info("GCI: " + classname + " mappedClassType: " + cti.typeclass);
    Integer typeindex = new Integer(0);
    Integer abstypeindex = new Integer(0);

    if (cti.typeclass instanceof String) {
      StringTokenizer toker = new StringTokenizer(cti.typeclass, classdata.DEFAULT_TYPE_SEPARATOR);
      String atoken = null;
      Integer tmptypeindex = null;
      Integer tmpabstypeindex = null;

      while (toker.hasMoreTokens()) {
        atoken = toker.nextToken().toUpperCase().trim();
        tmptypeindex = (Integer) typeindices.get(atoken);
        Log.info("GCI: getting: " + atoken + ", " + tmptypeindex);
        tmptypeindex =
            (tmptypeindex == null) ? new Integer(1) : new Integer(tmptypeindex.intValue() + 1);
        Log.index(
            "GCI: ... "
                + StringUtils.getSpaces(new Integer(objLevel))
                + atoken
                + ":"
                + tmptypeindex);
        typeindices.put(atoken, tmptypeindex);
        tmpabstypeindex = (Integer) absindices.get(atoken);
        tmpabstypeindex =
            (tmpabstypeindex == null)
                ? new Integer(1)
                : new Integer(tmpabstypeindex.intValue() + 1);
        absindices.put(atoken, tmpabstypeindex);
        Log.info("TYPE:absindices.put(" + atoken + ", " + tmpabstypeindex + ")");

        // use the correct typeindex for the classtype that matches recognition string
        if (atoken.equalsIgnoreCase(gorClassType)) {
          typeindex = tmptypeindex;
          cti.typeindex = typeindex.intValue();
          abstypeindex = tmpabstypeindex;
          cti.absolutetypeindex = abstypeindex.intValue();
        }
      }
    }
    return cti;
  }
示例#2
0
  /**
   * Called internally by processChildren only.
   *
   * <p>
   *
   * @param children -- array of child objects to examine to see if any one of them satisfies the
   *     piece of the recognition string for the current object vector level--the current substring
   *     of the full recognition string. May be array of cached keys if GuiObjectVector is in
   *     EXTERNAL_PROCESSING_MODE.
   *     <p>
   * @param govVector -- the currently active GuiObjectVector.
   *     <p>
   * @param govLevel -- the hierarchy level (current substring)in the GuiObjectVector we are trying
   *     to satisfy.
   *     <p>
   * @param objLevel -- the depth in the actual application's object hierarchy currently being
   *     searched.
   *     <p>
   * @param entry_classindices -- the storage for class counts.
   *     <p>
   * @param entry_typeindices -- the storage for object type counts.
   *     <p>
   * @param onlyOneChildVisible -- true if parent is a TabControl-like component,
   */
  protected void processNextLevel(
      Object[] children, // children\key array to process
      GuiObjectVector govVector, // the full recognition vector
      int govLevel, // depth within the vector to process
      int objLevel, // depth within obj hierarchy being processed
      Hashtable entry_classindices, // class=count storage for class indices
      Hashtable entry_typeindices, // class=count storage for object indices
      boolean onlyOneChildVisible) { // if true, parent is tab
    boolean notDone = true;

    Hashtable classindices = entry_classindices;
    Hashtable typeindices = entry_typeindices;
    Hashtable save_classindices = (Hashtable) entry_classindices.clone();
    Hashtable save_typeindices = (Hashtable) entry_typeindices.clone();

    for (int i = 0; ((notFound) && (notDone) && (i < children.length)); i++) {

      Object _child = null;
      Object child = null;
      Object[] childsChildren = new Object[0];

      // reset indices for all but the last level of searching:
      // when dealing with things like TabControls with non-visible panels
      // and in CLASSIC_SEARCH_MODE.
      // In FULLPATH_SEARCH_MODE these hidden panels get unique indices
      if ((govLevel < govVector.getRecognitionDepth() - 1 && onlyOneChildVisible)
          && (SEARCH_MODE != FULLPATH_SEARCH_MODE)) {
        if (i > 0) {
          Log.info(".....class/type indices reset for all but the last level of searching");
          classindices = (Hashtable) save_classindices.clone();
          typeindices = (Hashtable) save_typeindices.clone();
        }
      }

      // get next child and reset index counters
      // only play with GuiTestObjects
      Log.info("GCI: Seeking child(" + i + ")outof(" + children.length + ")...");
      _child = children[i];
      child = _child;
      if (!govVector.isValidGuiObject(_child)) {
        Log.debug("GCI: skipping invalid Gui Object found in child array.");
        continue;
      }
      Log.info("GCI: child(" + i + ") is a valid GUI object.");

      if (govVector.getProcessMode() == GuiObjectVector.MODE_EXTERNAL_PROCESSING) {
        try {
          child = govVector.getCachedItem(_child);
        } catch (Exception e) {
        }
      }
      GuiObjectRecognition gor = govVector.getParentGuiObjectRecognition();
      String classname = gor.getObjectClassName(child);
      ClassTypeInfo typeinfo = null;

      // **** if (! classname.equalsIgnoreCase("Html.!")) { // this kills IE
      Log.info("GCI: child classname is:" + classname);

      // check to see if it is visible
      if (!gor.isObjectShowing(child)) {

        // if not, skip it if it is a container (like a TabControl Panel)
        Log.info("GCI: child is not showing.");
        if (govVector.isValidGuiContainer(_child)) {
          if (govVector.isFullPathSearchMode()) {
            incrementClassTypeIndices(
                child, govVector, govLevel, objLevel, classindices, typeindices, classname);
          }
          Log.info("GCI: skipping non-visible Gui Container: " + classname);
          continue;
        }
      }
      // } end if classname == "Html.!"
      typeinfo =
          incrementClassTypeIndices(
              child, govVector, govLevel, objLevel, classindices, typeindices, classname);
      if (typeinfo == null) continue; // invalid gorInfo at this level

      int classindex = typeinfo.classindex;
      int typeindex = typeinfo.typeindex;
      int abstypeindex = typeinfo.absolutetypeindex;
      String typeclass = typeinfo.typeclass;
      GuiObjectRecognition gorInfo = typeinfo.gorInfo;

      // classname  will ALWAYS have a class value
      // classindex will ALWAYS be at least 1
      // typeclass MAY BE null if we can't match the type
      // typeindex MAY BE  0   if we can't match the type
      int passindex, abspassindex;
      if (gorInfo.getClassCategoryID() == gorInfo.CATEGORY_CLASS_ID) {
        passindex = classindex;
        abspassindex = typeinfo.absoluteclassindex;
      }
      // TYPE is only alternative to CLASS right now
      else {
        passindex = typeindex;
        abspassindex = abstypeindex;
      }
      // see if we match the object at this level
      boolean classMatch;
      try {
        String[] tmpName = null;
        if (gather != null) tmpName = new String[1];
        classMatch =
            gorInfo.isMatchingObject(
                child, passindex,
                abspassindex, tmpName);

        // this is a special case test when we are doing this algorithm
        // but we want to gather *ALL* of the names which match, rather
        // than just the first name.  In that event, the parameter
        // 'gather' is used.  If not null, then don't let 'classMatch' get
        // beyond this place as 'true', but instead, stuff the name
        // into the List 'gather' and use 'false' for the classMatch...
        if (gather != null) {
          if (tmpName != null && tmpName[0] != null) {
            Log.info(" .....  ADD TO GATHER: " + tmpName[0]);
            gather.add(tmpName[0]);
          } else { // maybe use the index
            Log.info(
                " .....  GATHER INDEX?? passindex, abspassindex: "
                    + passindex
                    + ", "
                    + abspassindex
                    + ", classmatch would be: "
                    + classMatch);
          }
          // if we are gathering then lets also gather matched child objects
          if (classMatch) {
            // for recognitions with Path=, we must get that object
            // this is primarily used when we want ALL possible objects of
            // a given type.  For example, all HTMLLinks on a page.
            Object matchObject = gorInfo.getMatchingObject(child);
            MatchData adata = new MatchData(govVector, govLevel, objLevel, matchObject);
            matches.addElement(adata);
          }
          classMatch = false;
        }
      } catch (SAFSObjectRecognitionException ore) {
        classMatch = false;
        Log.debug(ore.getMessage());
      }

      if (classMatch) {
        // see if we have matched to the last object vector recognition level
        notDone = (govLevel < (govVector.getRecognitionDepth() - 1));
        Log.debug(
            "GCI: notDone matching vector: "
                + notDone
                + " :govLevel="
                + govLevel
                + ", maxLevel="
                + (govVector.getRecognitionDepth() - 1)
                + ", path="
                + govVector.getPathVector());
        if (notDone) {
          // see if this child has some children
          try {
            int lenchildren =
                (typeinfo.childsChildren != null)
                    ? typeinfo.childsChildren.length
                    : govVector.getChildObjects(child).length;
            if (lenchildren > 0) {
              // Log.index("notDone: processChildren: "+(objLevel+1));
              if (SEARCH_MODE == FULLPATH_SEARCH_MODE) {
                processChildren(
                    child,
                    govVector,
                    govLevel + 1,
                    objLevel + 1,
                    save_classindices,
                    save_typeindices,
                    typeclass);
              } else { // assume CLASSIC_SEARCH_MODE
                processChildren(
                    child,
                    govVector,
                    govLevel + 1,
                    objLevel + 1,
                    classindices,
                    typeindices,
                    typeclass);
              }
            }
            // if there are no children, then we are done going down this branch
            // and this path will not be a match for our recognition string
            else {
              // signal this branch is done
              // should this just be a continue?
              Log.debug("GCI: Branch completed. 0 children for " + gorInfo);
              notDone = false;
            }
            // signal this branch is done if no children (exception thrown for .length)
          } catch (Exception np) {
            Log.debug("GCI: Branch completed. NullPointer/No children for " + gorInfo, np);
            notDone = false;
          }
        }
        // **************************************************************
        // **** see if this is THEE child that completes our search! ****
        // **************************************************************
        else {
          hasFinalMatch = gorInfo.isFinalMatch(child);
          notFound = !hasFinalMatch;
          // for recognitions with Path=, we must get that object
          Object matchObject = gorInfo.getMatchingObject(child);
          // removing this unregister because currently unregistering any one reference
          // to an object seems to unregister ALL stored references to an object,
          // including cached references in our AppMaps.
          // // must unregister child if a subitem was actually the finalObject
          // if( !(matchObject == child)) {
          //   Log.debug("RGCI: Unregistering parent "+ child.getObjectClassName() +" from JVM as
          // needed.");
          //   child.unregister();
          // }
          //
          MatchData adata = new MatchData(govVector, govLevel, objLevel, matchObject);
          matches.addElement(adata);
        }
      }
      // not a class match for this object
      // we have to handle looking for the nth match inside a container
      // if not complete match, see if the match is farther down the hierarchy
      // but only for the CLASSIC_SEARCH_MODE.
      // We do not go down hierarchy paths for FULLPATH_SEARCH_MODE if the parent did not match
      else if (SEARCH_MODE
          != FULLPATH_SEARCH_MODE) { // will be CLASSIC_SEARCH_MODE (or anything else) by default
        // Log.index("processChildren: "+(objLevel+1));
        processChildren(
            child, govVector, govLevel, objLevel + 1, classindices, typeindices, typeclass);
      }
    } // end FOR LOOP
  }
示例#3
0
  /**
   * Called only once by some external routine kicking off a TestObject search. The govLevel and
   * objLevel in the ObjectVector will be assumed to be 0. The routine will install an initial class
   * and type indices for the provided parent.
   *
   * <p>If we can deduce that the parent actually exists in the path vector then that govLevel of
   * the vector will be matched and skipped. If we find that the parent info is NOT in the provided
   * vector then we will not skip the govLevel.
   *
   * <p>We can assume the parent info is in the path if the path begins with "\;". The next item in
   * the path is assumed to be the topmost parent.
   *
   * <p>We can ignore the first path info if it instead begins with ".\;". The next item would be
   * considered to be the first child of the parent.
   *
   * <p>
   *
   * @param aparent the topmost parent to search.
   *     <p>
   * @param agovVector the govVector (recognition string) to satisfy with the search.
   *     <p>
   * @param gather, List containing names matched, if null, then match first name
   */
  public GuiChildIterator(Object aparent, GuiObjectVector agovVector, java.util.List gather) {
    this(gather);
    if (agovVector.isFullPathSearchMode()) {
      setSearchMode(FULLPATH_SEARCH_MODE);
    } else {
      setSearchMode(CLASSIC_SEARCH_MODE);
    }
    Hashtable classindices = new Hashtable(8);
    Hashtable typeindices = new Hashtable(8);
    matches = new Vector(10, 3);
    notFound = true;
    hasFinalMatch = false;

    // class (ex: JFrame) and Type (ex: Window) counters are complimentary
    // for each class that is a known type BOTH counters get incremented.

    // always initialize class index counters for the retrieved class

    // it is possible this "parent" info is actually info for the first child govLevel 0
    GuiObjectRecognition gorParent = agovVector.getParentGuiObjectRecognition();
    GuiClassData classdata = agovVector.getGuiClassData();

    String classname = gorParent.getObjectClassName(aparent);
    Log.info("GCI: processing children of parent:" + classname);
    classindices.put(classname, new Integer(1));

    // always initialize the Type index counter if it is equivalent to a known type
    String typeclass = classdata.getMappedClassType(classname, aparent);
    Log.info("GCI: processing parent of type:" + typeclass);
    if (typeclass instanceof String) {
      StringTokenizer toker = new StringTokenizer(typeclass, classdata.DEFAULT_TYPE_SEPARATOR);
      String atoken = null;
      while (toker.hasMoreTokens()) {
        atoken = toker.nextToken().trim();
        typeindices.put(atoken, new Integer(1));
      }
    }

    // add our entry govVector and parent object as the first match
    // CANAGL - modifying to only store finalMatches
    // MatchData adata = new MatchData(agovVector, 0, 0, aparent);
    // matches.addElement(adata);

    int agovDepth = agovVector.getRecognitionDepth();
    Log.info(
        "GCI: processing GOV with depth of:" + agovDepth + ", path=" + agovVector.getPathVector());

    // begin the reentrant search for the matching child
    int startlevel = (agovDepth > 1) ? 1 : 0;
    if ((gorParent.getGovLevel() == 0)
        && (!(gorParent.pathInfo.equals(GuiObjectVector.ACTIVE_WINDOW_REFERENCE)))) {

      // Robot Java recognition strings often contain a JavaWindow reference
      // to the parent window that needs to be skipped.	Same with Flex recognition strings(JunwuMa).
      if (!gorParent.getClassRecognition().equalsIgnoreCase("Type=JavaWindow")
          && !gorParent.getClassRecognition().equalsIgnoreCase("Type=FlexWindow")) {
        startlevel = 0;
      } else {
        Log.info(
            "GCI: bypassing govLevel=0 for child 'Type=JavaWindow'. Assuming duplicate parent info.");
      }
    }
    // Try to match the parent for some popupmenu
    Hashtable save_classindices = (Hashtable) classindices.clone();
    Hashtable save_typeindices = (Hashtable) typeindices.clone();

    processParent(aparent, agovVector, startlevel, 1, classindices, typeindices, typeclass);
    Object matchedObject = this.getMatchedGuiObject();

    if (matchedObject == null) {
      if (SEARCH_MODE != FULLPATH_SEARCH_MODE) {
        Log.info("GCI: CLASSIC_SEARCH_MODE calling processChildren...");
        processChildren(aparent, agovVector, startlevel, 1, classindices, typeindices, typeclass);
      } else {
        Log.info("GCI: FULLPATH_SEARCH_MODE calling processChildren...");
        processChildren(
            aparent, agovVector, startlevel, 1, save_classindices, save_typeindices, typeclass);
      }
    }
  }