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.hayabusa.taglib;
017
018import org.opengion.hayabusa.common.HybsSystem;
019import org.opengion.hayabusa.common.HybsSystemException;
020import org.opengion.hayabusa.common.SystemManager;                                      // 7.3.2.0 (2021/03/19)
021import org.opengion.hayabusa.resource.GUIInfo;
022import org.opengion.hayabusa.resource.UserInfo;
023import org.opengion.hayabusa.resource.CodeData;
024import org.opengion.hayabusa.resource.FavoriteGUIData;
025import org.opengion.hayabusa.resource.ResourceManager;
026import org.opengion.fukurou.util.XHTMLTag;
027import org.opengion.fukurou.util.FileMap;
028import org.opengion.fukurou.util.TagBuffer;
029import org.opengion.fukurou.util.ToString;                                                      // 6.1.1.0 (2015/01/17)
030import org.opengion.fukurou.util.StringUtil;
031import org.opengion.fukurou.util.ArraySet;                                                      // 6.4.3.4 (2016/03/11)
032import org.opengion.fukurou.util.Cleanable;                                                     // 7.3.2.0 (2021/03/19)
033
034import org.opengion.fukurou.system.OgBuilder;                                           // 6.4.4.1 (2016/03/18)
035import java.util.concurrent.ConcurrentMap;                                                      // 7.3.2.0 (2021/03/19)
036import java.util.concurrent.ConcurrentHashMap;                                          // 7.3.2.0 (2021/03/19)
037
038import static org.opengion.fukurou.util.StringUtil.nval;
039import static org.opengion.fukurou.system.HybsConst.BUFFER_LARGE;       // 6.1.0.0 (2014/12/26) refactoring
040import static org.opengion.fukurou.system.HybsConst.BR;                         // 6.1.0.0 (2014/12/26) refactoring
041
042import java.util.Set;
043import java.util.LinkedHashSet;
044import java.util.TreeSet;                                                                                       // 6.8.3.1 (2017/12/01)
045import java.util.Iterator;
046import java.util.Map;
047
048/**
049 * 画面アクセスメニューを作成します。
050 *
051 * 画面リソースの階層番号(レベル)は、
052 *  0:グループ分類メニュー(class="GUI_GRP"のtdタグで囲われます)
053 *  1:トップ階層(【分類名称】)
054 *  2:選択階層(通常の折りたたみメニュー)
055 *  3:選択非表示(通常は、隠してあります)
056 * です。
057 *
058 * ※ 6.9.4.1 (2018/04/09) HYBS_BR の廃止
059 *    以前から、画面メニューを少し空けるために、HYBS_BR が使われていましたが、廃止しました。
060 *
061 * @og.formSample
062 * ●形式:<og:topMenu />
063 * ●body:なし
064 *
065 * ●Tag定義:
066 *   <og:topMenu
067 *       menuType           【TAG】作成するメニューの種類(NORMAL,GROUP,ONELEVEL,NEXTGUI,MATRIX,MATRIX2,NONE,TILE)を指定します(初期値:NORMAL)
068 *       expand             【TAG】折り返しメニューを構築するかどうかを指定します(初期値:true)
069 *       groups             【TAG】表示対象となるグループをCSV形式で指定します
070 *       classify           【TAG】表示対象となる分類(classify)を指定します
071 *       href               【TAG】グループメニューの表示対象となるソース名(href)を指定します(初期値:menu.jsp)
072 *       target             【TAG】グループメニューの表示対象となるフレーム名(target)を指定します(初期値:MENU)
073 *       imageOnly          【TAG】グループメニューの表示に、画像のみかどうか[true:画像のみ/false:画像+ラベル]を指定します(初期値:false)
074 *       sideCount          【TAG】グループメニューの表示対象となるメニューを横並びさせる数を指定します
075 *       minCellCount       【TAG】表形式メニュー(MATRIX)の一つのセルに含まれる最小行数を指定します(初期値:8)
076 *       maxCellCount       【TAG】表形式メニュー(MATRIX)の一つのセルに含まれる最大行数を指定します(初期値:8)
077 *       cache              【TAG】グループメニューのキャッシュを使用するかどうか[true/false]を指定します(初期値:true)
078 *       match              【TAG】正判定(マッチする場合に、メニューに出す)条件を設定します
079 *       unmatch            【TAG】逆判定(マッチする場合に、メニューに出さない)条件を設定します
080 *       useButton          【TAG】画面リンクにボタンを使用するかどうか[true/false]を指定します(初期値:false)
081 *       buttonRequest      【TAG】マトリクスからの遷移先でボタンメニュー表示するかどうか[true/false]を指定します(初期値:false)
082 *       inlineStyle        【TAG】標準画面を初期状態で表示するかどうか[true/false]を指定します(初期値:false)
083 *       useDivOneLevel     【TAG】ONELEVEL,NEXTGUI で、DIVタグ+design-onelevel 処理をするかどうか[true/false]を指定します(初期値:false)
084 *       useLongName        【TAG】画面名称に、名前(長) を使う場合は、trueを指定します(初期値:false) 8.2.1.0 (2022/07/15)
085 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
086 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
087 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない)
088 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない)
089 *       caseIf             【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない)
090 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
091 *   >   ... Body ...
092 *   </og:topMenu>
093 *
094 * ●使用例
095 *    <og:topMenu />
096 *
097 *    <og:topMenu
098 *          menuType     = "NORMAL"      NORMAL:通常 / GROUP:グループメニュー / ONELEVEL:1レベル / NEXTGUI:次アクセス先
099 *                                           / MATRIX:一覧表メニュー / MATRIX2:一覧表メニュー(大分類なし版) / NONE:表示しない / TILE:タイル表示
100 *          expand       = "true"        true:折り返しメニュー / false:階層メニュー
101 *          groups       = "AA,BB,CC"    表示対象となるグループをCSV形式で指定します。
102 *          classify     = "ABC"         表示対象となる分類を指定します。
103 *          href         = "menu.jsp"    グループメニューの対象ソース名(href)を指定します。
104 *          target       = "MENU"        グループメニューの対象フレーム名(target)を指定します。
105 *          imageOnly    = "false"       グループメニューに、 true:画像のみ / false:画像+ラベル を指定します。
106 *          sideCount    = "6"           グループメニューの表示対象となるメニューを横並びさせる数を指定します。
107 *          minCellCount = "8"           表形式メニューの1セルの最小行数を指定します。
108 *          maxCellCount = "8"           表形式メニューの1セルの最大行数を指定します。
109 *          cache        = "true"        グループメニューのキャッシュを使用するかどうか指定します。
110 *          match        = "正規表現"    正判定(マッチする場合に、メニューに出す)条件を設定します。
111 *          unmatch      = "正規表現"    逆判定(マッチする場合に、メニューに出さない)条件を設定します。
112 *          useButton    = "false"       ボタン形式のリンクを使用するかを指定します。
113 *          useDivOneLevel  = "false"    ONELEVEL,NEXTGUI で、DIVタグ+design-onelevel 処理をするかどうかを指定します。
114 *    />
115 *
116 * @og.rev 3.5.5.3 (2004/04/09) 新規作成
117 * @og.group メニュー制御
118 *
119 * @version  4.0
120 * @author   Kohei Naruse
121 * @since    JDK5.0,
122 */
123public class TopMenuTag extends CommonTagSupport {
124        /** このプログラムのVERSION文字列を設定します。 {@value} */
125        private static final String VERSION = "8.4.2.1 (2023/03/10)" ;
126        private static final long serialVersionUID = 842120230310L ;
127
128//      private static final String FIELD_IN  = "<fieldset style=\"display:inline;\">";
129        private static final String FIELD_IN  = "<fieldset style=\"display:inline;\" class=\"menu_field\">";    // 8.4.1.2 (2023/03/03)
130        private static final String FIELD_OUT = "</fieldset>" + BR;
131//      private static final String JSP          = HybsSystem.sys( "JSP" );
132//      private static final String CNTX         = HybsSystem.sys( "CONTEXT_NAME" );    // 5.5.4.2 (2012/07/13) META-INF/resources 対応
133        private static final String MENU_IMG = "/jsp/menuImage/" ;                                      // 5.5.4.2 (2012/07/13) META-INF/resources 対応
134
135        // 6.9.5.0 (2018/04/23) multiSessionCheck 廃止(true固定)
136//      private boolean multiSessionCheck = HybsSystem.sysBool( "USE_MULTI_SESSION_CHECK" );
137
138        // 6.7.5.0 (2017/03/10) TILE表示追加
139        private static final Set<String> MENU_TYPE_SET = new ArraySet<>( "NORMAL","GROUP","ONELEVEL","NEXTGUI","MATRIX","MATRIX2","NONE","TILE" );
140
141        private String   menuType       = "NORMAL" ;            // NORMAL,GROUP,ONELEVEL,NEXTGUI,MATRIX,MATRIX2,NONE,TILE
142        private boolean  expand         = true;                         // true:折り返しメニュー / false:階層メニュー
143        private String[] groups         ;                                       // 表示対象となるグループをCSV形式で指定します。
144        private String   selClassify;                                   // 表示対象となる分類を指定します。
145        private String   href           = "menu.jsp";           // グループメニューの対象ソース名(href)を指定します。
146        private String   target         = "MENU";                       // グループメニューの対象フレーム名(target)を指定します。
147        private boolean  imageOnly      ;                                       // グループメニューに、 true:画像のみ / false:画像+ラベル を指定します
148        private int      sideCount      = -1;                           // 5.2.3.0 (2010/12/01) 表示対象となるメニューを横並びさせる数を指定します。
149        private int      minCellCount   = 8;                    // 表形式メニューの1セルの最小行数を指定します。
150        private int      maxCellCount   = 8;                    // 表形式メニューの1セルの最大行数を指定します。
151        private boolean  cache          = true;                         // グループメニューのキャッシュを使用するかどうか指定します。
152        // 3.8.8.7 (2007/05/01) メニューの表示条件指定追加
153        private String match            ;                                       // 正判定(マッチする場合に、メニューに出す)条件を設定
154        private String unmatch          ;                                       // 逆判定(マッチする場合に、メニューに出さない)条件を設定
155        private String imageDir         = MENU_IMG;                     // 6.7.5.0 (2017/03/10) TILE表示追加
156
157        private final String JSP         = HybsSystem.sys( "JSP" );                             // 6.9.9.3 (2018/09/25) JavaDoc エラー対応
158
159        // MULTI_SESSION_CHECK 時のリンクに付加する情報
160        private String  mscKey          ;
161
162        private boolean  useButton              ;                               // ボタン形式のリンクを使用するか 4.2.1.0 (2008/04/01)
163        private boolean  buttonRequest  ;                               // マトリクス2からの遷移でボタン形式にするかのリクエスト変数 4.2.1.0 (2008/04/17)
164        private boolean  excludeButton  ;                               // 4.3.3.0 (2008/10/01) ボタンメニューの場合でも強制的に従来のプルダウンにします。
165        private boolean  inlineStyle    ;                               // 4.3.3.0 (2008/10/01) trueでLv3の画面にstyle属性でinlineを付加
166
167        private boolean  useDivOneLevel ;                               // 5.5.2.3 (2012/05/15) ONELEVEL,NEXTGUI で、DIVタグ+design-onelevel 処理をするかどうかを指定します。
168        private boolean  useLongName    ;                               // 8.2.1.0 (2022/07/15) 画面名称に、名前(長) を使う場合は、trueを指定します(初期値:false)
169
170        // 7.3.2.0 (2021/03/19) FileMapは、static化して使いまわす。
171//      private final transient FileMap imgFileMap = new FileMap() ;            // 6.3.9.0 (2015/11/06) helpMapの初期化を、initメソッドに変更する。
172        private FileMap imgFileMap ;                                                                            // いろんな箇所で使用するので、キャッシュ代わりに用意しておく
173        private static final ConcurrentMap<String,FileMap> IMG_MAP = new ConcurrentHashMap<>();
174
175        static {
176                final Cleanable clr = new Cleanable() {
177                        /**
178                         * 初期化(クリア)します。
179                         * 主に、キャッシュクリアで利用します。
180                         */
181                        public void clear() {
182                                IMG_MAP.forEach( (key,immap) -> immap.clear() );
183                        }
184                };
185                SystemManager.addCleanable( clr );
186        }
187
188        /**
189         * デフォルトコンストラクター
190         *
191         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
192         */
193        public TopMenuTag() { super(); }                // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
194
195        /**
196         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
197         *
198         * @og.rev 4.0.0.0 (2007/10/31) 1レベルメニューの見直し
199         * @og.rev 4.2.1.0 (2008/04/01) マトリクスメニュー2追加
200         * @og.rev 5.2.3.0 (2010/12/01) NEXTGUI 追加
201         * @og.rev 5.3.0.0 (2010/11/22) NEXTGUI もマルチセッションチェックをしない。
202         * @og.rev 5.3.9.0 (2011/09/01) メニューでのヘルプアイコン対応
203         * @og.rev 5.5.0.4 (2012/03/12) FAQ表示対応
204         * @og.rev 5.5.2.5 (2012/05/21) FAQ対応 廃止
205         * @og.rev 5.5.4.2 (2012/07/13) META-INF/resources からの読み取り対応
206         * @og.rev 6.3.8.3 (2015/10/03) NONE(表示しない) 追加。
207         * @og.rev 6.3.8.4 (2015/10/09) topMenu 内でのHelp機能を廃止します。
208         * @og.rev 6.3.8.4 (2015/10/09) FileMap のコンストラクタ変更に伴う対応。
209         * @og.rev 6.3.9.0 (2015/11/06) helpMapの初期化を、initメソッドに変更する。
210         * @og.rev 6.7.5.0 (2017/03/10) TILE表示追加(imageDir 属性追加)
211         * @og.rev 6.9.4.0 (2018/04/02) caseKey 、caseVal 属性対応
212         * @og.rev 6.9.5.0 (2018/04/23) multiSessionCheck 廃止(true固定)
213         * @og.rev 6.9.5.0 (2018/04/23) 6.9.9.3 (2018/09/25) JavaDoc エラー対応
214         * @og.rev 7.3.2.0 (2021/03/19) FileMapは、static化して使いまわす。
215         *
216         * @return      後続処理の指示
217         */
218        @Override
219        public int doEndTag() {
220                debugPrint();           // 4.0.0 (2005/02/28)
221                if( useTag() ) {                // 6.9.4.0 (2018/04/02) caseKey 、caseVal 属性対応
222
223                        // 6.3.8.3 (2015/10/03) NONE(表示しない) 追加。
224                        if( "NONE".equals( menuType ) ) { return EVAL_PAGE; }
225
226                        // Ver 4.0.0 2007/09/04
227                        // ONELEVEL, NEXTGUI の場合は、multiSessionCheck を行いません。
228//                      if( multiSessionCheck && !"ONELEVEL".equals( menuType ) && !"NEXTGUI".equals( menuType ) ) {
229                        if( !"ONELEVEL".equals( menuType ) && !"NEXTGUI".equals( menuType ) ) {                                                 // 6.9.5.0 (2018/04/23) multiSessionCheck 廃止(true固定)
230                                final String cnt = (String)getSessionAttribute( HybsSystem.MULTI_SESSION_CHECK );
231                                if( cnt == null ) {
232                                        final String errMsg = "マルチセッションチェックのキーが存在しません。"
233                                                                + "topMenu タグを実行する前に、必ず jspInit タグを"
234                                                                + "実行しておいてください。" ;
235                                        jspPrint( errMsg );
236                                        return SKIP_PAGE ;              // ページの残りの処理を行わない。
237                                }
238                                mscKey = HybsSystem.MULTI_SESSION_CHECK + "=" + cnt ;
239                        }
240
241                        // 7.3.2.0 (2021/03/19) FileMapは、static化して使いまわす。
242                        imgFileMap = IMG_MAP.computeIfAbsent( imageDir, k -> new FileMap() ) ;
243                        if( !imgFileMap.isInit() ) {
244                                final Set<String> pathSet = pageContext.getServletContext().getResourcePaths( imageDir );
245                                if( pathSet != null ) {
246                                        imgFileMap.init( imageDir , "/" + HybsSystem.getContextName() + imageDir , pathSet );   // 6.9.9.3 (2018/09/25) JavaDoc エラー対応
247                                }
248                        }
249
250//                      // 6.7.5.0 (2017/03/10) TILE表示追加(imageDir 属性追加)
251//      //              final Set<?> set = pageContext.getServletContext().getResourcePaths( imageDir );
252//                      // 6.3.8.4 (2015/10/09) FileMap のコンストラクタ変更に伴う対応。
253//                      // 6.3.9.0 (2015/11/06) helpMapの初期化を、initメソッドに変更する。
254////            imgFileMap.init( imageDir , "/" + CNTX + imageDir , set );
255//                      imgFileMap.init( imageDir , "/" + HybsSystem.getContextName() + imageDir , set );               // 6.9.9.3 (2018/09/25) JavaDoc エラー対応
256
257                        if( "NORMAL".equals( menuType ) ) {
258                                jspPrint( "<div class=\"forpos\" id=\"dummy\"></div>" + CR );
259                                if( ! useButton ){ // 4.2.1.0 (2008/04/26) ボタン時にはお気に入りを出さない
260                                        jspPrint( makeFavoriteMenu() );
261                                }
262                                jspPrint( makeMenu() );
263                        }
264                        else if( "GROUP".equals( menuType ) ) {
265                                jspPrint( makeGroupMenu() );
266                        }
267                //      else if( "CLASSIFY".equals( menuType ) ) {
268                //              jspPrint( makeClassifyMenu() );
269                //      }
270                        else if( "ONELEVEL".equals( menuType ) && selClassify != null ) {
271                                jspPrint( makeOneLevelMenu() );
272                        }
273                        // 5.2.3.0 (2010/12/01) NEXTGUI 追加
274                        else if( "NEXTGUI".equals( menuType ) ) {
275                                jspPrint( makeNextguiMenu() );
276                        }
277                        else if( "MATRIX".equals( menuType ) ) {
278                                jspPrint( makeMatrixMenu() );
279                        }
280                        else if( "MATRIX2".equals( menuType ) ) {       // 4.2.1.0 (2008/04/01) 大分類なし版追加
281                                jspPrint( makeMatrixMenu2() );
282                        }
283                        else if( "TILE".equals( menuType ) ) {          // 6.7.5.0 (2017/03/10) TILE表示追加
284                                jspPrint( makeTileMenu() );
285                        }
286                //      else {
287                //              jspPrint( "menuType が想定外です。menuType=[" + menuType + "]" );
288                //      }
289                }
290
291                return EVAL_PAGE ;              // ページの残りを評価する。
292        }
293
294        /**
295         * タグリブオブジェクトをリリースします。
296         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
297         *
298         * @og.rev 5.2.3.0 (2010/12/01) sideCountの初期値を -1(無制限)に変更
299         * @og.rev 5.3.9.0 (2011/09/01) メニューでのヘルプアイコン対応
300         * @og.rev 5.5.2.3 (2012/05/15) ONELEVEL,NEXTGUI で、DIVタグ+design-onelevel 処理をするかどうかを指定します。
301         * @og.rev 6.3.8.4 (2015/10/09) topMenu 内でのHelp機能を廃止します。
302         * @og.rev 6.3.9.0 (2015/11/06) helpMapの初期化を、initメソッドに変更する。
303         * @og.rev 6.7.5.0 (2017/03/10) TILE表示追加(imageDir 属性追加)
304         * @og.rev 6.9.5.0 (2018/04/23) multiSessionCheck 廃止(true固定)
305         * @og.rev 7.3.2.0 (2021/03/19) FileMapは、static化して使いまわす。
306         * @og.rev 8.2.1.0 (2022/07/15) useLongName 属性追加
307         */
308        @Override
309        protected void release2() {
310                super.release2();
311                expand                          = true;
312                menuType                        = "NORMAL";
313                groups                          = null;
314                selClassify                     = null;
315//              multiSessionCheck       = HybsSystem.sysBool( "USE_MULTI_SESSION_CHECK" );
316                href                            = "menu.jsp";           // グループメニューの対象ソース名(href)を指定します。
317                imageOnly                       = false;                        // グループメニューに、 true:画像のみ / false:画像+ラベル を指定します
318                target                          = "MENU";                       // グループメニューの対象フレーム名(target)を指定します。
319                sideCount                       = -1;                           // 5.2.3.0 (2010/12/01) 表示対象となるメニューを横並びさせる数を指定します。
320                minCellCount            = 8;                            // 表形式メニューの1セルの最小行数を指定します。
321                maxCellCount            = 8;                            // 表形式メニューの1セルの最大行数を指定します。
322                mscKey                          = null;                         // MULTI_SESSION_CHECK 時のリンクに付加する情報
323//              imgFileMap.clear();                                             // 6.3.9.0 (2015/11/06) helpMapの初期化を、initメソッドに変更する。
324                imgFileMap                      = null;                         // 7.3.2.0 (2021/03/19) FileMapは、static化して使いまわす。imgFileMapはMapから取り出したキャッシュ
325                cache                           = true;                         // グループメニューのキャッシュを使用するかどうか指定します。
326                match                           = null;                         // 正判定(マッチする場合に、メニューに出す)条件を設定
327                unmatch                         = null;                         // 逆判定(マッチする場合に、メニューに出さない)条件を設定
328                imageDir                        = MENU_IMG;                     // 6.7.5.0 (2017/03/10) TILE表示追加
329                useButton                       = false;                        // ボタン形式のリンクを使用するか
330                buttonRequest           = false;                        // trueでボタンメニューの表示を行う
331                excludeButton           = false;                        // trueでボタンメニュー時でも強制的に従来のプルダウンにする。
332                inlineStyle                     = false;                        // trueの場合は標準画面(Lv3)にdisplay:inlineを付加
333                useDivOneLevel          = false;                        // 5.5.2.3 (2012/05/15) ONELEVEL,NEXTGUI で、DIVタグ+design-onelevel 処理をするかどうかを指定します。
334                useLongName                     = false;                        // 8.2.1.0 (2022/07/15) 画面名称に、名前(長) を使う場合は、trueを指定します(初期値:false)
335        }
336
337        /**
338         * メニューを表示する為のHTMLを作成します(折り返しJavaScript対応版)。
339         *
340         * @og.rev 3.5.6.5 (2004/08/09) GUIInfo の comments 属性を title にセットする。
341         * @og.rev 3.6.0.9 (2004/12/03) リアルアドレス設定時に、{&#064;XXXX}処理を追加
342         * @og.rev 3.8.0.0 (2005/06/07) 同一セッションでのマルチ起動対策を行います。
343         * @og.rev 4.0.0.0 (2005/01/31) GUIInfoの実アドレスのパラメータを考慮する。
344         * @og.rev 4.0.0.0 (2007/10/31) 分類の廃止に伴い、全面見直し
345         * @og.rev 4.2.1.0 (2008/04/01) 小分類指定での表示対応(↑の対応での再実装漏れ)
346         * @og.rev 4.2.1.0 (2008/04/11) 小分類をexpandしない場合にはspanタグで囲う。
347         * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(makeTagMenuのパラメータ変更)
348         * @og.rev 6.9.4.1 (2018/04/09) HYBS_BR の廃止 , gamenId の変数設定
349         * @og.rev 8.2.1.0 (2022/07/15) useLongName 属性追加
350         *
351         * @return  メニュー
352         * @og.rtnNotNull
353         */
354        private String makeMenu() {
355                final StringBuilder rtn = new StringBuilder( BUFFER_LARGE );
356
357                final UserInfo userInfo = getUser();
358
359                // 4.0.0 (2005/01/31)
360
361                final GUIInfo[] guiInfos = userInfo.getGUIInfos();
362//              String gamenId          ;                       // 画面ID
363                int menuNo = 11;
364                int kmokuNo = 0;
365
366                boolean isInFieldset    = false;                // 大分類の中か?
367                boolean isInClassify    = false;                // 小分類の中か?
368                boolean isHiddenMenu    = false;                // 隠しメニューが存在するか?        6.0.2.5 (2014/10/31) refactoring
369                boolean isClassHidden   = false;                // 分類隠しが存在するか?          6.0.2.5 (2014/10/31) refactoring
370                int level ;
371                int preLevel = 0;
372
373                for( int i=0; i<guiInfos.length; i++ ) {
374                        if( guiInfos[i].isRead() ) {            // 4.0.0 (2005/01/31)
375                                final String gamenId = guiInfos[i].getKey() ;
376
377//                              if( match   != null && !gamenId.matches( match  ) ) { continue; }
378//                              if( unmatch != null && gamenId.matches( unmatch ) ) { continue; }
379                                // 6.9.7.0 (2018/05/14) PMD
380                                if(             match  != null && !gamenId.matches( match )
381                                        || unmatch != null && gamenId.matches( unmatch ) ) { continue; }
382
383                                // 4.2.1.0 (2008/04/01)
384                                // 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined
385//                              if( selClassify != null ) {
386////                                    if( !selClassify.equals( guiInfos[i].getKey() ) && !selClassify.equals( guiInfos[i].getClassify() ) ) {
387//                                      if( !selClassify.equals( gamenId ) && !selClassify.equals( guiInfos[i].getClassify() ) ) {
388                                if( selClassify != null && !selClassify.equals( gamenId ) && !selClassify.equals( guiInfos[i].getClassify() ) ) {
389                                                continue; // 分類(classify) に含まれない
390//                                      }
391                                }
392
393                                // 処理すべき画面かのチェック
394                                final int guiFlg = guiCheck( guiInfos, i );
395                                if( guiFlg == 0 ) { continue; }
396
397                                level = guiInfos[i].getLevel();         // 4.0.0 (2005/01/31)
398
399                                // 隠しメニュー展開用
400                                if( preLevel >= 3 && level < 3 ) {
401                                        if( isHiddenMenu ) {                    // 6.0.2.5 (2014/10/31) refactoring
402                                                rtn.append( makeEllipses( menuNo,kmokuNo,3 ) );
403                                                kmokuNo++;
404                                        }
405                                        isHiddenMenu = false;                   // 6.0.2.5 (2014/10/31) refactoring
406                                }
407
408                                // 大分類(フィールドメニュー)
409                                if( level == 1 ) {
410                                        if( isInFieldset ) {
411                                                rtn.append( FIELD_OUT )
412                                                        .append( "</div>" );
413                                        }
414                                        isInFieldset = true;
415
416                                        // 隠しメニュー用
417                                        if( expand ) {
418                                                rtn.append( "<div class=\"expand1 " );
419
420                                                if( guiFlg == 1 ) {
421                                                        rtn.append( "unpopular ");
422                                                }
423
424                                                rtn.append( "\">" );
425                                        }
426//                                      rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),level ) );                   // 5.5.2.5 (2012/05/21) イメージアイコン対応
427                                        rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(useLongName),level ) );        // 8.2.1.0 (2022/07/15) true:名前(長)/false:名前(短)
428
429                                        isInClassify = false;
430                                }
431                                // 小分類・直リンク
432                                else if( level == 2 ) {
433                                        menuNo++;
434                                        kmokuNo = 0;
435                                        if( expand ) {
436                                                rtn.append( "<div class=\"expand1 " );
437
438                                                // 隠しメニュー用
439                                                if( guiFlg == 1 ) {
440                                                        rtn.append( "unpopular " );
441                                                        isClassHidden = true;                   // 6.0.2.5 (2014/10/31) refactoring
442                                                }
443
444                                                // rtn.append( "\" id=\"menu" + menuNo + "\">" );
445                                                // 4.3.3.0 (2008/10/01) useButton=true時は表示しない
446                                                rtn.append( "\" id=\"menu" + menuNo + "\" ");
447                                                if( useButton ){
448                                                        rtn.append( "style=\"display:none\"");
449                                                }
450                                                rtn.append( '>');               // 6.0.2.5 (2014/10/31) char を append する。
451                                        }
452                                        else{   // 4.2.1.0 (2008/04/11)expandしない場合にはspan要素で囲ってnon-expandクラスを指定。
453                                                rtn.append( "<span class=\"non-expand\">" );
454                                        }
455
456//                                      rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),level ) );           // 5.5.2.5 (2012/05/21) イメージアイコン対応
457                                        rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(useLongName),level ) );        // 8.2.1.0 (2022/07/15) true:名前(長)/false:名前(短)
458                                        rtn.append( BR );
459                                        if( expand ) {
460                                                rtn.append( "</div>" );
461                                        }
462                                        else{   // 4.2.1.0 (2008/04/11)
463                                                rtn.append( "</span>");
464                                        }
465
466                                        isInClassify = true;
467                                }
468                                // 通常メニュー・隠しメニュー
469                                // 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined
470//                              else if( level >= 3 ) {
471//                                      if( isInClassify ) {
472                                else if( level >= 3 && isInClassify ) {
473                                                if( expand ) {
474                                                        rtn.append( "<div class=\"expand2 " );
475
476                                                        // 隠しメニュー用
477                                                        if( level == 4 ) {
478                                                                rtn.append( "unpopular " );
479                                                                isHiddenMenu = true;                    // 6.0.2.5 (2014/10/31) refactoring
480                                                        }
481
482                                                        // rtn.append( "\" id=\"menu" + menuNo + "_" + kmokuNo + "\">" );
483                                                        // 4.3.3.0 (2008/10/01) メニューを初期状態で開けるようにする
484                                                        // 6.0.2.5 (2014/10/31) char を append する。
485                                                        rtn.append( "\" id=\"menu" ).append( menuNo ).append( '_' ).append( kmokuNo ).append( "\" " );
486                                                        if( inlineStyle && level == 3 ) {
487                                                                rtn.append( " style=\"display:inline\"" );
488                                                        }
489                                                        rtn.append( '>' );              // 6.0.2.5 (2014/10/31) char を append する。
490                                                }
491                        //                      // 6.9.4.1 (2018/04/09) HYBS_BR 対応
492                        //                      if( "HYBS_BR".equals( guiInfos[i].getAddress() ) ) {
493                        //                              rtn.append( BR );
494                        //                      }
495                        //                      else {
496//                      //                      // 画面IDが"HYBS_BR"の時は処理しない
497//                      //                      if( !"HYBS_BR".equals( guiInfos[i].getKey() ) ) {
498//                                                      rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),level ) );           // 5.5.2.5 (2012/05/21) イメージアイコン対応
499                                                        rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(useLongName),level ) );        // 8.2.1.0 (2022/07/15) true:名前(長)/false:名前(短)
500                        //                      }
501                                                rtn.append( BR );
502                                                if( expand ) {
503                                                        rtn.append( "</div>" );
504                                                }
505                                                kmokuNo++;
506//                                      }
507                                }
508
509                                rtn.append( CR );
510
511                                preLevel = level;
512                        }
513                }
514
515                // 終了処理
516                if( isHiddenMenu ) {                                                                            // 6.0.2.5 (2014/10/31) refactoring
517                        rtn.append( makeEllipses( menuNo,kmokuNo,3 ) );
518                }
519
520                if( isInFieldset ) {
521                        rtn.append( FIELD_OUT );
522                        rtn.append( "</div>" );
523                }
524
525                if( isClassHidden ) {                                                                           // 6.0.2.5 (2014/10/31) refactoring
526                        rtn.append( makeEllipses( menuNo,0,2 ) );
527                }
528
529                return rtn.toString();
530        }
531
532        /**
533         * TILEメニューを表示する為のHTMLを作成します(折り返しJavaScript対応版)。
534         *
535         * @og.rev 6.7.5.0 (2017/03/10) TILE表示追加
536         * @og.rev 6.9.4.0 (2018/04/02) HYBS_BR(ブレイク)の条件を緩める。
537         * @og.rev 6.9.4.1 (2018/04/09) HYBS_BR の廃止 , gamenId の変数設定
538         * @og.rev 8.2.1.0 (2022/07/15) useLongName 属性追加
539         *
540         * @return  メニュー
541         * @og.rtnNotNull
542         */
543        private String makeTileMenu() {
544                final StringBuilder rtn = new StringBuilder( BUFFER_LARGE );
545
546                final UserInfo userInfo = getUser();
547
548                // 4.0.0 (2005/01/31)
549
550                final GUIInfo[] guiInfos = userInfo.getGUIInfos();
551//              String gamenId          ;                       // 画面ID
552                int menuNo = 11;
553                int kmokuNo = 0;
554
555                boolean isInFieldset    = false;                // 大分類の中か?
556                boolean isInClassify    = false;                // 小分類の中か?
557                boolean isHiddenMenu    = false;                // 隠しメニューが存在するか?        6.0.2.5 (2014/10/31) refactoring
558                boolean isClassHidden   = false;                // 分類隠しが存在するか?          6.0.2.5 (2014/10/31) refactoring
559                int level ;
560                int preLevel = 0;
561
562                String hybsBR = "";                                             // 6.7.5.0 (2017/03/10)
563                for( int i=0; i<guiInfos.length; i++ ) {
564                        if( guiInfos[i].isRead() ) {            // 4.0.0 (2005/01/31)
565                                final String gamenId = guiInfos[i].getKey() ;
566                                if( match   != null && !gamenId.matches( match  ) ) { continue; }
567                                if( unmatch != null && gamenId.matches( unmatch ) ) { continue; }
568
569                                // 4.2.1.0 (2008/04/01)
570                                // 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined
571//                              if( selClassify != null ) {
572//                                      if( !selClassify.equals( gamenId ) && !selClassify.equals( guiInfos[i].getClassify() ) ) {
573                                if( selClassify != null && !selClassify.equals( gamenId ) && !selClassify.equals( guiInfos[i].getClassify() ) ) {
574                                                continue; // 分類(classify) に含まれない
575//                                      }
576                                }
577
578                                // 6.9.4.0 (2018/04/02) HYBS_BR(ブレイク)の条件を緩める。
579                                if( isInFieldset && isInClassify && "HYBS_BR".equals( guiInfos[i].getAddress() ) ) {            // 6.7.5.0 (2017/03/10)
580//                              if( "HYBS_BR".equals( gamenId ) ) {                                                                             // 6.9.4.0 (2018/04/02)
581                                        hybsBR = "</tr><tr>" ;
582                                }
583
584                                // 処理すべき画面かのチェック
585                                final int guiFlg = guiCheck( guiInfos, i );
586                                if( guiFlg == 0 ) { continue; }
587
588                                level = guiInfos[i].getLevel();         // 4.0.0 (2005/01/31)
589
590                                // 隠しメニュー展開用
591                                if( preLevel >= 3 && level < 3 ) {
592                                        if( isHiddenMenu ) {                    // 6.0.2.5 (2014/10/31) refactoring
593                                                rtn.append( makeEllipses( menuNo,kmokuNo,3 ) );
594                                                kmokuNo++;
595                                        }
596                                        isHiddenMenu = false;                   // 6.0.2.5 (2014/10/31) refactoring
597                                }
598
599                                // 大分類(フィールドメニュー)
600                                if( level == 1 ) {
601                                        if( isInFieldset ) {
602                                                rtn.append( "</td></tr></table>" )              // 6.7.5.0 (2017/03/10)
603                                                        .append( FIELD_OUT )
604                                                        .append( "</div>" );
605                                        }
606                                        isInFieldset = true;
607
608                                        // 隠しメニュー用
609                                        if( expand ) {
610                                                rtn.append( "<div class=\"expand1 " );
611
612                                                if( guiFlg == 1 ) {
613                                                        rtn.append( "unpopular ");
614                                                }
615                                                rtn.append( "\">" );
616                                        }
617//                                      rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),level ) )            // 5.5.2.5 (2012/05/21) イメージアイコン対応
618                                        rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(useLongName),level ) ) // 8.2.1.0 (2022/07/15) true:名前(長)/false:名前(短)
619                                                .append( "<table><tr>" );               // 6.7.5.0 (2017/03/10)
620
621                                        isInClassify = false;
622                                }
623                                // 小分類・直リンク
624                                else if( level == 2 ) {
625                                        menuNo++;
626                                        kmokuNo = 0;
627                                        if( expand ) {
628                                                if( isInFieldset ) {            // 6.7.5.0 (2017/03/10)
629                                                        if( isInClassify ) {
630                                                                rtn.append( "</td>" ).append( hybsBR ).append( "<td>" );
631                                                                hybsBR = "";
632                                                        }
633                                                        else {
634                                                                rtn.append( "<td>" );
635                                                        }
636                                                }
637                                                rtn.append( "<div class=\"expand1 " );
638
639                                                // 隠しメニュー用
640                                                if( guiFlg == 1 ) {
641                                                        rtn.append( "unpopular " );
642                                                        isClassHidden = true;                   // 6.0.2.5 (2014/10/31) refactoring
643                                                }
644
645                                                // rtn.append( "\" id=\"menu" + menuNo + "\">" );
646                                                // 4.3.3.0 (2008/10/01) useButton=true時は表示しない
647                                                rtn.append( "\" id=\"menu" + menuNo + "\" ");
648                                                if( useButton ){
649                                                        rtn.append( "style=\"display:none\"");
650                                                }
651                                                rtn.append( '>');               // 6.0.2.5 (2014/10/31) char を append する。
652                                        }
653                                        else{   // 4.2.1.0 (2008/04/11)expandしない場合にはspan要素で囲ってnon-expandクラスを指定。
654                                                rtn.append( "<span class=\"non-expand\">" );
655                                        }
656
657//                                      rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),-6 ) );                      // 6.7.5.0 (2017/03/10) TILE表示
658                                        rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(useLongName),-6 ) );   // 8.2.1.0 (2022/07/15) true:名前(長)/false:名前(短)
659                                        rtn.append( BR );
660                                        if( expand ) {
661                                                rtn.append( "</div>" );
662                                        }
663                                        else{   // 4.2.1.0 (2008/04/11)
664                                                rtn.append( "</span>");
665                                        }
666
667                                        isInClassify = true;
668                                }
669                                // 通常メニュー・隠しメニュー
670                                // 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined
671//                              else if( level >= 3 ) {
672//                                      if( isInClassify ) {
673                                else if( level >= 3 && isInClassify ) {
674                                                if( expand ) {
675                                                        rtn.append( "<div class=\"expand2 " );
676
677                                                        // 隠しメニュー用
678                                                        if( level == 4 ) {
679                                                                rtn.append( "unpopular " );
680                                                                isHiddenMenu = true;                    // 6.0.2.5 (2014/10/31) refactoring
681                                                        }
682
683                                                        // rtn.append( "\" id=\"menu" + menuNo + "_" + kmokuNo + "\">" );
684                                                        // 4.3.3.0 (2008/10/01) メニューを初期状態で開けるようにする
685                                                        // 6.0.2.5 (2014/10/31) char を append する。
686                                                        rtn.append( "\" id=\"menu" ).append( menuNo ).append( '_' ).append( kmokuNo ).append( "\" " );
687                                                        if( inlineStyle && level == 3 ) {
688                                                                rtn.append( " style=\"display:inline\"" );
689                                                        }
690                                                        rtn.append( '>' );              // 6.0.2.5 (2014/10/31) char を append する。
691                                                }
692
693                        //                      // 6.9.4.1 (2018/04/09) HYBS_BR 対応
694                        //                      if( "HYBS_BR".equals( guiInfos[i].getAddress() ) ) {                                    // 6.9.4.1 (2018/04/09) HYBS_BR は、アドレスに設定
695                        //                              rtn.append( BR );
696                        //                      }
697                        //                      else {
698//                      //                      // 画面IDが"HYBS_BR"の時は処理しない
699//                      //                      if( !"HYBS_BR".equals( gamenId ) ) {
700//                                                      rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),level ) );           // 5.5.2.5 (2012/05/21) イメージアイコン対応
701                                                        rtn.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(useLongName),level ) );        // 8.2.1.0 (2022/07/15) true:名前(長)/false:名前(短)
702                        //                      }
703                                                rtn.append( BR );
704                                                if( expand ) {
705                                                        rtn.append( "</div>" );
706                                                }
707                                                kmokuNo++;
708//                                      }
709                                }
710
711                                rtn.append( CR );
712                                preLevel = level;
713                        }
714                }
715
716                // 終了処理
717                if( isHiddenMenu ) {                                                                            // 6.0.2.5 (2014/10/31) refactoring
718                        rtn.append( makeEllipses( menuNo,kmokuNo,3 ) );
719                }
720
721                if( isInFieldset ) {
722                        rtn.append( "</td></tr></table>" )                                              // 6.7.5.0 (2017/03/10)
723                                .append( FIELD_OUT )
724                                .append( "</div>" );
725                }
726
727                if( isClassHidden ) {                                                                           // 6.0.2.5 (2014/10/31) refactoring
728                        rtn.append( makeEllipses( menuNo,0,2 ) );
729                }
730
731                return rtn.toString();
732        }
733
734        /**
735         * メニューを表示する為のHTMLを作成します(折り返しJavaScript対応版)。
736         *
737         * @og.rev 4.0.0.0 (2005/01/31) 個人別のお気に入りメニューを作成します。
738         * @og.rev 4.0.0.0 (2007/10/31) 分類項目の廃止
739         * @og.rev 4.1.1.0 (2008/02/05) お気に入り情報はGEA09から取得するように変更
740         * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(makeTagMenuのパラメータ変更)
741         * @og.rev 6.4.4.1 (2016/03/18) StringBuilderの代わりに、OgBuilderを使用する。
742         * @og.rev 6.9.9.1 (2018/08/27) お気に入り編集メニュー(GE0014→GFX000)変更。
743         *
744         * @return  個人別のお気に入りメニュー
745         * @og.rtnNotNull
746         */
747        private String makeFavoriteMenu() {
748
749                final UserInfo userInfo = getUser();
750                final Map<String,FavoriteGUIData> favoriteMap = userInfo.getFavoriteMap();
751
752                if( favoriteMap.isEmpty() ) { return ""; }
753
754                final ResourceManager resource = getResource(); // リソース参照
755                final String    largeClassify    = resource.getLabelData( "FAVORITE_MENU" ).getShortLabel(); // お気に入り
756                String  lastClassify     = "";                          // 前方画面の分類
757                int             menuNo                   = 99999;
758                int             kmokuNo                  = 0;
759
760                // fieldSetタグ、お気に入り編集画面リンクの出力
761//              final GUIInfo editFavorite = userInfo.getGUIInfo( "GE0014" );
762                final GUIInfo editFavorite = userInfo.getGUIInfo( "GFX000" );           // 6.9.9.1 (2018/08/27)
763
764                final OgBuilder rtn = new OgBuilder()
765                        .append( "<div class=\"expand1\"> "
766                                        , makeTagMenuString( null,null,largeClassify,null,1 )
767                                        , makeTagMenu( editFavorite,resource.getLabelData( "EDIT" ).getShortLabel(),2 )         // 5.5.2.5 (2012/05/21) イメージアイコン対応
768                                        , BR );
769
770                String thisClassify = null;
771//              String gamenId = null;
772                FavoriteGUIData favoriteGui = null;
773                // 4.3.4.4 (2009/01/01) findBugs警告対応
774                for( final Map.Entry<String, FavoriteGUIData> entry : favoriteMap.entrySet() ) {
775                        final String gamenId     = entry.getKey();
776                        favoriteGui = entry.getValue();
777                        final GUIInfo guiInfo = userInfo.getGUIInfo( gamenId );
778
779                        if( match   != null && !gamenId.matches( match  ) ) { continue; }
780                        if( unmatch != null && gamenId.matches( unmatch ) ) { continue; }
781
782                        thisClassify = favoriteGui.getClassify();
783                        if( !lastClassify.equals( thisClassify ) ) {
784                                menuNo++;
785                                kmokuNo = 0;
786                                rtn.appendIf( expand , "<div class=\"expand1\" id=\"menu" , String.valueOf( menuNo ) , "\">" )
787                                        .append( makeTagMenuString( null,null,thisClassify,thisClassify,2 ) )
788                                        .append( BR )
789                                        .appendIfCR( expand , "</div>" );
790                                lastClassify = thisClassify;
791                        }
792
793                        final String linkLabel = favoriteGui.getName();
794                        rtn.appendIf( expand
795                                                        , "<div class=\"expand2\" id=\"menu"
796                                                        , String.valueOf( menuNo ) , "_" , String.valueOf( kmokuNo ) , "\">" )
797                                .append( makeTagMenu( guiInfo,linkLabel,3 ) )           // 5.5.2.5 (2012/05/21) イメージアイコン対応
798                                .append( BR )
799                                .appendIfCR( expand , "</div>" );
800                        kmokuNo++;
801                }
802                return rtn.append( FIELD_OUT , "</div>" ).toString();
803        }
804
805        /**
806         * 折りたたみメニューで、非標準メニューの 表示に使う、"←・・・→" を作成します。
807         *
808         * @param       menuNo  階層番号
809         * @param       kmokuNo 階層項目番号
810         * @param       type    タイプ(1,2限定)
811         *
812         * @og.rev 4.0.0.0 (2005/01/31) 新規作成
813         * @og.rev 6.4.4.1 (2016/03/18) StringBuilderの代わりに、OgBuilderを使用する。
814         *
815         * @return  メニュー
816         * @og.rtnNotNull
817         */
818        private String makeEllipses( final int menuNo,final int kmokuNo,final int type ) {
819                final int tmpType = type-1; // 超暫定対応 4.0.0.0 (2007/10/31)
820                final String kmkNo = ( tmpType == 1 ) ? "" : "_" + kmokuNo ;
821
822                // 4.3.3.0 (2008/10/01) inlineStyleがtrueの場合は←・・・→をinlineで表示する
823                return new OgBuilder()
824                                .append( "<div class=\"expand"          , String.valueOf( tmpType ) )
825                                .append( " ellipses\" id=\"menu"        , String.valueOf( menuNo ) , kmkNo )
826                                .append( "\" " )
827                                .appendIf( inlineStyle , "style=\"display:inline\" " )                          // if
828                                .appendCR( ">" , makeTagMenuString( null,null,"←・・・→",null,type )
829                                                        , BR , "</div>" )
830                                .toString();
831        }
832
833        /**
834         * menuType="GROUP" 時に作成するグループメニュー。
835         *
836         * @og.rev 4.0.0.0 (2005/01/31) 新規作成
837         * @og.rev 4.0.0.0 (2007/10/05) グループのコードリソースが存在しない場合
838         * @og.rev 4.2.2.0 (2008/05/14) buttonRequestがtrueの場合はTOPへのリンクを表示しない
839         * @og.rev 4.2.2.0 (2008/05/15) グループ絞込解除(GUI_ALL)の表示文字にラベルリソースを使う。
840         * @og.rev 5.0.0.3 (2009/09/22) グループが1件の場合に表示されないバグを修正
841         * @og.rev 5.1.8.0 (2010/07/01) コードリソースのキーが存在しない場合にエラーとなるバグを修正
842         * @og.rev 5.9.7.1 (2016/04/06) GROPUにgroupsが効くようにする
843         * @og.rev 6.4.5.0 (2016/04/08) GROPUにgroupsが効くようにする(効率化、ループから出す)
844         * @og.rev 6.8.3.1 (2017/12/01) GROPUの表示順を、コードリソースの並び順にします。
845         * @og.rev 5.10.15.2 (2019/09/20) GROUPのマルチバイト文字対応
846         *
847         * @return  メニュー
848         */
849        private String makeGroupMenu() {
850
851                // 画面のグループメニューのキャッシュを取得します。
852                String groupMenu ;
853                final String cacheKey  = HybsSystem.GUI_GR_MENU_CACHE_KEY + href + target ;
854                if( cache ) {
855                        groupMenu = (String)getSessionAttribute( cacheKey );
856                        if( groupMenu != null ) { return groupMenu; }   // キャッシュを返します。
857                }
858                else {
859                        removeSessionAttribute( cacheKey );
860                }
861
862                final UserInfo userInfo = getUser();
863
864                // 6.8.3.1 (2017/12/01) GROPUの表示順を、コードリソースの並び順にします。
865                final CodeData groupCode = getResource().getCodeData( "GROUPS" ) ;
866                final Set<String> groupSet = groupCode == null ? new LinkedHashSet<>()                          // 要素がセットに挿入された順序です(挿入順)。
867                                                                                                           : new TreeSet<>( (v1,v2) -> groupCode.getAddress( v1 ) - groupCode.getAddress( v2 ) );       // コードリソースの並び順
868
869                // そのユーザーで使用できる画面をすべてピックアップします。
870                // その上で、読取可能なメニューを含むグループを順番に Set にセットしていきます。
871                final GUIInfo[] guiInfos = userInfo.getGUIInfos();
872
873                // 7.2.9.4 (2020/11/20) PMD:This for loop can be replaced by a foreach loop
874                for( final GUIInfo guiInfo : guiInfos ) {
875                        if( guiInfo.isRead() ) {
876//              for( int i=0; i<guiInfos.length; i++ ) {
877//                      if( guiInfos[i].isRead() ) {
878                                final String gamenId = guiInfo.getKey() ;
879//                              final String gamenId = guiInfos[i].getKey() ;
880                                if( match   != null && !gamenId.matches( match  ) ) { continue; }
881                                if( unmatch != null && gamenId.matches( unmatch ) ) { continue; }
882                                // 6.4.5.0 (2016/04/08) 元のループを、拡張for文に変更しただけ。
883                                final String[] guiGroups = StringUtil.csv2Array( guiInfo.getGroups() );
884//                              final String[] guiGroups = StringUtil.csv2Array( guiInfos[i].getGroups() );
885                                for( final String grp : guiGroups ) { groupSet.add( grp ); }
886                        }
887                }
888
889                // 6.4.5.0 (2016/04/08) groupsの削除は、後でまとめて行う。
890                if( groups != null ) {
891                        for( final String grp : groups ) { groupSet.remove( grp ); }
892                }
893
894                // 5.0.0.3 (2009/09/22)
895                // 6.1.1.0 (2015/01/17) refactoring 。size()判定をisEmpty() にすると同時に、if...else を反転する。
896                if( groupSet.isEmpty() ) {
897                        groupMenu = "";
898                }
899                else {
900                        int sideTmpCnt = 1;
901                        final StringBuilder rtn = new StringBuilder( BUFFER_LARGE );
902                        rtn.append( "<tr>" );
903
904                        final String allMenu = getLabel( "ALL_MENU" ); // 4.2.2.0 (2008/05/15) ALLはラベルリソース使うように変更
905                        rtn.append( makeTagMenuString( href,target,allMenu,"GUI_ALL",-1 ) );
906                        if( sideCount > 0 && sideTmpCnt % sideCount == 0 ) { rtn.append("</tr><tr>"); }
907                        sideTmpCnt++ ;
908
909                        final Iterator<String> ite = groupSet.iterator() ;
910                        if( groupCode != null ) {
911                                while( ite.hasNext() ) {
912                                        final String group = ite.next();
913                                        final int cdAdrs = groupCode.getAddress( group ) ;
914                                        // 4.0.0.0 (2007/10/05) グループのコードリソースが存在しない場合
915                                        String groupLabel = "";
916                                        if( cdAdrs >= 0 ) { groupLabel = groupCode.getLongLabel( cdAdrs ); }
917
918                                        // 5.1.8.0 (2010/07/01) コードリソースのキーが存在しない場合にエラーとなるバグを修正
919                                        if( groupLabel.isEmpty() && group != null && group.length() > 0 ) {
920                                                groupLabel = group;
921                                        }
922
923//                                      final String src = XHTMLTag.addUrlEncode( href,"group=" + group );
924                                        final String src = XHTMLTag.addUrlEncode( href,"group=" + StringUtil.urlEncode( group ) ); // 5.10.15.2 (2019/09/20)
925                                        rtn.append( makeTagMenuString( src,target,groupLabel,group,-1 ) );
926                                        if( sideCount > 0 && sideTmpCnt % sideCount == 0 ) { rtn.append("</tr><tr>"); }
927                                        sideTmpCnt++ ;
928                                }
929                        }
930
931                        if( ! imageOnly && ! buttonRequest ) { // 4.2.2.0 (2008/05/14) ボタンメニュー時はトップメニュー
932                                rtn.append( makeTagMenuString( JSP + "/index.jsp",target,"Top","GUI_TOP",-1 ) );
933                        }
934                        rtn.append( "</tr>" );
935
936                        // 画面のグループメニューのキャッシュをセットします。
937                        groupMenu = rtn.toString() ;
938                }
939
940                if( cache ) {
941                        setSessionAttribute( cacheKey,groupMenu );
942                }
943
944                return groupMenu;
945        }
946
947        /**
948         * メニューを表示する為のHTMLを作成します(折り返しJavaScript対応版)。
949         *
950         * @og.rev 4.0.0.0 (2005/01/31) GUIInfoの実アドレスのパラメータを考慮する。
951         * @og.rev 4.0.0.0 (2007/10/31) 一旦廃止
952         * @og.rev 5.5.2.3 (2012/05/15) useDivOneLevel 対応
953         * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(makeTagMenuのパラメータ変更)
954         * @og.rev 5.5.6.0 (2013/01/07) useDivOneLevelの折り返し方法変更
955         * @og.rev 6.2.6.0 (2015/06/19) QUERYに表示される1行メニュは、説明なしの画面名称のみ表示する。
956         * @og.rev 5.9.6.1 (2016/03/04) フレーム対応
957         * @og.rev 6.9.4.1 (2018/04/09) HYBS_BR の廃止 , gamenId の変数設定
958         * @og.rev 8.4.2.1 (2023/03/10) 画面名称は Long → short をセット
959         *
960         * @return  メニュー
961         * @og.rtnNotNull
962         */
963        private String makeOneLevelMenu() {
964                final StringBuilder rtn = new StringBuilder( BUFFER_LARGE );
965
966                // 5.5.2.3 (2012/05/15) useDivOneLevel 対応
967                if( useDivOneLevel ) { rtn.append("<div id=\"design-onelevel\">"); }
968
969                final UserInfo userInfo = getUser();
970
971                // 4.0.0 (2005/01/31)
972                final GUIInfo[] guiInfos = userInfo.getGUIInfos();
973//              String gamenId  ;                       // 画面ID
974                int sideTmpCnt = 1;
975
976                boolean isInClassify = false;
977
978                // 7.2.9.4 (2020/11/20) PMD:This for loop can be replaced by a foreach loop
979                for( final GUIInfo guiInfo : guiInfos ) {
980                        final String gamenId = guiInfo.getKey() ;                               // 6.9.4.1 (2018/04/09)
981                        final int    level   = guiInfo.getLevel();
982//              for( int i=0; i<guiInfos.length; i++ ) {
983//                      final String gamenId = guiInfos[i].getKey() ;                   // 6.9.4.1 (2018/04/09)
984//                      final int level = guiInfos[i].getLevel();
985
986                        if( level == 2 ) {
987//                              isInClassify = selClassify.equals( guiInfos[i].getKey() );
988                                // 6.9.8.0 (2018/05/28) FindBugs:コンストラクタで初期化されていないフィールドを null チェックなしで null 値を利用している
989                                // makeOneLevelMenu() メソッドが呼ばれる条件に、selClassify != null があるのだが。
990//                              isInClassify = selClassify.equals( gamenId );
991                                isInClassify = gamenId.equals( selClassify );                   // 6.9.8.0 (2018/05/28) とりあえず比較方法を入れ替えます。
992                        }
993
994                        if( guiInfo.isRead() && level == 3 && isInClassify ) {          // 4.0.0 (2005/01/31)
995//                      if( guiInfos[i].isRead() && level == 3 && isInClassify ) {              // 4.0.0 (2005/01/31)
996//                              gamenId = guiInfos[i].getKey() ;
997                                if( match   != null && !gamenId.matches( match  ) ) { continue; }
998                                if( unmatch != null && gamenId.matches( unmatch ) ) { continue; }
999
1000//                              final String guiLabel = guiInfo.getLabel();                     // 6.2.6.0 (2015/06/19) 画面名称(title無)
1001                                final String guiLabel = guiInfo.getName();                      // 8.4.2.1 (2023/03/10) Modify
1002//                              final String guiLabel = guiInfos[i].getLabel();         // 6.2.6.0 (2015/06/19) 画面名称(title無)
1003
1004                                final String thisGamenId = getGUIInfoAttri( "KEY" );
1005                                if( gamenId.equals( thisGamenId ) ) {
1006                                        // 5.5.2.3 (2012/05/15) useDivOneLevel 対応
1007                                        if( useDivOneLevel ) {
1008                                                rtn.append("<span class=\"design-onelevel\">").append( guiLabel ).append( "</span>" );
1009                                        }
1010                                        else {
1011                                                rtn.append( '[' ).append( guiLabel ).append( "] " );            // 6.0.2.5 (2014/10/31) char を append する。
1012                                        }
1013                                }
1014                                else {
1015                                        // 5.5.2.3 (2012/05/15) useDivOneLevel 対応
1016                                        if( useDivOneLevel ) {
1017                                                // 5.5.2.5 (2012/05/21) イメージアイコン対応
1018                                                rtn.append("<span class=\"design-onelevel\">").append( makeTagMenu( guiInfo,guiLabel,-5 ) ).append( "</span>" ); // 5.9.6.1
1019//                                              rtn.append("<span class=\"design-onelevel\">").append( makeTagMenu( guiInfos[i],guiLabel,-5 ) ).append( "</span>" ); // 5.9.6.1
1020                                        }
1021                                        else {
1022                                                rtn.append( makeTagMenu( guiInfo,guiLabel,-2 ) );               // 5.5.2.5 (2012/05/21) イメージアイコン対応
1023//                                              rtn.append( makeTagMenu( guiInfos[i],guiLabel,-2 ) );           // 5.5.2.5 (2012/05/21) イメージアイコン対応
1024                                        }
1025                                }
1026
1027                                if( sideCount > 0 ) {
1028                                        // 全件数をサイドカウント数で割った値が最大行数の場合は、終了する。
1029                                        if( sideTmpCnt / sideCount >= maxCellCount ) {
1030                                                //                                              rtn.append("・・・");
1031                                                break;
1032                                        }
1033                                        // 全件数をサイドカウント数で割った余りがゼロの場合は、行ブレイクする。
1034                                        // 5.5.2.3 (2012/05/15) useDivOneLevel 対応
1035                                        if( sideTmpCnt % sideCount == 0 ) {
1036                                                // 5.5.2.3 (2012/05/15) useDivOneLevel 対応
1037                                                // 6.0.2.5 (2014/10/31) refactoring: findBugs対応。分岐もコメントアウトする。
1038                                //              if( useDivOneLevel ) {
1039                                //                      rtn.append( BR ); // 5.6.0.0 (2013/01/07) BRにする(条件分岐は残しておく)
1040                                //                      // rtn.append("<span style=\"clear: both;\" />");
1041                                //              }
1042                                //              else {
1043                                                        rtn.append( BR );
1044                                //              }
1045                                        }
1046                                        sideTmpCnt++ ;
1047                                }
1048                        }
1049                }
1050
1051                // 5.5.2.3 (2012/05/15) useDivOneLevel 対応
1052                if( useDivOneLevel ) {
1053                        rtn.append("<span style=\"clear: both;\" ><!-- --></span></div>");      // 5.9.1.2 (2015/10/23)
1054                }
1055
1056                return rtn.toString();
1057        }
1058
1059        /**
1060         * 既存のページの次にアクセスされる画面郡のリンクを作成します。
1061         *
1062         * これは、現時点の画面に対して、次にアクセスされる画面の候補を
1063         * ピックアップしておく機能です。
1064         * 実際には、過去にアクセスされた結果より取得しています。
1065         * これは、ONELEVEL と置き換えることになる機能です。
1066         *
1067         * @og.rev 5.2.3.0 (2010/12/01) NEXTGUI 追加
1068         * @og.rev 5.5.2.3 (2012/05/15) useDivOneLevel 対応
1069         * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(makeTagMenuのパラメータ変更)
1070         * @og.rev 6.2.6.0 (2015/06/19) QUERYに表示される1行メニュは、説明なしの画面名称のみ表示する。
1071         * @og.rev 6.3.1.0 (2015/06/28) useDivOneLevel がうまく動かなかったので、修正。
1072         * @og.rev 5.9.6.1 (2016/03/04) フレーム対応
1073         * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。
1074         *
1075         * @return  メニュー
1076         * @og.rtnNotNull
1077         */
1078        private String makeNextguiMenu() {
1079                final StringBuilder rtn = new StringBuilder( BUFFER_LARGE );
1080
1081                // 今、アクセスしている画面
1082                final GUIInfo thisGamen = (GUIInfo)getSessionAttribute( HybsSystem.GUIINFO_KEY );
1083                final String[] nextGuis = thisGamen.getNextGuiArray();
1084
1085                final UserInfo userInfo = getUser();
1086                int sideTmpCnt = 1;
1087
1088                // 5.5.2.3 (2012/05/15) useDivOneLevel 対応
1089                if( useDivOneLevel ) { rtn.append("<div id=\"design-onelevel\">"); }
1090
1091                GUIInfo guiInfo = null;
1092                // 7.2.9.4 (2020/11/20) PMD:This for loop can be replaced by a foreach loop
1093                for( final String nxtGrp : nextGuis ) {
1094                        guiInfo = userInfo.getGUIInfo( nxtGrp );
1095//              for( int i=0; i<nextGuis.length; i++ ) {
1096//                      guiInfo = userInfo.getGUIInfo( nextGuis[i] );
1097                        if( guiInfo == null ) { continue; }             // 存在しない、またはアクセス拒否の場合は、無視する。
1098
1099                        if( guiInfo.isRead() ) {
1100                                final String guiLabel = guiInfo.getLabel();             // 6.2.6.0 (2015/06/19) 画面名称(title無)
1101
1102                                // 5.5.2.3 (2012/05/15) useDivOneLevel 対応
1103                                if( useDivOneLevel ) {
1104                                        // 5.5.2.5 (2012/05/21) イメージアイコン対応
1105                                        rtn.append("<span class=\"design-onelevel\">").append( makeTagMenu( guiInfo,guiLabel,-5 ) ).append( "</span>" );
1106                                }
1107                                else {
1108                                        rtn.append( makeTagMenu( guiInfo,guiLabel,-2 ) );               // 5.5.2.5 (2012/05/21) イメージアイコン対応
1109                                }
1110
1111                                if( sideCount > 0 ) {
1112                                        // 全件数をサイドカウント数で割った値が最大行数の場合は、終了する。
1113                                        if( sideTmpCnt / sideCount >= maxCellCount ) {
1114                                                break;
1115                                        }
1116                                        // 全件数をサイドカウント数で割った余りがゼロの場合は、行ブレイクする。
1117                                        // 5.5.2.3 (2012/05/15) useDivOneLevel 対応
1118                                        if( sideTmpCnt % sideCount == 0 ) {
1119                                                // 6.3.1.0 (2015/06/28) useDivOneLevel がうまく動かなかったので、修正。
1120                        //                      if( useDivOneLevel ) {
1121                        //                              rtn.append("<span style=\"clear: both;\" />");
1122                        //                      }
1123                        //                      else {
1124                                                        rtn.append( BR );
1125                        //                      }
1126                                        }
1127                                        sideTmpCnt++ ;
1128                                }
1129                        }
1130                }
1131
1132                // 5.5.2.3 (2012/05/15) useDivOneLevel 対応
1133                // 6.3.1.0 (2015/06/28) useDivOneLevel がうまく動かなかったので、修正。
1134                if( useDivOneLevel ) {
1135//                      rtn.append("<span style=\"clear: both;\" /></div>");
1136                        rtn.append("<span style=\"clear: both;\" ></span></div>");                      // 7.0.1.0 (2018/10/15)
1137                }
1138
1139                return rtn.toString();
1140        }
1141
1142        /**
1143         * メニューを表示する為のHTMLを作成します(マトリクスメニュー)。
1144         *
1145         * 分類まとめ、クラス色指定、最小行数設定、最大行数設定の機能があります。
1146         * 《分類まとめ》 最大行数設定(maxCellCount)に達したセルは、一つ右に新たにセルを作成
1147         * します。このとき、ヘッダーの CLASSIFY を同じにして、colspan でまとめます。
1148         * 《クラス色指定》ヘッダー毎に 順次 CLR0,CLR1,・・・・ というクラス属性を付与します。
1149         * ヘッダーには、MENU_H も出力されています。CLR0 は、大分類ごとに加算されていきますので、
1150         * 繰り返して同じ色を指定する場合は、CSSファイルでまとめて指定してください。
1151         * 《最小行数設定》minCellCount 属性を指定することで、1セルに含まれる最小行数を指定できます。
1152         * これは、セルに入れる &lt;br /&gt; の個数を指定することと同じです。
1153         * 《最大行数設定》maxCellCount 属性を指定することで、1セルに含まれる最大行数を指定できます。
1154         * 分類まとめでも説明しましたように、最大値をオーバーすると次のセルから書き始めます。
1155         *
1156         * @og.rev 4.0.0.0 (2005/11/30) 新規追加
1157         * @og.rev 4.0.0.0 (2007/10/05) 分類のコードリソースが存在しない場合
1158         * @og.rev 5.2.3.0 (2010/12/01) sideCount対応
1159         * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(makeTagMenuのパラメータ変更)
1160         * @og.rev 5.5.5.3 (2012/08/17) th,tdにヘッダの画面IDをクラスとして出力
1161         * @og.rev 6.8.2.3 (2017/11/10) minCellCountの数が、一つ足りない事の修正
1162         * @og.rev 6.9.4.1 (2018/04/09) HYBS_BR の廃止 , gamenId の変数設定
1163         * @og.rev 8.2.1.0 (2022/07/15) useLongName 属性追加
1164         *
1165         * @return  マトリクスメニュー
1166         * @og.rtnNotNull
1167         */
1168        private String makeMatrixMenu() {
1169                final StringBuilder rtn = new StringBuilder( BUFFER_LARGE );
1170
1171                final UserInfo userInfo = getUser();
1172
1173                // 4.0.0 (2005/01/31)
1174                final GUIInfo[] guiInfos = userInfo.getGUIInfos();
1175//              String gamenId          ;                       // 画面ID
1176                String bkClassifyKey    = null;         // 分類コード(旧)
1177                String bkClassifyName   = null;         // 分類名称(旧)
1178                int        cellColorCnt = 0;            // MENU_H に 追加する CLR クラス属性の連番
1179
1180                String headGuikey = "";                         //  5.5.5.3 (2012/08/17) ヘッダのgamenId
1181
1182                final StringBuilder rtnH = new StringBuilder( BUFFER_LARGE );
1183                final StringBuilder rtnB = new StringBuilder( BUFFER_LARGE );
1184
1185                int level ;
1186                int preLevel = 0;
1187
1188                int lineTmpCnt = 0;                             // セル中の行カウント
1189                int cellTmpCnt = 0;                             // 1つの分類中のセルカウント
1190                int cellTmpAllCnt = 0;                  // 5.2.3.0 (2010/12/01) 該当行のセルカウント
1191
1192                boolean isInClassify  = false;  // 分類の中か?
1193                boolean isChangeLevel = false;  // 直リンク用(無理やり通常画面の階層として扱うので)
1194                boolean isDummyMENU   = false;  // 5.2.3.0 (2010/12/01) sideCountブレーク時の大分類領域の出力可否              7.2.9.4 (2020/11/20) isDummyMENU_S → isDummyMENU
1195
1196                for( int i=0; i<guiInfos.length; i++ ) {
1197                        if( guiInfos[i].isRead() ) {            // 4.0.0 (2005/01/31)
1198                                final String gamenId = guiInfos[i].getKey() ;
1199                                if( match   != null && !gamenId.matches( match  ) ) { continue; }
1200                                if( unmatch != null && gamenId.matches( unmatch ) ) { continue; }
1201
1202                                // 処理すべき画面かのチェック
1203                                final int guiFlg = guiCheck( guiInfos, i );
1204                                if( guiFlg == 0 ) { continue; }
1205
1206                                level = guiInfos[i].getLevel();         // 4.0.0 (2005/01/31)
1207
1208                                // 大分類が来るまでは処理しない
1209                                if( level > 1 && rtnH == null ) { continue; }
1210
1211                                // 直リンクの場合、無理やり通常画面に変換
1212                                if( level == 2 && guiInfos[i].getAddress() != null && guiInfos[i].getAddress().length() != 0 ) {
1213                                        level = 3;
1214                                        if( !isChangeLevel ) {
1215                                                isChangeLevel = true;
1216                                                isInClassify = false;
1217                                        }
1218                                }
1219                                else {
1220                                        isChangeLevel = false;
1221                                }
1222
1223                                // 分類のブレイク処理
1224                                if( preLevel >= 3 && level < 3 || !isInClassify ) {                                                             // 6.9.7.0 (2018/05/14) PMD Useless parentheses.
1225                                        if(  lineTmpCnt != 0 ) {
1226                                                for( int j=lineTmpCnt; j<minCellCount; j++ ) { rtnB.append( BR ); }             // 6.8.2.3 (2017/11/10)
1227                                                rtnB.append( "</td>" ).append( CR );
1228                                        }
1229
1230                                        if( bkClassifyKey != null ) {
1231                                                rtnH.append( "<th colspan=\"" ).append( cellTmpCnt ).append( "\" class=\"MENU_H CLR" )
1232                                                        .append( cellColorCnt ).append( ' ' ).append( headGuikey ).append( "\">" ); // 5.5.5.3 (2012/08/17)
1233                                                if( "_SPACE".equals( bkClassifyKey ) ) {
1234                                                        rtnH.append( ' ' );             // 6.0.2.5 (2014/10/31) char を append する。
1235                                                }
1236                                                else {
1237                                                        rtnH.append( makeTagMenuString( null,null,bkClassifyName,bkClassifyKey,-3 ) );
1238                                                }
1239                                                rtnH.append( "</th>" );
1240
1241                                                // 5.2.3.0 (2010/12/01) sideCount によるセルの改行
1242                                                cellTmpAllCnt += cellTmpCnt;
1243                                                if( sideCount > 0 && cellTmpAllCnt >= sideCount ) {
1244                                                        rtn.append( rtnH ).append( "</tr><tr>" ).append( rtnB ).append( "</tr>" );
1245
1246                                                        rtnH.setLength(0);              // 6.1.0.0 (2014/12/26) refactoring
1247                                                        rtnB.setLength(0);              // 6.1.0.0 (2014/12/26) refactoring
1248                                                        cellTmpAllCnt = 0;
1249                                                        isDummyMENU   = true;   // 出力予約
1250                                                }
1251                                        }
1252
1253                                        bkClassifyKey = null;
1254                                        isInClassify = false;
1255                                        lineTmpCnt = 0;
1256                                        cellTmpCnt = 0;
1257                                }
1258
1259                                // 大分類(フィールドメニュー)
1260                                if( level == 1 ) {
1261                                        headGuikey = gamenId; // 5.5.5.3 (2012/08/17)
1262                                        if( preLevel > 0 ) {
1263                                                cellColorCnt++ ;
1264                                                rtn.append( rtnH ).append( "</tr><tr>" ).append( rtnB ).append( "</tr>" );
1265                                        }
1266
1267                                        rtn.append( "<tr><td rowspan=\"2\" class=\"MENU_S "+ headGuikey +"\">" )        // 5.5.5.3 (2012/08/17)
1268//                                              .append( makeTagMenuString( null,null,guiInfos[i].getName(),gamenId,-3 ) )
1269                                                .append( makeTagMenuString( null,null,guiInfos[i].getName(useLongName),gamenId,-3 ) )   // 8.2.1.0 (2022/07/15) true:名前(長)/false:名前(短)
1270                                                .append( "</td>" ).append( CR );
1271
1272                                        rtnH.setLength(0);              // 6.1.0.0 (2014/12/26) refactoring
1273                                        rtnB.setLength(0);              // 6.1.0.0 (2014/12/26) refactoring
1274                                        cellTmpAllCnt = 0;              // 5.2.3.0 (2010/12/01)
1275                                        isDummyMENU   = false;  // 5.2.3.0 (2010/12/01) 出力予約解除
1276                                }
1277                                // 分類(直リンクの場合は、level=3で処理)
1278                                else if( level == 2 ) {
1279                                        isInClassify = true;
1280//                                      bkClassifyKey = guiInfos[i].getKey();
1281                                        bkClassifyKey = gamenId;                                                // 6.9.4.1 (2018/04/09)
1282//                                      bkClassifyName = guiInfos[i].getName();
1283                                        bkClassifyName = guiInfos[i].getName(useLongName);      // 8.2.1.0 (2022/07/15) true:名前(長)/false:名前(短)
1284                                }
1285                                // 通常メニュー・隠しメニュー
1286                                else if( level >= 3 ) {
1287
1288                                        // 元のMENU_Sに戻り、rowspan を書き換える・・・のが邪魔くさいので、td のみ出力しておく。
1289                                        // 5.2.3.0 (2010/12/01) sideCount によるセルの改行
1290                                        if( isDummyMENU ) {
1291                                                rtn.append( "<tr><td rowspan=\"2\" class=\"MENU_S " )
1292                                                        .append( headGuikey ).append( "\"></td>" )      // 5.5.5.3 (2012/08/17)
1293                                                        .append( CR );
1294                                                isDummyMENU = false;            // 出力予約解除
1295                                        }
1296
1297                                        // 画面ID="HYBS_BR"の場合は、セルを変える。
1298//                                      if( "HYBS_BR".equals( guiInfos[i].getKey() ) ) {
1299                                        if( "HYBS_BR".equals( guiInfos[i].getAddress() ) ) {                                    // 6.9.4.1 (2018/04/09) HYBS_BR は、アドレスに設定
1300                                                if( lineTmpCnt != 0 ) {
1301                                                        for( int j=lineTmpCnt; j<minCellCount; j++ ) { rtnB.append( BR ); }             // 6.8.2.3 (2017/11/10)
1302                                                        lineTmpCnt = 0;
1303                                                }
1304                                        }
1305                                        // 通常画面
1306                                        else {
1307                                                if( lineTmpCnt == 0 ) {
1308                                                        rtnB.append( "<td class=\"MENU_B " + headGuikey + "\">" ); // 5.5.5.3 (2012/08/17)
1309                                                        cellTmpCnt++;
1310                                                }
1311
1312//                                              rtnB.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),-3 ) );             // 5.5.2.5 (2012/05/21) イメージアイコン対応
1313                                                rtnB.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(useLongName),-3 ) );  // 8.2.1.0 (2022/07/15) true:名前(長)/false:名前(短)
1314                                                lineTmpCnt++;
1315
1316                                                if( lineTmpCnt >= maxCellCount ) {
1317                                                        rtnB.append( "</td>" );
1318                                                        lineTmpCnt = 0;
1319                                                }
1320                                                else {
1321                                                        rtnB.append( BR );
1322                                                }
1323
1324                                                // 分類の中に入っていない通常画面
1325                                                if( !isInClassify ) {
1326                                                        bkClassifyKey = "_SPACE";
1327                                                        isInClassify = true;
1328                                                }
1329                                        }
1330                                }
1331
1332                                preLevel = level;
1333                        }
1334                }
1335
1336                // 終了処理
1337                for( int j=lineTmpCnt; j<minCellCount; j++ ) { rtnB.append( BR ); }             // 6.8.2.3 (2017/11/10)
1338                rtnB.append( "</td>" ).append( CR );
1339
1340                if( bkClassifyKey != null ) {
1341                        rtnH.append( "<th colspan=\"" ).append( cellTmpCnt )
1342                                .append( "\" class=\"MENU_H CLR" ) .append(  cellColorCnt )
1343                                .append( ' ' ).append(  headGuikey ).append( "\">" )                    // 5.5.5.3 (2012/08/17)
1344                                .append( makeTagMenuString( null,null,bkClassifyName,bkClassifyKey,-3 ) )
1345                                .append( "</th>" );
1346                }
1347
1348                rtn.append( rtnH ).append( "</tr><tr>" ).append( rtnB ).append( "</tr>" );
1349
1350                return rtn.toString();
1351        }
1352
1353        /**
1354         * メニューを表示する為のHTMLを作成します(マトリクスメニュー2)。
1355         *
1356         * マトリクスメニューをベースとした特別バージョンです。
1357         * 通常のマトリクスメニューからの変更点は以下の通りです。
1358         * ①大分類が表示されない
1359         *   ⇒ 変わりに、1行に表示されているセル数がsideCountで指定した数を超えた場合に
1360         *      自動的に改行されます。
1361         * ②画面リンクのターゲット
1362         *   ⇒ 自分自身のフレームに対してリンク先を表示します。
1363         *      リンク先は、通常メニュー構成ですが左メニューには該当する小分類の画面しか表示されません。
1364         * ③小分類でのリンク
1365         *   ⇒ 小分類をクリックした際に、通常のメニュー構成画面にリンクします。
1366         *      但し、②と同様に左メニューには該当する小分類の画面しか表示されません。
1367         *
1368         * @og.rev 4.2.1.0 (2008/04/01) 新規追加
1369         * @og.rev 4.2.1.1 (2008/05/02) カテゴリーリンクで一番上の画面のモードが-wとなっている場合に、
1370         *                               その画面が立ち上がってしまうバグを修正
1371         * @og.rev 4.2.2.0 (2008/05/14) buttonRequestの付加をmakeTagMenuString()に変更
1372         * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(makeTagMenuのパラメータ変更)
1373         * @og.rev 5.5.5.3 (2012/08/17) ヘッダ部のgamenIdをth,tdのクラスに追加
1374         * @og.rev 6.8.2.3 (2017/11/10) minCellCountの数が、一つ足りない事の修正
1375         * @og.rev 6.9.4.1 (2018/04/09) HYBS_BR の廃止 , gamenId の変数設定
1376         * @og.rev 7.4.2.2 (2021/05/28) マトリクスメニュー(MATRIX)で、グループのボタンリンクを止めます。
1377         * @og.rev 8.2.1.0 (2022/07/15) useLongName 属性追加
1378         *
1379         * @return  マトリクスメニュー
1380         * @og.rtnNotNull
1381         */
1382        private String makeMatrixMenu2() {
1383                final StringBuilder rtn = new StringBuilder( BUFFER_LARGE );
1384
1385                final UserInfo userInfo = getUser();
1386
1387                final GUIInfo[] guiInfos = userInfo.getGUIInfos();
1388//              String gamenId          ;                       // 画面ID
1389                String bkClassifyKey    = null;         // 分類コード(旧)
1390        //      String nextKey                  = null;         // 分類ボタンを押した時に最初の画面が開くようにする            8.0.0.0 (2021/07/31) Delete
1391                String bkClassifyName   = null;         // 分類名称(旧)
1392                final int          cellColorCnt = 0;            // MENU_H に 追加する CLR クラス属性の連番
1393
1394                final StringBuilder rtnH = new StringBuilder( BUFFER_LARGE );           // 分類部分の出力用
1395                final StringBuilder rtnB = new StringBuilder( BUFFER_LARGE );           // 実画面のリンク部分の出力用
1396
1397                int level ;
1398                int preLevel = 0;
1399
1400                int lineTmpCnt = 0;                             // セル中の行カウント
1401                int cellTmpCnt = 0;                             // 1つの分類中のセルカウント
1402                int cellTmpAllCnt = 0;                  // 該当行のセルカウント
1403
1404                boolean isInClassify = false;   // 分類の中か?
1405                boolean isChangeLevel = false;  // 直リンク用(無理やり通常画面の階層として扱うので)
1406
1407                String headGuikey = "" ;                // 5.5.5.3 (2012/08/17)
1408
1409                rtn.append( "<tr>" ).append( CR );
1410
1411                for( int i=0; i<guiInfos.length; i++ ) {
1412                        if( guiInfos[i].isRead() ) {            // 4.0.0 (2005/01/31)
1413                                final String gamenId = guiInfos[i].getKey() ;
1414                                if( match   != null && !gamenId.matches( match  ) ) { continue; }
1415                                if( unmatch != null && gamenId.matches( unmatch ) ) { continue; }
1416
1417                                // 処理すべき画面かのチェック
1418                                final int guiFlg = guiCheck( guiInfos, i );
1419                                if( guiFlg == 0 ) { continue; }
1420
1421                                level = guiInfos[i].getLevel();         // 4.0.0 (2005/01/31)
1422
1423                                // 直リンクの場合、無理やり通常画面に変換
1424                                if( level == 2 && guiInfos[i].getAddress() != null && guiInfos[i].getAddress().length() != 0 ) {
1425                                        level = 3;
1426                                        if( !isChangeLevel ) {
1427                                                isChangeLevel = true;
1428                                                isInClassify = false;
1429                                        }
1430                                }
1431                                else {
1432                                        isChangeLevel = false;
1433                                }
1434
1435                                // 分類のブレイク処理
1436                                if( preLevel >= 3 && level < 3 || !isInClassify ) {                                                             // 6.9.7.0 (2018/05/14) PMD Useless parentheses.
1437                                        if(  lineTmpCnt != 0 ) {
1438                                                for( int j=lineTmpCnt; j<minCellCount; j++ ) { rtnB.append( BR ); }             // 6.8.2.3 (2017/11/10)
1439                                                //rtnB.append( "</td>" ).append( CR ); // 4.2.1.0 (2008/04/03) リスト
1440                                                rtnB.append( "</ul></div></td>" ).append( CR );
1441                                        }
1442
1443                                        if( bkClassifyKey != null ) {
1444                                                // 6.0.2.5 (2014/10/31) char を append する。
1445                                                rtnH.append( "<th colspan=\"" ).append( cellTmpCnt ).append( "\" class=\"MENU_H CLR" )
1446                                                        .append( cellColorCnt ).append( ' ' ).append( headGuikey ).append( "\">" ).append( "<div>" );           // 5.5.5.3 (2012/08/17)
1447                                                if( "_SPACE".equals( bkClassifyKey ) ) {
1448                                                        rtnH.append( ' ' );                                     // 6.0.2.5 (2014/10/31) refactoring
1449                                                }
1450                                                else {
1451                                                        // 6.4.2.1 (2016/02/05) PMD refactoring.
1452                                //                      final String classifyHref = JSP + "/index.jsp?classify=" + bkClassifyKey + "&amp;GAMENID="+nextKey;             // ボタンを押した場合に最初の画面が現れる
1453                                //                      rtnH.append( makeTagMenuString( classifyHref,"_self",bkClassifyName,bkClassifyKey,-3 ) );
1454                                                        rtnH.append( makeTagMenuString( null,null,bkClassifyName,bkClassifyKey,-3 ) );                                  // 7.4.2.2 (2021/05/28)
1455                                                }
1456                                                rtnH.append( "</div>" ).append( "</th>" );
1457
1458                                                cellTmpAllCnt += cellTmpCnt;
1459
1460                                                if( sideCount > 0 && cellTmpAllCnt >= sideCount ) {
1461                                                        rtn.append( rtnH ).append( "</tr><tr>" ).append( rtnB ).append( "</tr>" );
1462
1463                                                        rtnH.setLength(0);                              // 6.1.0.0 (2014/12/26) refactoring
1464                                                        rtnB.setLength(0);                              // 6.1.0.0 (2014/12/26) refactoring
1465                                                        cellTmpAllCnt = 0;
1466                                                }
1467                                        }
1468
1469                                        bkClassifyKey = null;
1470                //                      nextKey           = null;
1471                                        isInClassify = false;
1472                                        lineTmpCnt = 0;
1473                                        cellTmpCnt = 0;
1474                                }
1475
1476                                // 5.5.5.3 (2012/08/17) 大分類(フィールドメニュー)
1477                                if( level == 1 ) {
1478                                        headGuikey = gamenId;
1479                                }
1480                                // 分類(直リンクの場合は、level=3で処理)
1481                                else if( level == 2 ) {
1482                                        isInClassify = true;
1483                                        if( guiInfos[i].isPulldown() ){ // 4.3.3.0 (2008/10/01) プルダウン化チェック
1484                                                excludeButton = true;
1485                                        }
1486                                        else{
1487                                                excludeButton = false;
1488                                        }
1489//                                      bkClassifyKey = guiInfos[i].getKey();
1490                                        bkClassifyKey = gamenId;                                        // 6.9.4.1 (2018/04/09)
1491//                                      bkClassifyName = guiInfos[i].getName();
1492                                        bkClassifyName = guiInfos[i].getName(useLongName);      // 8.2.1.0 (2022/07/15) true:名前(長)/false:名前(短)
1493                        //              for( int j=i+1; j<guiInfos.length; j++ ) {
1494                        //                      if( guiInfos[j] != null && guiInfos[j].isRead() ) {
1495                        //                              nextKey = guiInfos[j].getKey();
1496                        //                              break;
1497                        //                      }
1498                        //              }
1499                                }
1500                                // 通常メニュー・隠しメニュー
1501                                else if( level >= 3 ) {
1502                                        // 画面ID="HYBS_BR"の場合は、セルを変える。
1503//                                      if( "HYBS_BR".equals( guiInfos[i].getKey() ) ) {
1504                                        if( "HYBS_BR".equals( guiInfos[i].getAddress() ) ) {                                    // 6.9.4.1 (2018/04/09) HYBS_BR は、アドレスに設定
1505                                                if( lineTmpCnt != 0 ) {
1506                                                        for( int j=lineTmpCnt; j<minCellCount; j++ ) { rtnB.append( BR ); }             // 6.8.2.3 (2017/11/10)
1507                                                        lineTmpCnt = 0;
1508                                                }
1509                                        }
1510                                        // 通常画面
1511                                        else {
1512                                                if( lineTmpCnt == 0 ) {
1513                                                        // rtnB.append( "<td class=\"MENU_B\">" );
1514                                                        // 4.2.1.0 (2008/04/03) リンクをリスト形式で出す案
1515                                                        rtnB.append( "<td class=\"MENU_B "+ headGuikey +"\"> <div class=\"gamen-menu-wrap\"><ul class=\"gamen-menu\">" ); // 5.5.5.3 (2012/08/17)
1516                                                        cellTmpCnt++;
1517                                                }
1518
1519                                                // 5.5.2.5 (2012/05/21) リストは、イメージを設定するので、メソッド側で付与します。
1520//                                              rtnB.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(),-4 ) );             // 5.5.2.5 (2012/05/21) イメージアイコン対応
1521                                                rtnB.append( makeTagMenu( guiInfos[i],guiInfos[i].getName(useLongName),-4 ) );  // 8.2.1.0 (2022/07/15) true:名前(長)/false:名前(短)
1522                                                lineTmpCnt++;
1523
1524                                                if( lineTmpCnt >= maxCellCount ) {
1525                                                        // rtnB.append( "</td>" );
1526                                                        rtnB.append( " </ul> </div></td>" ); // 4.2.1.0 (008/04/03) リスト
1527                                                        lineTmpCnt = 0;
1528                                                }
1529                                //              else {
1530                                //                      rtnB.append( BR ); // 4.2.1.0 (2008/04/03) リスト。改行不要。
1531                                //              }
1532
1533                                                // 分類の中に入っていない通常画面
1534                                                if( !isInClassify ) {
1535                                                        bkClassifyKey = "_SPACE";
1536                                                        isInClassify = true;
1537                                                }
1538                                        }
1539                                }
1540                                preLevel = level;
1541                        }
1542                }
1543
1544                // 終了処理
1545                // 4.3.3.0 (2008/10/01) 終了処理は0の時行はない
1546                if( lineTmpCnt != 0){
1547                        for( int j=lineTmpCnt; j<minCellCount; j++ ) { rtnB.append( BR ); }                     // 6.8.2.3 (2017/11/10)
1548                        rtnB.append( "</td>" ).append( CR );
1549                }
1550
1551                if( bkClassifyKey != null ) {
1552                        rtnH.append( "<th colspan=\"" + cellTmpCnt + "\" class=\"MENU_H CLR" + cellColorCnt + " " + headGuikey + "\">" ).append( "<div>" ); // 5.5.5.3 (2012/08/17)
1553
1554                        // 6.4.2.1 (2016/02/05) PMD refactoring.
1555        //              final String classifyHref = JSP + "/index.jsp?classify=" + bkClassifyKey + "&amp;GAMENID="+nextKey;
1556        //              rtnH.append( makeTagMenuString( classifyHref,"_self",bkClassifyName,bkClassifyKey,-3 ) );
1557                        rtnH.append( makeTagMenuString( null,null,bkClassifyName,bkClassifyKey,-3 ) );                                                  // 7.4.2.2 (2021/05/28)
1558                        rtnH.append( "</div>" ).append( "</th>" );
1559                }
1560
1561                rtn.append( rtnH ).append( "</tr><tr>" ).append( rtnB ).append( "</tr>" );
1562
1563                return rtn.toString();
1564        }
1565
1566        /**
1567         * タイプに応じたメニューを表示する為の文字列を作成します。
1568         * 引数の GUIInfo より、アクセスすべきメニューのhrefと、targetを求めます。
1569         * type = -3 (マトリクスメニュー) の場合だけ、タグ属性の target を使用します。
1570         *
1571         *  0:フィールドセットメニュー
1572         *  1:トップ階層(【分類名称】)
1573         *  2:選択階層(通常の折りたたみメニュー)
1574         *  3:選択非表示(通常は、隠してあります)
1575         *  -1:グループ分類メニュー(class="GUI_GRP"のtdタグで囲われます)
1576         *  -2:ラインメニュー([画面名称] )
1577         *  -3:マトリクスメニュー(一覧)
1578         *  -4:マトリクスメニュー2(一覧)
1579         *  -5:1レベル表示(後続処理は-3と同じ)
1580         *  -6:TILE表示時の選択階層(通常の折りたたみメニュー,2:と同じ)
1581         *
1582         * @og.rev 4.0.0.0 (2005/01/31) 新規登録(makeTopMenu、makeSecondMenuの置き換え)
1583         * @og.rev 4.1.0.1 (2008/01/22) アドレスが[..]から始まる画面はマルチセッションチェックを行わない。
1584         * @og.rev 4.2.1.0 (2008/04/01) マトリクスメニュー2用のタグ作成処理追加
1585         * @og.rev 4.2.1.0 (2008/04/17) マトリクス2からの遷移先でボタンメニューにする処理
1586         * @og.rev 4.2.2.0 (2008/05/14) buttonRequestの付加をmakeTagMenuString()に変更
1587         * @og.rev 4.3.3.7 (2008/11/22) https対応
1588         * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(画面ID単位ではなく、IMAGE_KEYパラメータで指定可能にする。)
1589         * @og.rev 5.7.8.1 (2014/07/18) realAddress の "/" 対応
1590         * @og.rev 6.3.8.4 (2015/10/09) KBLINK(リンク区分)を画面のイメージファイルに割り当てます。
1591         * @og.rev 5.9.6.1 (2016/03/04) -5を追加。-3との違いはresult.jspに飛ばない事
1592         * @og.rev 6.9.5.0 (2018/04/23) multiSessionCheck 廃止(true固定)
1593         *
1594         * @param       guiInfo GUIInfoリンク
1595         * @param       bodyIn  BODY部(表示)
1596         * @param       type    タイプ
1597         *
1598         * @return  階層別メニュー文字列
1599         * @og.rtnNotNull
1600         */
1601        private String makeTagMenu( final GUIInfo guiInfo, final String bodyIn, final int type ) {
1602
1603                String href              = null;
1604                String tmpTarget = null;
1605                final  String gamenId   = guiInfo.getKey();             // 5.5.2.5 (2012/05/21) イメージアイコン対応
1606                int                       tmpType       = type;                                 // 5.9.6.1
1607
1608                if( guiInfo.getAddress() != null && guiInfo.getAddress().length() > 0 ) {
1609                        final String readAdrs = guiInfo.getRealAddress( "index.jsp" );
1610                        final String reqParam = getRequestParameter( guiInfo.getParam() );
1611                        href = XHTMLTag.addUrlEncode( readAdrs,reqParam );
1612                        tmpTarget = guiInfo.getTarget();
1613
1614                        // 4.3.3.7 (2008/11/22) https対応
1615                        // 5.7.8.1 (2014/07/18) realAddress の "/" 対応
1616                        final String kblink = guiInfo.getKblink();
1617                        if( ! readAdrs.startsWith( "http://" ) && ! readAdrs.startsWith( "https://" ) && !"/".equals( kblink ) ) {
1618                                if( type == -3 ) {
1619                                        tmpTarget = target;
1620                                        href = XHTMLTag.addUrlEncode( JSP + "/result.jsp",reqParam );   // 6.2.0.0 (2015/02/27)
1621                                }
1622                                else if( type == -4 ) {         // 4.2.1.0 (2008/04/01)
1623                                        tmpTarget = "_self";
1624                                        href = XHTMLTag.addUrlEncode( JSP + "/index.jsp",reqParam );    // 6.2.0.0 (2015/02/27)
1625                                        href = XHTMLTag.addUrlEncode( href,"classify=" + guiInfo.getClassify() );
1626                                }
1627                                else if( type == -5 ){          // 5.9.6.1 (2016/03/04)
1628                                        tmpTarget = target;
1629                                        tmpType = -3;
1630                                }
1631                                href = XHTMLTag.addUrlEncode( href,"GAMENID=" + gamenId );                      // 5.5.2.5 (2012/05/21) せっかくなので、利用する。
1632
1633                                // 3.8.0.0 (2005/06/07) 同一セッションでのマルチ起動対策を行います。
1634                                // 4.1.0.1 (2008/01/22) アドレスが[..]から始まる画面はマルチセッションチェックを行いません。
1635                                // 4.1.0.1 (2008/04/01) マトリクスメニュー2はマルチセッションチェックを行いません。
1636//                              if( multiSessionCheck && !guiInfo.getAddress().startsWith( ".." ) && type != -4 ) {
1637                                if( !guiInfo.getAddress().startsWith( ".." ) && type != -4 ) {          // 6.9.5.0 (2018/04/23) multiSessionCheck 廃止(true固定)
1638                                        href = XHTMLTag.addUrlEncode( href,mscKey );
1639                                }
1640                        }
1641                }
1642                // 5.5.2.5 (2012/05/21) イメージアイコン対応(画面ID単位ではなく、IMAGE_KEYパラメータで指定可能にする。)
1643                final String imgKey = guiInfo.getImageKey() ;
1644                return makeTagMenuString( href,tmpTarget,bodyIn,gamenId,imgKey,tmpType ) ; // 5.9.6.1
1645        }
1646
1647        /**
1648         * タイプに応じたメニューを表示する為の文字列を作成します。
1649         * 従来からのメソッドの引数のままで、新しい gamenId は、imgKey をそのままセットします。
1650         *
1651         *  0:フィールドセットメニュー
1652         *  1:トップ階層(【分類名称】)
1653         *  2:選択階層(通常の折りたたみメニュー)
1654         *  3:選択非表示(通常は、隠してあります)
1655         *  -1:グループ分類メニュー(class="GUI_GRP"のtdタグで囲われます)
1656         *  -2:ラインメニュー([画面名称] )
1657         *  -3:マトリクスメニュー(一覧)
1658         *  -4:マトリクスメニュー2(一覧)
1659         *  -5:1レベル表示(後続処理は-3と同じだが、絶対パスの場合は、画面リソースのtargetを使用する。)
1660         *  -6:TILE表示時の選択階層(通常の折りたたみメニュー,2:と同じ)
1661         *
1662         * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(画面ID単位ではなく、IMAGE_KEYパラメータで指定可能にする。)
1663         *
1664         * @param       href    リンク
1665         * @param       target  ターゲット
1666         * @param       bodyIn  BODY部(表示)
1667         * @param       imgKey  imageファイルの検索キー
1668         * @param       type    タイプ
1669         *
1670         * @return  階層別メニュー文字列
1671         * @og.rtnNotNull
1672         */
1673        private String makeTagMenuString( final String href,final String target, final String bodyIn,
1674                                                                final String imgKey,final int type ) {
1675                return makeTagMenuString( href,target,bodyIn,imgKey,imgKey,type );      // gamenId の代わりに、imgKey をセットする。
1676        }
1677
1678        /**
1679         * タイプに応じたメニューを表示する為の文字列を作成します。
1680         *
1681         * タイプは、階層別になっていますが、マイナスは、内部で処理するための記号です。
1682         *
1683         *  0:フィールドセットメニュー
1684         *  1:トップ階層(【分類名称】)
1685         *  2:選択階層(通常の折りたたみメニュー)
1686         *  3:選択非表示(通常は、隠してあります)
1687         *  -1:グループ分類メニュー(class="GUI_GRP"のtdタグで囲われます)
1688         *  -2:ラインメニュー([画面名称] )
1689         *  -3:マトリクスメニュー(一覧)
1690         *  -4:マトリクスメニュー2(一覧)
1691         *  -5:1レベル表示(後続処理は-3と同じだが、絶対パスの場合は、画面リソースのtargetを使用する。)
1692         *  -6:TILE表示時の選択階層(通常の折りたたみメニュー,2:と同じ)
1693         *
1694         * @og.rev 4.0.0.0 (2005/01/31) 新規登録(makeTopMenu、makeSecondMenuの置き換え)
1695         * @og.rev 4.0.0.0 (2007/11/28) switch文の中の二重コードを統一します。
1696         * @og.rev 4.2.1.0 (2008/04/01) ボタン形式のリンク対応、マトリクスメニュー2対応
1697         * @og.rev 4.2.2.0 (2008/05/14) buttonRequestの付加をここで行うようにする
1698         * @og.rev 4.3.5.0 (2009/02/01) switch の case で重複項目をまとめます。
1699         * @og.rev 5.1.4.0 (2010/03/01) onClick,onMouseOver,onMouseOutの処理は、外部のJavaScriptファイルで記述します。
1700         * @og.rev 5.1.8.0 (2010/07/01) コードリソースのキーが存在しない場合にエラーとなるバグを修正
1701         * @og.rev 5.3.9.0 (2011/09/01) メニューでのヘルプアイコン対応
1702         * @og.rev 5.4.4.4 (2012/02/15) ヘルプアイコンはimgKeyがnullでない場合のみとする
1703         * @og.rev 5.5.0.4 (2012/03/14) FAQ対応
1704         * @og.rev 5.5.2.5 (2012/05/21) イメージアイコン対応(画面ID単位ではなく、IMAGE_KEYパラメータで指定可能にする。)
1705         * @og.rev 5.5.4.2 (2012/07/13) JSP(/gf/jsp/) ではなく、CNTX(gf)+MENU_IMG(/jsp/menuImage/) で処理するように変更
1706         * @og.rev 6.2.2.0 (2015/03/27) BRと\nを相互に変換する処理を追加
1707         * @og.rev 6.2.2.3 (2015/04/10) htmlフィルターに、BR→改行処理機能を追加。
1708         * @og.rev 6.3.8.4 (2015/10/09) topMenu 内でのHelp機能を廃止します。
1709         * @og.rev 6.3.8.4 (2015/10/09) FileMap のコンストラクタ変更に伴う対応。
1710         * @og.rev 6.7.5.0 (2017/03/10) TILE表示追加
1711         * @og.rev 6.8.0.1 (2017/06/30) -5:1レベル表示追加(元は、相対パスのみ対応していたが、絶対パスにも対応)
1712         * @og.rev 6.8.1.6 (2017/09/29) imageOnly="true" で、イメージにリンクが付かないバグ修正。
1713         * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。
1714         * @og.rev 7.2.9.4 (2020/11/20) spotbugs:switch 文の2つの case のために同じコードを使用しているメソッド
1715         * @og.rev 7.3.2.0 (2021/03/19) FileMapは、static化して使いまわす。
1716         *
1717         * @param       href    リンク
1718         * @param       target  ターゲット
1719         * @param       bodyIn  BODY部(表示)
1720         * @param       gamenId 画面ID/グループIDなど
1721         * @param       imgKey  imageファイルの検索キー
1722         * @param       type    タイプ
1723         *
1724         * @return  階層別メニュー文字列
1725         * @og.rtnNotNull
1726         */
1727        private String makeTagMenuString( final String href,final String target, final String bodyIn,
1728                                                                final String gamenId,final String imgKey,final int type ) {
1729
1730                final String body ;
1731                final String img ;                      // 6.7.5.0 (2017/03/10) イメージを、【】の外に出す。
1732                String listStyle = "<li>";
1733                // 6.3.8.4 (2015/10/09) FileMap のコンストラクタ変更に伴う対応。
1734                // 最初に見つけたキーが優先されるので、画面IDのファイルを優先します。
1735//              final String imgFile = imgFileMap.getFilename( gamenId,imgKey );        // 5.5.2.5 (2012/05/21) 属性名変更
1736                final String imgFile = imgFileMap == null ? null : imgFileMap.getFilename( gamenId,imgKey );    // 7.3.2.0 (2021/03/19) 一応、チェック
1737                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
1738                if( imgFile == null ) {
1739                        img = "";
1740                        if( imageOnly && bodyIn != null && bodyIn.length() > 0 ) {
1741                                body = "<span title=\"" + StringUtil.htmlFilter( bodyIn,true ) + "\" >" + bodyIn.charAt(0) + "</span>" ;
1742                        }
1743                        else {
1744                                body = bodyIn ;
1745                        }
1746                }
1747                else {
1748                        if( imageOnly ) {
1749                                // 6.8.1.6 (2017/09/29) imageOnly="true" で、イメージにリンクが付かないバグ修正。リンクは、body に付く
1750                                img = "";
1751                                body = "<img src=\"" + imgFile + "\" class=\"ICON1\" title=\""
1752//                                                       + StringUtil.htmlFilter( bodyIn,true ) + "\" />" ;
1753                                                         + StringUtil.htmlFilter( bodyIn,true ) + "\" >" ;                      // 7.0.1.0 (2018/10/15)
1754                        }
1755                        // 5.5.2.5 (2012/05/21) -4(MATRIX Menu2)の場合は、<li style="list-style:url(画像URL);"> で処理する。
1756                        else if( type == -4 ) {
1757                                listStyle = "<li style=\"list-style:url(" + imgFile + ");\">" ;
1758                                body = bodyIn ;
1759                                img = "";
1760                        }
1761                        else {
1762                                // 6.7.5.0 (2017/03/10) TILE表示のレベル-6では、イメージ直後に BR を入れる。(暫定処置)
1763                                if( type == -6 ) {
1764//                                      img = "<img src=\"" + imgFile + "\" class=\"ICON2\" /><br />" ;         // ICON2 + BR
1765                                        img = "<img src=\"" + imgFile + "\" class=\"ICON2\" ><br>" ;            // ICON2 + BR   7.0.1.0 (2018/10/15)
1766                                }
1767                                else {
1768//                                      img = "<img src=\"" + imgFile + "\" class=\"ICON1\" />" ;                       // ICON1
1769                                        img = "<img src=\"" + imgFile + "\" class=\"ICON1\" >" ;                        // ICON1                7.0.1.0 (2018/10/15)
1770                                }
1771                                body = bodyIn;
1772                        }
1773                }
1774
1775                final String in ;
1776                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
1777                if( href == null ) {
1778                        in = body;
1779                }
1780                else {
1781                        if( useButton ) { // 4.2.1.0 (2008/04/01)
1782                                // 6.1.1.0 (2015/01/17) TagBufferの連結記述
1783                                in = new TagBuffer( "button" )
1784                                                .add( "onclick" , "top."+target+".location.href=\'"+ href + "\';" )             // 5.1.4.0 (2010/03/01)
1785                                                .add( "class"   , "buttonMenu" )                // 4.2.1.0 (2008/04/03) classを追加
1786                                                .add( "id"              , gamenId )                             // 5.5.2.5 (2012/05/21) idを本当の画面IDで設定
1787                                                .addBody( body )
1788                                                .makeTag();
1789                        }
1790                        else {
1791                                // 4.2.2.0 (2008/05/14) ボタン式にする場合はリクエスト変数付加
1792                                // 4.3.3.0 (2008/10/01) 強制プルダウン化の場合はfalseで渡す(excludeButton の値の反転)
1793                                final String href2 = buttonRequest
1794                                                                                        ? XHTMLTag.addUrlEncode( href,"buttonRequest=" + !excludeButton)
1795                                                                                        : href ;
1796                                // 6.1.1.0 (2015/01/17) TagBufferの連結記述
1797                                in = new TagBuffer( "a" )
1798                                                .add( "class"   , "buttonClassify" , buttonRequest )
1799                                                .add( "href"    , href2 )
1800                                                .add( "target"  , target )
1801                                                .addBody( body )
1802                                                .makeTag();
1803                        }
1804                }
1805
1806                // 6.7.5.0 (2017/03/10) イメージを、【】の外に出す。
1807                String rtn = null;
1808                switch( type ) {
1809                        // 6.9.8.0 (2018/05/28) FindBugs:switch 文の2つの case のために同じコードを使用しているメソッド
1810                        // 偶然同じになったのと、これを対応するとソースがみにくくなるので、このままとします。
1811                        case 1:  rtn = FIELD_IN + "<legend>" + img + in + "</legend>" ; break;  // 大分類
1812        //              case 2:  rtn = img + "【" + in + "】"     ; break;                // 小分類・直リンク
1813                        case 3:                                                                                                 // 通常メニュー
1814                        case 4:  rtn = " " + img + in                   ; break;                // 隠れメニュー
1815                        case -1: rtn = "<td class=\"MENU_G " + gamenId + "\">" + img + in + "</td>" ; break;    // 5.5.2.5 (2012/05/21) グループメニュー
1816                        case -2: rtn = img + "[" + in + "] "    ; break;                // ラインメニュー
1817        //              case -3: rtn = img + in                                 ; break;                // マトリクスメニュー
1818                        case -4: rtn = listStyle + in + "</li>" ; break;                // 4.2.1.0 (2008/04/03) リスト。リストのため■はいらない
1819                        case -3:                                                                                                // 7.2.9.4 (2020/11/20) マトリクスメニュー
1820                        case -5: rtn = img + in                                 ; break;                // 6.8.0.1 (2017/06/30) 1レベル表示絶対パス
1821                        case  2:                                                                                                // 7.2.9.4 (2020/11/20) 小分類・直リンク
1822                        case -6: rtn = img + "【" + in + "】"     ; break;                // 小分類・直リンク(TILE)
1823                        default :
1824                                rtn = "X_" + in ;  break;                                                       // 6.0.2.5 (2014/10/31) break追記
1825                }
1826
1827                return rtn ;
1828        }
1829
1830        /**
1831         * 【TAG】作成するメニューの種類[NORMAL/GROUP/ONELEVEL/NEXTGUI/MATRIX/MATRIX2]を指定します(初期値:NORMAL)。
1832         *
1833         * @og.tag
1834         * 作成するメニューには、複数の種類があります。
1835         * <table class="plain">
1836         *   <caption>メニューの種類</caption>
1837         *   <tr><th>種類    </th><th>説明  </th></tr>
1838         *   <tr><td>NORMAL  </td><td>通常の階層メニュー</td></tr>
1839         *   <tr><td>GROUP   </td><td>GROUPのみを取り出してリンクを作成します。(topMenuに利用)</td></tr>
1840         *   <tr><td>ONELEVEL</td><td>指定のclassify のメニューのみを取り出してリンクを作成します。(lineMenuに利用)</td></tr>
1841         *   <tr><td>NEXTGUI </td><td>既存のページの次にアクセスされる画面郡のリンクを作成します。</td></tr>
1842         *   <tr><td>MATRIX  </td><td>一覧表形式のメニューを作成します。(大分類付きマルチメニュー)</td></tr>
1843         *   <tr><td>MATRIX2 </td><td>一覧表形式のメニューを作成します。(大分類なしボタンメニュー)</td></tr>
1844         *   <tr><td>NONE    </td><td>表示しない(ヘッダーメニューを表示しない時などに使用)</td></tr>
1845         *   <tr><td>TILE    </td><td>イメージを使った全面アイコン画面</td></tr>
1846         * </table>
1847         *
1848         * @og.rev 4.0.0.0 (2005/01/31) 新規登録
1849         * @og.rev 5.2.3.0 (2010/12/01) NEXTGUI 追加
1850         * @og.rev 6.3.4.0 (2015/08/01) Arrays.toString から String.join に置き換え。
1851         * @og.rev 6.3.8.3 (2015/10/03) NONE(表示しない) 追加(JavaDoc追記のみ)。
1852         * @og.rev 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。
1853         * @og.rev 6.7.5.0 (2017/03/10) TILE表示追加
1854         *
1855         * @param       type メニューの種類 [NORMAL/GROUP/ONELEVEL/NEXTGUI/MATRIX/MATRIX2/NONE/TILE]
1856         */
1857        public void setMenuType( final String type ) {
1858                menuType = nval( getRequestParameter( type ),menuType );
1859                if( ! check( menuType, MENU_TYPE_SET ) ) {
1860                        final String errMsg = "menuType に、指定できない種類の文字が指定されました。" + CR
1861                                                        + "menuType=[" + menuType + "] "                                                                + CR
1862                                                        + "menuType List=" + String.join( ", " , MENU_TYPE_SET ) ;
1863                        throw new HybsSystemException( errMsg );
1864                }
1865        }
1866
1867        /**
1868         * 【TAG】折り返しメニューを構築するかどうかを指定します(初期値:true)。
1869         *
1870         * @og.tag
1871         * trueを設定すると、JavaScriptによる折り返しメニューを構築します。
1872         * false の場合は、通常のHTMLのみで、階層メニューを構築します。
1873         * 初期値は、true(折り返しメニュー)です。
1874         *
1875         * @og.rev 4.0.0.0 (2005/01/31) 新規登録
1876         *
1877         * @param       flag 折り返しメニュー [true:する/false:しない]
1878         */
1879        public void setExpand( final String flag ) {
1880                expand = nval( getRequestParameter( flag ),expand );
1881        }
1882
1883        /**
1884         * 【TAG】表示対象となるグループをCSV形式で指定します。
1885         *
1886         * @og.tag
1887         * メニューの表示対象グループをCSV形式で複数指定できます。
1888         * 指定のグループのメニューだけが、表示対象になります。
1889         * メニューにも、複数のグループを指定できるため、1グループの指定で、
1890         * 複数のくくりを表示することも可能です。
1891         * グループを指定しない場合は、全グループが対象になります。
1892         * また、メニュー側にグループ指定がない場合は、グループ指定に
1893         * 関係なく、対象になります。
1894         * 初期値は、未指定(全メニューが対象)です。
1895         * 分解方法は、通常のパラメータ取得後に、CSV分解します。
1896         *
1897         * @og.rev 4.0.0.0 (2005/01/31) 新規登録
1898         *
1899         * @param       menuGroups 表示対象グループ (CSV形式)
1900         */
1901        public void setGroups( final String menuGroups ) {
1902                groups = StringUtil.csv2Array( getRequestParameter( menuGroups ) );
1903                if( groups.length == 0 ) { groups = null; }
1904        }
1905
1906        /**
1907         * 【TAG】表示対象となる分類(classify)を指定します。
1908         *
1909         * @og.tag
1910         * メニューの表示対象となる分類(classify)を指定することで、一まとまりの
1911         * メニューを作成します。これは、3段階メニューの最終メニューを求める場合に
1912         * 指定します。
1913         * 最終メニューは、画面上部に設ける予定のメニューで、上下フレーム分割での
1914         * 運用時に使用します。
1915         * 分類の指定がない場合は、すべてが表示対象になります。
1916         * 初期値は、未指定(全メニューが対象)です。
1917         *
1918         * @og.rev 4.0.0.0 (2005/01/31) 新規登録
1919         *
1920         * @param       classify 表示対象分類 (classify)
1921         */
1922        public void setClassify( final String classify ) {
1923                selClassify = nval( getRequestParameter( classify ),selClassify );
1924        }
1925
1926        /**
1927         * 【TAG】グループメニューの表示対象となるソース名(href)を指定します(初期値:menu.jsp)。
1928         *
1929         * @og.tag
1930         * GROUPメニューの表示対象となるソース名(href)を指定することで、
1931         * サブメニューを自分自身のフレームに対して割り当てるのか、フレームを分けて
1932         * 管理するのかを自由に設定できます。
1933         * 初期値は、menu.jspです。
1934         *
1935         * @og.rev 4.0.0.0 (2005/01/31) 新規登録
1936         *
1937         * @param       inHref 表示対象ソース名 (href)
1938         */
1939        public void setHref( final String inHref ) {
1940                href = nval( getRequestParameter( inHref ),href );
1941        }
1942
1943        /**
1944         * 【TAG】グループメニューの表示対象となるフレーム名(target)を指定します(初期値:MENU)。
1945         *
1946         * @og.tag
1947         * GROUPメニューの表示対象となるフレーム名(target)を指定することで、
1948         * サブメニューを自分自身のフレームに対して割り当てるのか、フレームを分けて
1949         * 管理するのかを自由に設定できます。
1950         * フレーム分割を行うと、変更箇所は、サブメニューのみになる為、動きに無駄が
1951         * なくなりますが、グループメニューの大きさが固定されてしまいます。
1952         * 自分自身にすると、グループメニューとサブメニューを一つのフレームに
1953         * 入れることで、更新時の画面のちらつきは発生しますが、無駄なスペースは
1954         * 省くことが可能になります。
1955         * 初期値は、MENU(通常のメニューフレーム)です。
1956         *
1957         * @og.rev 4.0.0.0 (2005/01/31) 新規登録
1958         *
1959         * @param       inTarget 表示対象フレーム名 (target)
1960         */
1961        public void setTarget( final String inTarget ) {
1962                target = nval( getRequestParameter( inTarget ),target );
1963        }
1964
1965        /**
1966         * 【TAG】グループメニューの表示に、画像のみかどうか[true:画像のみ/false:画像+ラベル]を指定します(初期値:false)。
1967         *
1968         * @og.tag
1969         * GROUPメニューの表示対象として、jsp/menuImage 以下に グループ名と同一の
1970         * 画像ファイルが存在する場合は、画像を使用します。
1971         * このフラグを、true に設定すると、画像のみを使用します。
1972         * false の場合は、画像+グループ名のラベルを使用します。
1973         * 画像のみの場合でも、title 属性にグループ名のラベルをセットしますので、
1974         * マウスカーソルをオーバーすれば、名称がTips表示されます。
1975         * 画像が存在しない場合に、true(画像のみ)に設定した場合は、ラベルの最初の1文字
1976         * のみを出力します。
1977         * 初期値は、false(画像+ラベル)です。
1978         *
1979         * @og.rev 4.0.0.0 (2005/01/31) 新規登録
1980         *
1981         * @param       flag グループメニュー表示 [true:画像のみ/false:画像+ラベル]
1982         */
1983        public void setImageOnly( final String flag ) {
1984                imageOnly = nval( getRequestParameter( flag ),imageOnly );
1985        }
1986
1987        /**
1988         * 【TAG】グループメニューの表示対象となるメニューを横並びさせる数を指定します。
1989         *
1990         * @og.tag
1991         * GROUPメニューなどの表示を行う場合に、横方向に何個のメニューを表示させるかを
1992         * 指定します。例えば、画像のみのリンクと組み合わせれば、より、多くのグループを
1993         * 横方向に並べることで、小領域に多くの情報を詰めることが可能になります。
1994         * 0 を設定すると、横方向にのみ並べる(折り返さない)メニューを作ることが
1995         * 可能になります。
1996         * 初期値は、無制限です。
1997         *
1998         * @og.rev 4.0.0.0 (2005/01/31) 新規登録
1999         *
2000         * @param       count 横並び数
2001         */
2002        public void setSideCount( final String count ) {
2003                sideCount = nval( getRequestParameter( count ),sideCount );
2004        }
2005
2006        /**
2007         * 【TAG】表形式メニュー(MATRIX)の一つのセルに含まれる最小行数を指定します(初期値:8)。
2008         *
2009         * @og.tag
2010         * 表形式メニュー(MATRIX)では、一つのセルの高さを同一にする為、&lt;br /&gt;タグを挿入します。
2011         * このタグの挿入する個数を指定します。
2012         * この個数だけ、メニューの数があろうとなかろうと行を確保します。
2013         * 指定の値が、実際の行数より少ない場合は、実際の行数分だけ拡張されます。
2014         * 初期値は、8 です。
2015         *
2016         * @og.rev 4.0.0.0 (2005/01/31) 新規登録
2017         *
2018         * @param       count セル内最小行数
2019         * @see         #setMaxCellCount( String )
2020         */
2021        public void setMinCellCount( final String count ) {
2022                minCellCount = nval( getRequestParameter( count ),minCellCount );
2023        }
2024
2025        /**
2026         * 【TAG】表形式メニュー(MATRIX)の一つのセルに含まれる最大行数を指定します(初期値:8)。
2027         *
2028         * @og.tag
2029         * 表形式メニュー(MATRIX)では、一つのセルの高さを同一にする為、指定の行数で
2030         * 新たな セルを作成して、セルを横方向に連結します。
2031         * 初期値は、8 です。
2032         *
2033         * @og.rev 4.0.0.0 (2005/01/31) 新規登録
2034         *
2035         * @param       count セル内最大行数
2036         * @see         #setMinCellCount( String )
2037         */
2038        public void setMaxCellCount( final String count ) {
2039                maxCellCount = nval( getRequestParameter( count ),maxCellCount );
2040        }
2041
2042        /**
2043         * 【TAG】グループメニューのキャッシュを使用するかどうか[true/false]を指定します(初期値:true)。
2044         *
2045         * @og.tag
2046         * GROUPメニューの表示は、一旦作成すると、ほとんど書き換えることがありません。
2047         * 作成は、使用できる全メニューをスキャンして、その中からグループ属性をピックアップ
2048         * するという処理を行っている為、明らかに無駄な処理です。
2049         * そこで、jsp/index.jsp が実行された場合のみキャッシュをクリアして、内部では
2050         * キャッシュがなければ作成し、あればキャッシュを使うロジックになっています。
2051         * ここでは、キャッシュを使用するのか、毎回作成しなおすのかを指定します。
2052         * 対象として、jsp/menuImage 以下に グループ名と同一の
2053         * 画像ファイルが存在する場合は、画像を使用します。
2054         * このフラグを、true に設定すると、画像のみを使用します。
2055         * false の場合は、画像+グループ名のラベルを使用します。
2056         * 画像のみの場合でも、title 属性にグループ名のラベルをセットしますので、
2057         * マウスカーソルをオーバーすれば、名称がTips表示されます。
2058         * 画像が存在しない場合は、たとえ、true(画像のみ)に設定しても、ラベルを出力します。
2059         * 初期値は、true(キャッシュする)です。
2060         *
2061         * @og.rev 4.0.0.0 (2005/01/31) 新規登録
2062         *
2063         * @param       flag キャッシュ可否 [true:キャッシュする/false:キャッシュしない]
2064         */
2065        public void setCache( final String flag ) {
2066                cache = nval( getRequestParameter( flag ),cache );
2067        }
2068
2069        /**
2070         * 【TAG】正判定(マッチする場合に、メニューに出す)条件を設定します。
2071         *
2072         * @og.tag
2073         * メニューを表示する/しないの判定を、画面IDのマッチングで判断します。
2074         * これは、正規表現で表される引数と、画面IDがマッチする場合に、
2075         * メニューを表示させます。
2076         * マッチしない場合は、表示されません。
2077         * 何も指定しない場合は、ロールの判定みの行われます。
2078         *
2079         * @param   mt 正判定条件 (マッチする場合に、メニューに出す)
2080         */
2081        public void setMatch( final String mt ) {
2082                match = nval( getRequestParameter( mt ),match );
2083        }
2084
2085        /**
2086         * 【TAG】逆判定(マッチする場合に、メニューに出さない)条件を設定します。
2087         *
2088         * @og.tag
2089         * メニューを表示する/しないの判定を、画面IDのマッチングで判断します。
2090         * これは、正規表現で表される引数と、画面IDがマッチする場合に、
2091         * メニューを表示させません。
2092         * マッチしない場合は、表示されます。
2093         * 何も指定しない場合は、ロールの判定みの行われます。
2094         *
2095         * @param   umt 逆判定条件 (マッチする場合に、メニューに出さない)
2096         */
2097        public void setUnmatch( final String umt ) {
2098                unmatch = nval( getRequestParameter( umt ),unmatch );
2099        }
2100
2101        /**
2102         * 【TAG】メニューに使用する画像ファイルのフォルダを指定します(初期値:{@og.value #MENU_IMG})。
2103         *
2104         * @og.tag
2105         * メニューに使用する画像ファイルのフォルダを指定します。
2106         * 画面IDのキーと一致する画像ファイルを使用します。
2107         * 初期値は、{@og.value #MENU_IMG} です。
2108         * /jspからのフォルダ指定が必要です。
2109         *
2110         * @og.rev 6.7.5.0 (2017/03/10) TILE表示追加(imageDir 属性追加)
2111         *
2112         * @param   dir メニューに使用する画像ファイルのフォルダ
2113         */
2114        public void setImageDir( final String dir ) {
2115                imageDir = nval( getRequestParameter( dir ),imageDir );
2116        }
2117
2118        /**
2119         * 【TAG】画面リンクにボタンを使用するかどうか[true/false]を指定します(初期値:false)。
2120         *
2121         * @og.tag
2122         * 画面リンクをボタンリンク形式で表示するかを指定します。
2123         * falseの場合は、通常のリンクになります。
2124         * 初期値は、false(通常リンク)です。
2125         *
2126         * @og.rev 4.2.1.0 (2008/04/01) 新規登録
2127         *
2128         * @param       flag ボタンリンク [true:ボタン形式リンク/false:通常リンク]
2129         */
2130        public void setUseButton( final String flag ) {
2131                useButton = nval( getRequestParameter( flag ),useButton );
2132        }
2133
2134        /**
2135         * 【TAG】マトリクスからの遷移先でボタンメニュー表示するかどうか[true/false]を指定します(初期値:false)。
2136         *
2137         * @og.tag
2138         * マトリクスメニューからの遷移先でボタンメニューを表示させるために
2139         * アドレスに付加するリクエスト変数を指定します。
2140         * trueにするとbuttonRequest=trueのリクエスト変数を付けます。
2141         * falseの場合はリクエスト変数を付けません。
2142         * 初期値は、false(プルダウン形式で表示)です。
2143         *
2144         * @og.rev 4.2.1.0 (2008/04/17) 新規登録
2145         *
2146         * @param       flag メニュー形式 [true:ボタン形式/false:通常形式]
2147         */
2148        public void setButtonRequest( final String flag ) {
2149                buttonRequest = nval( getRequestParameter( flag ),buttonRequest );
2150        }
2151
2152        /**
2153         * 【TAG】標準画面を初期状態で開いた状態で表示するかどうか[true/false]を指定します(初期値:false)。
2154         *
2155         * @og.tag
2156         * 通常expand=trueの状態では、メニューが折りたたまれています。
2157         * このinlineStyle属性をtrueにすると標準画面のスタイルにdisplay:inlineを
2158         * 付加する事で、初期状態でメニューが開いた状態になります。
2159         * expand=falseとの違いは、隠しメニュー及び分類の折りたたみ機能が利用できる事です。
2160         * 初期値は、false(折りたたまれた状態)です。
2161         *
2162         * @og.rev 4.3.3.0 (2008/10/01) 新規
2163         *
2164         * @param       flag メニュースタイル [true:開いた状態/false:閉じた状態]
2165         */
2166        public void setInlineStyle( final String flag ) {
2167                inlineStyle = nval( getRequestParameter( flag ),inlineStyle );
2168        }
2169
2170        /**
2171         * 【TAG】ONELEVEL,NEXTGUI で、DIVタグ+design-onelevel 処理をするかどうか[true/false]を指定します(初期値:false)。
2172         *
2173         * @og.tag
2174         * ONELEVEL,NEXTGUI は、QUERY 画面の上部に表示される簡易メニューです。
2175         * この表記は、[画面リンク] 形式のテキスト表示されていますが、画面名称を固定長にするなどの処理を入れるため、
2176         * DIVでフォーマットします。
2177         * 作りは、出力される HTML を確認いただきたいと思います。
2178         * 全体を、&lt;div id="design-onelevel" &gt; で、囲い、画面名称は、&lt;span clas="design-onelevel" &gt; で、囲います。
2179         * これを、標準CSSで、固定幅と背景色、リンクの文字色など書き換えて、体裁を整えます。
2180         * 初期値は、false(従来と同じ)です。
2181         *
2182         * @og.rev 5.5.2.3 (2012/05/15) 新規追加
2183         *
2184         * @param       flag DIVタグ処理するか [true:DIVタグ処理をする/false:しない]
2185         */
2186        public void setUseDivOneLevel( final String flag ) {
2187                useDivOneLevel = nval( getRequestParameter( flag ),useDivOneLevel );
2188        }
2189
2190        /**
2191         * 【TAG】画面名称に、名前(長) を使う場合は、trueを指定します(初期値:false)。
2192         *
2193         * @og.tag
2194         * 画面の名称は、画面リソースの GUIInfo#getName() を使用しますが、通常、画面名称(short) です。
2195         * 画面名称(long) を使いたい場合は、このフラグを true に設定すると、GUIInfo#getLongName() を使用します。
2196         * 初期値は、false(従来と同じ)です。
2197         *
2198         * menuType が NORMAL,MATRIX,MATRIX2,TILE の場合のみ効きます。
2199         *
2200         * @og.rev 8.2.1.0 (2022/07/15) useLongName 属性追加
2201         *
2202         * @param       flag 画面の名称 [true:名前(長)/false:名前(短)]
2203         */
2204        public void setUseLongName( final String flag ) {
2205                useLongName = nval( getRequestParameter( flag ),useLongName );
2206        }
2207
2208        /**
2209         * 画面オブジェクト一覧より、指定されたインデックスより後に実体となる画面ID
2210         * (直リンク、通常メニュー、隠しメニュー※改行メニューは除く)が存在するかを判定します。
2211         * グループスが指定されている場合は、グループで絞り込まれた結果に対して判定を行います。
2212         *
2213         * @og.rev 4.0.0.0 (2007/10/30) 新規追加
2214         * @og.rev 6.9.8.0 (2018/05/28) FindBugs 対応で、groupCheckの判定方法に、groups == null も入れる。
2215         *
2216         * @param guiInfos 画面オブジェクト一覧
2217         * @param idx 検索を開始するインデックス番号
2218         *
2219         * @return 0:実体画面が存在せず 1:全て隠しの分類 2:実体画面 or 通常画面を含む分類
2220         */
2221        private int guiCheck( final GUIInfo[] guiInfos, final int idx ) {
2222                int flg = 0;
2223
2224                // 実態探し
2225                if( levelCheck( guiInfos[idx] ) > 0 ) {
2226                        // グループメニューリンク時の処理
2227                        // 6.9.8.0 (2018/05/28) FindBugs 対応で、groupCheckの判定方法に、groups == null も入れる。
2228//                      if( groups == null ) { flg = 2; }
2229//                      else { flg = groupCheck( guiInfos[idx] ) ? 2 : 0; }
2230                        flg = groupCheck( guiInfos[idx] ) ? 2 : 0;
2231                }
2232                else {
2233                        for( int j=idx+1; j<guiInfos.length; j++ ) {
2234                                if( !guiInfos[j].isRead() ) { continue; }
2235                                if( flg > 1 || guiInfos[j].getLevel() <= guiInfos[idx].getLevel() ) { break; }
2236
2237                                // 6.9.8.0 (2018/05/28) FindBugs 対応で、groupCheckの判定方法に、groups == null も入れる。
2238//                              if( groups == null || groupCheck( guiInfos[j] ) ) {
2239                                if( groupCheck( guiInfos[j] ) ) {
2240                                        if( levelCheck( guiInfos[j] ) > 0 ) {
2241                                                flg = levelCheck( guiInfos[j] );
2242                                        }
2243                                }
2244                        }
2245                }
2246
2247                return flg;
2248        }
2249
2250        /**
2251         * 指定された画面IDが実体であるか(直リンク、通常メニュー、隠しメニュー※改行メニューは除く)を判定します。
2252         *
2253         * @og.rev 4.0.0.0 (2007/10/30) 新規追加
2254         * @og.rev 4.0.0.0 (2007/11/30) switch に default 追加
2255         * @og.rev 6.9.4.1 (2018/04/09) HYBS_BR の廃止
2256         *
2257         * @param guiInfo 画面オブジェクト
2258         *
2259         * @return 0:分類 1:実体画面(隠し) 2:実体画面(通常) or 直リンク
2260         */
2261        private int levelCheck( final GUIInfo guiInfo ) {
2262                int flg = 0;
2263
2264                final String adrs = guiInfo.getAddress();       // 6.9.4.1 (2018/04/09) HYBS_BR は、アドレスに設定
2265
2266                switch ( guiInfo.getLevel() ) {
2267                        case 2:
2268//                              final String adrs = guiInfo.getAddress();
2269                                if( adrs != null && adrs.length() > 0 ) {
2270                                        flg = 2;
2271                                }
2272                                break;
2273                        case 3:
2274//                              flg = "HYBS_BR".equals( guiInfo.getKey() ) ? flg : 2; break;
2275                                flg = "HYBS_BR".equals( adrs ) ? flg : 2; break;
2276                        case 4:
2277//                              flg = "HYBS_BR".equals( guiInfo.getKey() ) ? flg : 1; break;
2278                                flg = "HYBS_BR".equals( adrs ) ? flg : 1; break;
2279                        default :
2280                                flg = 0; break;
2281                }
2282
2283                return flg;
2284        }
2285
2286        /**
2287         * 指定された画面IDが設定されたグループスに含まれるかを判定します。
2288         *
2289         * groups == null か、または、画面IDが設定されたグループスに含まれる場合、true を返します。
2290         *
2291         * @og.rev 4.0.0.0 (2007/10/30) 新規追加
2292         * @og.rev 6.9.8.0 (2018/05/28) FindBugs 対応で、groupCheckの判定方法に、groups == null も入れる。
2293         *
2294         * @param guiInfo 画面オブジェクト
2295         *
2296         * @return groupsが nullか、グループスに含まれるかどうか
2297         */
2298        private boolean groupCheck( final GUIInfo guiInfo ) {
2299                // 6.9.8.0 (2018/05/28) FindBugs:コンストラクタで初期化されていないフィールドを null チェックなしで null 値を利用している
2300                if( groups == null ) { return true; }
2301                else {
2302                        boolean flg = false;
2303
2304                        // 7.2.9.4 (2020/11/20) PMD:This for loop can be replaced by a foreach loop
2305                        for( final String grp : groups ) {
2306                                if( guiInfo.isGroupIn( grp ) ) {
2307//                      for( int k=0; k<groups.length; k++ ) {
2308//                              if( guiInfo.isGroupIn( groups[k] ) ) {
2309                                        flg = true;
2310                                        break;
2311                                }
2312                        }
2313
2314                        return flg;
2315                }
2316        }
2317
2318        /**
2319         * このオブジェクトの文字列表現を返します。
2320         * 基本的にデバッグ目的に使用します。
2321         *
2322         * @return このクラスの文字列表現
2323         * @og.rtnNotNull
2324         */
2325        @Override
2326        public String toString() {
2327                return ToString.title( this.getClass().getName() )
2328                                .println( "VERSION"                             ,VERSION                        )
2329                                .println( "menuType"                    ,menuType                       )
2330                                .println( "expand"                              ,expand                         )
2331                                .println( "groups"                              ,groups                         )
2332                                .println( "selClassify"                 ,selClassify            )
2333                                .println( "href"                                ,href                           )
2334                                .println( "target"                              ,target                         )
2335                                .println( "imageOnly"                   ,imageOnly                      )
2336                                .println( "sideCount"                   ,sideCount                      )
2337                                .println( "minCellCount"                ,minCellCount           )
2338                                .println( "maxCellCount"                ,maxCellCount           )
2339                                .println( "cache"                               ,cache                          )
2340                                .println( "mscKey"                              ,mscKey                         )
2341//                              .println( "multiSessionCheck"   ,multiSessionCheck      )       // 6.9.5.0 (2018/04/23) multiSessionCheck 廃止(true固定)
2342                                .println( "useButton"                   ,useButton                      )
2343                                .println( "buttonRequest"               ,buttonRequest          )
2344                                .println( "MENU_TYPE"                   ,MENU_TYPE_SET          )       // 6.4.3.4 (2016/03/11)
2345                                .println( "Other..."    ,getAttributes().getAttribute() )
2346                                .fixForm().toString() ;
2347        }
2348}