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 }