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     */
016    package org.opengion.plugin.table;
017    
018    import java.util.HashMap;
019    import java.util.Map;
020    
021    import org.opengion.fukurou.util.StringUtil;
022    import org.opengion.hayabusa.db.AbstractTableFilter;
023    import org.opengion.hayabusa.db.DBColumn;
024    import org.opengion.hayabusa.db.DBColumnConfig;
025    import org.opengion.hayabusa.db.DBTableModel;
026    import org.opengion.hayabusa.db.DBTableModelUtil;
027    import org.opengion.hayabusa.resource.ResourceManager;
028    
029    /**
030     * TableFilter_ROTATE は、TableFilter インターフェースを継承した、DBTableModel 処?の
031     * 実?ラスです?
032     *
033     * ここでは??ブルの回転、及びそ??転を行います?
034     *
035     * パラメータは、tableFilterタグの keys, vals にそれぞれ記述するか?BODY 部にCSS形式で記述します?
036     * 【パラメータ?
037     *  {
038     *       KEY_CLM    : キーカラ???可)
039     *       ROTATE_CLM : 回転するカラ?
040     *       VALUE_CLM  : 回転カラ??値
041     *       REVERSE    : 回転(false)・?転(true) (任意指?初期値:false)
042     *       MUST_CLM   : ??属?を定義するカラ? (任意指?初期値:false)
043     *       DEF_CLM    : 初期値を定義するカラ?   (任意指?
044     *  }
045     *
046     *  ※ それぞれに?されたカラ?が存在しな??合?、??れませんのでご注意下さ??
047     *
048     * ?転
049     *  キーカラ??された値が同じN行を1行として回転します?
050     *  (キーカラ??値がブレイクしたタイミングで、行を変更しま?
051     *  こ?N行に含まれる回転カラ??値がカラ?に、回転カラ??が各カラ??値になります?
052     *  キーカラ??、カンマ区?で??可能です?
053     *
054     *  生?されたテーブルモ?のカラ??、始めのMカラ?キーカラ?、その後ろのNカラ?
055     *  回転されたカラ?なります?
056     *
057     *  また??ーブルにMUST_CLMにより、各カラ????属?を定義すること?
058     *  できます?(MUST属?は?1'又?'true'の場合に??になります?)
059     *
060     * ②?転
061     *  回転時???挙動になります?
062     *  "キーカラ??されたカラ??を回転カラ??されたカラ??値として?します?
063     *  ?転カラ??値は、回転カラ??に?されたカラ?格納されます?
064     *
065     *  ?後?カラ?は、キーカラ? + 2 (回転カラ??回転カラ??)になります?
066     *  また?行数は??前?行数) x (回転カラ?)になります?
067     *
068     * @og.formSample
069     * ●形式?
070     *      ?<og:tableFilter classId="ROTATE" keys="KEY_CLM,REVERSE" vals='"AA,BB,CC",true' />
071     *
072     *      ② <og:tableFilter classId="ROTATE" >
073     *               {
074     *                   KEY_CLM    : キーカラ???可)
075     *                   ROTATE_CLM : 回転するカラ?
076     *                   VALUE_CLM  : 回転カラ??値
077     *                   REVERSE    : 回転(false)・?転(true) (任意指?初期値:false)
078     *                   MUST_CLM   : ??属?を定義するカラ? (任意指?初期値:false)
079     *                   DEF_CLM    : 初期値を定義するカラ?   (任意指?
080     *               }
081     *         </og:tableFilter>
082     *
083     * @og.rev 5.6.6.0 (2013/07/05) keys の整合?チェ?を追?
084     *
085     * @version  0.9.0  2000/10/17
086     * @author   Hiroki Nakamura
087     * @since    JDK1.1,
088     */
089    public class TableFilter_ROTATE extends AbstractTableFilter {
090            // * こ?プログラ??VERSION??を設定します? {@value} */
091            private static final String VERSION = "5.6.6.1 (2013/07/12)" ;
092    
093            /**
094             * keys の整合?チェ?を行うための初期設定を行います?
095             *
096             * @og.rev 5.6.6.1 (2013/07/12) keys の整合?チェ?対?
097             *
098             * @param       keysMap keys の整合?チェ?を行うための Map
099             */
100            @Override
101            protected void init( final Map<String,String> keysMap ) {
102                    keysMap.put( "KEY_CLM"          , "キーカラ???可)"                                 );
103                    keysMap.put( "ROTATE_CLM"       , "回転するカラ?                                                        );
104                    keysMap.put( "VALUE_CLM"        , "回転カラ??値"                                                       );
105                    keysMap.put( "REVERSE"          , "回転(false)/?転(true) (初期値:false)"       );
106                    keysMap.put( "MUST_CLM"         , "??属?を定義するカラ?(初期値:false)"  );
107                    keysMap.put( "DEF_CLM"          , "初期値を定義するカラ?                                 );
108            }
109    
110            private DBTableModel    table    = null;                        // 5.5.2.6 (2012/05/25) 共通に使?め?変数定義
111            private ResourceManager resource = null;                        // 5.5.2.6 (2012/05/25) 共通に使?め?変数定義
112    
113            /**
114             * DBTableModel処?実行します?
115             *
116             * @og.rev 4.3.7.4 (2009/07/01) 新規追?
117             * @og.rev 5.5.2.6 (2012/05/25) protected変数を?private化したため?getterメソ?で取得するよ?変更
118             *
119             * @return 処?果のDBTableModel
120             */
121            public DBTableModel execute() {
122                    boolean reverse = StringUtil.nval( getValue( "REVERSE" ), false );
123    
124                    table    = getDBTableModel();           // 5.5.2.6 (2012/05/25) インターフェースにgetterメソ?追?
125                    resource = getResource();                       // 5.5.2.6 (2012/05/25) インターフェースにgetterメソ?追?
126    
127                    // ?転
128                    if ( reverse ) {
129                            return getRecoverdTable();
130                    }
131                    // 回転
132                    else {
133                            return getRotateTable();
134                    }
135            }
136    
137            /**
138             * 回転後?DBTableModelを返します?
139             *
140             * @og.rev 5.1.8.0 (2010/07/01) メソ?名変更(setDefValue ?setDefault)
141             *
142             * @return 回転後?DBTableModel
143             */
144            private DBTableModel getRotateTable() {
145                    String[] keyClm = StringUtil.csv2Array( getValue( "KEY_CLM" ) );
146                    int rotateNo = table.getColumnNo( getValue( "ROTATE_CLM" ), false );
147                    int valNo = table.getColumnNo( getValue( "VALUE_CLM" ), false );
148    
149                    if ( keyClm == null || keyClm.length == 0 || rotateNo < 0 || valNo < 0 ) {
150                            return table;
151                    }
152    
153                    int mustNo = table.getColumnNo( getValue( "MUST_CLM"), false );
154                    int defNo = table.getColumnNo( getValue( "DEF_CLM"), false );
155    
156                    int clmCount = 0; // 回転後?カラ?
157                    // キーカラ??カラ?号を求め、カラ?としてカウントします?
158                    Map<String, Integer> clmMap = new HashMap<String, Integer>();
159                    int[] keyNos = new int[keyClm.length];
160                    for ( int i = 0; i < keyNos.length; i++ ) {
161                            keyNos[i] = table.getColumnNo( keyClm[i], false );
162                            if ( keyNos[i] < 0 ) {
163                                    return table;
164                            }
165                            clmMap.put( keyClm[i], clmCount );
166                            clmCount++;
167                    }
168    
169                    int rowCount = 0; // 回転後?行数
170                    // 回転カラ??値から回転後?カラ?を求めます?
171                    // また同時に、キーカラ??値のブレイク数により行数を求めます?
172                    Map<String, Integer> rowMap = new HashMap<String, Integer>();
173                    Map<String, Boolean> mustMap = new HashMap<String, Boolean>();
174                    Map<String, String> defaultMap = new HashMap<String, String>();
175                    for ( int i = 0; i < table.getRowCount(); i++ ) {
176                            String clmKey = table.getValue( i, rotateNo );
177                            if ( clmMap.get( clmKey ) == null ) {
178                                    clmMap.put( clmKey, clmCount );
179                                    clmCount++;
180                            }
181                            // ??カラ?き??
182                            if( mustNo > -1 && StringUtil.nval( table.getValue( i, mustNo ), false ) ) {
183                                    mustMap.put( clmKey, true );
184                            }
185                            // ?ォルト?を書き換えるカラ??抜き出?
186                            if( defNo > -1 && table.getValue( i, defNo ) != null && table.getValue( i, defNo ).length() > 0 ) {
187                                    defaultMap.put( clmKey, table.getValue( i, defNo ) );
188                            }
189    
190                            String rowKey = getSeparatedValue( i, keyNos );
191                            if ( rowKey != null && rowKey.length() > 0 ) {
192                                    if ( rowMap.get( rowKey ) == null ) {
193                                            rowMap.put( rowKey, rowCount );
194                                            rowCount++;
195                                    }
196                            }
197                    }
198    
199                    // 回転後?カラ??よりDBTableModelを?期化します?
200                    String names[] = new String[clmMap.size()];
201                    for ( Map.Entry<String, Integer> entry : clmMap.entrySet() ) {
202                            names[entry.getValue()] = entry.getKey();
203                    }
204                    DBTableModel nTable = DBTableModelUtil.newDBTable();
205                    nTable.init( names.length );
206                    for ( int i = 0; i < names.length; i++ ) {
207                            if( mustMap.get( names[i] ) != null ) {
208                                    table.addMustType( i, "must" );
209                            }
210                            DBColumn column = resource.makeDBColumn( names[i] );
211                            if( defaultMap.get( names[i] ) != null ) {
212                                    DBColumnConfig dbConfig = column.getConfig();
213    //                              dbConfig.setDefValue( defaultMap.get( names[i] ) );
214                                    dbConfig.setDefault( defaultMap.get( names[i] ) );              // 5.1.8.0 (2010/07/01)
215                                    column = new DBColumn( dbConfig );
216                            }
217    //                      nTable.setDBColumn( i, resource.makeDBColumn( names[i] ) );
218                            nTable.setDBColumn( i, column );                                                        // 5.1.8.0 (2010/07/01)
219                    }
220    
221                    // 値の?を作?し?DBTableModelに値をセ?します?
222                    if( rowCount > 0 ) {
223                            String[][] vals = new String[rowCount][names.length];
224                            for ( int i = 0; i < table.getRowCount(); i++ ) {
225                                    int row = rowMap.get( getSeparatedValue( i, keyNos ) );
226                                    int clm = clmMap.get( table.getValue( i, rotateNo ) );
227    
228                                    for ( int j = 0; j < keyNos.length; j++ ) {
229                                            vals[row][j] = table.getValue( i, keyNos[j] );
230                                    }
231                                    vals[row][clm] = table.getValue( i, valNo );
232                            }
233                            for ( int i = 0; i < vals.length; i++ ) {
234                                    nTable.addColumnValues( vals[i] );
235                            }
236                    }
237    
238                    return nTable;
239            }
240    
241            /**
242             * ??キーとなるキーカラ??値を?結した?を返します?
243             *
244             * @param       row             行番号
245             * @param       clmNo   カラ?号配?
246             *
247             * @return      ??キーとなるキーカラ??値を?結した?
248             */
249            private String getSeparatedValue( final int row, final int[] clmNo ) {
250                    StringBuilder buf = new StringBuilder();
251                    for ( int i = 0; i < clmNo.length; i++ ) {
252                            String val = table.getValue( row, clmNo[i] );
253                            if( val != null && val.length() > 0 ) {
254                                    if( i > 0 ) {
255                                            buf.append( "__" );
256                                    }
257                                    buf.append( val );
258                            }
259                    }
260                    return buf.toString();
261            }
262    
263            /**
264             * ?転後?DBTableModelを返します?
265             *
266             * @return ?転後?DBTableModel
267             */
268            private DBTableModel getRecoverdTable() {
269                    String[] keyClm = StringUtil.csv2Array( getValue( "KEY_CLM" ) );
270                    String rotateClm = getValue( "ROTATE_CLM" );
271                    String valClm = getValue( "VALUE_CLM" );
272    
273                    if ( keyClm == null || keyClm.length == 0 || rotateClm == null || rotateClm.length() == 0
274                                    || valClm == null || valClm.length() == 0 ) {
275                            return table;
276                    }
277    
278                    // キーカラ??カラ?号を求めます?
279                    int[] keyNos = new int[keyClm.length];
280                    for ( int i = 0; i < keyNos.length; i++ ) {
281                            keyNos[i] = table.getColumnNo( keyClm[i], false );
282                            if ( keyNos[i] < 0 ) {
283                                    return table;
284                            }
285                    }
286    
287                    // キーカラ??回転カラ??のカラ?号を求めます?
288                    int clmIdx = 0;
289                    int[] clmNos = new int[table.getColumnCount() - keyNos.length];
290                    for ( int i = 0; i < table.getColumnCount(); i++ ) {
291                            boolean isClm = true;
292                            for ( int j = 0; j < keyNos.length; j++ ) {
293                                    if ( i == keyNos[j] ) {
294                                            isClm = false;
295                                    }
296                            }
297                            if ( isClm ) {
298                                    clmNos[clmIdx] = i;
299                                    clmIdx++;
300                            }
301                    }
302    
303                    // ??ブルモ?を?期化します?
304                    DBTableModel nTable = DBTableModelUtil.newDBTable();
305                    nTable.init( keyNos.length + 2 );
306                    for ( int i = 0; i < keyNos.length; i++ ) {
307                            nTable.setDBColumn( i, resource.makeDBColumn( keyClm[i] ) );
308                    }
309                    nTable.setDBColumn( keyNos.length, resource.makeDBColumn( rotateClm ) );
310                    nTable.setDBColumn( keyNos.length + 1, resource.makeDBColumn( valClm ) );
311    
312                    // ?を作?し?DBTableModelに登録します?
313                    for ( int i = 0; i < table.getRowCount(); i++ ) {
314                            for ( int j = 0; j < clmNos.length; j++ ) {
315                                    String[] vals = new String[keyNos.length + 2];
316                                    for ( int k = 0; k < keyNos.length; k++ ) {
317                                            vals[k] = table.getValue( i, keyNos[k] );
318                                    }
319                                    vals[keyNos.length] = table.getColumnName( clmNos[j] );
320                                    vals[keyNos.length + 1] = table.getValue( i, clmNos[j] );
321                                    nTable.addColumnValues( vals );
322                            }
323                    }
324    
325                    return nTable;
326            }
327    
328    }