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