Logo Search packages:      
Sourcecode: javahelp2 version File versions  Download package

HelpUtilities.java

/*
 * @(#)HelpUtilities.java     1.56 06/10/30
 * 
 * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 * 
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 * 
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 * 
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.help;

import java.net.URL;

import java.io.InputStream;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Vector;

import java.beans.BeanInfo;
import java.beans.Introspector;

import java.text.CollationElementIterator;
import java.text.Collator;
import java.text.MessageFormat;
import java.text.RuleBasedCollator;

import java.awt.Component;
import java.awt.IllegalComponentStateException;


/**
 * Provides a number of utility functions:
 *
 * Support for Beans, mapping from a Bean class to its HelpSet and to
 * its ID.
 * Support for finding localized resources.
 * Support for getting the default Query Engine
 *
 * This class has no public constructor.
 *
 * @author Eduardo Pelegri-Llopart
 * @author Roger D. Brinkley
 * @version 1.56  10/30/06
 */

00068 public class HelpUtilities {

    //=========

    /**
     * Beans support
     */

    /**
     * Given the class for a bean, get its HelpSet.
     * Returns the helpSetName property of the BeanDescriptor if defined.
     * Otherwise it returns a name as follows:
     * If the class is in the unnamed package, it returns <em>beanClassName</em>Help.hs.
     * Otherwise if it's in the form <em>package.ClassName</em> it returns
     * <em>package</em>/Help.hs after replacing "." with "/" in <em>package</em>.
     *
     * @param beanClass The Class
     * @return A String with the name of the HelpSet
     */

00088     public static String getHelpSetNameFromBean(Class beanClass) {
      String helpSetName;
      try {
          BeanInfo bi = Introspector.getBeanInfo(beanClass);
          helpSetName =
            (String) bi.getBeanDescriptor().getValue("helpSetName");
      } catch (Exception ex) {
          helpSetName = null;
      }
      if (helpSetName == null) {
          String className = beanClass.getName();
          int index = className.lastIndexOf(".");
          if (index == -1) {
            // unnamed package
            helpSetName = className + "Help.hs";
          } else {
            String packageName = className.substring(0, index);
            helpSetName = packageName.replace('.','/') + "/Help.hs";
          }
      }
      return helpSetName;
    }

    /**
     * Given the class for a bean, get its ID string.
     * Returns the helpID property of the BeanDescriptor if defined,
     * otherwise it returns <em>beanName</em>.topID.
     *
     * @param beanClass the Class
     * @return A String with the ID to use
     */

00120     public static String getIDStringFromBean(Class beanClass) {
      String helpID;
      try {
          BeanInfo bi = Introspector.getBeanInfo(beanClass);
          helpID = (String) bi.getBeanDescriptor().getValue("helpID");
      } catch (Exception ex) {
          helpID = null;
      }
      if (helpID == null) {
          String className = beanClass.getName();
          helpID = className + ".topID";
      }
      return helpID;
    }


    //=======
    /**
     * Default for the search engine
     */
00140     public static String getDefaultQueryEngine() {
      return "com.sun.java.help.search.DefaultSearchEngine";
    }

    //========

    /**
     * I18N/ L10N support
     */

    /**
     * Search for a helpset file following the standard conventions
     * used in ResourceBundle.
     */

    /**
     * Locate a resource relative to a given classloader CL.
     * The name of the resource is composed by using FRONT,
     * adding _LANG _COUNTRY _VARIANT (with the usual rules)
     * and ending with BACK, which will usually be an extension
     * like ".hs" for a HelpSet, or ".class" for a class
     *
     * This method is a convenience method for getLocalizedResource() with
     * a tryRead parameter set to false.
     *
     * This functionality should likely be exposed as part of JDK1.2
     * @param cl The ClassLoader to get the resource from. If cl is null the default 
     * ClassLoader is used.
     * @returns the URL to the localized resource or null if not found.
     */
00170     public static URL getLocalizedResource(ClassLoader cl,
                                 String front,
                                 String back,
                                 Locale locale) {
      return getLocalizedResource(cl, front, back, locale, false);
    }

    /**
     * Locate a resource relative to a given classloader CL.
     * The name of the resource is composed by using FRONT,
     * adding _LANG _COUNTRY _VARIANT (with the usual rules)
     * and ending with BACK, which is usually an extension
     * like ".hs" for a HelpSet, or ".class" for a class
     *
     * This version accepts an explicit argument to work around some browser bugs.
     * 
     * This functionality should likely be exposed as part of JDK1.2
     * @param cl The ClassLoader to get the resource from. If cl is null the default
     * ClassLoader is used.
     * @returns the URL to the localized resource or null if not found.
     */
00191     public static URL getLocalizedResource(ClassLoader cl,
                                 String front,
                                 String back,
                                 Locale locale,
                                 boolean tryRead) {
      URL url;
      for (Enumeration tails = getCandidates(locale);
           tails.hasMoreElements(); ) {
          String tail = (String) tails.nextElement();
          String name   = (new StringBuffer(front)).append(tail).append(back).toString();
          if (cl == null) {
            url = ClassLoader.getSystemResource(name);
          } else {
            url = cl.getResource(name);
          }
          if (url != null) {
            if (tryRead) {
                // Try doing an actual read to be sure it exists
                try {
                  InputStream is = url.openConnection().getInputStream();
                  if (is != null) {
                      int i = is.read();
                      is.close();
                      if (i != -1) {
                        return url;
                      }
                  }
                } catch (Throwable t) {
                    // ignore and continue looking
                }
            } else {
                return url;
            }
          }
      }
      return null;
    }

    private static Hashtable tailsPerLocales = new Hashtable();

    /**
     * This returns an enumeration of String tails. 
     * 
     * The core functionality on which getLocalizedResource is based.
     *
     * The suffixes are based on (1) the desired locale and (2) the default locale
     * in the following order from lower-level (more specific) to parent-level
     * (less specific):
     * <p>  "_" + language1 + "_" + country1 + "_" + variant1
     * <BR> "_" + language1 + "_" + country1
     * <BR> "_" + language1
     * <BR> ""
     * <BR> "_" + language2 + "_" + country2 + "_" + variant2
     * <BR> "_" + language2 + "_" + country2
     * <BR> "_" + language2
     *
     * The enumeration is of StringBuffer.
     * We pay some attention to efficiency in case a method like this is promoted,
     * hence we cache per locale.
     */

00252     public static synchronized Enumeration getCandidates(Locale locale) {
      Vector tails;
      LocalePair pair = new LocalePair(locale, Locale.getDefault());
      tails = (Vector) tailsPerLocales.get(pair);
      if (tails != null) {
          debug("getCandidates - cached copy");
          return tails.elements();
      }

      String lname1 = locale.toString();
      StringBuffer name1 = new StringBuffer("_").append(lname1);
      if (lname1 == null) {
          name1.setLength(0);
      }
      tails = new Vector();
      // Now add them to the vector
      while (name1.length() != 0) {
          debug("  adding ", name1);
          String s = name1.toString();
          tails.addElement(s);
          int lastUnder = s.lastIndexOf('_');
          if (lastUnder != -1) {
            name1.setLength(lastUnder);
          }
      }
      debug("  addign -- null -- ");
      tails.addElement("");
      if (locale != Locale.getDefault()) {
          // Otherwise, no need to search twice
          String lname2 = Locale.getDefault().toString();
          StringBuffer name2 = new StringBuffer("_").append(lname2);
          if (lname2 == null) {
            name2.setLength(0);
          }
          while (name2.length() != 0) {
            debug("  adding ", name2);
            String s = name2.toString();
            tails.addElement(s);
            int lastUnder = s.lastIndexOf('_');
            if (lastUnder != -1) {
                name2.setLength(lastUnder);
            }
          }
      }
      tailsPerLocales.put(pair, tails);
      debug("tails is == ", tails);
      return tails.elements();
    }

    /**
     * Auxiliary class used in dealing with locale.
     */
    
00305     static class LocalePair {
      LocalePair(Locale locale1, Locale locale2) {
          this.locale1 = locale1;
          this.locale2 = locale2;
      }
      
      public int hashCode() {
          return locale1.hashCode() + locale2.hashCode();
      }
      
      public boolean equals(Object obj) {
          if (obj == null || ! (obj instanceof LocalePair)) {
            return false;
          } else {
            LocalePair p = (LocalePair) obj;
            return locale1.equals(p.locale1) && locale2.equals(p.locale2);
          }
      }
      
      Locale locale1;
      Locale locale2;
    }

    // ==========

    /**
     * Get a localized Error String
     */
00333     private static Hashtable bundles;
    private static ResourceBundle lastBundle = null;
    private static Locale lastLocale = null;

    /**
     * Gets the locale of a component. If the component is null
     * it returns the defaultLocale. If the call to component.getLocale
     * returns an IllegalComponentStateException, the defaultLocale is
     * returned.
     */
00343     public static Locale getLocale(Component c) {
      if (c == null) {
          return Locale.getDefault();
      }
      try {
          return c.getLocale();
      } catch (IllegalComponentStateException ex) {
          return Locale.getDefault();
      }
            
    }

    static synchronized private ResourceBundle getBundle(Locale l) {
      if (lastLocale == l) {
          return lastBundle;
      }
      if (bundles == null) {
          bundles = new Hashtable();
      }
      ResourceBundle back = (ResourceBundle) bundles.get(l);
      if (back == null) {
          try {
            back = ResourceBundle.getBundle("javax.help.resources.Constants",
                                    l);
          } catch (MissingResourceException ex) {
            throw new Error("Fatal: Resource for javahelp is missing");
          }
          bundles.put(l, back);
      }
      lastBundle = back;
      lastLocale = l;
      return back;
    }


    /**
     * Get the Text message for the default locale.
     *
     * The getString version does not involve a format.
     */
00383     static public String getString(String key) {
      return getString(Locale.getDefault(), key);
    }

    static public String getText(String key) {
      return getText(Locale.getDefault(), key, null, null);
    }

    /**
     * @param s1 The first parameter of a string. A null is valid for s1.
     */
00394     static public String getText(String key, String s1) {
      return getText(Locale.getDefault(), key, s1, null);
    }

    /**
     * @param s1 The first parameter of a string. A null is valid for s1.
     * @param s2 The first parameter of a string. A null is valid for s2.
     */
00402     static public String getText(String key, String s1, String s2) {
      return getText(Locale.getDefault(), key, s1, s2);
    }

    /**
     * @param s1 The first parameter of a string. A null is valid for s1.
     * @param s2 The first parameter of a string. A null is valid for s2.
     * @param s3 The first parameter of a string. A null is valid for s3.
     */
00411     static public String getText(String key, String s1, String s2, String s3) {
      return getText(Locale.getDefault(), key, s1, s2, s3);
    }

    /**
     * Versions with an explicit locale.
*/
00418     static public String getString(Locale l, String key) {
      ResourceBundle bundle = getBundle(l);
      try {
          return bundle.getString(key);
      } catch (MissingResourceException ex) {
          throw new Error("Fatal: Localization data for JavaHelp is broken.  Missing "+key+" key.");
      }
    }

    static public String[] getStringArray(Locale l, String key) {
      ResourceBundle bundle = getBundle(l);
      try {
          return bundle.getStringArray(key);
      } catch (MissingResourceException ex) {
          throw new Error("Fatal: Localization data for JavaHelp is broken.  Missing "+key+" key.");
      }
    }

    /**
     * @param s1 The first parameter of a string. A null is valid for s1.
     * @param s2 The first parameter of a string. A null is valid for s2.
     * @param s3 The first parameter of a string. A null is valid for s3.
     */
00441     static public String getText(Locale l, String key) {
      return getText(l, key, null, null, null);
    }

    /**
     * @param s1 The first parameter of a string. A null is valid for s1.
     */
00448     static public String getText(Locale l, String key, String s1) {
      return getText(l, key, s1, null, null);
    }

    /**
     * @param s1 The first parameter of a string. A null is valid for s1.
     * @param s2 The first parameter of a string. A null is valid for s2.
     */
00456     static public String getText(Locale l, String key, String s1, String s2) {
      return getText(l, key, s1, s2, null);
    }

    /**
     * @param s1 The first parameter of a string. A null is valid for s1.
     * @param s2 The first parameter of a string. A null is valid for s2.
     * @param s3 The first parameter of a string. A null is valid for s3.
     */
00465     static public String getText(Locale l, String key,
                         String s1, String s2, String s3) {
      ResourceBundle bundle = getBundle(l);
      // workaround bugs in JDK 1.1.6
      // This mimic's what JDK 1.2 will do.
      if (s1 == null) {
          s1 = "null";
      }
      if (s2 == null) {
          s2 = "null";
      }
      if (s3 == null) {
          s3 = "null";
      }
      // end workaround
      try {
          String fmt = bundle.getString(key);
          String[] args = {s1, s2, s3};
          MessageFormat format = new MessageFormat(fmt);
          // workaround a bug in MessageFormat.setLocale
          try {
            format.setLocale(l);
          } catch (NullPointerException ee) {
          }
          return format.format(args);
      } catch (MissingResourceException ex) {
          throw new Error("Fatal: Localization data for JavaHelp is broken.  Missing "+key+" key.");
      }
    }

    /**
     * Convenient method for creating a locale from a <tt>lang</tt> string.
     * Takes the <tt>lang</tt> string in the form of "language_country_variant"
     * or "language-country-variant" and 
     * parses the string and creates an appropriate locale.
     * @param lang A String representation of a locale, with the language, 
     * country and variant separated by underbars. Language is always lower
     * case, and country is always upper case. If the language is missing the
     * String begins with an underbar. If both language and country fields are
     * missing, a null Locale is returned. If lang is null a null Locale is 
     * returned
     * @returns The locale based on the string or null if the Locale could
     * not be constructed or lang was null.
     */
00509     public static Locale localeFromLang(String lang) {
      String language;
      String country;
      String variant=null;
      Locale newlocale=null;
      if (lang == null) {
          return newlocale;
      }
      int lpt = lang.indexOf("_");
      int lpt2 = lang.indexOf("-");
      if (lpt == -1 && lpt2 == -1) {
          language = lang;
          country = "";
          newlocale = new Locale(language, country);
      } else {
          if (lpt == -1 && lpt2 != -1) {
            lpt = lpt2;
          }
          language = lang.substring(0, lpt);
          int cpt = lang.indexOf("_", lpt+1);
          int cpt2 = lang.indexOf("-", lpt+1);
          if (cpt == -1 && cpt2 == -1) {
            country = lang.substring(lpt+1);
            newlocale = new Locale(language, country);
          } else {
            if (cpt == -1 && cpt2 != -1) {
                cpt = cpt2;
            }
            country = lang.substring(lpt+1, cpt);
            variant = lang.substring(cpt+1);
            newlocale = new Locale(language, country, variant);
          }
      }
      return newlocale;
    }

    /**
     * Returns information about whether a string is 
     * contained in another string. Compares the character data stored in two 
     * different strings based on the collation rules. 
     */
00550     public static boolean isStringInString(RuleBasedCollator rbc, 
                                 String source,
                                 String target) {
        // The basic algorithm here is that we use CollationElementIterators
        // to step through both the source and target strings.  We compare each
        // collation element in the source string against the corresponding one
        // in the target, checking for differences.
        //
        // If a difference is found, we set <result> to false.
        //
        // However, it's not that simple.  If we find a tertiary difference
        // (e.g. 'A' vs. 'a') near the beginning of a string, it can be
        // overridden by a primary difference (e.g. "A" vs. "B") later in
        // the string.  For example, "AA" < "aB", even though 'A' > 'a'.
        //
        // To keep track of this, we use strengthResult to keep track of the
        // strength of the most significant difference that has been found
        // so far.  When we find a difference whose strength is greater than
        // strengthResult, it overrides the last difference (if any) that
        // was found.

      debug("isStringInString source=" + source + " targe =" + target); 
          
      // Initial sanity checks
      if (source == null || target == null) {
          return false;
      }
      if (source.length() == 0 && target.length() == 0) {
          return true;
      }

      // on to the real code
        int strengthResult = Collator.IDENTICAL;
        CollationElementIterator sourceCursor, targetCursor;
      boolean isFrenchSec = false;

      // set up the RuleBasedCollator and extract
      // various attributes
      rbc.setDecomposition(Collator.FULL_DECOMPOSITION);
      String rules = rbc.getRules();
      if (rules.startsWith("@")) {
          // I suspect we are cheating here when multiple rules are merged
          // One would think you could get this attribute but you can't
          isFrenchSec = true;
      }

      // Get the CollationElementIterators for the source and target
      sourceCursor = rbc.getCollationElementIterator(source);
      targetCursor = rbc.getCollationElementIterator(target);
        
      // Various locale specific matching parameters
        int sOrder = 0, tOrder = 0;
      int pSOrder, pTOrder;
      short secSOrder, secTOrder;
      short terSOrder, terTOrder;
        boolean gets = true, gett = true;
      int toffset = 0;
        boolean initialCheckSecTer, checkSecTer, checkTertiary;

   startSearchForFirstMatch:
        while(true) {
          debug("while(true) toffset=" + toffset);
          // Set the starting point for this comparison
          try {
            sourceCursor.setOffset(0);
          } catch (NoSuchMethodError ex3) {
            // ingnore it
          }
          sOrder = sourceCursor.next();
          try {
            targetCursor.setOffset(toffset);
          } catch (NoSuchMethodError ex4) {
            // Can't really do anything here. Return false.
          } catch (Exception e) {
            // We can get an exception when the toffset is really the
            // end of string
            // Just catch it and return false;
            return false;
          }
          tOrder = targetCursor.next();

          if (tOrder == CollationElementIterator.NULLORDER) {
            break;
          }

          debug("sOrder=" + sOrder + " tOrder=" + tOrder);

          //Find the first character in the target that matches the first
          // character in the source. Look for a complete match of
          // primary, secondary and tertiary. Lacking that look for
          // a match of just primary.
          while (tOrder != CollationElementIterator.NULLORDER) {
            if (sOrder == tOrder) {
                try {
                  toffset = targetCursor.getOffset();
                } catch (NoSuchMethodError ex) {
                  //ignore it
                }
                break;
            }
            pSOrder = CollationElementIterator.primaryOrder(sOrder);
            pTOrder = CollationElementIterator.primaryOrder(tOrder);
            if (pSOrder == pTOrder) {
                try {
                  toffset = targetCursor.getOffset();
                } catch (NoSuchMethodError ex2) {
                  //ignore it
                }
                break;
            }
            tOrder = targetCursor.next();
            debug("next tOrder=" + tOrder);
          }

          // If at end there is no match
          if (tOrder == CollationElementIterator.NULLORDER) {
            return false;
          }

          gets = false;
          gett = false;
          initialCheckSecTer = rbc.getStrength() >= Collator.SECONDARY;
          checkSecTer = initialCheckSecTer;
          checkTertiary = rbc.getStrength() >= Collator.TERTIARY;
          
          while (true) {
            // Get the next collation element in each of the strings, unless
            // we've been requested to skip it.
            if (gets) {
                sOrder = sourceCursor.next(); 
            } else {
                gets = true;
            }
            if (gett) {
                tOrder = targetCursor.next(); 
            } else {
                gett = true;
            }

            // If we've hit the end of one of the strings, jump out of the loop
            if ((sOrder == CollationElementIterator.NULLORDER)||
                (tOrder == CollationElementIterator.NULLORDER)) {
                debug("One string at end");
                break;
            }

            pSOrder = CollationElementIterator.primaryOrder(sOrder);
            pTOrder = CollationElementIterator.primaryOrder(tOrder);

            // If there's no difference at this position, we can skip it
            if (sOrder == tOrder) {
                if (isFrenchSec && pSOrder != 0) {
                  if (!checkSecTer) {
                      // in french, a secondary difference more to the
                      // right is stronger,
                      // so accents have to be checked with each base
                      // element
                      checkSecTer = initialCheckSecTer;
                      // but tertiary differences are less important
                      // than the first 
                      // secondary difference, so checking tertiary
                      // remains disabled
                      checkTertiary = false;
                  }
                }
                debug("No diff at this positon continue");
                continue;
            }

            // Compare primary differences first.
            if ( pSOrder != pTOrder ) {
                if (sOrder == 0) {
                  // The entire source element is ignorable.
                  // Skip to the next source element, 
                  // but don't fetch another target element.
                  gett = false;
                  continue;
                }
                if (tOrder == 0) {
                  // The entire target element is ignorable.
                  // Skip to the next target element, 
                  // but don't fetch another source element.
                  gets = false;
                  continue;
                }

                // The source and target elements aren't ignorable,
                // but it's still possible
                // for the primary component of one of the elements
                // to be ignorable....
                
                if (pSOrder == 0) {
                  // The source's primary is ignorable, 
                  // but the target's isn't.  We treat ignorables
                  // as a secondary differenc
                  if (checkSecTer) {
                      // (strength is SECONDARY)
                      targetCursor.next();
                      toffset = targetCursor.getOffset();
                      debug("Strength is secondary pSOrder === 0");
                      continue startSearchForFirstMatch;
                  }
                  // Skip to the next source element, 
                  // but don't fetch another target element.
                  gett = false;
                } else if (pTOrder == 0) {
                  // record differences - see the comment above.
                  if (checkSecTer) {
                      // (stength is SECONDARY)
                      targetCursor.next();
                      toffset = targetCursor.getOffset();
                      debug("Strength is secondary - pTOrder == 0");
                      continue startSearchForFirstMatch;
                  }
                  // Skip to the next source element, 
                  // but don't fetch another target element.
                  gets = false;
                } else {
                  // Neither of the orders is ignorable,
                  // and we already know that the primary
                  // orders are different because of the 
                  // (pSOrder != pTOrder) test above.
                  // Record the difference and stop the
                  // comparison.
                  targetCursor.next();
                  toffset = targetCursor.getOffset();
                  debug("Order are ignorable");
                  continue startSearchForFirstMatch;
                }
            } else { // else of if ( pSOrder != pTOrder )
                // primary order is the same, but complete order is 
                // different. So there
                // are no base elements at this point, only 
                // ignorables (Since the strings are
                // normalized)
                
                if (checkSecTer) {
                  // a secondary or tertiary difference may 
                  // still matter
                  secSOrder = CollationElementIterator.secondaryOrder(sOrder);
                  secTOrder = CollationElementIterator.secondaryOrder(tOrder);
                  if (secSOrder != secTOrder) {
                      // there is a secondary difference
                      targetCursor.next();
                      toffset = targetCursor.getOffset();
                      debug("Secondary Difference");
                      continue startSearchForFirstMatch;
                      // (strength is SECONDARY)
                      // (even in french, only the first 
                      // secondary difference within
                      // a base character matters)
                  } else {
                      if (checkTertiary) {
                        // a tertiary difference may still matter
                        terSOrder = CollationElementIterator.tertiaryOrder(sOrder);
                        terTOrder = CollationElementIterator.tertiaryOrder(tOrder);
                        if (terSOrder != terTOrder) {
                            // there is a tertiary difference
                            targetCursor.next();
                            toffset = targetCursor.getOffset();
                            debug("Tertiary difference");
                            continue startSearchForFirstMatch;
                            // (strength is TERTIARY)
                        }
                      }
                  }
                } // if (checkSecTer)

            }  // if ( pSOrder != pTOrder )
          } // while()

          // There might be a match
          // Just do some final checking
          if (sOrder != CollationElementIterator.NULLORDER) {
            // (tOrder must be CollationElementIterator::NULLORDER,
            // since this point is only reached when sOrder or 
            // tOrder is NULLORDER.)
            // The source string has more elements, 
            // but the target string hasn't.
            do {
                if (CollationElementIterator.primaryOrder(sOrder) != 0) {
                  // We found an additional non-ignorable base 
                  // character in the source string.
                  // This is a primary difference, 
                  // so the source is greater
                  targetCursor.next();
                  toffset = targetCursor.getOffset();
                  debug("Additional non-ignborable base character in source string - source is greater");
                  continue startSearchForFirstMatch;
                  // (strength is PRIMARY)
                }
                else if (CollationElementIterator.secondaryOrder(sOrder) != 0) {
                  // Additional secondary elements mean the 
                  // source string is greater
                  if (checkSecTer) {
                      targetCursor.next();
                      toffset = targetCursor.getOffset();
                      debug("Additional secondary elements source is greater");
                      continue startSearchForFirstMatch;
                      // (strength is SECONDARY)
                  }
                } 
            } while ((sOrder = sourceCursor.next()) != CollationElementIterator.NULLORDER);
          }
          // Either the target string has more elements, 
          // but the source string hasn't or neither the target string
          // or the source string have any more elemnts.
          // In either case the source was contained in target
          // return true;
          return true;
      }
      return false;
    }



    /**
     * Debug support
     */

00870     private static final boolean debug = false;
    private static void debug(Object msg1, Object msg2, Object msg3) {
      if (debug) {
          System.err.println("HelpUtilities: "+msg1+msg2+msg3);
      }
    }
    private static void debug(Object msg1) { debug(msg1,"",""); }
    private static void debug(Object msg1, Object msg2) {
      debug(msg1,msg2,"");
    }

}

Generated by  Doxygen 1.6.0   Back to index