001// Copyright 2014 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014package org.apache.tapestry5.commons.internal; 015 016import java.util.Calendar; 017import java.util.Date; 018import java.util.HashMap; 019import java.util.Map; 020 021import org.apache.tapestry5.beaneditor.DataTypeConstants; 022import org.apache.tapestry5.commons.MappedConfiguration; 023import org.apache.tapestry5.commons.OrderedConfiguration; 024import org.apache.tapestry5.commons.internal.services.AnnotationDataTypeAnalyzer; 025import org.apache.tapestry5.commons.internal.services.DefaultDataTypeAnalyzer; 026import org.apache.tapestry5.commons.services.DataTypeAnalyzer; 027import org.apache.tapestry5.commons.services.PropertyAdapter; 028 029/** 030 * Class that provides Tapestry's basic default data type analyzers. 031 */ 032public class BasicDataTypeAnalyzers 033{ 034 035 public static void contributeDataTypeAnalyzer( 036 OrderedConfiguration<DataTypeAnalyzer> configuration, 037 DataTypeAnalyzer defaultDataTypeAnalyzer) { 038 configuration.add("Annotation", new AnnotationDataTypeAnalyzer()); 039 if (defaultDataTypeAnalyzer == null) 040 { 041 defaultDataTypeAnalyzer = createDefaultDataTypeAnalyzer(); 042 } 043 configuration.add("Default", defaultDataTypeAnalyzer, "after:*"); 044 } 045 046 public static DataTypeAnalyzer createDefaultDataTypeAnalyzer() 047 { 048 DefaultDataTypeAnalyzerMappedConfiguration mappedConfiguration = new DefaultDataTypeAnalyzerMappedConfiguration(); 049 provideDefaultDataTypeAnalyzers(mappedConfiguration); 050 return new CombinedDataTypeAnalyzer(new AnnotationDataTypeAnalyzer(), new DefaultDataTypeAnalyzer(mappedConfiguration.getMap())); 051 } 052 053 /** 054 * Maps property types to data type names: 055 * <ul> 056 * <li>String --> text 057 * <li>Number --> number 058 * <li>Enum --> enum 059 * <li>Boolean --> boolean 060 * <li>Date --> date 061 * </ul> 062 */ 063 public static void provideDefaultDataTypeAnalyzers(MappedConfiguration<Class, String> configuration) 064 { 065 // This is a special case contributed to avoid exceptions when a 066 // property type can't be 067 // matched. DefaultDataTypeAnalyzer converts the empty string to null. 068 069 configuration.add(Object.class, ""); 070 071 configuration.add(String.class, DataTypeConstants.TEXT); 072 configuration.add(Number.class, DataTypeConstants.NUMBER); 073 configuration.add(Enum.class, DataTypeConstants.ENUM); 074 configuration.add(Boolean.class, DataTypeConstants.BOOLEAN); 075 configuration.add(Date.class, DataTypeConstants.DATE); 076 configuration.add(Calendar.class, DataTypeConstants.CALENDAR); 077 } 078 079 final private static class DefaultDataTypeAnalyzerMappedConfiguration implements MappedConfiguration<Class, String> 080 { 081 082 final Map<Class, String> map = new HashMap<Class, String>(); 083 084 @Override 085 public void add(Class key, String value) { 086 map.put(key, value); 087 } 088 089 @Override 090 public void override(Class key, String value) { 091 throw new RuntimeException("Not implemented"); 092 } 093 094 @Override 095 public void addInstance(Class key, Class<? extends String> clazz) { 096 throw new RuntimeException("Not implemented"); 097 } 098 099 @Override 100 public void overrideInstance(Class key, Class<? extends String> clazz) { 101 throw new RuntimeException("Not implemented"); 102 } 103 104 public Map<Class, String> getMap() { 105 return map; 106 } 107 108 } 109 110 final private static class CombinedDataTypeAnalyzer implements DataTypeAnalyzer 111 { 112 113 final private DataTypeAnalyzer[] analyzers; 114 115 public CombinedDataTypeAnalyzer(DataTypeAnalyzer... analyzers) 116 { 117 this.analyzers = analyzers; 118 } 119 120 @Override 121 public String identifyDataType(PropertyAdapter adapter) 122 { 123 String type = null; 124 for (DataTypeAnalyzer analyzer : analyzers) 125 { 126 type = analyzer.identifyDataType(adapter); 127 if (type != null) 128 { 129 break; 130 } 131 } 132 return type; 133 } 134 135 } 136 137 138}