001    package org.tynamo.hibernate.services;
002    
003    import org.apache.tapestry5.hibernate.HibernateConfigurer;
004    import org.apache.tapestry5.hibernate.HibernateSessionSource;
005    import org.apache.tapestry5.hibernate.HibernateTransactionDecorator;
006    import org.apache.tapestry5.ioc.Configuration;
007    import org.apache.tapestry5.ioc.MappedConfiguration;
008    import org.apache.tapestry5.ioc.OrderedConfiguration;
009    import org.apache.tapestry5.ioc.ServiceBinder;
010    import org.apache.tapestry5.ioc.annotations.InjectService;
011    import org.apache.tapestry5.ioc.annotations.Match;
012    import org.apache.tapestry5.ioc.annotations.Symbol;
013    import org.apache.tapestry5.services.BeanBlockContribution;
014    import org.apache.tapestry5.services.LibraryMapping;
015    import org.hibernate.mapping.PersistentClass;
016    import org.tynamo.VersionedModule;
017    import org.tynamo.descriptor.DescriptorDecorator;
018    import org.tynamo.descriptor.DescriptorFactory;
019    import org.tynamo.descriptor.annotation.AnnotationDecorator;
020    import org.tynamo.hibernate.TynamoHibernateSymbols;
021    import org.tynamo.hibernate.TynamoInterceptor;
022    import org.tynamo.hibernate.TynamoInterceptorConfigurer;
023    import org.tynamo.hibernate.validation.HibernateClassValidatorFactory;
024    import org.tynamo.hibernate.validation.HibernateValidationDelegate;
025    import org.tynamo.util.Pair;
026    
027    import java.util.Iterator;
028    
029    public class TynamoHibernateModule extends VersionedModule
030    {
031    
032            public static void bind(ServiceBinder binder)
033            {
034                    // Make bind() calls on the binder object to define most IoC services.
035                    // Use service builder methods (example below) when the implementation
036                    // is provided inline, or requires more initialization than simply
037                    // invoking the constructor.
038    
039                    binder.bind(HibernatePersistenceService.class, HibernatePersistenceServiceImpl.class);
040                    binder.bind(HibernateClassValidatorFactory.class, HibernateClassValidatorFactory.class);
041                    binder.bind(HibernateValidationDelegate.class, HibernateValidationDelegate.class);
042                    binder.bind(TynamoInterceptor.class);
043                    binder.bind(HibernateConfigurer.class, TynamoInterceptorConfigurer.class).withId("TynamoInterceptorConfigurer");
044    
045            }
046    
047            /**
048             * Add our components and pages to the "trails" library.
049             */
050            public static void contributeComponentClassResolver(Configuration<LibraryMapping> configuration)
051            {
052                    configuration.add(new LibraryMapping("tynamo-hibernate", "org.tynamo.hibernate"));
053            }
054    
055            public static void contributeClasspathAssetAliasManager(MappedConfiguration<String, String> configuration)
056            {
057                    configuration.add("tynamo-hibernate/" + version, "org/tynamo/hibernate");
058            }
059    
060            public static void contributeValidationMessagesSource(OrderedConfiguration<String> configuration)
061            {
062                    configuration.add("Tynamo", "ValidationMessages");
063            }
064    
065            @Match("HibernatePersistenceService")
066            public static <T> T decorateTransactionally(HibernateTransactionDecorator decorator, Class<T> serviceInterface,
067                                                                                                    T delegate,
068                                                                                                    String serviceId)
069            {
070                    return decorator.build(serviceInterface, delegate, serviceId);
071            }
072    
073            /**
074             * Contributions to the DefaultDataTypeAnalyzer.
075             * <p/>
076             * DataTypeAnalyzer is a chain of command that can make match properties to data types based on property type or
077             * annotations on the property. In general, DefaultDataTypeAnalyzer is used, as that only needs to consider property
078             * type. DefaultDataTypeAnalyzer matches property types to data types, based on a search up the inheritance path.
079             */
080            public static void contributeDefaultDataTypeAnalyzer(MappedConfiguration<Class, String> configuration)
081            {
082    
083            }
084    
085            /**
086             * Contribution to the BeanBlockSource service to tell the BeanEditForm component about the editors. When the
087             * BeanEditForm sees a property of type BigDecimal, it will map that to datatype "currency" and from there to the
088             * currency block of the AppPropertyEditBlocks page of the application.
089             */
090            public static void contributeBeanBlockSource(Configuration<BeanBlockContribution> configuration)
091            {
092    
093            }
094    
095            public static void contributeDescriptorFactory(OrderedConfiguration<DescriptorDecorator> configuration,
096                                                                                                       HibernateDescriptorDecorator hibernateDescriptorDecorator)
097            {
098                    configuration.add("Hibernate", hibernateDescriptorDecorator);
099                    configuration.add("Annotation", new AnnotationDecorator());
100            }
101    
102            @SuppressWarnings("unchecked")
103            public static void contributeDescriptorService(Configuration<Class> configuration,
104                                                                                                       HibernateSessionSource hibernateSessionSource)
105            {
106    
107                    org.hibernate.cfg.Configuration config = hibernateSessionSource.getConfiguration();
108                    Iterator<PersistentClass> mappings = config.getClassMappings();
109                    while (mappings.hasNext())
110                    {
111                            final PersistentClass persistentClass = mappings.next();
112                            final Class entityClass = persistentClass.getMappedClass();
113    
114                            if (entityClass != null)
115                            {
116                                    configuration.add(entityClass);
117                            }
118                    }
119            }
120    
121            public static void contributeTynamoDataTypeAnalyzer(OrderedConfiguration<Pair> configuration)
122            {
123    
124                    addPairToOrderedConfiguration(configuration, "hidden", "hidden");
125                    addPairToOrderedConfiguration(configuration, "readOnly", "readOnly");
126                    addPairToOrderedConfiguration(configuration, "richText", "fckEditor");
127    //              addPairToOrderedConfiguration(configuration, "name.toLowerCase().endsWith('password')", "passwordEditor"); //USE @DataType("password")
128    //              addPairToOrderedConfiguration(configuration, "string and !large and !identifier", "stringEditor"); //managed by Tapestry
129                    addPairToOrderedConfiguration(configuration, "string and large and !identifier", "longtext");
130                    addPairToOrderedConfiguration(configuration, "date", "dateEditor");
131    //              addPairToOrderedConfiguration(configuration, "numeric and !identifier", "numberEditor"); //managed by Tapestry
132                    addPairToOrderedConfiguration(configuration, "identifier && generated", "readOnly");
133                    addPairToOrderedConfiguration(configuration, "identifier && not(generated) && string", "identifierEditor");
134    //              addPairToOrderedConfiguration(configuration, "identifier && objectReference", "objectReferenceIdentifierEditor");
135    //              addPairToOrderedConfiguration(configuration, "boolean", "booleanEditor"); //managed by Tapestry
136    //              addPairToOrderedConfiguration(configuration, "supportsExtension('org.tynamo.descriptor.extension.EnumReferenceDescriptor')", "enumEditor"); //managed by Tapestry
137                    addPairToOrderedConfiguration(configuration, "supportsExtension('org.tynamo.descriptor.extension.BlobDescriptorExtension')", "blob");
138    
139                    addPairToOrderedConfiguration(configuration, "objectReference", "single-valued-association" /* (aka: ManyToOne) */);
140                    addPairToOrderedConfiguration(configuration, "collection && not(childRelationship)", "many-valued-association" /* (aka: ManyToMany) */);
141                    addPairToOrderedConfiguration(configuration, "collection && childRelationship", "composition");
142                    addPairToOrderedConfiguration(configuration, "name == 'id'", "readOnly");
143                    addPairToOrderedConfiguration(configuration, "embedded", "embedded");
144            }
145    
146            private static void addPairToOrderedConfiguration(OrderedConfiguration<Pair> configuration, String key, String value)
147            {
148                    configuration.add(key, new Pair<String, String>(key, value));
149            }
150    
151    
152            public static void contributePropertyDescriptorFactory(Configuration<String> configuration)
153            {
154                    configuration.add("exclude.*");
155                    configuration.add("class");
156            }
157    
158            public static void contributeMethodDescriptorFactory(Configuration<String> configuration)
159            {
160                    configuration.add("shouldExclude");
161                    configuration.add("set.*");
162                    configuration.add("get.*");
163                    configuration.add("is.*");
164                    configuration.add("equals");
165                    configuration.add("wait");
166                    configuration.add("toString");
167                    configuration.add("notify.*");
168                    configuration.add("hashCode");
169            }
170    
171            public static HibernateDescriptorDecorator buildHibernateDescriptorDecorator(
172                                                                                                    HibernateSessionSource hibernateSessionSource,
173                                                                                                    DescriptorFactory descriptorFactory,
174                                                                                                    @Symbol(TynamoHibernateSymbols.LARGE_COLUMN_LENGTH)
175                                                                                                    final int largeColumnLength,
176                                                                                                    @Symbol(TynamoHibernateSymbols.IGNORE_NON_HIBERNATE_TYPES)
177                                                                                                    final boolean ignoreNonHibernateTypes)
178            {
179                    return new HibernateDescriptorDecorator(hibernateSessionSource, descriptorFactory, largeColumnLength, ignoreNonHibernateTypes);
180            }
181    
182            public static void contributeFactoryDefaults(MappedConfiguration<String, String> configuration)
183            {
184                    configuration.add(TynamoHibernateSymbols.LARGE_COLUMN_LENGTH, "100");
185                    configuration.add(TynamoHibernateSymbols.IGNORE_NON_HIBERNATE_TYPES, "false");
186            }
187    
188    
189            /**
190             * Adds the following configurers:
191             * <dl>
192             * <dt>TynamoInterceptorConfigurer
193             * <dd>add the TynamoInterceptor to the hibernate configuration
194             */
195            public static void contributeHibernateSessionSource(OrderedConfiguration<HibernateConfigurer> config,
196                                                                                                                    @InjectService("TynamoInterceptorConfigurer")
197                                                                                                                    HibernateConfigurer trailsInterceptorConfigurer)
198            {
199                    config.add("TynamoInterceptorConfigurer", trailsInterceptorConfigurer);
200            }
201    
202    
203    /**
204     * We don't need this just yet, and it gives an error under Tapestry 5.1.0.2
205     *
206     * [INFO] [talledLocalContainer] java.lang.IllegalArgumentException:
207     * Contribution org.tynamo.hibernate.services.TynamoHibernateModule.contributeTynamoEntityPackageManager(Configuration, HibernateEntityPackageManager)
208     * (at TynamoHibernateModule.java:145) is for service 'TynamoEntityPackageManager', which does not exist.
209     *
210            public static void contributeTynamoEntityPackageManager(Configuration<String> configuration, HibernateEntityPackageManager packageManager)
211            {
212                    for (String packageName : packageManager.getPackageNames())
213                    {
214                            configuration.add(packageName);
215                    }
216            }
217    */
218    
219    
220    /*
221            public static void contributeFieldValidatorSource(MappedConfiguration<String, Validator> configuration) {
222                            configuration.add("int", new ValidateInt());
223            }
224    */
225    
226    }