code: /**
   * Copyright 2014-2017 Alexey Ragozin
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.gridkit.util.formating;
  
  import java.text.DecimalFormat;
  import java.text.SimpleDateFormat;
  import java.util.Locale;
  import java.util.TimeZone;
  
  /**
   * This is utility class capable for formating numbers as numbers and dates.
   * <p>
   * Internally it is using
   * <li> {@link SimpleDateFormat} - prefix T </li>
   * <li> {@link DecimalFormat} - prefix D </li>
   * <li> {@link String#format(String, Object...)} - prefix D </li>
   * <p>
   * Formatter always using neutral locale.
   *
   * @author Alexey Ragozin (alexey.ragozin@gmail.com)
   */
  public class SimpleNumberFormatter implements NumberFormat {
  
      public static final SimpleNumberFormatter DEFAULT = new SimpleNumberFormatter("");
  
      private final LongFormatter lf;
      private final DoubleFormatter df;
  
      public SimpleNumberFormatter(String format) {
          this(format, TimeZone.getDefault());
      }
  
      public SimpleNumberFormatter(String format, TimeZone tz) {
          if (format.length() == 0) {
              // default
              lf = new DefaultLongFormatter();
              df = new DefaultDoubleFormatter();
          }
          else if (format.startsWith("D")) {
              DecimalFormat fmt = new DecimalFormat(format.substring(1));
              lf = new DecimalFormatLong(fmt);
              df = new DecimalFormatDouble(fmt);
          }
          else if (format.startsWith("T")) {
              SimpleDateFormat sdf = new SimpleDateFormat(format.substring(1));
              sdf.setTimeZone(tz);
              lf = new SDFFormatter(sdf);
              df = new D2L(lf);
          }
          else if (format.startsWith("F")) {
              lf = new JavaFormatterLong(format.substring(1));
              df = new JavaFormatterDouble(format.substring(1));
          }
          else {
              throw new IllegalArgumentException("Format spec should start with D, T or F");
          }
      }
  
      public String formatLong(long v) {
          return lf.formatLong(v);
      }
  
      public String formatDouble(double v) {
          return df.formatDouble(v);
      }
  
      private static abstract class LongFormatter {
  
          public abstract String formatLong(long v);
  
      }
  
      private static abstract class DoubleFormatter {
  
          public abstract String formatDouble(double v);
  
      }
  
      private static class DefaultLongFormatter extends LongFormatter {
  
          public String formatLong(long v) {
              return String.valueOf(v);
          }
      }
  
      private static class DefaultDoubleFormatter extends DoubleFormatter {
  
          public String formatDouble(double v) {
              return String.valueOf(v);
          }
      }
  
      private static class SDFFormatter extends LongFormatter {
  
          private final SimpleDateFormat sdf;
  
          public SDFFormatter(SimpleDateFormat sdf) {
              this.sdf = sdf;
          }
  
          @Override
          public String formatLong(long v) {
              return sdf.format(v);
          }
      }
  
      private static class DecimalFormatLong extends LongFormatter {
  
          private final java.text.DecimalFormat fmt;
  
          public DecimalFormatLong(DecimalFormat fmt) {
              this.fmt = fmt;
          }
  
          @Override
          public String formatLong(long v) {
              return fmt.format(v);
          }
      }
  
      private static class DecimalFormatDouble extends DoubleFormatter {
  
          private final java.text.DecimalFormat fmt;
  
          public DecimalFormatDouble(DecimalFormat fmt) {
              this.fmt = fmt;
          }
  
          @Override
          public String formatDouble(double v) {
              return fmt.format(v);
          }
      }
  
      private static class JavaFormatterLong extends LongFormatter {
  
          private final String fmt;
  
          public JavaFormatterLong(String fmt) {
              this.fmt = fmt;
          }
  
          @Override
          public String formatLong(long v) {
              return String.format(Locale.ROOT, fmt, v);
          }
      }
  
      private static class JavaFormatterDouble extends DoubleFormatter {
  
          private final String fmt;
  
          public JavaFormatterDouble(String fmt) {
              this.fmt = fmt;
          }
  
          @Override
          public String formatDouble(double v) {
              return String.format(Locale.ROOT, fmt, v);
          }
      }
  
      private static class D2L extends DoubleFormatter {
  
          private final LongFormatter lf;
  
          public D2L(LongFormatter lf) {
              this.lf = lf;
          }
  
          @Override
          public String formatDouble(double v) {
              return lf.formatLong((long) v);
          }
      }
  }
  