001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019
020 package org.apache.myfaces.tobago.convert;
021
022 import org.apache.commons.logging.Log;
023 import org.apache.commons.logging.LogFactory;
024 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_UNIT;
025
026 import javax.faces.component.UIComponent;
027 import javax.faces.context.FacesContext;
028 import javax.faces.convert.Converter;
029 import javax.faces.convert.ConverterException;
030 import java.text.DecimalFormat;
031 import java.text.NumberFormat;
032 import java.util.ArrayList;
033 import java.util.List;
034 import java.util.StringTokenizer;
035
036 @org.apache.myfaces.tobago.apt.annotation.Converter(id = DurationConverter.CONVERTER_ID)
037 public class DurationConverter implements Converter {
038
039 private static final Log LOG = LogFactory.getLog(DurationConverter.class);
040
041 public static final String CONVERTER_ID = "org.apache.myfaces.tobago.Duration";
042
043 private static final String NANO = "nano";
044 private static final String MILLI = "milli";
045 private static final String SECOND = "second";
046 private static final String MINUTE = "minute";
047 private static final String HOUR = "hour";
048 private static final String DAY = "day";
049 private static final String YEAR = "year";
050
051 public String getAsString(
052 FacesContext facesContext, UIComponent component, Object object)
053 throws ConverterException {
054 if (object == null || object instanceof String) {
055 return (String) object;
056 }
057 double aDouble = ((Number) object).doubleValue();
058 boolean negative = false;
059 if (aDouble < 0) {
060 negative = true;
061 aDouble = -aDouble;
062 }
063 double factor = getUnitFactor(component);
064 aDouble = aDouble * factor;
065
066 NumberFormat format = new DecimalFormat("00");
067 long value = Double.valueOf(aDouble).longValue();
068 int seconds = (int) (value % 60);
069 value = value / 60;
070 int minutes = (int) (value % 60);
071 value = value / 60;
072 String string;
073 if (value > 0) {
074 string = (negative ? "-" : "") + value + ":"
075 + format.format(minutes) + ":"
076 + format.format(seconds);
077 } else {
078 string = (negative ? "-" : "") + minutes + ":"
079 + format.format(seconds);
080 }
081 if (LOG.isDebugEnabled()) {
082 LOG.debug("string = '" + string + "'");
083 }
084 return string;
085 }
086
087 public Object getAsObject(
088 FacesContext facesContext, UIComponent component, String string)
089 throws ConverterException {
090 boolean negative = string.indexOf('-') > -1;
091 StringTokenizer tokenizer = new StringTokenizer(string, " :-");
092 List elements = new ArrayList();
093 while (tokenizer.hasMoreElements()) {
094 elements.add(tokenizer.nextElement());
095 }
096 int hours = 0;
097 int minutes;
098 int seconds;
099 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 double factor = getUnitFactor(component);
113 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(UIComponent component) {
122 String unit = null;
123 if (component != null) {
124 unit = (String) component.getAttributes().get(ATTR_UNIT);
125 }
126 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 }