    001/*
    002 * Copyright (c) 2017 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 */
    016package org.opengion.fukurou.fileexec;
    017
    018//      import java.nio.file.Paths;                                                     // 6.8.1.5 (2017/09/08)
    019
    020import java.util.logging.Logger;
    021import java.util.logging.Level;
    022import java.util.function.Supplier;                                             // 6.8.1.0 (2017/07/14)
    023import java.util.function.Function;                                             // 7.2.5.0 (2020/06/01)
    024
    025/**
    026 * XLoggerは、Throwable を引数に取るwarningと、Level 600 の debug メソッドを
    027 * 持つ、Logger の拡張クラスです。
    028 * ここでは、継承するのではなく、委譲で、最低限のメソッドだけに対応しています。
    029 * (LogManager とか、色々とややこしそうなので、調査する暇が無い)
    030 *
    031 * WARNING(900) → INFO(800) → CONFIG(700) → XXXX(600) → FINE(500) → ALL(Integer.MIN_VALUE)
    032 * となっていますが、FINE では、多すぎ、INFO は、通常使用、間に、DEBUG的な、
    033 * ロギングが欲しい場合に使用します。
    034 * CONFIG を使いたいところですが、｢CONFIGは静的な構成メッセージのメッセージ・レベルです。｣と
    035 * JavaDocにわざわざ、書かれていることから、使用を避けます。
    036 *
    037 * @og.rev 7.0.0.0 (2017/07/07) 新規作成
    038 *
    039 * @version  7.0
    040 * @author   Kazuhiko Hasegawa
    041 * @since    JDK1.8,
    042 */
    043public class XLogger {
    044        // 7.2.5.0 (2020/06/01) 各クラスで、class.getSimpleName() を渡すようにしたので短縮不要。
    045//      /** 初期設定されているリソースバンドルのbaseName {@value} */
    046//      public static final String OMIT_NAME = "org.opengion.fukurou." ;        // fileexec は残す
    047
    048        /**
    049         * デバッグレベルを新規に定義します。
    050         *
    051         * OFF:Integer.MAX_VALUE , SEVERE:1000 , WARNING:900 , INFO:800 , CONFIG:700 , FINE:500 , FINER:400 , FINEST:300 , ALL:Integer.MIN_VALUE
    052         * LEVEL_DEBUG:600 で定義することで、INFO より細かいが、FINE より荒いログ出力が可能です。
    053         * 他のアプリケーションで、INFO は許せても、FINE は許せない場合があるので、独自のログ出力が、可能です。
    054         */
    055        private static final class LEVEL_DEBUG extends Level {
    056                private static final long serialVersionUID = 681020170714L ;            // 6.8.1.0 (2017/07/14)
    057                /**
    058                 * デバッグレベルのコンストラクター
    059                 */
    060                public LEVEL_DEBUG() { super( "DEBUG",600 ); }
    061        };
    062
    063//      private static final Level DEBUG = new LEVEL_DEBUG();
    064        private static final Level L_DEBUG = new LEVEL_DEBUG();                                 // 6.9.7.0 (2018/05/14) PMD Field DEBUG has the same name as a method
    065
    066        private final Logger LOGGER;
    067
    068        /**
    069         * 名前を指定して、XLoggerオブジェクトを作成します。
    070         *
    071         * @og.rev 6.8.1.5 (2017/09/08) logフォルダの存在チェックと作成
    072         *
    073         * @param       name     ロガーの名前。通常は、クラス.class.getName() を渡せばよいです。
    074         */
    075        private XLogger( final String name ) {
    076//              FileUtil.mkdirs( Paths.get( "log" ) );          // Logger の log フォルダが無ければ作成します。
    077
    078                LOGGER = Logger.getLogger( name );
    079        }
    080
    081        /**
    082         * 名前を指定して、XLoggerオブジェクトを作成します。
    083         *
    084         * @og.rev 7.2.1.0 (2020/03/13) ロガーの名前から、共通部分を削除します。
    085         * @og.rev 7.2.5.0 (2020/06/01) 各クラスで、class.getSimpleName() を渡すようにした。
    086         *
    087         * @param       name     ロガーの名前。通常は、クラス.class.getName() を渡せばよいです。
    088         * @return      XLoggerオブジェクト
    089         */
    090        public static XLogger getLogger( final String name ) {
    091//              String key = name ;
    092//              if( key.startsWith( OMIT_NAME ) ) {
    093//                      key = name.substring( OMIT_NAME.length() );
    094//              }
    095
    096//              return new XLogger( name );             // 今は、個別に作成していますが、本来は、同じオブジェクトを返すようにすべき。
    097                return new XLogger( name );             // 各クラスで static で持つのでキャッシュしません。
    098        }
    099
    100        /**
    101         * INFO レベルのログをとります。
    102         *
    103         * 引数は Supplier のみなので、実行直前まで処理されません。
    104         * よって、呼出元では、log level guards する必要はありません。
    105         *
    106         * @og.rev 7.3.0.0 (2021/01/06) PMD:GuardLogStatement:  Logger calls should be surrounded by log level guards.
    107         *
    108         * @param       msgSupplier     呼び出されると、目的のログ・メッセージを生成する関数
    109         * @see         Logger#info( Supplier )
    110         */
    111        public void info( final Supplier<String> msgSupplier ) {
    112                if( LOGGER.isLoggable( Level.INFO ) ) {
    113                        LOGGER.info( msgSupplier );
    114                }
    115        }
    116
    117        /**
    118         * WARNING レベルのログをとります。
    119         *
    120         * 引数は Supplier のみなので、実行直前まで処理されません。
    121         * よって、呼出元では、log level guards する必要はありません。
    122         *
    123         * @og.rev 7.3.0.0 (2021/01/06) PMD:GuardLogStatement:  Logger calls should be surrounded by log level guards.
    124         *
    125         * @param       msgSupplier     呼び出されると、目的のログ・メッセージを生成する関数
    126         * @see         Logger#warning( Supplier )
    127         */
    128        public void warning( final Supplier<String> msgSupplier ) {
    129                if( LOGGER.isLoggable( Level.WARNING ) ) {
    130                        LOGGER.warning( msgSupplier );
    131                }
    132        }
    133
    134        /**
    135         * WARNING レベルのログが、処理されるか、判定します。
    136         *
    137         * 引数が Supplier のみでない場合は、実行前に、log level guards してください。
    138         *
    139         * @og.rev 7.3.0.0 (2021/01/06) 新規追加
    140         *
    141         * @return  args        WARNINGレベルのログを出力する場合は、trueを返します。
    142         */
    143        public boolean isWarningEnabled() {
    144                return LOGGER.isLoggable( Level.WARNING );
    145        }
    146
    147        /**
    148         * WARNING レベルのログをとります。
    149         *
    150         * 引数処理が発生しますので、呼出元で、log level guards してください。
    151         *
    152         * if( XLogger.isWarningEnabled() ) {
    153         *    XLogger.warning( id,args1,args2,… );
    154         * }
    155         *
    156         * @og.rev 7.2.5.0 (2020/06/01) メソッド追加。
    157         *
    158         * @param id    リソースのキーとなるID。
    159         * @param args  リソースを、MessageFormat.format で加工する場合の引数。
    160         * @see         Logger#warning( Supplier )
    161         */
    162        public void warning( final String id , final Object... args ) {
    163                LOGGER.warning( MsgUtil.errPrintln( id,args ) );
    164        }
    165
    166        /**
    167         * WARNING レベルのログをとります。
    168         *
    169         * これは、Throwable を引数に取る拡張されたメソッドです。
    170         * 引数処理が発生しますので、呼出元で、log level guards してください。
    171         *
    172         * @param       th      ログ・メッセージに関連したThrowable。
    173         * @param       msgSupplier     呼び出されると、目的のログ・メッセージを生成する関数
    174         * @see         Logger#log( Level,Throwable,Supplier )
    175         */
    176        public void warning( final Throwable th , final Supplier<String> msgSupplier ) {
    177                LOGGER.log( Level.WARNING , th , msgSupplier );
    178        }
    179
    180        /**
    181         * WARNING レベルのログをとります。
    182         *
    183         * これは、Throwable を引数に取る拡張されたメソッドです。
    184         * 引数処理が発生しますので、呼出元で、log level guards してください。
    185         *
    186         * @og.rev 7.2.5.0 (2020/06/01) メソッド追加。
    187         *
    188         * @param th    発生元のThrowable( null値は許容されます )
    189         * @param id    リソースのキーとなるID。
    190         * @param args  リソースを、MessageFormat.format で加工する場合の引数。
    191         * @see         Logger#log( Level,Throwable,Supplier )
    192         */
    193        public void warning( final Throwable th , final String id , final Object... args ) {
    194                LOGGER.log( Level.WARNING , MsgUtil.errPrintln( id,args ) , th );                       // 1.4.0 (2019/10/01) StackTraceの重複を避けるため
    195        }
    196
    197        /**
    198         * 600 レベルのログをとります。
    199         *
    200         * Supplierを引数に、Level = 600 のログをとります。
    201         *
    202         * 引数は Supplier のみなので、実行直前まで処理されません。
    203         * よって、呼出元では、log level guards する必要はありません。
    204         *
    205         * @og.rev 7.3.0.0 (2021/01/06) PMD:GuardLogStatement:  Logger calls should be surrounded by log level guards.
    206         *
    207         * @param       msgSupplier     呼び出されると、目的のログ・メッセージを生成する関数
    208         * @see         Logger#log( Level,Supplier )
    209         */
    210        public void debug( final Supplier<String> msgSupplier ) {
    211//              LOGGER.log( DEBUG , msgSupplier );
    212                if( LOGGER.isLoggable( L_DEBUG ) ) {
    213                        LOGGER.log( L_DEBUG , msgSupplier );
    214                }
    215        }
    216
    217        /**
    218         * WARNING レベルのログが、処理されるか、判定します。
    219         *
    220         * 引数が Supplier のみでない場合は、実行前に、log level guards してください。
    221         *
    222         * @og.rev 7.3.0.0 (2021/01/06) 新規追加
    223         *
    224         * @return  args        WARNINGレベルのログを出力する場合は、trueを返します。
    225         */
    226        public boolean isDebugEnabled() {
    227                return LOGGER.isLoggable( L_DEBUG );
    228        }
    229
    230        /**
    231         * 数値の変数を受け取って表示する、600 レベルのログをとります。
    232         *
    233         * Supplierを引数に、Level = 600 のログをとります。
    234         * 関数型インタフェースは引数にfinal変数しか使えませんが、数値は大抵可変なので
    235         * final化せずに、引数として渡すことが出来るようにします。
    236         * 引数処理が発生しますので、呼出元で、log level guards してください。
    237         *
    238         * @og.rev 7.2.5.0 (2020/06/01) メソッド追加。
    239         *
    240         * @param       num                     数値引数
    241         * @param       msgFunction     呼び出されると、目的のログ・メッセージを生成する関数
    242         * @see         Logger#log( Level,Supplier )
    243         */
    244        public void debug( final int num , final Function<Integer,String> msgFunction ) {
    245                LOGGER.log( L_DEBUG , () -> msgFunction.apply( num ) );
    246        }
    247}