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 */
016package org.opengion.fukurou.util;
017
018import java.io.File;
019import java.io.IOException;
020import java.util.Locale;
021import java.util.List;                                          // 6.3.9.0 (2015/11/06) KEYS配列を止めて、変更不可Listを返す。
022import java.util.Arrays;                                        // 6.3.9.0 (2015/11/06) KEYS配列を止めて、変更不可Listを返す。
023import java.util.Collections;                           // 6.3.9.0 (2015/11/06) KEYS配列を止めて、変更不可Listを返す。
024
025import org.opengion.fukurou.system.OgRuntimeException ;         // 6.4.2.0 (2016/01/29)
026
027/**
028 * FileInfo.java は、共通的に使用される File関連の情報管理を行うクラスです。
029 *
030 * ファイルオブジェクトより、ファイル名、ファイル名(拡張子無し)、拡張子(ピリオド無)、
031 * 親パスの情報を、分割します。
032 * また、一部のFileUtilのファイル属性を扱うメソッド類を移植してきました。
033 *
034 * 絶対パス は、File#getCanonicalPath() の値を設定します。
035 * ../AAA/BBB/CCC.XLS というファイルオブジェクトに対して、
036 *
037 *   FILE    : CCC.xls            ファイル名
038 *   NAME    : CCC                拡張子なしのファイル名
039 *   SUFIX   : xls                ピリオド無しの拡張子(小文字に統一)
040 *   DIR     : C:\tmp\BBB         親パス
041 *
042 * ファイル名と、拡張子は、File#getName() の結果から、一番最後に見つかった
043 * ピリオドで、前後を分割します。拡張子にはピリオドを含みません。
044 * ピリオドがなければ、File#getName() の結果をファイル名に設定し、
045 * 拡張子は、空文字列を設定します。
046 *
047 * @og.rev 6.2.0.0 (2015/02/27) 新規追加
048 * @og.group ユーティリティ
049 *
050 * @version  6.0
051 * @author       Kazuhiko Hasegawa
052 * @since    JDK8.0,
053 */
054public final class FileInfo {
055        /** 8.0.0.0 (2021/09/30) ファイルの拡張子の区切りを表す文字      */
056        public static final char EXTENSION_SEPARATOR = '.';
057
058        // 6.3.9.0 (2015/11/06) KEYS配列を止めて、変更不可Listを返す。
059
060        /** CCC.xls            ファイル名 */
061        public final String FILE   ;
062        /** CCC                拡張子なしのファイル名 */
063        public final String NAME   ;
064        /** xls                ピリオド無しの拡張子(小文字に統一) */
065        public final String SUFIX  ;
066        /** C:\tmp\BBB         親パス */
067        public final String DIR    ;
068
069        // 6.3.9.0 (2015/11/06) KEYS配列を止めて、変更不可Listを返す。
070        /** ファイル情報のキーList */
071        public static final List<String> KEY_LIST = Collections.unmodifiableList( Arrays.asList( "FILE","NAME","SUFIX","DIR" ) );
072
073        /**
074         * ファイルオブジェクトを引数に取るコンストラクター
075         *
076         * 絶対パス は、File#getCanonicalPath() の値を設定します。
077         * ../AAA/BBB/CCC.XLS というファイルオブジェクトに対して、
078         *   FILE   : Fileオブジェクト   File#getCanonicalFile() の値
079         *
080         *   FILE    : CCC.xls            ファイル名
081         *   NAME    : CCC                拡張子なしのファイル名
082         *   SUFIX   : xls                ピリオド無しの拡張子(小文字に統一)
083         *   DIR     : C:\tmp\BBB         親パス
084         *
085         * ファイルオブジェクトは、File#getCanonicalFile(File) で、絶対パスに変換後、内部処理されます。
086         * 必要な情報は、final String に設定されるため、そこから情報を取得してください。
087         *
088         * @og.rev 6.2.0.0 (2015/02/27) 新規作成
089         *
090         * @param       file    ファイルオブジェクト
091         */
092        public FileInfo( final File file ) {
093                final File ccFile ;
094                try {
095                        ccFile = file.getCanonicalFile();
096                }
097                catch( final IOException ex ) {
098                        final String errMsg = "ファイルの正式パス名が取得できません。[" + file + "]";
099                        throw new OgRuntimeException( errMsg,ex );
100                }
101
102                FILE = ccFile.getName();
103                final int extPos = FILE.lastIndexOf( '.' );
104                if( extPos >= 0 ) {
105                        NAME  = FILE.substring( 0,extPos );
106                        SUFIX = FILE.substring( extPos + 1 ).toLowerCase( Locale.JAPAN );               // ピリオドを含まない
107                }
108                else {
109                        NAME  = FILE;
110                        SUFIX = "";                                                                     // 拡張子が無ければ、空文字列
111                }
112                DIR = ccFile.getParent();
113        }
114
115        /**
116         * キーに対応した値を返します。
117         *
118         * キーは、値が文字列の分だけです。
119         *
120         * @og.rev 6.2.0.0 (2015/02/27) 新規作成
121         * @og.rev 8.5.5.1 (2024/02/29) switch式の使用
122         *
123         * @param       key     ファイル情報のキー
124         * @return      ファイル情報の値(キーが未設定の場合はnull)
125         * @throws NullPointerException key に null がセットされた場合
126         */
127        public String getValue( final String key ) {
128                // 8.5.5.1 (2024/02/29) switch式の使用
129//              final String rtn ;
130//              switch( key ) {
131//                      case "FILE"             : rtn = FILE;           break;
132//                      case "NAME"             : rtn = NAME;           break;
133//                      case "SUFIX"    : rtn = SUFIX;          break;
134//                      case "DIR"              : rtn = DIR;            break;
135//                      default                 : rtn = null;           break;
136//              }
137//              return rtn ;
138
139                return switch( key ) {
140                        case "FILE"  -> FILE;
141                        case "NAME"  -> NAME;
142                        case "SUFIX" -> SUFIX;
143                        case "DIR"   -> DIR;
144                        default      -> null;
145                };
146        }
147
148        /**
149         * ファイルオブジェクトから、名前部分のみを取得します。
150         *
151         * 名前だけ取得したい場合の、簡易スタティックメソッドです。
152         * ピリオドがない場合は、ファイル名を、先頭がピリオドの場合は、
153         * ゼロ文字列です。
154         * オブジェクトを作成しません。
155         *
156         * @og.rev 6.2.3.0 (2015/05/01) 新規作成
157         *
158         * @param       file    ファイルオブジェクト
159         * @return      ファイルの名称(引数がnullの場合はnull)
160         */
161        public static String getNAME( final File file ) {
162                return file == null ? null : getNAME( file.getName() ) ;
163        }
164
165        /**
166         * ファイル文字列から、名前部分のみを取得します。
167         *
168         * 名前だけ取得したい場合の、簡易スタティックメソッドです。
169         * ピリオドがない場合は、ファイル名を、先頭がピリオドの場合は、
170         * ゼロ文字列です。
171         *
172         * @og.rev 6.2.3.0 (2015/05/01) 新規作成
173         *
174         * @param       filename        ファイル文字列
175         * @return      ファイルの名称(引数がnullの場合はnull)
176         */
177        public static String getNAME( final String filename ) {
178                String name = null;
179                if( filename != null ) {
180                        final int extPos = filename.lastIndexOf( '.' );
181                        if( extPos >= 0 ) {
182                                name = filename.substring( 0,extPos );
183                        }
184                }
185                return name ;
186        }
187
188        /**
189         * ファイルオブジェクトから、拡張子(小文字に統一)のみを取得します。
190         *
191         * 拡張子だけ取得したい場合の、簡易スタティックメソッドです。
192         * ピリオドがない場合は、ゼロ文字列を返します。
193         * オブジェクトを作成しません。
194         *
195         * @og.rev 6.2.3.0 (2015/05/01) 新規作成
196         *
197         * @param       file    ファイルオブジェクト
198         * @return      ファイルの拡張子(小文字に統一,引数がnullの場合はnull)
199         */
200        public static String getSUFIX( final File file ) {
201                return file == null ? null : getSUFIX( file.getName() ) ;
202        }
203
204        /**
205         * ファイル文字列から、拡張子(小文字に統一)のみを取得します。
206         *
207         * 拡張子だけ取得したい場合の、簡易スタティックメソッドです。
208         * ピリオドがない場合は、ゼロ文字列を返します。
209         *
210         * @og.rev 6.2.3.0 (2015/05/01) 新規作成
211         *
212         * @param       filename        ファイル文字列
213         * @return      ファイルの拡張子(小文字に統一,引数がnullの場合はnull)
214         */
215        public static String getSUFIX( final String filename ) {
216                String sufix = null;
217                if( filename != null ) {
218                        final int extPos = filename.lastIndexOf( '.' );
219                        if( extPos >= 0 ) {
220                                sufix = filename.substring( extPos + 1 ).toLowerCase( Locale.JAPAN );   // ピリオドを含まない
221                        }
222                        else {
223                                sufix = "";                                                                     // 拡張子が無ければ、空文字列
224                        }
225                }
226                return sufix ;
227        }
228
229        /**
230         * ファイルオブジェクトから、指定の拡張子かどうかを判定します。
231         *
232         * 拡張子判定に特化した、簡易スタティックメソッドです。
233         * 引数の拡張子には、ピリオドは含めません。
234         * 比較する拡張子の大文字小文字は区別しません。
235         *
236         * @og.rev 6.2.4.0 (2015/05/15) 新規作成
237         *
238         * @param       file    ファイルオブジェクト
239         * @param       suffixes        拡張子群
240         * @return      true:拡張子が含まれる/false:含まれない
241         */
242        public static boolean isSUFIX( final File file , final String... suffixes ) {
243                // 8.5.5.1 (2024/02/29) PMD 7.0.0 OnlyOneReturn メソッドには終了ポイントが 1 つだけ必要
244                boolean flag = false;
245
246                final String fsfx = getSUFIX( file );
247                if( fsfx != null && !fsfx.isEmpty() ) {
248                        // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
249//                      for( int i=0; i<suffixes.length; i++ ) {
250//                              if( fsfx.equalsIgnoreCase( suffixes[i] ) ) { return true; }
251//                      }
252                        for( final String sufix : suffixes ) {
253//                              if( fsfx.equalsIgnoreCase( sufix ) ) { return true; }
254                                if( fsfx.equalsIgnoreCase( sufix ) ) {
255                                        flag = true;
256                                        break;
257                                }
258                        }
259                }
260//              return false;
261                return flag;
262        }
263
264        /**
265         * ファイル文字列から、指定の拡張子かどうかを判定します。
266         *
267         * 拡張子判定に特化した、簡易スタティックメソッドです。
268         * 引数の拡張子には、ピリオドは含めません。
269         * 比較する拡張子の大文字小文字は区別しません。
270         *
271         * @og.rev 6.2.4.0 (2015/05/15) 新規作成
272         *
273         * @param       filename        ファイル文字列
274         * @param       suffixes        拡張子群
275         * @return      true:拡張子が含まれる/false:含まれない
276         */
277        public static boolean isSUFIX( final String filename , final String... suffixes ) {
278                // 8.5.5.1 (2024/02/29) PMD 7.0.0 OnlyOneReturn メソッドには終了ポイントが 1 つだけ必要
279                boolean flag = false;
280
281                final String fsfx = getSUFIX( filename );
282                if( fsfx != null && !fsfx.isEmpty() ) {
283                        // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach
284//                      for( int i=0; i<suffixes.length; i++ ) {
285//                              if( fsfx.equalsIgnoreCase( suffixes[i] ) ) { return true; }
286//                      }
287                        for( final String sufix : suffixes ) {
288//                              if( fsfx.equalsIgnoreCase( sufix ) ) { return true; }
289                                if( fsfx.equalsIgnoreCase( sufix ) ) {
290                                        flag = true;
291                                        break;
292                                }
293                        }
294                }
295//              return false;
296                return flag;
297        }
298}