You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ColumnFormatter.java 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. Copyright (c) 2019 James Ahlborn
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package com.healthmarketscience.jackcess.util;
  14. import java.io.IOException;
  15. import java.util.Map;
  16. import com.healthmarketscience.jackcess.Column;
  17. import com.healthmarketscience.jackcess.PropertyMap;
  18. import com.healthmarketscience.jackcess.expr.EvalConfig;
  19. import com.healthmarketscience.jackcess.expr.EvalException;
  20. import com.healthmarketscience.jackcess.impl.ColEvalContext;
  21. import com.healthmarketscience.jackcess.impl.ColumnImpl;
  22. import com.healthmarketscience.jackcess.impl.expr.FormatUtil;
  23. import org.apache.commons.lang3.StringUtils;
  24. /**
  25. * Utility for applying Column formatting to column values for display. This
  26. * utility loads the "Format" property from the given column and builds an
  27. * appropriate formatter (essentially leveraging the internals of the
  28. * expression execution engine's support for the "Format()" function). Since
  29. * formats leverage the expression evaluation engine, the underlying
  30. * Database's {@link EvalConfig} can be used to alter how this utility formats
  31. * values. Note, formatted values may be suitable for <i>display only</i>
  32. * (i.e. a formatted value may not be accepted as an input value to a Table
  33. * add/update method).
  34. *
  35. * @author James Ahlborn
  36. * @usage _general_class_
  37. */
  38. public class ColumnFormatter
  39. {
  40. private final ColumnImpl _col;
  41. private final FormatEvalContext _ctx;
  42. private String _fmtStr;
  43. private FormatUtil.StandaloneFormatter _fmt;
  44. public ColumnFormatter(Column col) throws IOException {
  45. _col = (ColumnImpl)col;
  46. _ctx = new FormatEvalContext(_col);
  47. reload();
  48. }
  49. /**
  50. * Returns the currently loaded "Format" property for this formatter, may be
  51. * {@code null}.
  52. */
  53. public String getFormatString() {
  54. return _fmtStr;
  55. }
  56. /**
  57. * Sets the given format string as the "Format" property for the underlying
  58. * Column and reloads this formatter.
  59. *
  60. * @param fmtStr the new format string. may be {@code null}, in which case
  61. * the "Format" property is removed from the underlying Column
  62. */
  63. public void setFormatString(String fmtStr) throws IOException {
  64. PropertyMap props = _col.getProperties();
  65. if(!StringUtils.isEmpty(fmtStr)) {
  66. props.put(PropertyMap.FORMAT_PROP, fmtStr);
  67. } else {
  68. props.remove(PropertyMap.FORMAT_PROP);
  69. }
  70. props.save();
  71. reload();
  72. }
  73. /**
  74. * Formats the given value according to the format currently defined for the
  75. * underlying Column.
  76. *
  77. * @param val a valid input value for the DataType of the underlying Column
  78. * (i.e. a value which could be passed to a Table add/update
  79. * method for this Column). may be {@code null}
  80. *
  81. * @return the formatted result, always non-{@code null}
  82. */
  83. public String format(Object val) {
  84. return _ctx.format(val);
  85. }
  86. /**
  87. * Convenience method for retrieving the appropriate Column value from the
  88. * given row array and formatting it.
  89. *
  90. * @return the formatted result, always non-{@code null}
  91. */
  92. public String getRowValue(Object[] rowArray) {
  93. return format(_col.getRowValue(rowArray));
  94. }
  95. /**
  96. * Convenience method for retrieving the appropriate Column value from the
  97. * given row map and formatting it.
  98. *
  99. * @return the formatted result, always non-{@code null}
  100. */
  101. public String getRowValue(Map<String,?> rowMap) {
  102. return format(_col.getRowValue(rowMap));
  103. }
  104. /**
  105. * If the properties for the underlying Column have been modified directly
  106. * (or the EvalConfig for the underlying Database has been modified), this
  107. * method may be called to reload the format for the underlying Column.
  108. */
  109. public final void reload() throws IOException {
  110. _fmt = null;
  111. _fmtStr = null;
  112. _fmtStr = (String)_col.getProperties().getValue(PropertyMap.FORMAT_PROP);
  113. _fmt = FormatUtil.createStandaloneFormatter(_ctx, _fmtStr, 1, 1);
  114. }
  115. /**
  116. * Utility class to provide an EvalContext for the expression evaluation
  117. * engine format support.
  118. */
  119. private class FormatEvalContext extends ColEvalContext
  120. {
  121. private FormatEvalContext(ColumnImpl col) {
  122. super(col);
  123. }
  124. public String format(Object val) {
  125. try {
  126. return _fmt.format(toValue(val)).getAsString(this);
  127. } catch(EvalException ee) {
  128. // invalid values for a given format result in returning the value as is
  129. return val.toString();
  130. }
  131. }
  132. }
  133. }