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