View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.convert;
21  
22  import org.slf4j.Logger;
23  import org.slf4j.LoggerFactory;
24  import org.apache.myfaces.tobago.component.Attributes;
25  
26  import javax.faces.component.UIComponent;
27  import javax.faces.context.FacesContext;
28  import javax.faces.convert.Converter;
29  import javax.faces.convert.ConverterException;
30  import java.text.DecimalFormat;
31  import java.text.NumberFormat;
32  import java.util.ArrayList;
33  import java.util.List;
34  import java.util.StringTokenizer;
35  
36  @org.apache.myfaces.tobago.apt.annotation.Converter(id = DurationConverter.CONVERTER_ID)
37  public class DurationConverter implements Converter {
38  
39    private static final Logger LOG = LoggerFactory.getLogger(DurationConverter.class);
40  
41    public static final String CONVERTER_ID = "org.apache.myfaces.tobago.Duration";
42  
43    private static final String NANO = "nano";
44    private static final String MILLI = "milli";
45    private static final String SECOND = "second";
46    private static final String MINUTE = "minute";
47    private static final String HOUR = "hour";
48    private static final String DAY = "day";
49    private static final String YEAR = "year";
50  
51    public String getAsString(
52        final FacesContext facesContext, final UIComponent component, final Object object)
53        throws ConverterException {
54      if (object == null || object instanceof String) {
55        return (String) object;
56      }
57      double aDouble = ((Number) object).doubleValue();
58      boolean negative = false;
59      if (aDouble < 0) {
60        negative = true;
61        aDouble = -aDouble;
62      }
63      final double factor = getUnitFactor(component);
64      aDouble = aDouble * factor;
65  
66      final NumberFormat format = new DecimalFormat("00");
67      long value = Double.valueOf(aDouble).longValue();
68      final int seconds = (int) (value % 60);
69      value = value / 60;
70      final int minutes = (int) (value % 60);
71      value = value / 60;
72      final String string;
73      if (value > 0) {
74        string = (negative ? "-" : "") + value + ":"
75            + format.format(minutes) + ":"
76            + format.format(seconds);
77      } else {
78        string = (negative ? "-" : "") + minutes + ":"
79            + format.format(seconds);
80      }
81      if (LOG.isDebugEnabled()) {
82        LOG.debug("string = '{}'", string);
83      }
84      return string;
85    }
86  
87    public Object getAsObject(
88        final FacesContext facesContext, final UIComponent component, final String string)
89        throws ConverterException {
90      final boolean negative = string.indexOf('-') > -1;
91      final StringTokenizer tokenizer = new StringTokenizer(string, " :-");
92      final List elements = new ArrayList();
93      while (tokenizer.hasMoreElements()) {
94        elements.add(tokenizer.nextElement());
95      }
96      int hours = 0;
97      final int minutes;
98      final int seconds;
99      switch (elements.size()) {
100       case 3:
101         hours = Integer.parseInt((String) elements.get(0));
102         minutes = Integer.parseInt((String) elements.get(1));
103         seconds = Integer.parseInt((String) elements.get(2));
104         break;
105       case 2:
106         minutes = Integer.parseInt((String) elements.get(0));
107         seconds = Integer.parseInt((String) elements.get(1));
108         break;
109       default:
110         throw new ConverterException("Cannot parse string='" + string + "'");
111     }
112     final double factor = getUnitFactor(component);
113     final long value = (long) (((hours * 60L + minutes) * 60L + seconds) / factor);
114     if (negative) {
115       return Long.valueOf(-value);
116     } else {
117       return Long.valueOf(value);
118     }
119   }
120 
121   private static double getUnitFactor(final UIComponent component) {
122     String unit = null;
123     if (component != null) {
124       unit = (String) component.getAttributes().get(Attributes.UNIT);
125     }
126     final double factor;
127     if (unit == null) {
128       factor = 0.001;
129     } else if (NANO.equals(unit)) {
130       factor = 0.000000001;
131     } else if (MILLI.equals(unit)) {
132       factor = 0.001;
133     } else if (SECOND.equals(unit)) {
134       factor = 1.0;
135     } else if (MINUTE.equals(unit)) {
136       factor = 60.0;
137     } else if (HOUR.equals(unit)) {
138       factor = 3600.0;
139     } else if (DAY.equals(unit)) {
140       factor = 86400.0;
141     } else if (YEAR.equals(unit)) {
142       factor = 31556736.0;
143     } else {
144       LOG.warn("Unsupported unit: '" + unit + "'");
145       factor = 0.001;
146     }
147     return factor;
148   }
149 
150 }