class StringSearcher {

  public static final void findMetaData( Object object, int level, List<StringSearchResult> stringList,
    Object parentObject, Object grandParentObject ) {
    // System.out.println(Const.rightPad(" ", level)+"Finding strings in "+object.toString());

    if ( ( object == null ) || level > 5 ) {
      return;
    }

    PluginRegistry registry = PluginRegistry.getInstance();

    if ( stepPluginPackages == null ) {
      stepPluginPackages = registry.getPluginPackages( StepPluginType.class );
    }
    if ( jobEntryPluginPackages == null ) {
      jobEntryPluginPackages = registry.getPluginPackages( JobEntryPluginType.class );
    }

    Class<? extends Object> baseClass = object.getClass();
    Field[] fields = baseClass.getDeclaredFields();
    for ( int i = 0; i < fields.length; i++ ) {
      Field field = fields[i];

      boolean processThisOne = true;

      if ( ( field.getModifiers() & Modifier.FINAL ) > 0 ) {
        processThisOne = false;
      }
      if ( ( field.getModifiers() & Modifier.STATIC ) > 0 ) {
        processThisOne = false;
      }

      // Investigate only if we're dealing with a sanctioned package.
      // A sanctioned package is either the local package (org.pentaho.di) or
      // a package of one of the plugins.
      //
      boolean sanctionedPackage = false;
      String fieldToString = field.toString();
      if ( fieldToString.indexOf( LOCAL_PACKAGE ) >= 0 ) {
        sanctionedPackage = true;
      }
      for ( int x = 0; x < JAVA_PACKAGES.length && !sanctionedPackage; x++ ) {
        if ( fieldToString.indexOf( JAVA_PACKAGES[x] ) >= 0 ) {
          sanctionedPackage = true;
        }
      }
      for ( int x = 0; x < stepPluginPackages.size() && !sanctionedPackage; x++ ) {
        if ( fieldToString.indexOf( stepPluginPackages.get( x ) ) >= 0 ) {
          sanctionedPackage = true;
        }
      }
      for ( int x = 0; x < jobEntryPluginPackages.size() && !sanctionedPackage; x++ ) {
        if ( fieldToString.indexOf( jobEntryPluginPackages.get( x ) ) >= 0 ) {
          sanctionedPackage = true;
        }
      }
      if ( !sanctionedPackage ) {
        processThisOne = false; // Stay in the sanctioned code-base.
      }

      // Dig into the metadata from here...
      //
      if ( processThisOne ) {
        try {
          Object obj = field.get( object );
          if ( obj != null ) {
            stringSearchInObject( obj, level, stringList, parentObject, grandParentObject, field );
          }
        } catch ( IllegalAccessException e ) {
          // OK, it's private, let's see if we can go there later on using
          // getters and setters...
          // fileName becomes: getFileName();
          // OK, how do we get the value now?
          try {

            Method method = findMethod( baseClass, field.getName() );
            if ( method != null ) {
              // String fullMethod =
              // baseClass.getName()+"."+method.getName()+"()";

              Object string = method.invoke( object, (Object[]) null );
              if ( string != null ) {
                stringSearchInObject( string, level, stringList, parentObject, grandParentObject, field );
              }
            }
          } catch ( Throwable ex ) {
            // Ignore this error silently. If we can't access the method there
            // is nothing you can do about it.
          }
        }
      }
    }
  }

}