context: /* ====================================================================
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
    this work for Additional information regarding copyright ownership.
    The ASF licenses this file to You 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.
  ==================================================================== */
  
  namespace AL.Utils.NPOI.SS.Format
  {
      using System;
  
      using AL.Utils.NPOI.SS.UserModel;
      using System.Text.RegularExpressions;
      using System.Collections.Generic;
      using System.Windows.Forms;
      using System.Drawing;
  
  
  
  
  
  
  
  
      /**
       * Format a value according to the standard Excel behavior.  This "standard" is
       * not explicitly documented by Microsoft, so the behavior is determined by
       * experimentation; see the tests.
       * 
       * An Excel format has up to four parts, Separated by semicolons.  Each part
       * specifies what to do with particular kinds of values, depending on the number
       * of parts given: 
       * 
       * - One part (example: <c>[Green]#.##</c>) 
       * If the value is a number, display according to this one part (example: green text,
       * with up to two decimal points). If the value is text, display it as is.
       * 
       * - Two parts (example: <c>[Green]#.##;[Red]#.##</c>) 
       * If the value is a positive number or zero, display according to the first part (example: green
       * text, with up to two decimal points); if it is a negative number, display
       * according to the second part (example: red text, with up to two decimal
       * points). If the value is text, display it as is. 
       * 
       * - Three parts (example: <c>[Green]#.##;[Black]#.##;[Red]#.##</c>) 
       * If the value is a positive number, display according to the first part (example: green text, with up to
       * two decimal points); if it is zero, display according to the second part
       * (example: black text, with up to two decimal points); if it is a negative
       * number, display according to the third part (example: red text, with up to
       * two decimal points). If the value is text, display it as is.
       * 
       * - Four parts (example: <c>[Green]#.##;[Black]#.##;[Red]#.##;[@]</c>)
       * If the value is a positive number, display according to the first part (example: green text,
       * with up to two decimal points); if it is zero, display according to the
       * second part (example: black text, with up to two decimal points); if it is a
       * negative number, display according to the third part (example: red text, with
       * up to two decimal points). If the value is text, display according to the
       * fourth part (example: text in the cell's usual color, with the text value
       * surround by brackets).
       * 
       * In Addition to these, there is a general format that is used when no format
       * is specified.  This formatting is presented by the {@link #GENERAL_FORMAT}
       * object.
       *
       * @author Ken Arnold, Industrious Media LLC
       */
      public class CellFormat
      {
          private String format;
          private CellFormatPart posNumFmt;
          private CellFormatPart zeroNumFmt;
          private CellFormatPart negNumFmt;
          private CellFormatPart textFmt;
  
          private static Regex ONE_PART = new Regex(CellFormatPart.FORMAT_PAT.ToString() + "(;|$)", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
  
          private static CellFormatPart DEFAULT_TEXT_FORMAT =
                  new CellFormatPart("@");
  
          private static CellFormat GENERAL_FORMAT = new GeneralCellFormat();
          /**
           * Format a value as it would be were no format specified.  This is also
           * used when the format specified is <tt>General</tt>.
           */
          public class GeneralCellFormat : CellFormat
          {
              public GeneralCellFormat()
                  : base("General")
              {
              }
              public override CellFormatResult Apply(Object value)
              {
                  String text;
                  if (value == null)
                  {
                      text = "";
                  }
                  else if (value.GetType().IsPrimitive/* is Number*/)
                  {
                      throw new NotImplementedException();
                      //text = CellNumberFormatter.SIMPLE_NUMBER.Format(value);
                  }
                  else
                  {
                      text = value.ToString();
                  }
                  return new CellFormatResult(true, text, Color.Empty);
              }
          }
  
          /** Maps a format string to its Parsed version for efficiencies sake. */
          private static Dictionary<String, CellFormat> formatCache =
                  new Dictionary<String, CellFormat>();
  
          /**
           * Returns a {@link CellFormat} that applies the given format.  Two calls
           * with the same format may or may not return the same object.
           *
           * @param format The format.
           *
           * @return A {@link CellFormat} that applies the given format.
           */
          public static CellFormat GetInstance(String format)
          {
              CellFormat fmt = null;
              if (formatCache.ContainsKey(format))
                  fmt = formatCache[format];
              if (fmt == null)
              {
                  if (format.Equals("General"))
                      fmt = GENERAL_FORMAT;
                  else
                      fmt = new CellFormat(format);
                  formatCache.Add(format, fmt);
              }
              return fmt;
          }
  
          /**
           * Creates a new object.
           *
           * @param format The format.
           */
          private CellFormat(String format)
          {
              this.format = format;
              MatchCollection mc = ONE_PART.Matches(format);
              List<CellFormatPart> parts = new List<CellFormatPart>();
  
              //while (m.Success)
              foreach(Match m in mc)
              {
                  try
                  {
                      String valueDesc = m.Groups[0].Value;
  
                      // Strip out the semicolon if it's there
                      if (valueDesc.EndsWith(";"))
                          valueDesc = valueDesc.Substring(0, valueDesc.Length - 1);
  
                      parts.Add(new CellFormatPart(valueDesc));
                  }
                  catch (Exception)
                  {
                      //CellFormatter.logger.Log(Level.WARNING,
                      //        "Invalid format: " + CellFormatter.Quote(m.Group()), e);
                      parts.Add(null);
                  }
              }
  
              switch (parts.Count)
              {
                  case 1:
                      posNumFmt = zeroNumFmt = negNumFmt = parts[(0)];
                      textFmt = DEFAULT_TEXT_FORMAT;
                      break;
                  case 2:
                      posNumFmt = zeroNumFmt = parts[0];
                      negNumFmt = parts[1];
                      textFmt = DEFAULT_TEXT_FORMAT;
                      break;
                  case 3:
                      posNumFmt = parts[0];
                      zeroNumFmt = parts[1];
                      negNumFmt = parts[2];
                      textFmt = DEFAULT_TEXT_FORMAT;
                      break;
                  case 4:
                  default:
                      posNumFmt = parts[0];
                      zeroNumFmt = parts[1];
                      negNumFmt = parts[2];
  
gt:                     textFmt = parts[3];