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