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