You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sa...@apache.org on 2013/05/06 00:26:36 UTC

svn commit: r1479410 [9/10] - in /lucene/dev/branches/lucene4956/lucene/analysis/arirang: ./ src/java/org/apache/lucene/analysis/kr/ src/java/org/apache/lucene/analysis/kr/morph/ src/java/org/apache/lucene/analysis/kr/tagging/ src/java/org/apache/lucen...

Modified: lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/StringEscapeUtil.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/StringEscapeUtil.java?rev=1479410&r1=1479409&r2=1479410&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/StringEscapeUtil.java (original)
+++ lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/StringEscapeUtil.java Sun May  5 22:26:35 2013
@@ -23,126 +23,124 @@ import java.io.Writer;
 
 public class StringEscapeUtil {
 
-    /**
-     * <p>Unescapes any Java literals found in the <code>String</code>.
-     * For example, it will turn a sequence of <code>'\'</code> and
-     * <code>'n'</code> into a newline character, unless the <code>'\'</code>
-     * is preceded by another <code>'\'</code>.</p>
-     * 
-     * @param str  the <code>String</code> to unescape, may be null
-     * @return a new unescaped <code>String</code>, <code>null</code> if null string input
-     */
-    public static String unescapeJava(String str) {
-        if (str == null) {
-            return null;
-        }
-        try {
-            StringWriter writer = new StringWriter(str.length());
-            unescapeJava(writer, str);
-            return writer.toString();
-        } catch (IOException ioe) {
-            // this should never ever happen while writing to a StringWriter
-            throw new UnhandledException(ioe);
-        }
+  /**
+   * <p>Unescapes any Java literals found in the <code>String</code>.
+   * For example, it will turn a sequence of <code>'\'</code> and
+   * <code>'n'</code> into a newline character, unless the <code>'\'</code>
+   * is preceded by another <code>'\'</code>.</p>
+   * 
+   * @param str  the <code>String</code> to unescape, may be null
+   * @return a new unescaped <code>String</code>, <code>null</code> if null string input
+   */
+  public static String unescapeJava(String str) {
+    if (str == null) {
+      return null;
+    }
+    try {
+      StringWriter writer = new StringWriter(str.length());
+      unescapeJava(writer, str);
+      return writer.toString();
+    } catch (IOException ioe) {
+      // this should never ever happen while writing to a StringWriter
+      throw new UnhandledException(ioe);
     }
+  }
 
-    /**
-     * <p>Unescapes any Java literals found in the <code>String</code> to a
-     * <code>Writer</code>.</p>
-     *
-     * <p>For example, it will turn a sequence of <code>'\'</code> and
-     * <code>'n'</code> into a newline character, unless the <code>'\'</code>
-     * is preceded by another <code>'\'</code>.</p>
-     * 
-     * <p>A <code>null</code> string input has no effect.</p>
-     * 
-     * @param out  the <code>Writer</code> used to output unescaped characters
-     * @param str  the <code>String</code> to unescape, may be null
-     * @throws IllegalArgumentException if the Writer is <code>null</code>
-     * @throws IOException if error occurs on underlying Writer
-     */
-    public static void unescapeJava(Writer out, String str) throws IOException {
-        if (out == null) {
-            throw new IllegalArgumentException("The Writer must not be null");
-        }
-        if (str == null) {
-            return;
-        }
-        int sz = str.length();
-        StrBuilder unicode = new StrBuilder(4);
-        boolean hadSlash = false;
-        boolean inUnicode = false;
-        for (int i = 0; i < sz; i++) {
-            char ch = str.charAt(i);
-            if (inUnicode) {
-                // if in unicode, then we're reading unicode
-                // values in somehow
-                unicode.append(ch);
-                if (unicode.length() == 4) {
-                    // unicode now contains the four hex digits
-                    // which represents our unicode character
-                    try {
-                        int value = Integer.parseInt(unicode.toString(), 16);
-                        out.write((char) value);
-                        unicode.setLength(0);
-                        inUnicode = false;
-                        hadSlash = false;
-                    } catch (NumberFormatException nfe) {
-                        throw new UnhandledException("Unable to parse unicode value: " + unicode, nfe);
-                    }
-                }
-                continue;
-            }
-            if (hadSlash) {
-                // handle an escaped value
-                hadSlash = false;
-                switch (ch) {
-                    case '\\':
-                        out.write('\\');
-                        break;
-                    case '\'':
-                        out.write('\'');
-                        break;
-                    case '\"':
-                        out.write('"');
-                        break;
-                    case 'r':
-                        out.write('\r');
-                        break;
-                    case 'f':
-                        out.write('\f');
-                        break;
-                    case 't':
-                        out.write('\t');
-                        break;
-                    case 'n':
-                        out.write('\n');
-                        break;
-                    case 'b':
-                        out.write('\b');
-                        break;
-                    case 'u':
-                        {
-                            // uh-oh, we're in unicode country....
-                            inUnicode = true;
-                            break;
-                        }
-                    default :
-                        out.write(ch);
-                        break;
-                }
-                continue;
-            } else if (ch == '\\') {
-                hadSlash = true;
-                continue;
-            }
-            out.write(ch);
-        }
-        if (hadSlash) {
-            // then we're in the weird case of a \ at the end of the
-            // string, let's output it anyway.
+  /**
+   * <p>Unescapes any Java literals found in the <code>String</code> to a
+   * <code>Writer</code>.</p>
+   *
+   * <p>For example, it will turn a sequence of <code>'\'</code> and
+   * <code>'n'</code> into a newline character, unless the <code>'\'</code>
+   * is preceded by another <code>'\'</code>.</p>
+   * 
+   * <p>A <code>null</code> string input has no effect.</p>
+   * 
+   * @param out  the <code>Writer</code> used to output unescaped characters
+   * @param str  the <code>String</code> to unescape, may be null
+   * @throws IllegalArgumentException if the Writer is <code>null</code>
+   * @throws IOException if error occurs on underlying Writer
+   */
+  public static void unescapeJava(Writer out, String str) throws IOException {
+    if (out == null) {
+      throw new IllegalArgumentException("The Writer must not be null");
+    }
+    if (str == null) {
+      return;
+    }
+    int sz = str.length();
+    StrBuilder unicode = new StrBuilder(4);
+    boolean hadSlash = false;
+    boolean inUnicode = false;
+    for (int i = 0; i < sz; i++) {
+      char ch = str.charAt(i);
+      if (inUnicode) {
+        // if in unicode, then we're reading unicode
+        // values in somehow
+        unicode.append(ch);
+        if (unicode.length() == 4) {
+          // unicode now contains the four hex digits
+          // which represents our unicode character
+          try {
+            int value = Integer.parseInt(unicode.toString(), 16);
+            out.write((char) value);
+            unicode.setLength(0);
+            inUnicode = false;
+            hadSlash = false;
+          } catch (NumberFormatException nfe) {
+            throw new UnhandledException("Unable to parse unicode value: " + unicode, nfe);
+          }
+        }
+        continue;
+      }
+      if (hadSlash) {
+        // handle an escaped value
+        hadSlash = false;
+        switch (ch) {
+          case '\\':
             out.write('\\');
+            break;
+          case '\'':
+            out.write('\'');
+            break;
+          case '\"':
+            out.write('"');
+            break;
+          case 'r':
+            out.write('\r');
+            break;
+          case 'f':
+            out.write('\f');
+            break;
+          case 't':
+            out.write('\t');
+            break;
+          case 'n':
+            out.write('\n');
+            break;
+          case 'b':
+            out.write('\b');
+            break;
+          case 'u': {
+            // uh-oh, we're in unicode country....
+            inUnicode = true;
+            break;
+          }
+          default :
+            out.write(ch);
+            break;
         }
+        continue;
+      } else if (ch == '\\') {
+        hadSlash = true;
+        continue;
+      }
+      out.write(ch);
+    }
+    if (hadSlash) {
+      // then we're in the weird case of a \ at the end of the
+      // string, let's output it anyway.
+      out.write('\\');
     }
-    
+  }
 }

Modified: lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/SyllableUtil.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/SyllableUtil.java?rev=1479410&r1=1479409&r2=1479410&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/SyllableUtil.java (original)
+++ lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/SyllableUtil.java Sun May  5 22:26:35 2013
@@ -25,111 +25,110 @@ import org.apache.lucene.analysis.kr.mor
 
 public class SyllableUtil {
 
-	public static int IDX_JOSA1 = 0; // 조사의 첫음절로 사용되는 음절 48개
-	public static int IDX_JOSA2 = 1; // 조사의 두 번째 이상의 음절로 사용되는 음절 58개
-	public static int IDX_EOMI1 = 2; // 어미의 첫음절로 사용되는 음절 72개
-	public static int IDX_EOMI2 = 3; // 어미의 두 번째 이상의 음절로 사용되는 음절 105개
-	public static int IDX_YONG1 = 4; // 1음절 용언에 사용되는 음절 362개
-	public static int IDX_YONG2 = 5; // 2음절 용언의 마지막 음절로 사용되는 음절 316개
-	public static int IDX_YONG3 = 6; // 3음절 이상 용언의 마지막 음절로 사용되는 음절 195개
-	public static int IDX_CHEON1 = 7; // 1음절 체언에 사용되는 음절 680개
-	public static int IDX_CHEON2 = 8; // 2음절 체언의 마지막 음절로 사용되는 음절 916개
-	public static int IDX_CHEON3 = 9; // 3음절 체언의 마지막 음절로 사용되는 음절 800개
-	public static int IDX_CHEON4 = 10; // 4음절 체언의 마지막 음절로 사용되는 음절 610개
-	public static int IDX_CHEON5 = 11; // 5음절 이상 체언의 마지막 음절로 사용되는 음절 330개
-	public static int IDX_BUSA1 = 12; // 1음절 부사의 마지막 음절로 사용되는 음절 191개
-	public static int IDX_BUSA2 = 13; // 2음절 부사의 마지막 음절로 사용되는 음절 519개
-	public static int IDX_BUSA3 = 14; // 3음절 부사의 마지막 음절로 사용되는 음절 139개
-	public static int IDX_BUSA4 = 15; // 4음절 부사의 마지막 음절로 사용되는 음절 366개
-	public static int IDX_BUSA5 = 16; // 5음절 부사의 마지막 음절로 사용되는 음절 79개
-	public static int IDX_PRONOUN = 17; // 대명사의 마지막 음절로 사용되는 음절 77개
-	public static int IDX_EXCLAM = 18; // 관형사와 감탄사의 마지막 음절로 사용되는 음절 241개
-	
-	public static int IDX_YNPNA = 19; // (용언+'-ㄴ')에 의하여 생성되는 음절 129개
-	public static int IDX_YNPLA = 20; // (용언+'-ㄹ')에 의해 생성되는 음절 129개
-	public static int IDX_YNPMA = 21; // (용언+'-ㅁ')에 의해 생성되는 음절 129개
-	public static int IDX_YNPBA = 22; // (용언+'-ㅂ')에 의해 생성되는 음절 129개
-	public static int IDX_YNPAH = 23; // 모음으로 끝나는 음절 129개중 'ㅏ/ㅓ/ㅐ/ㅔ/ㅕ'로 끝나는 것이 선어말 어미 '-었-'과 결합할 때 생성되는 음절
-	public static int IDX_YNPOU = 24; // 모음 'ㅗ/ㅜ'로 끝나는 음절이 '아/어'로 시작되는 어미나 선어말 어미 '-었-'과 결합할 때 생성되는 음절
-	public static int IDX_YNPEI = 25; // 모음 'ㅣ'로 끝나는 용언이 '아/어'로 시작되는 어미나 선어말 어미 '-었-'과 결합할 때 생성되는 음절
-	public static int IDX_YNPOI = 26; // 모음 'ㅚ'로 끝나는 용언이 '아/어'로 시작되는 어미나 선어말 어미 '-었-'과 결합할 때 생성되는 음절
-	public static int IDX_YNPLN = 27; // 받침 'ㄹ'로 끝나는 용언이 어미 '-ㄴ'과 결합할 때 생성되는 음절
-	public static int IDX_IRRLO = 28; // '러' 불규칙(8개)에 의하여 생성되는 음절 : 러, 렀
-	public static int IDX_IRRPLE = 29; // '르' 불규칙(193개)에 의하여 생성되는 음절 
-	public static int IDX_IRROO = 30; // '우' 불규칙에 의하여 생성되는 음절 : 퍼, 펐
-	public static int IDX_IRROU = 31; // '어' 불규칙에 의하여 생성되는 음절 : 해, 했
-	public static int IDX_IRRDA = 32; // 'ㄷ' 불규칙(37개)에 의하여 생성되는 음절
-	public static int IDX_IRRBA = 33; // 'ㅂ' 불규칙(446개)에 의하여 생성되는 음절
-	public static int IDX_IRRSA = 34; // 'ㅅ' 불규칙(39개)에 의하여 생성되는 음절
-	public static int IDX_IRRHA = 35; // 'ㅎ' 불규칙(96개)에 의하여 생성되는 음절 
-	public static int IDX_PEND = 36; // 선어말 어미 : 시 셨 았 었 였 겠
-	
-	public static int IDX_YNPEOMI = 37; // 용언이 어미와 결합할 때 생성되는 음절의 수 734개
-	
-	/**	 용언의 표층 형태로만 사용되는 음절 */
-	public static int IDX_WDSURF = 38; 
-	
-	public static int IDX_EOGAN = 39; // 어미 또는 어미의 변형으로 존재할 수 있는 음 (즉 IDX_EOMI 이거나 IDX_YNPNA 이후에 1이 있는 음절)
-	
-	private static List Syllables;  // 음절특성 정보
-	
-	/**
-	 * 인덱스 값에 해당하는 음절의 특성을 반환한다.
-	 * 영자 또는 숫자일 경우는 모두 해당이 안되므로 가장 마지막 글자인 '힣' 의 음절특성을 반환한다.
-	 * 
-	 * @param idx '가'(0xAC00)이 0부터 유니코드에 의해 한글음절을 순차적으로 나열한 값
-	 * @return
-	 * @throws Exception 
-	 */
-	public static char[] getFeature(int idx)  throws MorphException {
-		
-		if(Syllables==null) Syllables = getSyllableFeature();
-	
-		if(idx<0||idx>=Syllables.size()) 
-			return (char[])Syllables.get(Syllables.size()-1);
-		else 
-			return (char[])Syllables.get(idx);
-		
-	}
-	
-	/**
-	 * 각 음절의 특성을 반환한다.
-	 * @param syl  음절 하나
-	 * @return
-	 * @throws Exception 
-	 */
-	public static char[] getFeature(char syl) throws MorphException {
-		
-		int idx = syl - 0xAC00;
-		return getFeature(idx);
-		
-	}
-	
-	/**
-	 * 음절정보특성을 파일에서 읽는다.
-	 * 
-	 * @return
-	 * @throws Exception
-	 */	
-	private static List getSyllableFeature() throws MorphException {
-	
-		try{
-			Syllables = new ArrayList<char[]>();
+  public static int IDX_JOSA1 = 0; // 조사의 첫음절로 사용되는 음절 48개
+  public static int IDX_JOSA2 = 1; // 조사의 두 번째 이상의 음절로 사용되는 음절 58개
+  public static int IDX_EOMI1 = 2; // 어미의 첫음절로 사용되는 음절 72개
+  public static int IDX_EOMI2 = 3; // 어미의 두 번째 이상의 음절로 사용되는 음절 105개
+  public static int IDX_YONG1 = 4; // 1음절 용언에 사용되는 음절 362개
+  public static int IDX_YONG2 = 5; // 2음절 용언의 마지막 음절로 사용되는 음절 316개
+  public static int IDX_YONG3 = 6; // 3음절 이상 용언의 마지막 음절로 사용되는 음절 195개
+  public static int IDX_CHEON1 = 7; // 1음절 체언에 사용되는 음절 680개
+  public static int IDX_CHEON2 = 8; // 2음절 체언의 마지막 음절로 사용되는 음절 916개
+  public static int IDX_CHEON3 = 9; // 3음절 체언의 마지막 음절로 사용되는 음절 800개
+  public static int IDX_CHEON4 = 10; // 4음절 체언의 마지막 음절로 사용되는 음절 610개
+  public static int IDX_CHEON5 = 11; // 5음절 이상 체언의 마지막 음절로 사용되는 음절 330개
+  public static int IDX_BUSA1 = 12; // 1음절 부사의 마지막 음절로 사용되는 음절 191개
+  public static int IDX_BUSA2 = 13; // 2음절 부사의 마지막 음절로 사용되는 음절 519개
+  public static int IDX_BUSA3 = 14; // 3음절 부사의 마지막 음절로 사용되는 음절 139개
+  public static int IDX_BUSA4 = 15; // 4음절 부사의 마지막 음절로 사용되는 음절 366개
+  public static int IDX_BUSA5 = 16; // 5음절 부사의 마지막 음절로 사용되는 음절 79개
+  public static int IDX_PRONOUN = 17; // 대명사의 마지막 음절로 사용되는 음절 77개
+  public static int IDX_EXCLAM = 18; // 관형사와 감탄사의 마지막 음절로 사용되는 음절 241개
+  
+  public static int IDX_YNPNA = 19; // (용언+'-ㄴ')에 의하여 생성되는 음절 129개
+  public static int IDX_YNPLA = 20; // (용언+'-ㄹ')에 의해 생성되는 음절 129개
+  public static int IDX_YNPMA = 21; // (용언+'-ㅁ')에 의해 생성되는 음절 129개
+  public static int IDX_YNPBA = 22; // (용언+'-ㅂ')에 의해 생성되는 음절 129개
+  public static int IDX_YNPAH = 23; // 모음으로 끝나는 음절 129개중 'ㅏ/ㅓ/ㅐ/ㅔ/ㅕ'로 끝나는 것이 선어말 어미 '-었-'과 결합할 때 생성되는 음절
+  public static int IDX_YNPOU = 24; // 모음 'ㅗ/ㅜ'로 끝나는 음절이 '아/어'로 시작되는 어미나 선어말 어미 '-었-'과 결합할 때 생성되는 음절
+  public static int IDX_YNPEI = 25; // 모음 'ㅣ'로 끝나는 용언이 '아/어'로 시작되는 어미나 선어말 어미 '-었-'과 결합할 때 생성되는 음절
+  public static int IDX_YNPOI = 26; // 모음 'ㅚ'로 끝나는 용언이 '아/어'로 시작되는 어미나 선어말 어미 '-었-'과 결합할 때 생성되는 음절
+  public static int IDX_YNPLN = 27; // 받침 'ㄹ'로 끝나는 용언이 어미 '-ㄴ'과 결합할 때 생성되는 음절
+  public static int IDX_IRRLO = 28; // '러' 불규칙(8개)에 의하여 생성되는 음절 : 러, 렀
+  public static int IDX_IRRPLE = 29; // '르' 불규칙(193개)에 의하여 생성되는 음절 
+  public static int IDX_IRROO = 30; // '우' 불규칙에 의하여 생성되는 음절 : 퍼, 펐
+  public static int IDX_IRROU = 31; // '어' 불규칙에 의하여 생성되는 음절 : 해, 했
+  public static int IDX_IRRDA = 32; // 'ㄷ' 불규칙(37개)에 의하여 생성되는 음절
+  public static int IDX_IRRBA = 33; // 'ㅂ' 불규칙(446개)에 의하여 생성되는 음절
+  public static int IDX_IRRSA = 34; // 'ㅅ' 불규칙(39개)에 의하여 생성되는 음절
+  public static int IDX_IRRHA = 35; // 'ㅎ' 불규칙(96개)에 의하여 생성되는 음절 
+  public static int IDX_PEND = 36; // 선어말 어미 : 시 셨 았 었 였 겠
+  
+  public static int IDX_YNPEOMI = 37; // 용언이 어미와 결합할 때 생성되는 음절의 수 734개
+  
+  /**   용언의 표층 형태로만 사용되는 음절 */
+  public static int IDX_WDSURF = 38; 
+  
+  public static int IDX_EOGAN = 39; // 어미 또는 어미의 변형으로 존재할 수 있는 음 (즉 IDX_EOMI 이거나 IDX_YNPNA 이후에 1이 있는 음절)
+  
+  private static List Syllables;  // 음절특성 정보
+  
+  /**
+   * 인덱스 값에 해당하는 음절의 특성을 반환한다.
+   * 영자 또는 숫자일 경우는 모두 해당이 안되므로 가장 마지막 글자인 '힣' 의 음절특성을 반환한다.
+   * 
+   * @param idx '가'(0xAC00)이 0부터 유니코드에 의해 한글음절을 순차적으로 나열한 값
+   * @return
+   * @throws Exception 
+   */
+  public static char[] getFeature(int idx)  throws MorphException {
+    
+    if(Syllables==null) Syllables = getSyllableFeature();
+  
+    if(idx<0||idx>=Syllables.size()) 
+      return (char[])Syllables.get(Syllables.size()-1);
+    else 
+      return (char[])Syllables.get(idx);
+    
+  }
+  
+  /**
+   * 각 음절의 특성을 반환한다.
+   * @param syl  음절 하나
+   * @return
+   * @throws Exception 
+   */
+  public static char[] getFeature(char syl) throws MorphException {
+    
+    int idx = syl - 0xAC00;
+    return getFeature(idx);
+    
+  }
+  
+  /**
+   * 음절정보특성을 파일에서 읽는다.
+   * 
+   * @return
+   * @throws Exception
+   */  
+  private static List getSyllableFeature() throws MorphException {
+  
+    try{
+      Syllables = new ArrayList<char[]>();
 
-			List<String> line = FileUtil.readLines(KoreanEnv.getInstance().getValue(KoreanEnv.FILE_SYLLABLE_FEATURE),"UTF-8");	
-			for(int i=0;i<line.size();i++) {				
-				if(i!=0)
-					Syllables.add(line.get(i).toCharArray());
-			}
-		}catch(IOException e) {
- 		    throw new MorphException(e.getMessage());
-		} 
+      List<String> line = FileUtil.readLines(KoreanEnv.getInstance().getValue(KoreanEnv.FILE_SYLLABLE_FEATURE),"UTF-8");  
+      for(int i=0;i<line.size();i++) {        
+        if(i!=0)
+          Syllables.add(line.get(i).toCharArray());
+      }
+    }catch(IOException e) {
+      throw new MorphException(e.getMessage());
+    } 
 
-		return Syllables;
-		
-	}	
-	
-	public static boolean isAlpanumeric(char ch) {
-		return (ch>='0'&&ch<='z');
-	}
+    return Syllables;
+  }  
+  
+  public static boolean isAlpanumeric(char ch) {
+    return (ch>='0'&&ch<='z');
+  }
 }

Modified: lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/Trie.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/Trie.java?rev=1479410&r1=1479409&r2=1479410&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/Trie.java (original)
+++ lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/Trie.java Sun May  5 22:26:35 2013
@@ -54,463 +54,463 @@ import java.util.NoSuchElementException;
  * discussion of Tries.
  */
 public class Trie<S,V> {
-    /**
-     * Our representation consists of a tree of nodes whose edges are labelled
-     * by strings. The first characters of all labels of all edges of a node
-     * must be distinct. Typically the edges are sorted, but this is determined
-     * by TrieNode.
-     * <p>
-     * 
-     * An abstract TrieNode is a mapping from String keys to values, { <K1, V1>,
-     * ..., <KN, VN> }, where all Ki and Kj are distinct for all i != j. For any
-     * node N, define KEY(N) to be the concatenation of all labels on the edges
-     * from the root to that node. Then the abstraction function is:
-     * <p>
-     * 
-     * <blockquote> { <KEY(N), N.getValue() | N is a child of root and
-     * N.getValue() != null} </blockquote>
-     * 
-     * An earlier version used character labels on edges. This made
-     * implementation simpler but used more memory because one node would be
-     * allocated to each character in long strings if that string had no common
-     * prefixes with other elements of the Trie.
-     * <p>
-     * 
-     * <dl>
-     * <dt>INVARIANT:</td>
-     * <dd>For any node N, for any edges Ei and Ej from N,<br>
-     * i != j &lt;==&gt; Ei.getLabel().getCharAt(0) !=
-     * Ej.getLabel().getCharAt(0)</dd>
-     * <dd>Also, all invariants for TrieNode and TrieEdge must hold.</dd>
-     * </dl>
-     */
-    private TrieNode<V> root;
-
-    /**
-     * Indicates whever search keys are case-sensitive or not. If true, keys
-     * will be canonicalized to lowercase.
-     */
-    private boolean ignoreCase;
-
-    /**
-     * The constant EmptyIterator to return when nothing matches.
-     */
-    private final static Iterator EMPTY_ITERATOR = new EmptyIterator();
+  /**
+   * Our representation consists of a tree of nodes whose edges are labelled
+   * by strings. The first characters of all labels of all edges of a node
+   * must be distinct. Typically the edges are sorted, but this is determined
+   * by TrieNode.
+   * <p>
+   * 
+   * An abstract TrieNode is a mapping from String keys to values, { <K1, V1>,
+   * ..., <KN, VN> }, where all Ki and Kj are distinct for all i != j. For any
+   * node N, define KEY(N) to be the concatenation of all labels on the edges
+   * from the root to that node. Then the abstraction function is:
+   * <p>
+   * 
+   * <blockquote> { <KEY(N), N.getValue() | N is a child of root and
+   * N.getValue() != null} </blockquote>
+   * 
+   * An earlier version used character labels on edges. This made
+   * implementation simpler but used more memory because one node would be
+   * allocated to each character in long strings if that string had no common
+   * prefixes with other elements of the Trie.
+   * <p>
+   * 
+   * <dl>
+   * <dt>INVARIANT:</td>
+   * <dd>For any node N, for any edges Ei and Ej from N,<br>
+   * i != j &lt;==&gt; Ei.getLabel().getCharAt(0) !=
+   * Ej.getLabel().getCharAt(0)</dd>
+   * <dd>Also, all invariants for TrieNode and TrieEdge must hold.</dd>
+   * </dl>
+   */
+  private TrieNode<V> root;
+
+  /**
+   * Indicates whever search keys are case-sensitive or not. If true, keys
+   * will be canonicalized to lowercase.
+   */
+  private boolean ignoreCase;
+
+  /**
+   * The constant EmptyIterator to return when nothing matches.
+   */
+  private final static Iterator EMPTY_ITERATOR = new EmptyIterator();
+
+  /**
+   * Constructs a new, empty tree.
+   */
+  public Trie(boolean ignoreCase) {
+    this.ignoreCase = ignoreCase;
+    clear();
+  }
+
+  /**
+   * Makes this empty.
+   * 
+   * @modifies this
+   */
+  public void clear() {
+    this.root = new TrieNode<V>();
+  }
+
+  /**
+   * Returns the canonical version of the given string.
+   * <p>
+   * 
+   * In the basic version, strings are added and searched without
+   * modification. So this simply returns its parameter s.
+   * <p>
+   * 
+   * Other overrides may also perform a conversion to the NFC form
+   * (interoperable across platforms) or to the NFKC form after removal of
+   * accents and diacritics from the NFKD form (ideal for searches using
+   * strings in natural language).
+   * <p>
+   * 
+   * Made public instead of protected, because the public Prefix operations
+   * below may need to use a coherent conversion of search prefixes.
+   */
+  public String canonicalCase(final String s) {
+    if (!ignoreCase)
+      return s;
+    return s.toUpperCase(Locale.US).toLowerCase(Locale.US);
+  }
+
+  /**
+   * Matches the pattern <tt>b</tt> against the text
+   * <tt>a[startOffset...stopOffset - 1]</tt>.
+   * 
+   * @return the first <tt>j</tt> so that:<br>
+   *         <tt>0 &lt;= i &lt; b.length()</tt> AND<br>
+   *         <tt>a[startOffset + j] != b[j]</tt> [a and b differ]<br>
+   *         OR <tt>stopOffset == startOffset + j</tt> [a is undefined];<br>
+   *         Returns -1 if no such <tt>j</tt> exists, i.e., there is a
+   *         match.<br>
+   *         Examples:
+   *         <ol>
+   *         <li>a = "abcde", startOffset = 0, stopOffset = 5, b = "abc"<br>
+   *         abcde ==&gt; returns -1<br>
+   *         abc
+   *         <li>a = "abcde", startOffset = 1, stopOffset = 5, b = "bXd"<br>
+   *         abcde ==&gt; returns 1 bXd
+   *         <li>a = "abcde", startOffset = 1, stopOffset = 3, b = "bcd"<br>
+   *         abc ==&gt; returns 2<br>
+   *         bcd
+   *         </ol>
+   * 
+   * @requires 0 &lt;= startOffset &lt;= stopOffset &lt;= a.length()
+   */
+  private final int match(String a, int startOffset, int stopOffset, String b) {
+    // j is an index into b
+    // i is a parallel index into a
+    int i = startOffset;
+    for (int j = 0; j < b.length(); j++) {
+      if (i >= stopOffset)
+        return j;
+      if (a.charAt(i) != b.charAt(j))
+        return j;
+      i++;
+    }
+    return -1;
+  }
+
+
+  /**
+   * Maps the given key (which may be empty) to the given value.
+   * 
+   * @return the old value associated with key, or <tt>null</tt> if none
+   * @requires value != null
+   * @modifies this
+   */
+  public V add(String key, V value) {
+    // early conversion of key, for best performance
+    key = canonicalCase(key);
+    // Find the largest prefix of key, key[0..i - 1], already in this.
+    TrieNode<V> node = root;
+    int i = 0;
+    while (i < key.length()) {
+      // Find the edge whose label starts with key[i].
+      TrieEdge<V> edge = node.get(key.charAt(i));
+      if (edge == null) {
+        // 1) Additive insert.
+        TrieNode<V> newNode = new TrieNode<V>(value);
+        node.put(key.substring(i), newNode);
+        return null;
+      }
+      // Now check that rest of label matches
+      String label = edge.getLabel();
+      int j = match(key, i, key.length(), label);
+      if (j >= 0) {
+        // 2) Prefix overlaps perfectly with just part of edge label
+        // Do split insert as follows...
+        //
+        // node node ab = label
+        // ab | ==> a | a = label[0...j - 1] (inclusive)
+        // child intermediate b = label[j...] (inclusive)
+        // b / \ c c = key[i + j...] (inclusive)
+        // child newNode
+        //
+        // ...unless c = "", in which case you just do a "splice
+        // insert" by ommiting newNew and setting intermediate's value.
+        TrieNode<V> child = edge.getChild();
+        TrieNode<V> intermediate = new TrieNode<V>();
+        String a = label.substring(0, j);
+        // Assert.that(canonicalCase(a).equals(a), "Bad edge a");
+        String b = label.substring(j);
+        // Assert.that(canonicalCase(b).equals(b), "Bad edge a");
+        String c = key.substring(i + j);
+        if (c.length() > 0) {
+          // Split.
+          TrieNode<V> newNode = new TrieNode<V>(value);
+          node.remove(label.charAt(0));
+          node.put(a, intermediate);
+          intermediate.put(b, child);
+          intermediate.put(c, newNode);
+        } else {
+          // Splice.
+          node.remove(label.charAt(0));
+          node.put(a, intermediate);
+          intermediate.put(b, child);
+          intermediate.setValue(value);
+        }
+        return null;
+      }
+      // Prefix overlaps perfectly with all of edge label.
+      // Keep searching.
+      node = edge.getChild();
+      i += label.length();
+    }
+    // 3) Relabel insert. Prefix already in this, though not necessarily
+    // associated with a value.
+    V ret = node.getValue();
+    node.setValue(value);
+    return ret;
+  }
+
+  /**
+   * Returns the node associated with prefix, or null if none. (internal)
+   */
+  private TrieNode<V> fetch(String prefix) {
+    // This private method uses prefixes already in canonical form.
+    TrieNode<V> node = root;
+    for (int i = 0; i < prefix.length();) {
+      // Find the edge whose label starts with prefix[i].
+      TrieEdge<V> edge = node.get(prefix.charAt(i));
+      if (edge == null)
+        return null;
+      // Now check that rest of label matches.
+      String label = edge.getLabel();
+      int j = match(prefix, i, prefix.length(), label);
+      if (j != -1)
+        return null;
+      i += label.length();
+      node = edge.getChild();
+    }
+    return node;
+  }
+
+  /**
+   * Returns the value associated with the given key, or null if none.
+   * 
+   * @return the <tt>Object</tt> value or <tt>null</tt>
+   */
+  public Object get(String key) {
+    // early conversion of search key
+    key = canonicalCase(key);
+    // search the node associated with key, if it exists
+    TrieNode node = fetch(key);
+    if (node == null)
+      return null;
+    // key exists, return the value
+    return node.getValue();
+  }
+
+  /**
+   * Ensures no values are associated with the given key.
+   * 
+   * @return <tt>true</tt> if any values were actually removed
+   * @modifies this
+   */
+  public boolean remove(String key) {
+    // early conversion of search key
+    key = canonicalCase(key);
+    // search the node associated with key, if it exists
+    TrieNode<V> node = fetch(key);
+    if (node == null)
+      return false;
+    // key exists and can be removed.
+    // TODO: prune unneeded nodes to save space
+    boolean ret = node.getValue() != null;
+    node.setValue(null);
+    return ret;
+  }
+
+  /**
+   * Returns an iterator (of Object) of the values mapped by keys in this that
+   * start with the given prefix, in any order. That is, the returned iterator
+   * contains exactly the values v for which there exists a key k so that
+   * k.startsWith(prefix) and get(k) == v. The remove() operation on the
+   * iterator is unimplemented.
+   * 
+   * @requires this not modified while iterator in use
+   */
+  public Iterator getPrefixedBy(String prefix) {
+    // Early conversion of search key
+    prefix = canonicalCase(prefix);
+    // Note that canonicalization MAY have changed the prefix length!
+    return getPrefixedBy(prefix, 0, prefix.length());
+  }
+
+  /**
+   * Same as getPrefixedBy(prefix.substring(startOffset, stopOffset). This is
+   * useful as an optimization in certain applications to avoid allocations.
+   * <p>
+   * 
+   * Important: canonicalization of prefix substring is NOT performed here!
+   * But it can be performed early on the whole buffer using the public method
+   * <tt>canonicalCase(String)</tt> of this.
+   * 
+   * @requires 0 &lt;= startOffset &lt;= stopOffset &lt;= prefix.length
+   * @see #canonicalCase(String)
+   */
+  public Iterator getPrefixedBy(String prefix, int startOffset, int stopOffset) {
+    // Find the first node for which "prefix" prefixes KEY(node). (See the
+    // implementation overview for a definition of KEY(node).) This code is
+    // similar to fetch(prefix), except that if prefix extends into the
+    // middle of an edge label, that edge's child is considered a match.
+    TrieNode node = root;
+    for (int i = startOffset; i < stopOffset;) {
+      // Find the edge whose label starts with prefix[i].
+      TrieEdge edge = node.get(prefix.charAt(i));
+      if (edge == null) {
+        return EMPTY_ITERATOR;
+      }
+      // Now check that rest of label matches
+      node = edge.getChild();
+      String label = edge.getLabel();
+      int j = match(prefix, i, stopOffset, label);
+      if (i + j == stopOffset) {
+        // a) prefix overlaps perfectly with just part of edge label
+        break;
+      } else if (j >= 0) {
+        // b) prefix and label differ at some point
+        node = null;
+        break;
+      } else {
+        // c) prefix overlaps perfectly with all of edge label.
+      }
+      i += label.length();
+    }
+    // Yield all children of node, including node itself.
+    if (node == null)
+      return EMPTY_ITERATOR;
+    else
+      return new ValueIterator(node);
+  }
+
+  /**
+   * Returns all the (non-null) values associated with a given node and its
+   * children. (internal)
+   */
+  private class ValueIterator extends NodeIterator {
+    ValueIterator(TrieNode start) {
+      super(start, false);
+    }
+
+    // inherits javadoc comment
+    public Object next() {
+      return ((TrieNode) super.next()).getValue();
+    }
+  }
+
+  /**
+   * Yields nothing. (internal)
+   */
+  private static class EmptyIterator implements Iterator {
+    // inherits javadoc comment
+    public boolean hasNext() {
+      return false;
+    }
+
+    // inherits javadoc comment
+    public Object next() {
+      throw new NoSuchElementException();
+    }
+
+    public void remove() {
 
-    /**
-     * Constructs a new, empty tree.
-     */
-    public Trie(boolean ignoreCase) {
-        this.ignoreCase = ignoreCase;
-        clear();
     }
+  }
 
+  public class NodeIterator extends UnmodifiableIterator {
     /**
-     * Makes this empty.
-     * 
-     * @modifies this
-     */
-    public void clear() {
-        this.root = new TrieNode<V>();
-    }
-
-    /**
-     * Returns the canonical version of the given string.
-     * <p>
-     * 
-     * In the basic version, strings are added and searched without
-     * modification. So this simply returns its parameter s.
-     * <p>
-     * 
-     * Other overrides may also perform a conversion to the NFC form
-     * (interoperable across platforms) or to the NFKC form after removal of
-     * accents and diacritics from the NFKD form (ideal for searches using
-     * strings in natural language).
+     * Stack for DFS. Push and pop from back. The last element of stack is
+     * the next node who's value will be returned.
      * <p>
      * 
-     * Made public instead of protected, because the public Prefix operations
-     * below may need to use a coherent conversion of search prefixes.
-     */
-    public String canonicalCase(final String s) {
-        if (!ignoreCase)
-            return s;
-        return s.toUpperCase(Locale.US).toLowerCase(Locale.US);
-    }
-
-    /**
-     * Matches the pattern <tt>b</tt> against the text
-     * <tt>a[startOffset...stopOffset - 1]</tt>.
-     * 
-     * @return the first <tt>j</tt> so that:<br>
-     *         <tt>0 &lt;= i &lt; b.length()</tt> AND<br>
-     *         <tt>a[startOffset + j] != b[j]</tt> [a and b differ]<br>
-     *         OR <tt>stopOffset == startOffset + j</tt> [a is undefined];<br>
-     *         Returns -1 if no such <tt>j</tt> exists, i.e., there is a
-     *         match.<br>
-     *         Examples:
-     *         <ol>
-     *         <li>a = "abcde", startOffset = 0, stopOffset = 5, b = "abc"<br>
-     *         abcde ==&gt; returns -1<br>
-     *         abc
-     *         <li>a = "abcde", startOffset = 1, stopOffset = 5, b = "bXd"<br>
-     *         abcde ==&gt; returns 1 bXd
-     *         <li>a = "abcde", startOffset = 1, stopOffset = 3, b = "bcd"<br>
-     *         abc ==&gt; returns 2<br>
-     *         bcd
-     *         </ol>
-     * 
-     * @requires 0 &lt;= startOffset &lt;= stopOffset &lt;= a.length()
-     */
-    private final int match(String a, int startOffset, int stopOffset, String b) {
-        // j is an index into b
-        // i is a parallel index into a
-        int i = startOffset;
-        for (int j = 0; j < b.length(); j++) {
-            if (i >= stopOffset)
-                return j;
-            if (a.charAt(i) != b.charAt(j))
-                return j;
-            i++;
-        }
-        return -1;
-    }
-
-
-    /**
-     * Maps the given key (which may be empty) to the given value.
-     * 
-     * @return the old value associated with key, or <tt>null</tt> if none
-     * @requires value != null
-     * @modifies this
-     */
-    public V add(String key, V value) {
-        // early conversion of key, for best performance
-        key = canonicalCase(key);
-        // Find the largest prefix of key, key[0..i - 1], already in this.
-        TrieNode<V> node = root;
-        int i = 0;
-        while (i < key.length()) {
-            // Find the edge whose label starts with key[i].
-            TrieEdge<V> edge = node.get(key.charAt(i));
-            if (edge == null) {
-                // 1) Additive insert.
-                TrieNode<V> newNode = new TrieNode<V>(value);
-                node.put(key.substring(i), newNode);
-                return null;
-            }
-            // Now check that rest of label matches
-            String label = edge.getLabel();
-            int j = match(key, i, key.length(), label);
-            if (j >= 0) {
-                // 2) Prefix overlaps perfectly with just part of edge label
-                // Do split insert as follows...
-                //
-                // node node ab = label
-                // ab | ==> a | a = label[0...j - 1] (inclusive)
-                // child intermediate b = label[j...] (inclusive)
-                // b / \ c c = key[i + j...] (inclusive)
-                // child newNode
-                //
-                // ...unless c = "", in which case you just do a "splice
-                // insert" by ommiting newNew and setting intermediate's value.
-                TrieNode<V> child = edge.getChild();
-                TrieNode<V> intermediate = new TrieNode<V>();
-                String a = label.substring(0, j);
-                // Assert.that(canonicalCase(a).equals(a), "Bad edge a");
-                String b = label.substring(j);
-                // Assert.that(canonicalCase(b).equals(b), "Bad edge a");
-                String c = key.substring(i + j);
-                if (c.length() > 0) {
-                    // Split.
-                    TrieNode<V> newNode = new TrieNode<V>(value);
-                    node.remove(label.charAt(0));
-                    node.put(a, intermediate);
-                    intermediate.put(b, child);
-                    intermediate.put(c, newNode);
-                } else {
-                    // Splice.
-                    node.remove(label.charAt(0));
-                    node.put(a, intermediate);
-                    intermediate.put(b, child);
-                    intermediate.setValue(value);
-                }
-                return null;
-            }
-            // Prefix overlaps perfectly with all of edge label.
-            // Keep searching.
-            node = edge.getChild();
-            i += label.length();
-        }
-        // 3) Relabel insert. Prefix already in this, though not necessarily
-        // associated with a value.
-        V ret = node.getValue();
-        node.setValue(value);
-        return ret;
-    }
-
-    /**
-     * Returns the node associated with prefix, or null if none. (internal)
-     */
-    private TrieNode<V> fetch(String prefix) {
-        // This private method uses prefixes already in canonical form.
-        TrieNode<V> node = root;
-        for (int i = 0; i < prefix.length();) {
-            // Find the edge whose label starts with prefix[i].
-            TrieEdge<V> edge = node.get(prefix.charAt(i));
-            if (edge == null)
-                return null;
-            // Now check that rest of label matches.
-            String label = edge.getLabel();
-            int j = match(prefix, i, prefix.length(), label);
-            if (j != -1)
-                return null;
-            i += label.length();
-            node = edge.getChild();
-        }
-        return node;
-    }
-
-    /**
-     * Returns the value associated with the given key, or null if none.
-     * 
-     * @return the <tt>Object</tt> value or <tt>null</tt>
-     */
-    public Object get(String key) {
-        // early conversion of search key
-        key = canonicalCase(key);
-        // search the node associated with key, if it exists
-        TrieNode node = fetch(key);
-        if (node == null)
-            return null;
-        // key exists, return the value
-        return node.getValue();
-    }
-
-    /**
-     * Ensures no values are associated with the given key.
-     * 
-     * @return <tt>true</tt> if any values were actually removed
-     * @modifies this
+     * INVARIANT: Top of stack contains the next node with not null value to
+     * pop. All other elements in stack are iterators.
      */
-    public boolean remove(String key) {
-        // early conversion of search key
-        key = canonicalCase(key);
-        // search the node associated with key, if it exists
-        TrieNode<V> node = fetch(key);
-        if (node == null)
-            return false;
-        // key exists and can be removed.
-        // TODO: prune unneeded nodes to save space
-        boolean ret = node.getValue() != null;
-        node.setValue(null);
-        return ret;
-    }
+    private ArrayList /* of Iterator of TrieNode */stack = new ArrayList();
+    private boolean withNulls;
 
     /**
-     * Returns an iterator (of Object) of the values mapped by keys in this that
-     * start with the given prefix, in any order. That is, the returned iterator
-     * contains exactly the values v for which there exists a key k so that
-     * k.startsWith(prefix) and get(k) == v. The remove() operation on the
-     * iterator is unimplemented.
-     * 
-     * @requires this not modified while iterator in use
-     */
-    public Iterator getPrefixedBy(String prefix) {
-        // Early conversion of search key
-        prefix = canonicalCase(prefix);
-        // Note that canonicalization MAY have changed the prefix length!
-        return getPrefixedBy(prefix, 0, prefix.length());
+     * Creates a new iterator that yields all the nodes of start and its
+     * children that have values (ignoring internal nodes).
+     */
+    public NodeIterator(TrieNode start, boolean withNulls) {
+      this.withNulls = withNulls;
+      if (withNulls || start.getValue() != null)
+        // node has a value, push it for next
+        stack.add(start);
+      else
+        // scan node children to find the next node
+        advance(start);
+    }
+
+    // inherits javadoc comment
+    public boolean hasNext() {
+      return !stack.isEmpty();
+    }
+
+    // inherits javadoc comment
+    public Object next() {
+      int size;
+      if ((size = stack.size()) == 0)
+        throw new NoSuchElementException();
+      TrieNode node = (TrieNode) stack.remove(size - 1);
+      advance(node);
+      return node;
     }
 
     /**
-     * Same as getPrefixedBy(prefix.substring(startOffset, stopOffset). This is
-     * useful as an optimization in certain applications to avoid allocations.
-     * <p>
-     * 
-     * Important: canonicalization of prefix substring is NOT performed here!
-     * But it can be performed early on the whole buffer using the public method
-     * <tt>canonicalCase(String)</tt> of this.
-     * 
-     * @requires 0 &lt;= startOffset &lt;= stopOffset &lt;= prefix.length
-     * @see #canonicalCase(String)
-     */
-    public Iterator getPrefixedBy(String prefix, int startOffset, int stopOffset) {
-        // Find the first node for which "prefix" prefixes KEY(node). (See the
-        // implementation overview for a definition of KEY(node).) This code is
-        // similar to fetch(prefix), except that if prefix extends into the
-        // middle of an edge label, that edge's child is considered a match.
-        TrieNode node = root;
-        for (int i = startOffset; i < stopOffset;) {
-            // Find the edge whose label starts with prefix[i].
-            TrieEdge edge = node.get(prefix.charAt(i));
-            if (edge == null) {
-                return EMPTY_ITERATOR;
-            }
-            // Now check that rest of label matches
-            node = edge.getChild();
-            String label = edge.getLabel();
-            int j = match(prefix, i, stopOffset, label);
-            if (i + j == stopOffset) {
-                // a) prefix overlaps perfectly with just part of edge label
-                break;
-            } else if (j >= 0) {
-                // b) prefix and label differ at some point
-                node = null;
-                break;
-            } else {
-                // c) prefix overlaps perfectly with all of edge label.
-            }
-            i += label.length();
-        }
-        // Yield all children of node, including node itself.
-        if (node == null)
-            return EMPTY_ITERATOR;
+     * Scan the tree (top-down) starting at the already visited node until
+     * finding an appropriate node with not null value for next(). Keep
+     * unvisited nodes in a stack of siblings iterators. Return either an
+     * empty stack, or a stack whose top will be the next node returned by
+     * next().
+     */
+    private void advance(TrieNode node) {
+      Iterator children = node.childrenForward();
+      while (true) { // scan siblings and their children
+        int size;
+        if (children.hasNext()) {
+          node = (TrieNode) children.next();
+          if (children.hasNext()) // save siblings
+            stack.add(children);
+          // check current node and scan its sibling if necessary
+          if (withNulls || node.getValue() == null)
+            children = node.childrenForward(); // loop from there
+          else { // node qualifies for next()
+            stack.add(node);
+            return; // next node exists
+          }
+        } else if ((size = stack.size()) == 0)
+          return; // no next node
         else
-            return new ValueIterator(node);
-    }
-
-    /**
-     * Returns all the (non-null) values associated with a given node and its
-     * children. (internal)
-     */
-    private class ValueIterator extends NodeIterator {
-        ValueIterator(TrieNode start) {
-            super(start, false);
-        }
-
-        // inherits javadoc comment
-        public Object next() {
-            return ((TrieNode) super.next()).getValue();
-        }
-    }
-
-    /**
-     * Yields nothing. (internal)
-     */
-    private static class EmptyIterator implements Iterator {
-        // inherits javadoc comment
-        public boolean hasNext() {
-            return false;
-        }
-
-        // inherits javadoc comment
-        public Object next() {
-            throw new NoSuchElementException();
-        }
-
-        public void remove() {
-
-        }
-    }
-
-    public class NodeIterator extends UnmodifiableIterator {
-        /**
-         * Stack for DFS. Push and pop from back. The last element of stack is
-         * the next node who's value will be returned.
-         * <p>
-         * 
-         * INVARIANT: Top of stack contains the next node with not null value to
-         * pop. All other elements in stack are iterators.
-         */
-        private ArrayList /* of Iterator of TrieNode */stack = new ArrayList();
-        private boolean withNulls;
-
-        /**
-         * Creates a new iterator that yields all the nodes of start and its
-         * children that have values (ignoring internal nodes).
-         */
-        public NodeIterator(TrieNode start, boolean withNulls) {
-            this.withNulls = withNulls;
-            if (withNulls || start.getValue() != null)
-                // node has a value, push it for next
-                stack.add(start);
-            else
-                // scan node children to find the next node
-                advance(start);
-        }
-
-        // inherits javadoc comment
-        public boolean hasNext() {
-            return !stack.isEmpty();
-        }
-
-        // inherits javadoc comment
-        public Object next() {
-            int size;
-            if ((size = stack.size()) == 0)
-                throw new NoSuchElementException();
-            TrieNode node = (TrieNode) stack.remove(size - 1);
-            advance(node);
-            return node;
-        }
-
-        /**
-         * Scan the tree (top-down) starting at the already visited node until
-         * finding an appropriate node with not null value for next(). Keep
-         * unvisited nodes in a stack of siblings iterators. Return either an
-         * empty stack, or a stack whose top will be the next node returned by
-         * next().
-         */
-        private void advance(TrieNode node) {
-            Iterator children = node.childrenForward();
-            while (true) { // scan siblings and their children
-                int size;
-                if (children.hasNext()) {
-                    node = (TrieNode) children.next();
-                    if (children.hasNext()) // save siblings
-                        stack.add(children);
-                    // check current node and scan its sibling if necessary
-                    if (withNulls || node.getValue() == null)
-                        children = node.childrenForward(); // loop from there
-                    else { // node qualifies for next()
-                        stack.add(node);
-                        return; // next node exists
-                    }
-                } else if ((size = stack.size()) == 0)
-                    return; // no next node
-                else
-                    // no more siblings, return to parent
-                    children = (Iterator) stack.remove(size - 1);
-            }
-        }
-    }
-
-    /**
-     * Returns a string representation of the tree state of this, i.e., the
-     * concrete state. (The version of toString commented out below returns a
-     * representation of the abstract state of this.
-     */
-    public String toString() {
-        StringBuffer buf = new StringBuffer();
-        buf.append("<root>"); //$NON-NLS-1$
-        toStringHelper(root, buf, 1);
-        return buf.toString();
-    }
-
-    /**
-     * Prints a description of the substree starting with start to buf. The
-     * printing starts with the given indent level. (internal)
-     */
-    private void toStringHelper(TrieNode start, StringBuffer buf, int indent) {
-        // Print value of node.
-        if (start.getValue() != null) {
-            buf.append(" -> "); //$NON-NLS-1$
-            buf.append(start.getValue().toString());
-        }
-        buf.append("\n"); //$NON-NLS-1$
-        // For each child...
-        for (Iterator iter = start.labelsForward(); iter.hasNext();) {
-            // Indent child appropriately.
-            for (int i = 0; i < indent; i++)
-                buf.append(" "); //$NON-NLS-1$
-            // Print edge.
-            String label = (String) iter.next();
-            buf.append(label);
-            // Recurse to print value.
-            TrieNode child = start.get(label.charAt(0)).getChild();
-            toStringHelper(child, buf, indent + 1);
-        }
+          // no more siblings, return to parent
+          children = (Iterator) stack.remove(size - 1);
+      }
+    }
+  }
+
+  /**
+   * Returns a string representation of the tree state of this, i.e., the
+   * concrete state. (The version of toString commented out below returns a
+   * representation of the abstract state of this.
+   */
+  public String toString() {
+    StringBuffer buf = new StringBuffer();
+    buf.append("<root>"); //$NON-NLS-1$
+    toStringHelper(root, buf, 1);
+    return buf.toString();
+  }
+
+  /**
+   * Prints a description of the substree starting with start to buf. The
+   * printing starts with the given indent level. (internal)
+   */
+  private void toStringHelper(TrieNode start, StringBuffer buf, int indent) {
+    // Print value of node.
+    if (start.getValue() != null) {
+      buf.append(" -> "); //$NON-NLS-1$
+      buf.append(start.getValue().toString());
+    }
+    buf.append("\n"); //$NON-NLS-1$
+    // For each child...
+    for (Iterator iter = start.labelsForward(); iter.hasNext();) {
+      // Indent child appropriately.
+      for (int i = 0; i < indent; i++)
+        buf.append(" "); //$NON-NLS-1$
+      // Print edge.
+      String label = (String) iter.next();
+      buf.append(label);
+      // Recurse to print value.
+      TrieNode child = start.get(label.charAt(0)).getChild();
+      toStringHelper(child, buf, indent + 1);
     }
+  }
 }
 
 /**
@@ -526,205 +526,205 @@ public class Trie<S,V> {
  * that is Trie's job. Nor does it deal with case.
  */
 final class TrieNode<V> {
-    /**
-     * The value of this node.
-     */
-    private V value = null;
-
-    /**
-     * The list of children. Children are stored as a sorted Vector because it
-     * is a more compact than a tree or linked lists. Insertions and deletions
-     * are more expensive, but they are rare compared to searching.
-     * <p>
-     * 
-     * INVARIANT: children are sorted by distinct first characters of edges,
-     * i.e., for all i &lt; j,<br>
-     * children[i].edge.charAt(0) &lt; children[j].edge.charAt(0)
-     */
-    private ArrayList<TrieEdge<V>> /* of TrieEdge */children = new ArrayList<TrieEdge<V>>(0);
-
-    /**
-     * Creates a trie with no children and no value.
-     */
-    public TrieNode() {
-    }
-
-    /**
-     * Creates a trie with no children and the given value.
-     */
-    public TrieNode(V value) {
-        this.value = value;
-    }
-
-    /**
-     * Gets the value associated with this node, or null if none.
-     */
-    public V getValue() {
-        return value;
-    }
-
-    /**
-     * Sets the value associated with this node.
-     */
-    public void setValue(V value) {
-        this.value = value;
-    }
-
-    /**
-     * Get the nth child edge of this node.
-     * 
-     * @requires 0 &lt;= i &lt; children.size()
-     */
-    private final TrieEdge<V> get(int i) {
-        return children.get(i);
-    }
-
-    /**
-     * (internal) If exact, returns the unique i so that:
-     * children[i].getLabelStart() == c<br>
-     * If !exact, returns the largest i so that: children[i].getLabelStart()
-     * &lt;= c<br>
-     * In either case, returns -1 if no such i exists.
-     * <p>
-     * 
-     * This method uses binary search and runs in O(log N) time, where N =
-     * children.size().<br>
-     * The standard Java binary search methods could not be used because they
-     * only return exact matches. Also, they require allocating a dummy Trie.
-     * 
-     * Example1: Search non exact c == '_' in {[0] => 'a...', [1] => 'c...'};
-     * start loop with low = 0, high = 1; middle = 0, cmiddle == 'a', c <
-     * cmiddle, high = 0 (low == 0); middle = 0, cmiddle == 'a', c < cmiddle,
-     * high = -1 (low == 0); end loop; return high == -1 (no match, insert at
-     * 0). Example2: Search non exact c == 'a' in {[0] => 'a', [1] => 'c'} start
-     * loop with low = 0, high = 1; middle = 0, cmiddle == 'a', c == cmiddle,
-     * abort loop by returning middle == 0 (exact match). Example3: Search non
-     * exact c == 'b' in {[0] => 'a...', [1] => 'c...'}; start loop with low =
-     * 0, high = 1; middle = 0, cmiddle == 'a', cmiddle < c, low = 1 (high ==
-     * 1); middle = 1, cmiddle == 'c', c < cmiddle, high = 0 (low == 1); end
-     * loop; return high == 0 (no match, insert at 1). Example4: Search non
-     * exact c == 'c' in {[0] => 'a...', [1] => 'c...'}; start loop with low =
-     * 0, high = 1; middle = 0, cmiddle == 'a', cmiddle < c, low = 1 (high ==
-     * 1); middle = 1, cmiddle == 'c', c == cmiddle, abort loop by returning
-     * middle == 1 (exact match). Example5: Search non exact c == 'd' in {[0] =>
-     * 'a...', [1] => 'c...'}; start loop with low = 0, high = 1; middle = 0,
-     * cmiddle == 'a', cmiddle < c, low = 1 (high == 1); middle = 1, cmiddle ==
-     * 'c', cmiddle < c, low = 2 (high == 1); end loop; return high == 1 (no
-     * match, insert at 2).
-     */
-    private final int search(char c, boolean exact) {
-        // This code is stolen from IntSet.search.
-        int low = 0;
-        int high = children.size() - 1;
-        while (low <= high) {
-            int middle = (low + high) / 2;
-            char cmiddle = get(middle).getLabelStart();
-            if (cmiddle < c)
-                low = middle + 1;
-            else if (c < cmiddle)
-                high = middle - 1;
-            else
-                // c == cmiddle
-                return middle; // Return exact match.
-        }
-        if (exact)
-            return -1; // Return no match.
-        return high; // Return closest *lower or equal* match. (This works!)
-    }
-
-    /**
-     * Returns the edge (at most one) whose label starts with the given
-     * character, or null if no such edge.
-     */
-    public TrieEdge<V> get(char labelStart) {
-        int i = search(labelStart, true);
-        if (i < 0)
-            return null;
-        TrieEdge<V> ret = get(i);
-        return ret;
-    }
-
-    /**
-     * Inserts an edge with the given label to the given child to this. Keeps
-     * all edges binary sorted by their label start.
-     * 
-     * @requires label not empty.
-     * @requires for all edges E in this, label.getLabel[0] != E not already
-     *           mapped to a node.
-     * @modifies this
-     */
-    public void put(String label, TrieNode<V> child) {
-        int i;
-        // If there's a match it is the closest lower or equal one, and
-        // precondition requires it to be lower, so we add the edge *after*
-        // it. If there's no match, there are two cases: the Trie is empty,
-        // or the closest match returned is the last edge in the list.
-        if ((i = search(label.charAt(0), // find closest match
-                false)) >= 0) {
-        }
-        children.add(i + 1, new TrieEdge<V>(label, child));
-    }
-
-    /**
-     * Removes the edge (at most one) whose label starts with the given
-     * character. Returns true if any edges where actually removed.
-     */
-    public boolean remove(char labelStart) {
-        int i;
-        if ((i = search(labelStart, true)) < 0)
-            return false;
-        children.remove(i);
-        return true;
-    }
-
-    /**
-     * Ensures that this's children take a minimal amount of storage. This
-     * should be called after numerous calls to add().
-     * 
-     * @modifies this
-     */
-    public void trim() {
-        children.trimToSize();
-    }
-
-    /**
-     * Returns the children of this in forward order, as an iterator of
-     * TrieNode.
-     */
-    public Iterator childrenForward() {
-        return new ChildrenForwardIterator();
-    }
-
-    /**
-     * Maps (lambda(edge) edge.getChild) on children.iterator().
-     */
-    private class ChildrenForwardIterator extends UnmodifiableIterator {
-        int i = 0;
-
-        public boolean hasNext() {
-            return i < children.size();
-        }
-
-        public Object next() {
-            if (i < children.size())
-                return get(i++).getChild();
-            throw new NoSuchElementException();
-        }
-    }
-
-    /**
-     * Returns the children of this in forward order, as an iterator of
-     * TrieNode.
-     */
-    /*
+  /**
+   * The value of this node.
+   */
+  private V value = null;
+
+  /**
+   * The list of children. Children are stored as a sorted Vector because it
+   * is a more compact than a tree or linked lists. Insertions and deletions
+   * are more expensive, but they are rare compared to searching.
+   * <p>
+   * 
+   * INVARIANT: children are sorted by distinct first characters of edges,
+   * i.e., for all i &lt; j,<br>
+   * children[i].edge.charAt(0) &lt; children[j].edge.charAt(0)
+   */
+  private ArrayList<TrieEdge<V>> /* of TrieEdge */children = new ArrayList<TrieEdge<V>>(0);
+
+  /**
+   * Creates a trie with no children and no value.
+   */
+  public TrieNode() {
+  }
+
+  /**
+   * Creates a trie with no children and the given value.
+   */
+  public TrieNode(V value) {
+    this.value = value;
+  }
+
+  /**
+   * Gets the value associated with this node, or null if none.
+   */
+  public V getValue() {
+    return value;
+  }
+
+  /**
+   * Sets the value associated with this node.
+   */
+  public void setValue(V value) {
+    this.value = value;
+  }
+
+  /**
+   * Get the nth child edge of this node.
+   * 
+   * @requires 0 &lt;= i &lt; children.size()
+   */
+  private final TrieEdge<V> get(int i) {
+    return children.get(i);
+  }
+
+  /**
+   * (internal) If exact, returns the unique i so that:
+   * children[i].getLabelStart() == c<br>
+   * If !exact, returns the largest i so that: children[i].getLabelStart()
+   * &lt;= c<br>
+   * In either case, returns -1 if no such i exists.
+   * <p>
+   * 
+   * This method uses binary search and runs in O(log N) time, where N =
+   * children.size().<br>
+   * The standard Java binary search methods could not be used because they
+   * only return exact matches. Also, they require allocating a dummy Trie.
+   * 
+   * Example1: Search non exact c == '_' in {[0] => 'a...', [1] => 'c...'};
+   * start loop with low = 0, high = 1; middle = 0, cmiddle == 'a', c <
+   * cmiddle, high = 0 (low == 0); middle = 0, cmiddle == 'a', c < cmiddle,
+   * high = -1 (low == 0); end loop; return high == -1 (no match, insert at
+   * 0). Example2: Search non exact c == 'a' in {[0] => 'a', [1] => 'c'} start
+   * loop with low = 0, high = 1; middle = 0, cmiddle == 'a', c == cmiddle,
+   * abort loop by returning middle == 0 (exact match). Example3: Search non
+   * exact c == 'b' in {[0] => 'a...', [1] => 'c...'}; start loop with low =
+   * 0, high = 1; middle = 0, cmiddle == 'a', cmiddle < c, low = 1 (high ==
+   * 1); middle = 1, cmiddle == 'c', c < cmiddle, high = 0 (low == 1); end
+   * loop; return high == 0 (no match, insert at 1). Example4: Search non
+   * exact c == 'c' in {[0] => 'a...', [1] => 'c...'}; start loop with low =
+   * 0, high = 1; middle = 0, cmiddle == 'a', cmiddle < c, low = 1 (high ==
+   * 1); middle = 1, cmiddle == 'c', c == cmiddle, abort loop by returning
+   * middle == 1 (exact match). Example5: Search non exact c == 'd' in {[0] =>
+   * 'a...', [1] => 'c...'}; start loop with low = 0, high = 1; middle = 0,
+   * cmiddle == 'a', cmiddle < c, low = 1 (high == 1); middle = 1, cmiddle ==
+   * 'c', cmiddle < c, low = 2 (high == 1); end loop; return high == 1 (no
+   * match, insert at 2).
+   */
+  private final int search(char c, boolean exact) {
+    // This code is stolen from IntSet.search.
+    int low = 0;
+    int high = children.size() - 1;
+    while (low <= high) {
+      int middle = (low + high) / 2;
+      char cmiddle = get(middle).getLabelStart();
+      if (cmiddle < c)
+        low = middle + 1;
+      else if (c < cmiddle)
+        high = middle - 1;
+      else
+        // c == cmiddle
+        return middle; // Return exact match.
+    }
+    if (exact)
+      return -1; // Return no match.
+    return high; // Return closest *lower or equal* match. (This works!)
+  }
+
+  /**
+   * Returns the edge (at most one) whose label starts with the given
+   * character, or null if no such edge.
+   */
+  public TrieEdge<V> get(char labelStart) {
+    int i = search(labelStart, true);
+    if (i < 0)
+      return null;
+    TrieEdge<V> ret = get(i);
+    return ret;
+  }
+
+  /**
+   * Inserts an edge with the given label to the given child to this. Keeps
+   * all edges binary sorted by their label start.
+   * 
+   * @requires label not empty.
+   * @requires for all edges E in this, label.getLabel[0] != E not already
+   *           mapped to a node.
+   * @modifies this
+   */
+  public void put(String label, TrieNode<V> child) {
+    int i;
+    // If there's a match it is the closest lower or equal one, and
+    // precondition requires it to be lower, so we add the edge *after*
+    // it. If there's no match, there are two cases: the Trie is empty,
+    // or the closest match returned is the last edge in the list.
+    if ((i = search(label.charAt(0), // find closest match
+        false)) >= 0) {
+    }
+    children.add(i + 1, new TrieEdge<V>(label, child));
+  }
+
+  /**
+   * Removes the edge (at most one) whose label starts with the given
+   * character. Returns true if any edges where actually removed.
+   */
+  public boolean remove(char labelStart) {
+    int i;
+    if ((i = search(labelStart, true)) < 0)
+      return false;
+    children.remove(i);
+    return true;
+  }
+
+  /**
+   * Ensures that this's children take a minimal amount of storage. This
+   * should be called after numerous calls to add().
+   * 
+   * @modifies this
+   */
+  public void trim() {
+    children.trimToSize();
+  }
+
+  /**
+   * Returns the children of this in forward order, as an iterator of
+   * TrieNode.
+   */
+  public Iterator childrenForward() {
+    return new ChildrenForwardIterator();
+  }
+
+  /**
+   * Maps (lambda(edge) edge.getChild) on children.iterator().
+   */
+  private class ChildrenForwardIterator extends UnmodifiableIterator {
+    int i = 0;
+
+    public boolean hasNext() {
+      return i < children.size();
+    }
+
+    public Object next() {
+      if (i < children.size())
+        return get(i++).getChild();
+      throw new NoSuchElementException();
+    }
+  }
+
+  /**
+   * Returns the children of this in forward order, as an iterator of
+   * TrieNode.
+   */
+  /*
      * public Iterator childrenBackward() { return new
      * ChildrenBackwardIterator(); }
      */
 
-    /**
-     * Maps (lambda(edge) edge.getChild) on children.iteratorBackward().
-     */
-    /*
+  /**
+   * Maps (lambda(edge) edge.getChild) on children.iteratorBackward().
+   */
+  /*
      * private class ChildrenBackwardIterator extends UnmodifiableIterator { int
      * i = children.size() - 1;
      * 
@@ -734,43 +734,43 @@ final class TrieNode<V> {
      * NoSuchElementException(); } }
      */
 
-    /**
-     * Returns the labels of the children of this in forward order, as an
-     * iterator of Strings.
-     */
-    public Iterator labelsForward() {
-        return new LabelForwardIterator();
-    }
-
-    /**
-     * Maps (lambda(edge) edge.getLabel) on children.iterator()
-     */
-    private class LabelForwardIterator extends UnmodifiableIterator {
-        int i = 0;
-
-        public boolean hasNext() {
-            return i < children.size();
-        }
-
-        public Object next() {
-            if (i < children.size())
-                return get(i++).getLabel();
-            throw new NoSuchElementException();
-        }
-    }
-
-    /**
-     * Returns the labels of the children of this in backward order, as an
-     * iterator of Strings.
-     */
-    /*
+  /**
+   * Returns the labels of the children of this in forward order, as an
+   * iterator of Strings.
+   */
+  public Iterator labelsForward() {
+    return new LabelForwardIterator();
+  }
+
+  /**
+   * Maps (lambda(edge) edge.getLabel) on children.iterator()
+   */
+  private class LabelForwardIterator extends UnmodifiableIterator {
+    int i = 0;
+
+    public boolean hasNext() {
+      return i < children.size();
+    }
+
+    public Object next() {
+      if (i < children.size())
+        return get(i++).getLabel();
+      throw new NoSuchElementException();
+    }
+  }
+
+  /**
+   * Returns the labels of the children of this in backward order, as an
+   * iterator of Strings.
+   */
+  /*
      * public Iterator labelsBackward() { return new LabelBackwardIterator(); }
      */
 
-    /**
-     * Maps (lambda(edge) edge.getLabel) on children.iteratorBackward()
-     */
-    /*
+  /**
+   * Maps (lambda(edge) edge.getLabel) on children.iteratorBackward()
+   */
+  /*
      * private class LabelBackwardIterator extends UnmodifiableIterator { int i =
      * children.size() - 1;
      * 
@@ -780,51 +780,50 @@ final class TrieNode<V> {
      * NoSuchElementException(); } }
      */
 
-    // inherits javadoc comment.
-    public String toString() {
-        Object val = getValue();
-        if (val != null)
-            return val.toString();
-        return "NULL"; //$NON-NLS-1$
-    }
-
-    /**
-     * Unit test.
-     * 
-     * @see TrieNodeTest
-     */
+  // inherits javadoc comment.
+  public String toString() {
+    Object val = getValue();
+    if (val != null)
+      return val.toString();
+    return "NULL"; //$NON-NLS-1$
+  }
+
+  /**
+   * Unit test.
+   * 
+   * @see TrieNodeTest
+   */
 }
 
 /**
  * A labelled edge, i.e., a String label and a TrieNode endpoint.
  */
 final class TrieEdge<V> {
-    private String label;
-    private TrieNode<V> child;
-
-    /**
-     * @requires label.size() > 0
-     * @requires child != null
-     */
-    TrieEdge(String label, TrieNode<V> child) {
-        this.label = label;
-        this.child = child;
-    }
-
-    public String getLabel() {
-        return label;
-    }
-
-    /**
-     * Returns the first character of the label, i.e., getLabel().charAt(0).
-     */
-    public char getLabelStart() {
-        // You could store this char as an optimization if needed.
-        return label.charAt(0);
-    }
-
-    public TrieNode<V> getChild() {
-        return child;
-    }
+  private String label;
+  private TrieNode<V> child;
 
+  /**
+   * @requires label.size() > 0
+   * @requires child != null
+   */
+  TrieEdge(String label, TrieNode<V> child) {
+    this.label = label;
+    this.child = child;
+  }
+
+  public String getLabel() {
+    return label;
+  }
+
+  /**
+   * Returns the first character of the label, i.e., getLabel().charAt(0).
+   */
+  public char getLabelStart() {
+    // You could store this char as an optimization if needed.
+    return label.charAt(0);
+  }
+
+  public TrieNode<V> getChild() {
+    return child;
+  }
 }
\ No newline at end of file

Modified: lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/UnhandledException.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/UnhandledException.java?rev=1479410&r1=1479409&r2=1479410&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/UnhandledException.java (original)
+++ lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/UnhandledException.java Sun May  5 22:26:35 2013
@@ -19,31 +19,29 @@ package org.apache.lucene.analysis.kr.ut
 
 public class UnhandledException extends RuntimeException {
 
-    /**
-     * Required for serialization support.
-     * 
-     * @see java.io.Serializable
-     */
-    private static final long serialVersionUID = 1832101364842773720L;
+  /**
+   * Required for serialization support.
+   * 
+   * @see java.io.Serializable
+   */
+  private static final long serialVersionUID = 1832101364842773720L;
 
-    /**
-     * Constructs the exception using a cause.
-     *
-     * @param cause  the underlying cause
-     */
-    public UnhandledException(Throwable cause) {
-        super(cause);
-    }
+  /**
+   * Constructs the exception using a cause.
+   *
+   * @param cause  the underlying cause
+   */
+  public UnhandledException(Throwable cause) {
+    super(cause);
+  }
 
-    /**
-     * Constructs the exception using a message and cause.
-     *
-     * @param message  the message to use
-     * @param cause  the underlying cause
-     */
-    public UnhandledException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    
+  /**
+   * Constructs the exception using a message and cause.
+   *
+   * @param message  the message to use
+   * @param cause  the underlying cause
+   */
+  public UnhandledException(String message, Throwable cause) {
+    super(message, cause);
+  }
 }

Modified: lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/UnmodifiableIterator.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/UnmodifiableIterator.java?rev=1479410&r1=1479409&r2=1479410&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/UnmodifiableIterator.java (original)
+++ lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/UnmodifiableIterator.java Sun May  5 22:26:35 2013
@@ -21,8 +21,7 @@ import java.util.Iterator;
 
 public abstract class UnmodifiableIterator implements Iterator {
 
-    public void remove() {
-        throw new UnsupportedOperationException("Cannot remove from this iterator");
-    }
-
+  public void remove() {
+    throw new UnsupportedOperationException("Cannot remove from this iterator");
+  }
 }
\ No newline at end of file