001 package org.tynamo.services;
002
003 import ognl.Ognl;
004 import ognl.OgnlException;
005 import org.apache.tapestry5.beaneditor.DataType;
006 import org.apache.tapestry5.ioc.services.PropertyAdapter;
007 import org.apache.tapestry5.services.DataTypeAnalyzer;
008 import org.slf4j.Logger;
009 import org.tynamo.descriptor.TynamoClassDescriptor;
010 import org.tynamo.descriptor.TynamoPropertyDescriptor;
011 import org.tynamo.util.Pair;
012
013 import java.util.List;
014
015 public class TynamoDataTypeAnalyzer implements DataTypeAnalyzer
016 {
017
018 private final DescriptorService descriptorService;
019 private final List<Pair> editorMap;
020 private final Logger logger;
021
022 /**
023 * @param descriptorService
024 * @param editorMap A map where the keys are OGNL expressions and the values are data type identifier used to select editor (or display) blocks
025 */
026 public TynamoDataTypeAnalyzer(final DescriptorService descriptorService, final List<Pair> editorMap, final Logger logger)
027 {
028 this.descriptorService = descriptorService;
029 this.editorMap = editorMap;
030 this.logger = logger;
031 }
032
033 /**
034 * The first data type identifier in the editorMap whose "key" evaluates to true for the descriptor will be used
035 * to load an editor (or display) block for the descriptor. Returns null if no match is found.
036 *
037 * @return returns the data type identifier, if known, or returns null if not known.
038 */
039 public String identifyDataType(PropertyAdapter adapter)
040 {
041 if (adapter.getAnnotation(DataType.class) == null)
042 {
043 TynamoPropertyDescriptor propertyDescriptor = getPropertyDescriptor(adapter);
044 if (propertyDescriptor != null) //ignore excluded properties
045 {
046 for (Pair<String, String> entry : editorMap)
047 {
048 try
049 {
050 if ((Boolean) Ognl.getValue(entry.getKey(), propertyDescriptor))
051 {
052 return entry.getValue();
053 }
054 } catch (OgnlException oe)
055 {
056 logger.error(String.format("Error evaluating expression: \"%s\" for the \"%s\" property of %s",
057 entry.getKey(), adapter.getName(), adapter.getBeanType().getName()), oe);
058 }
059 }
060 }
061 }
062
063 // To avoid "no strategy" exceptions, we expect a contribution of Object.class to the empty
064 // string. We convert that back to a null.
065 return null;
066 }
067
068 private TynamoPropertyDescriptor getPropertyDescriptor(PropertyAdapter adapter)
069 {
070
071 TynamoClassDescriptor classDescriptor = descriptorService.getClassDescriptor(adapter.getBeanType());
072 TynamoPropertyDescriptor propertyDescriptor = null;
073
074 if (classDescriptor != null)
075 {
076 propertyDescriptor = classDescriptor.getPropertyDescriptor(adapter.getName());
077 }
078
079 return propertyDescriptor;
080 }
081
082 }
083