/** * 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 }