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.taglet;
017    
018    import java.lang.reflect.Field;
019    
020    import com.sun.javadoc.Tag;
021    import com.sun.javadoc.Doc;
022    import com.sun.javadoc.MethodDoc;
023    import com.sun.javadoc.ClassDoc;
024    import com.sun.javadoc.PackageDoc;
025    import com.sun.javadoc.ProgramElementDoc;
026    
027    /**
028     * Doclet ã‚’å?ç?™ã‚‹ã?ログラãƒ?§å…±é€šã—ã¦ä½¿ç”¨ã•れる簡易メソãƒ?ƒ‰ç¾¤(ユーãƒ?‚£ãƒªãƒ?‚£ã‚¯ãƒ©ã‚¹)ã§ã™ã?
029     *
030     * @version  4.0
031     * @author   Kazuhiko Hasegawa
032     * @since    JDK5.0,
033     */
034    public final class DocletUtil {
035            /** リターンコー� System.getProperty("line.separator")  */
036            public static final String CR = System.getProperty("line.separator");
037    
038            private static final String CLS = "org.opengion.hayabusa.common.BuildNumber";           // package.class
039            private static final String FLD = "VERSION_NO";                                                                         // field
040            private static String versionNo = null; // æœ??ã«ä¸?º¦ã?‘å–å¾—ã—ã¦ãŠãã¾ã™ã?
041    
042            /**
043             * ã™ã¹ã¦ã?staticメソãƒ?ƒ‰ãªã®ã§ã€ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã‚’呼ã³å‡ºã•ãªãã—ã¦ãŠãã¾ã™ã?
044             *
045             */
046            private DocletUtil() {}
047    
048            /**
049             * 入力文字å?ã® HTML æ–?­—をフィルタリングã—ã¾ã™ã?
050             * "&" ã¯ã€?&amp;#38;" ã€?<" ã¯ã€?&amp;lt;" ã€?>" ã¯ã€?&amp;gt;" ã«å¤‰æ›ã—ã¾ã™ã?
051             * StringUtil.htmlFilter ã¨ã®é•ã„ã¯ã€?;' â†?"&#59;" ã¸ã®å¤‰æ›ãŒã‚ã‚‹ã“ã¨ã§ã™ã?
052             *
053             * @og.rev 5.5.4.1 (2012/07/06) DocletUtil.htmlFilter â†?StringUtil.htmlFilter ã«å¤‰æ›´ã®ãŸã‚ã€å»?­¢
054             *
055             * @param input String
056             *
057             * @return 変æ›å¾Œæ–‡å­—å?
058             */
059    //      public static String htmlFilter( final String input ) {
060    //              if( input == null ) { return ""; }
061    //
062    //              int len = input.length();
063    //
064    //              StringBuilder rtn = new StringBuilder( len + 50 );
065    //              char ch;
066    //              for(int i=0; i<len; i++) {
067    //                      ch = input.charAt(i);
068    //                      switch( ch ) {
069    //                              case '<'  : rtn.append("&lt;");   break;
070    //                              case '>'  : rtn.append("&gt;");   break;
071    //                              case '"'  : rtn.append("&quot;"); break;
072    //                              case '\'' : rtn.append("&#39;");  break;
073    //                              case '&'  : rtn.append("&amp;");  break;
074    //                              case ';'  : rtn.append("&#59;");  break;
075    //                              default   : rtn.append(ch);
076    //                      }
077    //              }
078    //              return( rtn.toString() );
079    //      }
080    
081            /**
082             * target æ–?­—å?ã«å«ã¾ã‚Œã‚‹ from æ–?­—å?ã‚?to æ–?­—å?ã«ç½®ãæ›ãˆã¾ã™ã?
083             *
084             * @param       target  å…??æ–?­—å?
085             * @param       from    ç½®æ›å?FROM
086             * @param       to              ç½®æ›å?TO
087             *
088             * @return      変æ›å¾Œæ–‡å­—å?
089             */
090            public static String replace( final String target,final String from,final String to ) {
091                    if( target == null || from == null || to == null ) { return target; }
092                    StringBuilder strBuf = new StringBuilder( 200 );
093    
094                    int start = 0;
095                    int end   = target.indexOf( from,start );
096                    while( end >= 0  ) {
097                            strBuf.append( target.substring( start,end ) );
098                            strBuf.append( to );
099                            start = end + from.length();
100                            end   = target.indexOf( from,start );
101                    }
102                    strBuf.append( target.substring( start ) );
103    
104                    return strBuf.toString();
105            }
106    
107            /**
108             * ã‚³ãƒ¡ãƒ³ãƒˆéƒ¨ã®æ–?­—å?ã‚’å–å¾—ã—ã¾ã™ã?
109             *
110             * @og.rev 5.5.4.1 (2012/07/06) コメントã?æ–?­—å?ã§ãªãã?Tagé…å?ã¨ã—ã¦å‡¦ç?•ã›ã‚‹ã€?
111             *
112             * @param cmnt String
113             *
114             * @return コメント文字å?
115             */
116    //      public static String commentText( final String cmnt ) {
117    //              if( cmnt == null ) { return ""; }
118    //
119    //              String rtn = cmnt;
120    //              int indx = cmnt.indexOf( "{@value}" );
121    //              if( indx >= 0 ) {
122    //                      rtn = cmnt.substring( indx+8 ); // {@value} 以å‰ã‚’削除
123    //              }
124    //              return htmlFilter( rtn );
125    //      }
126    
127            /**
128             * ã‚»ãƒ?‚¿ãƒ¼ãƒ¡ã‚½ãƒ?ƒ‰ã® setXXXX ã® set を削除ã—ã?æ¬¡ã®æ–?­—ã‚’å°æ–‡å­—化ã—ã¾ã™ã?
129             * ã¤ã¾ã‚Šã?ã‚»ãƒ?‚¿ãƒ¼ãƒ¡ã‚½ãƒ?ƒ‰ã‹ã‚‰å±žæ?値を推測ã—ã¾ã™ã?
130             * (è¶?‰¹æ®Šå?ç?ã‚»ãƒ?‚¿ãƒ¼ãƒ¡ã‚½ãƒ?ƒ‰ã®set以下2文字目ãŒå¤§æ–?­—ã?å ´åˆã?ã€?
131             * ?‘文字目も大æ–?­—ã¨è€?ˆã¦å°æ–‡å­—化を行ã„ã¾ã›ã‚“ã€?
132             * 例ãˆã°ã€setSYS ã‚?setUSER ãªã©ã€RequestValueTag.javaã«ä½¿ç”¨ã™ã‚‹ã‚±ãƒ¼ã‚¹ã§ã™ã?
133             *
134             * @param target 処ç?¯¾è±¡ã¨ãªã‚‹æ–‡å­—å?
135             *
136             * @return オプションæ–?­—å?
137             */
138            public static String removeSetter( final String target ) {
139                    if( target != null && target.startsWith( "set" ) ) {
140                            char[] chs = target.toCharArray();
141                            if( chs.length > 4 && !( chs[4] >= 'A' && chs[4] <= 'Z' ) ) {
142                                    chs[3] = Character.toLowerCase( chs[3] ) ;
143                            }
144                            return new String( chs,3,chs.length-3 );
145                    }
146                    return target;
147            }
148    
149            /**
150             * オプションé…å?æ–?­—å?ã‚ˆã‚Šã€æŒ‡å®šã?キーã«å¯¾å¿œã™ã‚‹ã‚ªãƒ—ション値を返ã—ã¾ã™ã?
151             *
152             * @param       key             キー
153             * @param       options オプションé…å?æ–?­—å?
154             *
155             * @return      オプションæ–?­—å?
156             */
157            public static String getOption( final String key , final String[][] options ) {
158                    String rtn = "";
159                    if( key == null || options == null ) { return rtn; }
160    
161                    for( int i=0; i<options.length; i++ ) {
162                            if( key.equalsIgnoreCase( options[i][0] ) ) {
163                                    rtn = options[i][1];
164                                    break ;
165                            }
166                    }
167                    return rtn ;
168            }
169    
170            /**
171             * {&#064;og.value package.class#field} å½¢å¼ã?valueタグを文字å?ã«ç½®ãæ›ãˆã¾ã™ã?
172             *
173             * 処ç?š„ã«ã¯ã€ãƒªãƒ•レクションã§ã€å?ã‚’å–å¾—ã—ã¾ã™ã?値ã¯ã€staticフィールドã?ã¿å–å¾—å¯èƒ½ã§ã™ã?
174             *
175             * @og.rev 5.5.4.1 (2012/07/06) æ–°è¦è¿½åŠ?
176             * @og.rev 5.5.5.6 (2012/08/31) クラスåã?å–å¾—ã§ã€ProgramElementDoc ã§å‡¦ç?™ã‚‹ã‚ˆã?«å¤‰æ›´
177             *
178             * @param tag Tagオブジェク�
179             *
180             * @return valueã‚¿ã‚°ã®è§£æžçµæžœã®æ–?­—å?
181             */
182            public static String valueTag( final Tag tag ) {
183                    String txt = tag.text();
184                    if( txt != null ) {
185                            String cls = null;              // package.class
186                            String fld = null;              // field
187    
188                            // package.class#field å½¢å¼ã?è§£æžã?
189                            int adrs = txt.indexOf('#') ;
190                            if( adrs > 0 ) {
191                                    cls = txt.substring( 0,adrs );          // package.class
192                                    fld = txt.substring( adrs+1 );          // field
193                            }
194                            else if( adrs == 0 ) {
195                                    fld = txt.substring( 1 );                       // #field
196                            }
197                            else {
198                                    String errMsg = "è­¦å‘?{@value package.class#field} å½¢å¼ã? フィールドå #field ãŒã‚りã¾ã›ã‚“ã€? + CR
199                                                                    + tag.position() + " : " + txt + CR ;
200                                    System.err.println( errMsg );
201                                    // # を付ã‘忘れãŸã¨è€?ˆã€è?åˆ??身ã®ã‚¯ãƒ©ã‚¹ã‚’利用
202                                    fld = txt;                                                      // field
203                            }
204    
205                            // package.class ã‚’ãã¡ã‚“ã¨ä½œæ?ã™ã‚‹ã€?
206                            Doc doc = tag.holder();
207    //                      if( doc.isMethod() ) {
208    //                              MethodDoc mdoc = (MethodDoc)doc;
209    //                              ClassDoc cdoc = mdoc.containingClass();
210    //                              if( cls == null ) {                                     // package.class ãŒç™»éŒ²ã•れã¦ã?ªã??åˆã?
211    //                                      cls = cdoc.qualifiedName() ;
212    //                              }
213    //                              else if( cls.indexOf('.') < 0 ) {    // class ã®ã¿ãŒç™»éŒ²ã•れã¦ã?‚‹å ´åˆã?findClass ã§ã€package è¾¼ã®æ­£å¼ã‚¯ãƒ©ã‚¹åを検索ã™ã‚‹ã€?
214    //                                      ClassDoc pdoc = cdoc.findClass( cls );
215    //                                      cls = pdoc.qualifiedName() ;
216    //                              }
217    //                      }
218    
219                            // 5.5.5.6 (2012/08/31) ProgramElementDoc ã§å‡¦ç?™ã‚‹ã‚ˆã?«å¤‰æ›´
220                            if( doc instanceof ProgramElementDoc ) {
221                                    ProgramElementDoc pdoc = (ProgramElementDoc)doc;
222                                    ClassDoc cdoc = pdoc.containingClass();
223                                    if( cdoc != null ) {
224                                            if( cls == null ) {                                     // package.class ãŒç™»éŒ²ã•れã¦ã?ªã??åˆã?
225                                                    cls = cdoc.qualifiedName() ;
226                                            }
227                                            else if( cls.indexOf('.') < 0 ) {    // class ã®ã¿ãŒç™»éŒ²ã•れã¦ã?‚‹å ´åˆã?findClass ã§ã€package è¾¼ã®æ­£å¼ã‚¯ãƒ©ã‚¹åを検索ã™ã‚‹ã€?
228                                                    ClassDoc fdoc = cdoc.findClass( cls );
229                                                    if( fdoc != null ) {
230                                                            cls = fdoc.qualifiedName() ;
231                                                    }
232                                            }
233                                    }
234                                    else {
235                                            if( cls == null ) {                                     // package.class ãŒç™»éŒ²ã•れã¦ã?ªã??åˆã?
236                                                    cls = pdoc.qualifiedName() ;
237                                            }
238                                    }
239                            }
240    
241                            //  5.6.3.3 (2013/04/19) メソãƒ?ƒ‰åŒ–ã§å…±æœ‰ã—ã¾ã™ã?
242                            txt = getStaticField( cls,fld );
243    
244    //                      try {
245    //                              Field fldObj = Class.forName( cls ).getDeclaredField( fld );
246    //                              // privateフィールドã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã€?セキュリãƒ?‚£ãƒ¼ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã«ã‚ˆã£ã¦ã‚¢ã‚¯ã‚»ã‚¹åˆ¶é™ãŒã‹ã‘られã¦ã?ªã??å?
247    //                              if( !fldObj.isAccessible() ) { fldObj.setAccessible( true ); }
248    //                              txt = String.valueOf( fldObj.get( null ) );             // static フィールドã?ã€å¼•æ•° null ã§å€¤ã‚’å–å¾?
249    //                      }
250    //                      catch( Exception ex ) {
251    //                              String errMsg = "è­¦å‘?{@value package.class#field} å½¢å¼ã?対象ãŒã‚りã¾ã›ã‚“ã€? + CR
252    //                                                              + tag.position() + " : " + tag.text() + CR
253    //                                                              + ex.getMessage() + CR;
254    //                              System.err.println( errMsg );
255    //                      }
256                    }
257                    return txt ;
258            }
259    
260            /**
261             * {&#064;og.doc03Link queryType Query_**** クラス} å½¢å¼ã?doc03Linkタグをリンクæ–?­—å?ã«ç½®ãæ›ãˆã¾ã™ã?
262             *
263             * <a href="/gf/jsp/DOC03/index.jsp?command=NEW&GAMENID=DOC03&VERNO=X.X.X.X&VALUENAME=queryType" target="CONTENTS">Query_**** クラス</a>
264             * ã®ã‚ˆã†ãªãƒªãƒ³ã‚¯ã‚’作æ?ã—ã¾ã™ã?
265             * 第ä¸?¼•æ•°ã¯ã€VALUENAME ã®å¼•æ•°ã§ã™ã?
266             * ãれ以é™ã?ãƒ?‚­ã‚¹ãƒˆã?ã€ãƒªãƒ³ã‚¯æ–?­—å?ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã«ãªã‚Šã¾ã™ã?
267             * DOC03 ç”»é¢ã¸ã®ãƒªãƒ³ã‚¯ã‚’作æ?ã™ã‚‹ã«å½“ãŸã‚Šã?ãƒã?ジョンãŒå¿?¦ã§ã™ã?org.opengion.hayabusa.common.BuildNumber#VERSION_NO ã‹ã‚‰å–å¾—ã—ã¾ã™ãŒã€?
268             * パッケージã®å„ªå…ˆé?ã®é–¢ä¿‚ã§ã€ãƒªãƒ•レクションを使用ã—ã¾ã™ã?
269             *
270             * @og.rev 5.6.3.3 (2013/04/19) æ–°è¦ä½œæ?
271             *
272             * @param tag Tagオブジェク�
273             *
274             * @return valueã‚¿ã‚°ã®è§£æžçµæžœã®æ–?­—å?
275             */
276            public static String doc03LinkTag( final Tag tag ) {
277                    if( versionNo == null ) { versionNo = getStaticField( CLS , FLD ); }
278    
279                    String txt = tag.text();
280                    if( txt != null ) {
281                            String valnm = null;                    // VALUENAME
282                            String body  = null;                    // ドキュメン�
283    
284                            int adrs = txt.indexOf(' ') ;   // æœ??ã®ã‚¹ãƒšã?スã§åˆ?›¢ã—ã¾ã™ã?
285                            if( adrs > 0 ) {
286                                    valnm = txt.substring( 0,adrs );                // VALUENAME
287                                    body  = txt.substring( adrs+1 );                // ドキュメン�
288                            }
289                            else {
290                                    valnm = txt;                                                    // VALUENAME
291                                    body  = txt;                                                    // ドキュメン�
292                            }
293    
294                            txt = "&lt;a href=\"/gf/jsp/DOC03/index.jsp?command=NEW&amp;GAMENID=DOC03"
295                                            + "&amp;VERNO="     + versionNo
296                                            + "&amp;VALUENAME=" + valnm
297                                            + "\" target=\"CONTENTS\"&gt;"
298                                            + body
299                                            + "&lt;/a&gt;" ;
300                    }
301                    return txt ;
302            }
303    
304            /**
305             * パッケージ.クラスå?ã¨ã€ãƒ•ィールドå ã‹ã‚‰ã€staticフィールドã?値をå–å¾—ã—ã¾ã™ã?
306             *
307             * Field fldObj = Class.forName( cls ).getDeclaredField( fld ); ã§ã€Fieldオブジェクトを呼出ã—ã?
308             * String.valueOf( fldObj.get( null ) ); ã§ã€å?ã‚’å–å¾—ã—ã¦ã?¾ã™ã?
309             * static フィールドã?ã€å¼•æ•° null ã§å€¤ã‚’å–å¾—ã§ãã¾ã™ã?
310             *
311             * 例�
312         *      String cls = "org.opengion.hayabusa.common.BuildNumber";        // package.class
313         *      String fld = "VERSION_NO";                                      // field
314             *
315             * @og.rev 5.6.3.3 (2013/04/19) æ–°è¦ä½œæ?
316             *
317             * @param cls パッケージ.クラスå?
318             * @param fld フィールドå
319             * @return å–å¾—å?
320             */
321            public static String getStaticField( final String cls , final String fld ) {
322    
323                    String txt = null;
324                    try {
325                            Field fldObj = Class.forName( cls ).getDeclaredField( fld );
326                            // privateフィールドã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã€?セキュリãƒ?‚£ãƒ¼ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã«ã‚ˆã£ã¦ã‚¢ã‚¯ã‚»ã‚¹åˆ¶é™ãŒã‹ã‘られã¦ã?ªã??å?
327                            if( !fldObj.isAccessible() ) { fldObj.setAccessible( true ); }
328                            txt = String.valueOf( fldObj.get( null ) );             // static フィールドã?ã€å¼•æ•° null ã§å€¤ã‚’å–å¾?
329                    }
330                    catch( Exception ex ) {
331                            String errMsg = "package.class = " + cls + " field = " + fld + " ã®å–å¾—ã«å¤±æ•—ã—ã¾ã—ãŸã€?
332                                                            + ex.getMessage() + CR;
333                            System.err.println( errMsg );
334                    }
335    
336                    return txt ;
337            }
338    }