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.plugin.column; 017 018import org.opengion.fukurou.util.StringUtil; 019import org.opengion.hayabusa.db.AbstractEditor; 020import org.opengion.hayabusa.db.CellEditor; 021import org.opengion.hayabusa.db.DBColumn; 022import org.opengion.fukurou.util.XHTMLTag; 023 024import java.text.DecimalFormat; 025 026/** 027 * DECIMAL エディターは、カラムのデータをDecimal(10進数、小数)表示する場合に 028 * 使用するクラスです。 029 * 030 * 編集パラメータに与えられた文字列は、java.text.DecimalFormat を使用して 031 * フォーマットされます。 032 * フォーマット変換前に、カンマなどの数値変換時にエラーになる情報を削除しておきます。 033 * 標準のフォーマットは"#,##0.#"です。 034 * default値が設定されていない場合の初期値は0.0にフォーマット処理をしたものです。 035 * 036 * フォーマットルールは、{@link java.text.DecimalFormat} を参照願います。 037 * 038 * 7.4.2.3 (2021/06/09) 039 * フォーマットは、表示桁数 に応じて決定します。 040 * ただし、パラメータ指定 が優先されます。 041 * 042 * カラムの表示に必要な属性は、DBColumn オブジェクト より取り出します。 043 * このクラスは、DBColumn オブジェクト毎に1つ作成されます。 044 * 045 * @og.group データ編集 046 * @og.rev 3.8.8.5 (2007/03/09) 新規作成 047 * @og.rev 5.4.3.6 (2012/01/19) コメント修正 048 * 049 * @version 4.0 050 * @author Kazuhiko Hasegawa 051 * @since JDK5.0, 052 */ 053public class Editor_DECIMAL extends AbstractEditor { 054 /** このプログラムのVERSION文字列を設定します。 {@value} */ 055 private static final String VERSION = "7.4.2.3 (2021/06/09)" ; 056 057 // 7.4.2.3 (2021/06/09) フォーマットは、表示桁数 に応じて決定します(小数6桁以上の精度は受け付けられない) 058 private static final String[] FRMT = new String[] { "#,##0" , "#,##0.0" , "#,##0.00" , "#,##0.000" , "#,##0.0000" , "#,##0.00000" , "#,##0.000000" } ; 059 060 private final int minFraction; 061 private final DecimalFormat format ; 062 private final String defValue ; 063 064 /** 065 * デフォルトコンストラクター。 066 * このコンストラクターで、基本オブジェクトを作成します。 067 * 068 */ 069 public Editor_DECIMAL() { 070 super(); // 6.4.1.1 (2016/01/16) PMD refactoring. It is a good practice to call super() in a constructor 071 // 4.3.4.4 (2009/01/01) 072 minFraction = 0; 073 format = null; 074 defValue = null; 075 } 076 077 /** 078 * DBColumnオブジェクトを指定したprivateコンストラクター。 079 * 080 * @og.rev 5.3.1.0 (2009/12/01) 初期値がnullの場合は、defValueはnullとする。 081 * @og.rev 5.4.0.0 (2011/10/01) RendererParamが読み込まれているバグを修正 082 * @og.rev 7.4.2.3 (2021/06/09) フォーマットは、表示桁数 に応じて決定します(パラメータ指定 が優先)。 083 * 084 * @param clm DBColumnオブジェクト 085 */ 086 private Editor_DECIMAL( final DBColumn clm ) { 087 super( clm ); 088 minFraction = clm.getSizeY(); 089 090 final String fm = makeFormat( clm ); 091// String fm = clm.getEditorParam(); 092// if( fm == null || fm.isEmpty() || fm.equals( "_" ) ) { 093// fm = "#,##0.#"; 094// } 095 format = new DecimalFormat( fm ); 096 097 // 5.3.1.0 (2009/12/01) 098 final String defv = clm.getDefault(); 099 if( defv == null || defv.isEmpty() ) { 100 defValue = ""; 101 } 102 else { 103 double dd = 0.0; 104 // 6.0.2.5 (2014/10/31) null でないことがわかっている値の冗長な null チェックがあります。 105 if( !"_".equals( defv ) ) { 106 dd = StringUtil.parseDouble( defv ); 107 } 108 defValue = format.format( dd ); 109 } 110 111 // -XXX,XXX,XXX.YYY 形式では、カンマ、小数点、マイナスなどの項目が入ります。 112 final int maxlength = (int)(clm.getSizeX() * 4.0/3.0) + minFraction + 2 ; // +2 は、マイナスと小数点 113 attributes.set( "maxlength" ,String.valueOf( maxlength ) ); 114 tagBuffer.add( XHTMLTag.inputAttri( attributes ) ); 115 } 116 117 /** 118 * フォーマット文字列を返します。 119 * 120 * フォーマットは、表示桁数 に応じて決定します。 121 * ただし、パラメータ指定 が優先されます。 122 * 123 * @og.rev 7.4.2.3 (2021/06/09) フォーマットは、表示桁数 に応じて決定します(パラメータ指定 が優先)。 124 * 125 * @param clm DBColumnオブジェクト 126 * 127 * @return フォーマット文字列 128 */ 129 private String makeFormat( final DBColumn clm ) { 130 String fm = clm.getEditorParam(); // パラメータ指定 が優先 131 132 if( fm == null || fm.isEmpty() || fm.equals( "_" ) ) { 133 fm = "#,##0.##"; // 初期値:桁を増やしておきます。 134 135 // 7.4.2.3 (2021/06/09) フォーマットは、表示桁数 に応じて決定します。 136 final String viewLen = clm.getViewLength(); 137 if( viewLen != null ) { 138 final int ad = viewLen.indexOf( '.' ); 139 if( ad >= 0 ) { 140 final String st = viewLen.substring( ad+1 ); // 小数点以下の桁数取得 141 try { 142 final int su = Integer.parseInt( st ); 143 fm = su < FRMT.length ? FRMT[su] : FRMT[FRMT.length-1] ; 144 } 145 catch( final Throwable th ) { 146 final String errMsg = "表示桁数の小数部の変換に失敗しました" + CR 147 + "viewLen=" + viewLen 148 + CR 149 + th.getMessage() ; 150 System.err.println( errMsg ); 151 } 152 } 153 } 154 } 155 156 return fm; 157 } 158 159 /** 160 * 各オブジェクトから自分のインスタンスを返します。 161 * 自分自身をキャッシュするのか、新たに作成するのかは、各サブクラスの実装に 162 * まかされます。 163 * 164 * @param clm DBColumnオブジェクト 165 * 166 * @return CellEditorオブジェクト 167 * @og.rtnNotNull 168 */ 169 public CellEditor newInstance( final DBColumn clm ) { 170 return new Editor_DECIMAL( clm ); 171 } 172 173 /** 174 * データの編集用文字列を返します。 175 * 176 * @param value 入力値 177 * 178 * @return データの編集用文字列 179 */ 180 @Override 181 public String getValue( final String value ) { 182 return super.getValue( formatValue( value ) ); 183 } 184 185 /** 186 * name属性を変えた、データ表示/編集用のHTML文字列を作成します。 187 * テーブル上の name に 行番号を付加して、名前_行番号 で登録するキーを作成し、 188 * リクエスト情報を1つ毎のフィールドで処理できます。 189 * 190 * @param row 行番号 191 * @param value 入力値 192 * 193 * @return データ表示/編集用の文字列 194 */ 195 @Override 196 public String getValue( final int row,final String value ) { 197 return super.getValue( row,formatValue( value ) ); 198 } 199 200 /** 201 * 内部的なフォーマット変換後の文字列を返します。 202 * 203 * @og.rev 5.3.1.0 (2009/12/01) 値が0の場合は、初期値を適用する。 204 * 205 * @param value 入力値 206 * 207 * @return データの表示用文字列 208 */ 209 private String formatValue( final String value ) { 210 if( value == null || value.trim().isEmpty() || "0".equals( value ) ) { 211 return defValue; 212 } 213 214 final double dd = StringUtil.parseDouble( value ); 215 216 final String rtn ; 217 synchronized( format ) { 218 rtn = format.format( dd ); 219 } 220 221 return rtn; 222 } 223}