content: /*
   *  This file is part of AndroidIDE.
   *
   *  AndroidIDE is free software: you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation, either version 3 of the License, or
   *  (at your option) any later version.
   *
   *  AndroidIDE 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 for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *   along with AndroidIDE.  If not, see <https://www.gnu.org/licenses/>.
   */
  
  /*
   * reserved comment block
   * DO NOT REMOVE OR ALTER!
   */
  /*
   * Copyright 1999-2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  /*
   * $Id: StringComparable.java,v 1.2.4.1 2005/09/15 08:15:55 suresh_emailid Exp $
   */
  
  package jaxp.sun.org.apache.xml.internal.utils;
  
  import java.text.Collator;
  import java.text.RuleBasedCollator;
  import java.text.CollationElementIterator;
  import java.util.Locale;
  
  
  /**
  * International friendly string comparison with case-order
   * @author Igor Hersht, igorh@ca.ibm.com
  */
  public class StringComparable implements Comparable  {
  
       public final static int UNKNOWN_CASE = -1;
       public final static int UPPER_CASE = 1;
       public final static int LOWER_CASE = 2;
  
       private  String m_text;
       private  Locale m_locale;
       private RuleBasedCollator m_collator;
       private String m_caseOrder;
       private int m_mask = 0xFFFFFFFF;
  
      public StringComparable(final String text, final Locale locale, final Collator collator, final String caseOrder){
           m_text =  text;
           m_locale = locale;
           m_collator = (RuleBasedCollator)collator;
           m_caseOrder = caseOrder;
           m_mask = getMask(m_collator.getStrength());
      }
  
     public final static Comparable getComparator( final String text, final Locale locale, final Collator collator, final String caseOrder){
         if((caseOrder == null) ||(caseOrder.length() == 0)){// no case-order specified
              return  ((RuleBasedCollator)collator).getCollationKey(text);
         }else{
              return new StringComparable(text, locale, collator, caseOrder);
         }
     }
  
     public final String toString(){return m_text;}
  
     public int compareTo(Object o) {
     final String pattern = ((StringComparable)o).toString();
     if(m_text.equals(pattern)){//Code-point equals
        return 0;
     }
     final int savedStrength = m_collator.getStrength();
     int comp = 0;
        // Is there difference more significant than case-order?
       if(((savedStrength == Collator.PRIMARY) || (savedStrength == Collator.SECONDARY))){
           comp = m_collator.compare(m_text, pattern );
       }else{// more than SECONDARY
           m_collator.setStrength(Collator.SECONDARY);
           comp = m_collator.compare(m_text, pattern );
           m_collator.setStrength(savedStrength);
       }
       if(comp != 0){//Difference more significant than case-order
          return comp ;
       }
  
        // No difference more significant than case-order.
        // Find case difference
         comp = getCaseDiff(m_text, pattern);
         if(comp != 0){
             return comp;
         }else{// No case differences. Less significant difference could exist
              return m_collator.compare(m_text, pattern );
         }
    }
  
  
    private final int getCaseDiff (final String text, final String pattern){
       final int savedStrength = m_collator.getStrength();
       final int savedDecomposition = m_collator.getDecomposition();
       m_collator.setStrength(Collator.TERTIARY);// not to ignore case
       m_collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION );// corresponds NDF
  
      final int diff[] =getFirstCaseDiff (text, pattern, m_locale);
      m_collator.setStrength(savedStrength);// restore
      m_collator.setDecomposition(savedDecomposition); //restore
      if(diff != null){
         if((m_caseOrder).equals("upper-first")){
              if(diff[0] == UPPER_CASE){
                  return -1;
              }else{
                  return 1;
              }
         }else{// lower-first
              if(diff[0] == LOWER_CASE){
                  return -1;
              }else{
                  return 1;
              }
         }
     }else{// No case differences
          return 0;
     }
  
    }
  
  
  
    private final int[] getFirstCaseDiff(final String text, final String pattern, final Locale locale){
  
          final CollationElementIterator targIter = m_collator.getCollationElementIterator(text);
          final CollationElementIterator patIter = m_collator.getCollationElementIterator(pattern);
          int startTarg = -1;
          int endTarg = -1;
          int startPatt = -1;
          int endPatt = -1;
          final int done = getElement(CollationElementIterator.NULLORDER);
          int patternElement = 0, targetElement = 0;
          boolean getPattern = true, getTarget = true;
  
          while (true) {
              if (getPattern){
                   startPatt = patIter.getOffset();
                   patternElement = getElement(patIter.next());
                   endPatt = patIter.getOffset();
              }
              if ((getTarget)){
                   startTarg  = targIter.getOffset();
                   targetElement   = getElement(targIter.next());
                   endTarg  = targIter.getOffset();
              }
              getTarget = getPattern = true;
              if ((patternElement == done) ||( targetElement == done)) {
                  return null;
              } else if (targetElement == 0) {
                getPattern = false;
              } else if (patternElement == 0) {
                getTarget = false;
              } else if (targetElement != patternElement) {// mismatch
                  if((startPatt < endPatt) && (startTarg < endTarg)){
                      final String  subText = text.substring(startTarg, endTarg);
                      final String  subPatt = pattern.substring(startPatt, endPatt);
                      final String  subTextUp = subText.toUpperCase(locale);
                      final String  subPattUp = subPatt.toUpperCase(locale);
                      if(m_collator.compare(subTextUp, subPattUp) != 0){ // not case diffference
                          continue;
                      }
  
                      int diff[] = {UNKNOWN_CASE, UNKNOWN_CASE};
                      if(m_collator.compare(subText, subTextUp) == 0){
                          diff[0] = UPPER_CASE;
                      }else if(m_collator.compare(subText, subText.toLowerCase(locale)) == 0){
                         diff[0] = LOWER_CASE;
                      }
                      if(m_collator.compare(subPatt, subPattUp) == 0){
                          diff[1] = UPPER_CASE;
                      }else if(m_collator.compare(subPatt, subPatt.toLowerCase(locale)) == 0){
                         diff[1] = LOWER_CASE;
                      }
  
                      if(((diff[0] == UPPER_CASE) && ( diff[1] == LOWER_CASE)) ||
                         ((diff[0] == LOWER_CASE) && ( diff[1] == UPPER_CASE))){
                          return diff;
                      }else{// not case diff
                        continue;
                      }
                  }else{
                      continue;
                  }
  
             }
          }
  
    }
  
  
   // Return a mask for the part of the order we're interested in
      private static final int getMask(final int strength) {
          switch (strength) {
              case Collator.PRIMARY:
                  return 0xFFFF0000;
              case Collator.SECONDARY:
                  return 0xFFFFFF00;
              default:
                  return 0xFFFFFFFF;
          }
      }
      //get collation element with given strength
      // from the element with max strength
    private final int getElement(int maxStrengthElement){
  
      return (maxStrengthElement & m_mask);
    }
  
  }//StringComparable
  