001 /*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016 package org.opengion.fukurou.util;
017
018 import java.util.Set;
019 import java.util.TreeSet;
020 import java.util.Iterator;
021
022 /**
023 * ReplaceString.java は、è¤?•°のæ–?—å?をä¸?‹¬置換するå?合に使用するクラスですã?
024 *
025 * add メソãƒ?ƒ‰でã€?–‹始アドレス、終äº?‚¢ドレス、置換文字å?を指定しã€?
026 * æœ?¾Œに、replaceAll で、変換を行いますã?
027 * 通常、異なる文字å?をä¸?‹¬で変換する場合ã?é€??に変換アドレスを求めてã€?
028 * 後ろからé ?�«置換してã�?�‹なã�?�¨、前から処ç�?�™ると処ç�?�”とにアドレスã�?
029 * 変更になりä¸?�‹らå?計算することになりますã?これは、登録時ã?、どのような
030 * é ?º�でもよくã?replaceAll 時に、å?部に登録æŒ?®šある変換æ–?—å?の開始アドレスより
031 * 自動的にé€??で置換するためã?è¤?•°の置換å?æ‰?�Œあってもã?まとめて処ç�?�§きますã?
032 * ただしã?è¤?•°の置換å?æ‰?�Œある場合ã?重è¤?¦�ç´?�Œあれば、エラーになりますã?
033 *
034 * @version 4.0
035 * @author Kazuhiko Hasegawa
036 * @since JDK5.0,
037 */
038 public final class ReplaceString {
039 private final Set<ReplaceData> set = new TreeSet<ReplaceData>();
040
041 /**
042 * 開始アドレス、終äº?‚¢ドレス、置換文字å?を指定し置換対象を追åŠ?�—ますã?
043 * 通常、文字å?を置換すると、å?のアドレスとずれるã?を防ぐ為ã€?
044 * 後ろから、置換を行いますã?ä¸?‹¬置換ã?、è¤?•°のæ–?—å?置換をã€?–‹始アドレスの
045 * 後ろから、置換を始める為の、å?期データを登録しますã?
046 * 登録é ??、置換é?とは無関係に設定可能ですã?
047 *
048 * @param start 置換開始アドレス
049 * @param end 置換終äº?‚¢ドレス
050 * @param newStr 置換文字å?
051 */
052 public void add( final int start, final int end, final String newStr ) {
053 set.add( new ReplaceData( start, end, newStr ) );
054 }
055
056 /**
057 * 置換å?æ–?—å?を指定して、置換å?ç�?‚’実行しますã?
058 * add メソãƒ?ƒ‰でæŒ?®šした文字å?を実際に置換å?ç�?�—ますã?
059 *
060 * @param target 置換å?æ–?—å?
061 *
062 * @return 置換後文字å?
063 */
064 public String replaceAll( final String target ) {
065 Iterator<ReplaceData> ite = set.iterator();
066 StringBuilder buf = new StringBuilder( target );
067 while( ite.hasNext() ) {
068 ReplaceData data = ite.next();
069 buf = data.replace( buf );
070 }
071 return buf.toString();
072 }
073
074 /**
075 * 置換文字å?を管ç�?�™るå?部クラス
076 *
077 * @version 4.0
078 * @author Kazuhiko Hasegawa
079 * @since JDK5.0,
080 */
081 private static class ReplaceData implements Comparable<ReplaceData> {
082 private final int start ;
083 private final int end ;
084 private final String newStr ;
085 private final int hCode ;
086
087 /**
088 * 開始アドレス、終äº?‚¢ドレス、置換文字å?を指定しますã?
089 * 通常、文字å?を置換すると、å?のアドレスとずれるã?を防ぐ為ã€?
090 * 後ろから、置換を行いますã?ä¸?‹¬置換ã?、è¤?•°のæ–?—å?置換をã€?–‹始アドレスの
091 * 後ろから、置換を始める為の、å?期データを登録しますã?
092 * 登録é ??、置換é?とは無関係に設定可能ですã?
093 *
094 * @param start 置換開始アドレス
095 * @param end 置換終äº?‚¢ドレス
096 * @param newStr 置換文字å?
097 */
098 public ReplaceData( final int start, final int end, final String newStr ) {
099 this.start = start;
100 this.end = end;
101 this.newStr = newStr ;
102 hCode = ( newStr + start + "_" + end ).hashCode();
103 }
104
105 /**
106 * 置換å?ç�?‚’実行しますã?
107 *
108 * @param buf StringBuilder 入力文字å?
109 * @return 出力文字å?
110 */
111 public StringBuilder replace( final StringBuilder buf ) {
112 return buf.replace( start,end,newStr );
113 }
114
115 /**
116 * æŒ?®šã?ReplaceDataの開å§?終äº?�Œ重なってã�?‚‹かどã�?�‹を判定しますã?
117 *
118 * @og.rev 5.7.2.1 (2014/01/17) 判定結果の true/false が反転してã�?�Ÿので、修正
119 *
120 * @param other ReplaceData 入力文字å?
121 * @return オーバã?ラãƒ??してã�?‚‹かどã�?�‹(true:不正/false:正常)
122 */
123 public boolean isOverlap( final ReplaceData other ) {
124 // return ! ( ( other == null ) || ( other.end < start ) || ( end < other.start ) );
125 // return ( ( other == null ) || ( other.end < start ) || ( end < other.start ) );
126 return ( other == null ) || ! ( ( other.end < start ) || ( end < other.start ) );
127
128 }
129
130 /**
131 * 自然比è¼?ƒ¡ソãƒ?ƒ‰
132 * インタフェース Comparable の 実è£?�§すã?
133 * 登録された開始アドレスの降é?になるよã�?�«比è¼?�—ますã?
134 * なおã?比è¼?¯¾照オブジェクトとオーバã?ラãƒ??してã�?‚‹場合ã?ã€?
135 * 比è¼?�§きなã�?�¨して、IllegalArgumentException を発行しますã?
136 *
137 * @og.rev 5.7.4.0 (2014/03/07) 同ä¸?‚ªブジェクトã?判定を追åŠ?
138 *
139 * @param other 比è¼?¯¾象のObject
140 * @return 開始アドレスの降é?(自åˆ??アドレスが小さã�??合ã?ã€?¼?
141 * @throws IllegalArgumentException 引数オブジェクトがオーバã?ラãƒ??してã�?‚‹場å�?
142 */
143 public int compareTo( final ReplaceData other ) {
144 if( other == null ) {
145 String errMsg = "引数に null は設定できませんã€? ;
146 throw new IllegalArgumentException( errMsg );
147 }
148
149 // 5.7.4.0 (2014/03/07) 同ä¸?‚ªブジェクトã?判定を追åŠ?
150 if( other.hCode == hCode ) { return 0; }
151
152 if( isOverlap( other) ) {
153 String errMsg = "比è¼?¯¾照オブジェクトとオーバã?ラãƒ??してã�?�¾すã?"
154 + " this =[" + start + "],[" + end + "],[" + newStr + "]"
155 + " other=[" + other.start + "],[" + other.end + "],[" + other.newStr + "]" ;
156 throw new IllegalArgumentException( errMsg );
157 }
158 return other.start - start; // 開始é?の降é?
159 }
160
161 /**
162 * こã?オブジェクトと他ã?オブジェクトが等しã�?�‹どã�?�‹を示しますã?
163 * インタフェース Comparable の 実è£?�«関連して、å?定義してã�?�¾すã?
164 *
165 * @param other 比è¼?¯¾象の参ç?オブジェクãƒ?
166 * @return obj 引数にæŒ?®šされたオブジェクトとこã?オブジェクトが等しã�??合ã? true、そã�?�§なã�??合ã? false
167 *
168 */
169 public boolean equals( final Object object ) {
170 if( object instanceof ReplaceData ) {
171 ReplaceData other = (ReplaceData)object ;
172 return start == other.start &&
173 end == other.end &&
174 newStr.equals( other.newStr ) ;
175 }
176 return false ;
177 }
178
179 /**
180 * オブジェクトã?ハッシュコードå?を返しますã?
181 * こã?メソãƒ?ƒ‰は、java.util.Hashtable によって提供されるような
182 * ハッシュãƒ??ブルで使用するために用意されてã�?�¾すã?
183 * equals( Object ) メソãƒ?ƒ‰をオーバã?ライトしたå?合ã?、hashCode() メソãƒ?ƒ‰ã‚?
184 * å¿?�š 記述するå¿?¦�がありますã?
185 *
186 *
187 * @return こã?オブジェクトã?ハッシュコードå?
188 *
189 */
190 public int hashCode() {
191 return hCode ;
192 }
193 }
194 }