Skip to content

Commit 7e51071

Browse files
author
graeme
committed
fix for GRAILS-1637
git-svn-id: https://svn.codehaus.org/grails/trunk@5752 1cfb16fd-6d17-0410-8ff1-b7e8e1e2867d
1 parent c2a1e8b commit 7e51071

File tree

8 files changed

+184
-46
lines changed

8 files changed

+184
-46
lines changed

src/commons/org/codehaus/groovy/grails/commons/AbstractGrailsClass.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ else if (GrailsClassUtils.isPublicField(ref.getWrappedInstance(), name))
192192
* @param type
193193
* @return The property value or null
194194
*/
195-
protected Object getPropertyValue(String name, Class type) {
195+
public Object getPropertyValue(String name, Class type) {
196196

197197
// Handle standard java beans normal or static properties
198198
BeanWrapper ref = getReference();
@@ -228,9 +228,10 @@ protected Object getPropertyValue(String name, Class type) {
228228
public Object getPropertyValue(String name) {
229229
return getPropertyOrStaticPropertyOrFieldValue(name, Object.class);
230230
}
231-
232-
233-
/* (non-Javadoc)
231+
232+
233+
234+
/* (non-Javadoc)
234235
* @see org.codehaus.groovy.grails.commons.GrailsClass#hasProperty(java.lang.String)
235236
*/
236237
public boolean hasProperty(String name) {

src/commons/org/codehaus/groovy/grails/commons/DefaultGrailsDomainClass.java

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ private void populateDomainClassProperties(PropertyDescriptor[] propertyDescript
164164

165165
PropertyDescriptor descriptor = propertyDescriptors[i];
166166
// ignore certain properties
167-
if(isNotConfigurational(descriptor) ) {
167+
if(GrailsDomainConfigurationUtil.isNotConfigurational(descriptor) ) {
168168

169169

170170
GrailsDomainClassProperty property = new DefaultGrailsDomainClassProperty(this, descriptor);
@@ -208,25 +208,6 @@ private Collection getEmbeddedList() {
208208
}
209209

210210

211-
/**
212-
* Checks whether is property is configurational
213-
*
214-
* @param descriptor The descriptor
215-
* @return True if it is configurational
216-
*/
217-
private boolean isNotConfigurational(PropertyDescriptor descriptor) {
218-
return !descriptor.getName().equals( GrailsDomainClassProperty.META_CLASS ) &&
219-
!descriptor.getName().equals( GrailsDomainClassProperty.CLASS ) &&
220-
!descriptor.getName().equals( GrailsDomainClassProperty.TRANSIENT) &&
221-
!descriptor.getName().equals( GrailsDomainClassProperty.RELATES_TO_MANY) &&
222-
!descriptor.getName().equals( GrailsDomainClassProperty.HAS_MANY) &&
223-
!descriptor.getName().equals( GrailsDomainClassProperty.EVANESCENT) &&
224-
!descriptor.getName().equals( GrailsDomainClassProperty.CONSTRAINTS )&&
225-
!descriptor.getName().equals( GrailsDomainClassProperty.MAPPING_STRATEGY ) &&
226-
!descriptor.getName().equals( GrailsDomainClassProperty.MAPPED_BY ) &&
227-
!descriptor.getName().equals( GrailsDomainClassProperty.BELONGS_TO );
228-
}
229-
230211
/**
231212
* Evaluates the constraints closure to build the list of constraints
232213
*

src/commons/org/codehaus/groovy/grails/commons/DefaultGrailsDomainClassProperty.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
public class DefaultGrailsDomainClassProperty implements GrailsDomainClassProperty {
3434

3535

36-
private DefaultGrailsDomainClass domainClass;
36+
private GrailsDomainClass domainClass;
3737
private boolean persistant;
3838
private boolean identity;
3939
private boolean oneToMany;
@@ -56,33 +56,36 @@ public class DefaultGrailsDomainClassProperty implements GrailsDomainClassProper
5656
private boolean embedded;
5757

5858

59-
public DefaultGrailsDomainClassProperty(DefaultGrailsDomainClass domainClass, PropertyDescriptor descriptor) {
59+
public DefaultGrailsDomainClassProperty(GrailsDomainClass domainClass, PropertyDescriptor descriptor) {
6060
this.domainClass = domainClass;
6161
// persistant by default
6262
this.persistant = true;
6363
this.name = descriptor.getName();
6464
this.naturalName = GrailsClassUtils.getNaturalName(descriptor.getName());
6565
this.type = descriptor.getPropertyType();
6666
this.identity = descriptor.getName().equals( IDENTITY );
67-
// figure out if this property is inherited
68-
if(!domainClass.isRoot()) {
69-
this.inherited = GrailsClassUtils.isPropertyInherited(domainClass.getClazz(), this.name);
70-
}
7167

7268
// establish if property is persistant
73-
List transientProps = getTransients(domainClass);
74-
checkIfTransient(transientProps);
69+
if(domainClass != null) {
70+
// figure out if this property is inherited
71+
if(!domainClass.isRoot()) {
72+
this.inherited = GrailsClassUtils.isPropertyInherited(domainClass.getClazz(), this.name);
73+
}
74+
List transientProps = getTransients(domainClass);
75+
checkIfTransient(transientProps);
7576

76-
establishFetchMode();
77+
establishFetchMode();
7778

79+
}
7880
}
7981

8082
/**
8183
* Evaluates the fetchmode
8284
*
8385
*/
8486
private void establishFetchMode() {
85-
Map fetchMap = (Map)domainClass.getPropertyOrStaticPropertyOrFieldValue(FETCH_MODE, Map.class);
87+
88+
Map fetchMap = (Map) domainClass.getPropertyValue(GrailsDomainClassProperty.FETCH_MODE, Map.class);
8689
if(fetchMap != null && fetchMap.containsKey(this.name)) {
8790
if("eager".equals(fetchMap.get(this.name))) {
8891
this.fetchMode = FETCH_EAGER;
@@ -121,12 +124,12 @@ private void checkIfTransient(List transientProps) {
121124
* @param domainClass The owning domain class
122125
* @return A list of transient properties
123126
*/
124-
private List getTransients(DefaultGrailsDomainClass domainClass) {
127+
private List getTransients(GrailsDomainClass domainClass) {
125128
List transientProps;
126-
transientProps= (List)domainClass.getPropertyOrStaticPropertyOrFieldValue( TRANSIENT, List.class );
129+
transientProps= (List)domainClass.getPropertyValue( TRANSIENT, List.class );
127130

128131
// Undocumented feature alert! Steve insisted on this :-)
129-
List evanescent = (List)domainClass.getPropertyOrStaticPropertyOrFieldValue( EVANESCENT, List.class );
132+
List evanescent = (List)domainClass.getPropertyValue(EVANESCENT, List.class );
130133
if(evanescent != null) {
131134
if(transientProps == null)
132135
transientProps = new ArrayList();

src/commons/org/codehaus/groovy/grails/commons/GrailsClass.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,11 @@ public interface GrailsClass {
116116
public MetaClass getMetaClass();
117117

118118
BeanWrapper getReference();
119+
120+
/**
121+
* Obtains a property value for the given name and type
122+
* @param name The name
123+
* @param type The type
124+
*/
125+
Object getPropertyValue(String name, Class type);
119126
}

src/commons/org/codehaus/groovy/grails/commons/GrailsDomainClass.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,5 @@ public interface GrailsDomainClass extends GrailsClass {
183183
* @return The map that defines association mappings
184184
*/
185185
Map getMappedBy();
186+
186187
}

src/commons/org/codehaus/groovy/grails/commons/GrailsDomainConfigurationUtil.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.sql.Time;
2828
import java.sql.Timestamp;
2929
import java.util.*;
30+
import java.beans.PropertyDescriptor;
3031

3132
/**
3233
* Utility methods used in configuring the Grails Hibernate integration
@@ -229,4 +230,22 @@ public static boolean isBasicType(Class propType) {
229230
}
230231

231232

233+
/**
234+
* Checks whether is property is configurational
235+
*
236+
* @param descriptor The descriptor
237+
* @return True if it is configurational
238+
*/
239+
public static boolean isNotConfigurational(PropertyDescriptor descriptor) {
240+
return !descriptor.getName().equals( GrailsDomainClassProperty.META_CLASS ) &&
241+
!descriptor.getName().equals( GrailsDomainClassProperty.CLASS ) &&
242+
!descriptor.getName().equals( GrailsDomainClassProperty.TRANSIENT) &&
243+
!descriptor.getName().equals( GrailsDomainClassProperty.RELATES_TO_MANY) &&
244+
!descriptor.getName().equals( GrailsDomainClassProperty.HAS_MANY) &&
245+
!descriptor.getName().equals( GrailsDomainClassProperty.EVANESCENT) &&
246+
!descriptor.getName().equals( GrailsDomainClassProperty.CONSTRAINTS )&&
247+
!descriptor.getName().equals( GrailsDomainClassProperty.MAPPING_STRATEGY ) &&
248+
!descriptor.getName().equals( GrailsDomainClassProperty.MAPPED_BY ) &&
249+
!descriptor.getName().equals( GrailsDomainClassProperty.BELONGS_TO );
250+
}
232251
}

src/persistence/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java

Lines changed: 134 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@
1616

1717

1818
import groovy.lang.Closure;
19+
import groovy.lang.GroovySystem;
20+
import groovy.lang.MetaClass;
1921
import org.apache.commons.lang.ArrayUtils;
2022
import org.apache.commons.lang.math.NumberUtils;
2123
import org.apache.commons.logging.Log;
2224
import org.apache.commons.logging.LogFactory;
23-
import org.codehaus.groovy.grails.commons.GrailsDomainClass;
24-
import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty;
25+
import org.codehaus.groovy.grails.commons.*;
2526
import org.codehaus.groovy.grails.validation.ConstrainedProperty;
2627
import org.hibernate.FetchMode;
2728
import org.hibernate.MappingException;
@@ -32,11 +33,15 @@
3233
import org.hibernate.id.PersistentIdentifierGenerator;
3334
import org.hibernate.mapping.*;
3435
import org.hibernate.mapping.Collection;
35-
import org.hibernate.persister.entity.SingleTableEntityPersister;
3636
import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
37+
import org.hibernate.persister.entity.SingleTableEntityPersister;
3738
import org.hibernate.usertype.UserType;
3839
import org.hibernate.util.StringHelper;
40+
import org.springframework.beans.BeanWrapper;
41+
import org.springframework.validation.Validator;
3942

43+
import java.beans.IntrospectionException;
44+
import java.beans.PropertyDescriptor;
4045
import java.util.*;
4146
import java.util.List;
4247
import java.util.Map;
@@ -1171,12 +1176,14 @@ private static boolean isBidirectionalManyToOne(GrailsDomainClassProperty curren
11711176
*/
11721177
private static void bindComponent(Component component, GrailsDomainClassProperty property, boolean isNullable, Mappings mappings) {
11731178
component.setEmbedded(true);
1174-
String role = StringHelper.qualify( property.getDomainClass().getFullName(), property.getName());
1179+
Class type = property.getType();
1180+
String role = StringHelper.qualify(type.getName(), property.getName());
11751181
component.setRoleName(role);
1176-
component.setComponentClassName(property.getType().getName());
1182+
component.setComponentClassName(type.getName());
11771183

1178-
GrailsDomainClass domainClass = property.getReferencedDomainClass();
11791184

1185+
1186+
GrailsDomainClass domainClass = property.getReferencedDomainClass() != null ? property.getReferencedDomainClass() : new ComponentDomainClass(type);
11801187
GrailsDomainClassProperty[] properties = domainClass.getPersistentProperties();
11811188
Table table = component.getOwner().getTable();
11821189
PersistentClass persistentClass = component.getOwner();
@@ -1199,6 +1206,17 @@ private static void bindComponent(Component component, GrailsDomainClassProperty
11991206

12001207
}
12011208

1209+
private static GrailsDomainClassProperty[] createDomainClassProperties(ComponentDomainClass type, PropertyDescriptor[] descriptors) {
1210+
List properties = new ArrayList();
1211+
for (int i = 0; i < descriptors.length; i++) {
1212+
PropertyDescriptor descriptor = descriptors[i];
1213+
if(GrailsDomainConfigurationUtil.isNotConfigurational(descriptor)) {
1214+
properties.add(new DefaultGrailsDomainClassProperty(type,descriptor));
1215+
}
1216+
}
1217+
return (GrailsDomainClassProperty[])properties.toArray(new GrailsDomainClassProperty[properties.size()]);
1218+
}
1219+
12021220
private static void bindComponentProperty(Component component, GrailsDomainClassProperty property, PersistentClass persistentClass, String path, Table table, Mappings mappings) {
12031221
Value value = null;
12041222
// see if its a collection type
@@ -1782,4 +1800,114 @@ private static int getMaxSize(List inListValues) {
17821800

17831801
return maxSize;
17841802
}
1803+
1804+
private static class ComponentDomainClass extends AbstractGrailsClass implements GrailsDomainClass {
1805+
private GrailsDomainClassProperty[] properties;
1806+
1807+
1808+
public ComponentDomainClass(Class type) {
1809+
super(type, "");
1810+
1811+
PropertyDescriptor[] descriptors;
1812+
try {
1813+
descriptors = java.beans.Introspector.getBeanInfo(type).getPropertyDescriptors();
1814+
} catch (IntrospectionException e) {
1815+
throw new MappingException("Failed to use class ["+type+"] as a component. Cannot introspect! " + e.getMessage());
1816+
}
1817+
1818+
this.properties = createDomainClassProperties(this,descriptors);
1819+
}
1820+
1821+
public boolean isOwningClass(Class domainClass) {
1822+
return false;
1823+
}
1824+
1825+
public GrailsDomainClassProperty[] getProperties() {
1826+
return properties;
1827+
}
1828+
1829+
public GrailsDomainClassProperty[] getPersistantProperties() {
1830+
return properties;
1831+
}
1832+
1833+
public GrailsDomainClassProperty[] getPersistentProperties() {
1834+
return properties;
1835+
}
1836+
1837+
public GrailsDomainClassProperty getIdentifier() {
1838+
return null; // no identifier for embedded component
1839+
}
1840+
1841+
public GrailsDomainClassProperty getVersion() {
1842+
return null; // no version for embedded component
1843+
}
1844+
1845+
public Map getAssociationMap() {
1846+
return Collections.EMPTY_MAP;
1847+
}
1848+
1849+
public GrailsDomainClassProperty getPropertyByName(String name) {
1850+
for (int i = 0; i < properties.length; i++) {
1851+
GrailsDomainClassProperty property = properties[i];
1852+
if(property.getName().equals(name)) return property;
1853+
}
1854+
return null;
1855+
}
1856+
1857+
public String getFieldName(String propertyName) {
1858+
return null;
1859+
}
1860+
1861+
1862+
public boolean isOneToMany(String propertyName) {
1863+
return false;
1864+
}
1865+
1866+
public boolean isManyToOne(String propertyName) {
1867+
return false;
1868+
}
1869+
1870+
public boolean isBidirectional(String propertyName) {
1871+
return false;
1872+
}
1873+
1874+
public Class getRelatedClassType(String propertyName) {
1875+
return getPropertyByName(propertyName).getReferencedPropertyType();
1876+
}
1877+
1878+
public Map getConstrainedProperties() {
1879+
return Collections.EMPTY_MAP;
1880+
}
1881+
1882+
public Validator getValidator() {
1883+
return null;
1884+
}
1885+
1886+
public void setValidator(Validator validator) {
1887+
}
1888+
1889+
public String getMappingStrategy() {
1890+
return GrailsDomainClass.GORM;
1891+
}
1892+
1893+
public boolean isRoot() {
1894+
return true;
1895+
}
1896+
1897+
public Set getSubClasses() {
1898+
return Collections.EMPTY_SET;
1899+
}
1900+
1901+
public void refreshConstraints() {
1902+
// do nothing
1903+
}
1904+
1905+
public boolean hasSubClasses() {
1906+
return false;
1907+
}
1908+
1909+
public Map getMappedBy() {
1910+
return Collections.EMPTY_MAP;
1911+
}
1912+
}
17851913
}

test/groovy/org/codehaus/groovy/grails/orm/hibernate/ComponentMappingTests.groovy

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class ComponentMappingTests extends AbstractGrailsHibernateTests {
77

88
void testComponentMapping() {
99
def personClass = ga.getDomainClass("Person")
10-
def addressClass = ga.getDomainClass("Address")
10+
def addressClass = ga.classLoader.loadClass("Address")
1111

1212
def p = personClass.newInstance()
1313

@@ -53,8 +53,6 @@ class Person {
5353
static embedded = ['homeAddress', 'workAddress']
5454
}
5555
class Address {
56-
Long id
57-
Long version
5856
Person person
5957
String number
6058
String postCode

0 commit comments

Comments
 (0)