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.apache.myfaces.tobago.component.Attributes;
23  import org.apache.myfaces.tobago.util.ComponentUtils;
24  import org.slf4j.Logger;
25  import org.slf4j.LoggerFactory;
26  
27  import javax.faces.component.UIComponent;
28  import javax.faces.context.FacesContext;
29  import javax.faces.convert.Converter;
30  import javax.faces.convert.ConverterException;
31  import java.text.DecimalFormat;
32  import java.text.NumberFormat;
33  import java.util.ArrayList;
34  import java.util.List;
35  import java.util.StringTokenizer;
36  
37  @org.apache.myfaces.tobago.apt.annotation.Converter(id = DurationConverter.CONVERTER_ID)
38  public class DurationConverter implements Converter {
39  
40    private static final Logger LOG = LoggerFactory.getLogger(DurationConverter.class);
41  
42    public static final String CONVERTER_ID = "org.apache.myfaces.tobago.Duration";
43  
44    private static enum Unit {
45      nano, milli, second, minute, hour, day, year
46    }
47  
48    @Override
49    public String getAsString(
50        final FacesContext facesContext, final UIComponent component, final Object object)
51        throws ConverterException {
52      if (object == null || object instanceof String) {
53        return (String) object;
54      }
55      double aDouble = ((Number) object).doubleValue();
56      boolean negative = false;
57      if (aDouble < 0) {
58        negative = true;
59        aDouble = -aDouble;
60      }
61      final double factor = getUnitFactor(component);
62      aDouble = aDouble * factor;
63  
64      final NumberFormat format = new DecimalFormat("00");
65      long value = Double.valueOf(aDouble).longValue();
66      final int seconds = (int) (value % 60);
67      value = value / 60;
68      final int minutes = (int) (value % 60);
69      value = value / 60;
70      final String string;
71      if (value > 0) {
72        string = (negative ? "-" : "") + value + ":"
73            + format.format(minutes) + ":"
74            + format.format(seconds);
75      } else {
76        string = (negative ? "-" : "") + minutes + ":"
77            + format.format(seconds);
78      }
79      if (LOG.isDebugEnabled()) {
80        LOG.debug("string = '{}'", string);
81      }
82      return string;
83    }
84  
85    @Override
86    public Object getAsObject(
87        final FacesContext facesContext, final UIComponent component, final String string)
88        throws ConverterException {
89      final boolean negative = string.indexOf('-') > -1;
90      final StringTokenizer tokenizer = new StringTokenizer(string, " :-");
91      final List<String> elements = new ArrayList<String>();
92      while (tokenizer.hasMoreTokens()) {
93        elements.add(tokenizer.nextToken());
94      }
95      int hours = 0;
96      final int minutes;
97      final int seconds;
98      switch (elements.size()) {
99        case 3:
100         hours = Integer.parseInt(elements.get(0));
101         minutes = Integer.parseInt(elements.get(1));
102         seconds = Integer.parseInt(elements.get(2));
103         break;
104       case 2:
105         minutes = Integer.parseInt(elements.get(0));
106         seconds = Integer.parseInt(elements.get(1));
107         break;
108       default:
109         throw new ConverterException("Cannot parse string='" + string + "'");
110     }
111     final double factor = getUnitFactor(component);
112     final long value = (long) (((hours * 60L + minutes) * 60L + seconds) / factor);
113     if (negative) {
114       return -value;
115     } else {
116       return value;
117     }
118   }
119 
120   private static double getUnitFactor(final UIComponent component) {
121     final String unitString = ComponentUtils.getStringAttribute(component, Attributes.unit);
122     Unit unit;
123     try {
124       unit = Unit.valueOf(unitString);
125     } catch (Exception e) {
126       LOG.warn("Unsupported unit: '{}'", unitString);
127       unit = Unit.milli;
128     }
129     switch (unit) {
130       case nano:
131         return 0.000000001;
132       default:
133       case milli:
134         return 0.001;
135       case second:
136         return 1.0;
137       case minute:
138         return 60.0;
139       case hour:
140         return 3600.0;
141       case day:
142         return 86400.0;
143       case year:
144         return 31556736.0;
145     }
146   }
147 
148 }