Java tutorial
/* * Copyright 2004-2005 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.codehaus.groovy.grails.commons; import grails.util.GrailsNameUtils; import java.beans.PropertyDescriptor; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.ClassUtils; import org.apache.commons.lang.StringUtils; import org.codehaus.groovy.grails.exceptions.GrailsDomainException; import org.codehaus.groovy.grails.exceptions.InvalidPropertyException; import org.codehaus.groovy.grails.validation.ConstraintsEvaluator; import org.codehaus.groovy.grails.validation.DefaultConstraintEvaluator; import org.springframework.context.ApplicationContext; import org.springframework.validation.Validator; /** * @author Graeme Rocher */ @SuppressWarnings("rawtypes") public class DefaultGrailsDomainClass extends AbstractGrailsClass implements GrailsDomainClass, ComponentCapableDomainClass { private GrailsDomainClassProperty identifier; private GrailsDomainClassProperty version; private GrailsDomainClassProperty[] properties; private GrailsDomainClassProperty[] persistentProperties; private Map<String, GrailsDomainClassProperty> propertyMap; private Map relationshipMap; private Map hasOneMap; private Map constraints; private Map mappedBy; private Validator validator; private String mappingStrategy = GrailsDomainClass.GORM; private List<Class<?>> owners = new ArrayList<Class<?>>(); private boolean root = true; private Set subClasses = new HashSet(); private Collection<String> embedded; private Map<String, Object> defaultConstraints; private List<GrailsDomainClass> components = new ArrayList<GrailsDomainClass>(); private List<GrailsDomainClassProperty> associations = new ArrayList<GrailsDomainClassProperty>(); /** * Constructor. * @param clazz * @param defaultConstraints */ public DefaultGrailsDomainClass(Class<?> clazz, Map<String, Object> defaultConstraints) { super(clazz, ""); PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(); final Class<?> superClass = clazz.getSuperclass(); if (DomainClassArtefactHandler.isDomainClass(superClass)) { root = false; } propertyMap = new LinkedHashMap<String, GrailsDomainClassProperty>(); relationshipMap = getAssociationMap(); embedded = getEmbeddedList(); this.defaultConstraints = defaultConstraints; // get mapping strategy by setting mappingStrategy = getStaticPropertyValue(GrailsDomainClassProperty.MAPPING_STRATEGY, String.class); if (mappingStrategy == null) { mappingStrategy = GORM; } // get any mappedBy settings mappedBy = getMergedConfigurationMap(GrailsDomainClassProperty.MAPPED_BY); hasOneMap = getMergedConfigurationMap(GrailsDomainClassProperty.HAS_ONE); if (hasOneMap == null) { hasOneMap = Collections.emptyMap(); } if (mappedBy == null) { mappedBy = Collections.emptyMap(); } // establish the owners of relationships establishRelationshipOwners(); // First go through the properties of the class and create domain properties // populating into a map populateDomainClassProperties(propertyDescriptors); // if no identifier property throw exception if (identifier == null) { throw new GrailsDomainException( "Identity property not found, but required in domain class [" + getFullName() + "]"); } // if no version property throw exception if (version == null) { throw new GrailsDomainException( "Version property not found, but required in domain class [" + getFullName() + "]"); } // set properties from map values properties = propertyMap.values().toArray(new GrailsDomainClassProperty[propertyMap.size()]); // establish relationships establishRelationships(); // set persistent properties establishPersistentProperties(); } /** * Constructor. * @param clazz */ public DefaultGrailsDomainClass(Class<?> clazz) { this(clazz, null); } public boolean hasSubClasses() { return !getSubClasses().isEmpty(); } /** * calculates the persistent properties from the evaluated properties */ private void establishPersistentProperties() { Collection<GrailsDomainClassProperty> tempList = new ArrayList<GrailsDomainClassProperty>(); for (Object o : propertyMap.values()) { GrailsDomainClassProperty currentProp = (GrailsDomainClassProperty) o; if (currentProp.getType() != Object.class && currentProp.isPersistent() && !currentProp.isIdentity() && !currentProp.getName().equals(GrailsDomainClassProperty.VERSION)) { tempList.add(currentProp); } } persistentProperties = tempList.toArray(new GrailsDomainClassProperty[tempList.size()]); } /** * Evaluates the belongsTo property to find out who owns who */ @SuppressWarnings("unchecked") private void establishRelationshipOwners() { Class<?> belongsTo = getStaticPropertyValue(GrailsDomainClassProperty.BELONGS_TO, Class.class); if (belongsTo == null) { List ownersProp = getStaticPropertyValue(GrailsDomainClassProperty.BELONGS_TO, List.class); if (ownersProp != null) { owners = ownersProp; } else { Map ownersMap = getStaticPropertyValue(GrailsDomainClassProperty.BELONGS_TO, Map.class); if (ownersMap != null) { owners = new ArrayList(ownersMap.values()); } } } else { owners = new ArrayList(); owners.add(belongsTo); } } /** * Populates the domain class properties map * * @param propertyDescriptors The property descriptors */ private void populateDomainClassProperties(PropertyDescriptor[] propertyDescriptors) { for (PropertyDescriptor descriptor : propertyDescriptors) { if (descriptor.getPropertyType() == null) { // indexed property continue; } // ignore certain properties if (GrailsDomainConfigurationUtil.isNotConfigurational(descriptor)) { GrailsDomainClassProperty property = new DefaultGrailsDomainClassProperty(this, descriptor, defaultConstraints); propertyMap.put(property.getName(), property); if (property.isIdentity()) { identifier = property; } else if (property.getName().equals(GrailsDomainClassProperty.VERSION)) { version = property; } } } } /** * Retrieves the association map */ public Map getAssociationMap() { if (relationshipMap == null) { relationshipMap = getMergedConfigurationMap(GrailsDomainClassProperty.HAS_MANY); } return relationshipMap; } @SuppressWarnings("unchecked") private Map getMergedConfigurationMap(String propertyName) { Map configurationMap = getStaticPropertyValue(propertyName, Map.class); if (configurationMap == null) { configurationMap = new HashMap(); } Class<?> theClass = getClazz(); while (theClass != Object.class) { theClass = theClass.getSuperclass(); ClassPropertyFetcher propertyFetcher = ClassPropertyFetcher.forClass(theClass); Map superRelationshipMap = propertyFetcher.getStaticPropertyValue(propertyName, Map.class); if (superRelationshipMap != null && !superRelationshipMap.equals(configurationMap)) { configurationMap.putAll(superRelationshipMap); } } return configurationMap; } /** * Retrieves the list of known embedded component types * * @return A list of embedded components */ @SuppressWarnings("unchecked") private Collection<String> getEmbeddedList() { Collection potentialList = getStaticPropertyValue(GrailsDomainClassProperty.EMBEDDED, Collection.class); if (potentialList != null) { return potentialList; } return Collections.emptyList(); } /** * Calculates the relationship type based other types referenced */ private void establishRelationships() { for (Object o : propertyMap.values()) { DefaultGrailsDomainClassProperty currentProp = (DefaultGrailsDomainClassProperty) o; if (!currentProp.isPersistent()) continue; Class currentPropType = currentProp.getType(); // establish if the property is a one-to-many // if it is a Set and there are relationships defined // and it is defined as persistent if (currentPropType != null) { if (Collection.class.isAssignableFrom(currentPropType) || Map.class.isAssignableFrom(currentPropType)) { establishRelationshipForCollection(currentProp); } // otherwise if the type is a domain class establish relationship else if (DomainClassArtefactHandler.isDomainClass(currentPropType) && currentProp.isPersistent()) { associations.add(currentProp); establishDomainClassRelationship(currentProp); } else if (embedded.contains(currentProp.getName())) { associations.add(currentProp); establishDomainClassRelationship(currentProp); } } } } /** * Establishes a relationship for a java.util.Set * * @param property The collection property */ private void establishRelationshipForCollection(DefaultGrailsDomainClassProperty property) { // is it a relationship Class<?> relatedClassType = getRelatedClassType(property.getName()); if (relatedClassType != null) { // set the referenced type in the property associations.add(property); property.setReferencedPropertyType(relatedClassType); // if the related type is a domain class // then figure out what kind of relationship it is if (DomainClassArtefactHandler.isDomainClass(relatedClassType)) { // check the relationship defined in the referenced type // if it is also a Set/domain class etc. Map relatedClassRelationships = GrailsDomainConfigurationUtil.getAssociationMap(relatedClassType); Class<?> relatedClassPropertyType = null; // First check whether there is an explicit relationship // mapping for this property (as provided by "mappedBy"). String mappingProperty = (String) mappedBy.get(property.getName()); if (!StringUtils.isBlank(mappingProperty)) { // First find the specified property on the related class, if it exists. PropertyDescriptor pd = findProperty( GrailsClassUtils.getPropertiesOfType(relatedClassType, getClazz()), mappingProperty); // If a property of the required type does not exist, search // for any collection properties on the related class. if (pd == null) pd = findProperty( GrailsClassUtils.getPropertiesAssignableToType(relatedClassType, Collection.class), mappingProperty); // We've run out of options. The given "mappedBy" // setting is invalid. boolean isNone = "none".equals(mappingProperty); if (pd == null && !isNone) { throw new GrailsDomainException( "Non-existent mapping property [" + mappingProperty + "] specified for property [" + property.getName() + "] in class [" + getClazz() + "]"); } else if (pd != null) { // Tie the properties together. relatedClassPropertyType = pd.getPropertyType(); property.setReferencePropertyName(pd.getName()); } } else { if (mappedBy.containsKey(property.getName()) && mappedBy.get(property.getName()) == null) return; // if the related type has a relationships map it may be a many-to-many // figure out if there is a many-to-many relationship defined if (isRelationshipManyToMany(property, relatedClassType, relatedClassRelationships)) { String relatedClassPropertyName = null; Map relatedClassMappedBy = GrailsDomainConfigurationUtil.getMappedByMap(relatedClassType); // retrieve the relationship property for (Object o : relatedClassRelationships.keySet()) { String currentKey = (String) o; String mappedByProperty = (String) relatedClassMappedBy.get(currentKey); if (mappedByProperty != null && !mappedByProperty.equals(property.getName())) continue; Class<?> currentClass = (Class<?>) relatedClassRelationships.get(currentKey); if (currentClass.isAssignableFrom(getClazz())) { relatedClassPropertyName = currentKey; break; } } // if there is one defined get the type if (relatedClassPropertyName != null) { relatedClassPropertyType = GrailsClassUtils.getPropertyType(relatedClassType, relatedClassPropertyName); } } // otherwise figure out if there is a one-to-many relationship by retrieving any properties that are of the related type // if there is more than one property then (for the moment) ignore the relationship if (relatedClassPropertyType == null) { PropertyDescriptor[] descriptors = GrailsClassUtils.getPropertiesOfType(relatedClassType, getClazz()); if (descriptors.length == 1) { relatedClassPropertyType = descriptors[0].getPropertyType(); property.setReferencePropertyName(descriptors[0].getName()); } else if (descriptors.length > 1) { // try now to use the class name by convention String classPropertyName = getPropertyName(); PropertyDescriptor pd = findProperty(descriptors, classPropertyName); if (pd == null) { throw new GrailsDomainException("Property [" + property.getName() + "] in class [" + getClazz() + "] is a bidirectional one-to-many with two possible properties on the inverse side. " + "Either name one of the properties on other side of the relationship [" + classPropertyName + "] or use the 'mappedBy' static to define the property " + "that the relationship is mapped with. Example: static mappedBy = [" + property.getName() + ":'myprop']"); } relatedClassPropertyType = pd.getPropertyType(); property.setReferencePropertyName(pd.getName()); } } } establishRelationshipForSetToType(property, relatedClassPropertyType); // if its a many-to-many figure out the owning side of the relationship if (property.isManyToMany()) { establishOwnerOfManyToMany(property, relatedClassType); } } // otherwise set it to not persistent as you can't persist // relationships to non-domain classes else { property.setBasicCollectionType(true); } } else if (!Map.class.isAssignableFrom(property.getType())) { // no relationship defined for set. // set not persistent property.setPersistent(false); } } /** * Finds a property type is an array of descriptors for the given property name * * @param descriptors The descriptors * @param propertyName The property name * @return The Class or null */ private PropertyDescriptor findProperty(PropertyDescriptor[] descriptors, String propertyName) { PropertyDescriptor d = null; for (PropertyDescriptor descriptor : descriptors) { if (descriptor.getName().equals(propertyName)) { d = descriptor; break; } } return d; } /** * Find out if the relationship is a many-to-many * * @param property The property * @param relatedClassType The related type * @param relatedClassRelationships The related types relationships * @return <code>true</code> if the relationship is a many-to-many */ private boolean isRelationshipManyToMany(DefaultGrailsDomainClassProperty property, Class<?> relatedClassType, Map relatedClassRelationships) { return relatedClassRelationships != null && !relatedClassRelationships.isEmpty() && !relatedClassType.equals(property.getDomainClass().getClazz()); } /** * Inspects a related classes' ownership settings against this properties class' ownership * settings to find out who owns a many-to-many relationship * * @param property The property * @param relatedClassType The related type */ @SuppressWarnings("unchecked") private void establishOwnerOfManyToMany(DefaultGrailsDomainClassProperty property, Class<?> relatedClassType) { ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(relatedClassType); Object relatedBelongsTo = cpf.getPropertyValue(GrailsDomainClassProperty.BELONGS_TO); boolean owningSide = false; boolean relatedOwner = isOwningSide(relatedClassType, owners); final Class<?> propertyClass = property.getDomainClass().getClazz(); if (relatedBelongsTo instanceof Collection) { final Collection associatedOwners = (Collection) relatedBelongsTo; owningSide = isOwningSide(propertyClass, associatedOwners); } else if (relatedBelongsTo instanceof Class) { final Collection associatedOwners = new ArrayList(); associatedOwners.add(relatedBelongsTo); owningSide = isOwningSide(propertyClass, associatedOwners); } property.setOwningSide(owningSide); if (relatedOwner && property.isOwningSide()) { throw new GrailsDomainException("Domain classes [" + propertyClass + "] and [" + relatedClassType + "] cannot own each other in a many-to-many relationship. Both contain belongsTo definitions that reference each other."); } if (!relatedOwner && !property.isOwningSide() && !(property.isCircular() && property.isManyToMany())) { throw new GrailsDomainException("No owner defined between domain classes [" + propertyClass + "] and [" + relatedClassType + "] in a many-to-many relationship. Example: static belongsTo = " + relatedClassType.getName()); } } private boolean isOwningSide(Class<?> relatedClassType, Collection<Class<?>> potentialOwners) { boolean relatedOwner = false; for (Class<?> relatedClass : potentialOwners) { if (relatedClass.isAssignableFrom(relatedClassType)) { relatedOwner = true; break; } } return relatedOwner; } /** * Establishes whether the relationship is a bi-directional or uni-directional one-to-many * and applies the appropriate settings to the specified property * * @param property The property to apply settings to * @param relatedClassPropertyType The related type */ private void establishRelationshipForSetToType(DefaultGrailsDomainClassProperty property, Class<?> relatedClassPropertyType) { if (relatedClassPropertyType == null) { // uni-directional one-to-many property.setOneToMany(true); property.setBidirectional(false); } else if (Collection.class.isAssignableFrom(relatedClassPropertyType) || Map.class.isAssignableFrom(relatedClassPropertyType)) { // many-to-many property.setManyToMany(true); property.setBidirectional(true); } else if (DomainClassArtefactHandler.isDomainClass(relatedClassPropertyType)) { // bi-directional one-to-many property.setOneToMany(true); property.setBidirectional(true); } } /** * Establish relationship with related domain class * * @param property Establishes a relationship between this class and the domain class property */ private void establishDomainClassRelationship(DefaultGrailsDomainClassProperty property) { Class<?> propType = property.getType(); if (embedded.contains(property.getName())) { property.setEmbedded(true); return; } // establish relationship to type Map relatedClassRelationships = GrailsDomainConfigurationUtil.getAssociationMap(propType); Map mappedBy = GrailsDomainConfigurationUtil.getMappedByMap(propType); Class<?> relatedClassPropertyType = null; if (mappedBy.containsKey(property.getName()) && mappedBy.get(property.getName()) == null) return; // if there is a relationships map use that to find out // whether it is mapped to a Set if (relatedClassRelationships != null && !relatedClassRelationships.isEmpty()) { String relatedClassPropertyName = findOneToManyThatMatchesType(property, relatedClassRelationships); PropertyDescriptor[] descriptors = GrailsClassUtils.getPropertiesOfType(getClazz(), property.getType()); // if there is only one property on many-to-one side of the relationship then // try to establish if it is bidirectional if (descriptors.length == 1 && isNotMappedToDifferentProperty(property, relatedClassPropertyName, mappedBy)) { if (!StringUtils.isBlank(relatedClassPropertyName)) { property.setReferencePropertyName(relatedClassPropertyName); // get the type of the property relatedClassPropertyType = GrailsClassUtils.getPropertyType(propType, relatedClassPropertyName); } } // if there is more than one property on the many-to-one side then we need to either // find out if there is a mappedBy property or whether a convention is used to decide // on the mapping property else if (descriptors.length > 1) { if (mappedBy.containsValue(property.getName())) { for (Object o : mappedBy.keySet()) { String mappedByPropertyName = (String) o; if (property.getName().equals(mappedBy.get(mappedByPropertyName))) { Class<?> mappedByRelatedType = (Class<?>) relatedClassRelationships .get(mappedByPropertyName); if (mappedByRelatedType != null && propType.isAssignableFrom(mappedByRelatedType)) relatedClassPropertyType = GrailsClassUtils.getPropertyType(propType, mappedByPropertyName); } } } else { String classNameAsProperty = GrailsNameUtils.getPropertyName(propType); if (property.getName().equals(classNameAsProperty) && !mappedBy.containsKey(relatedClassPropertyName)) { relatedClassPropertyType = GrailsClassUtils.getPropertyType(propType, relatedClassPropertyName); } } } } // otherwise retrieve all the properties of the type from the associated class if (relatedClassPropertyType == null) { PropertyDescriptor[] descriptors = GrailsClassUtils.getPropertiesOfType(propType, getClazz()); // if there is only one then the association is established if (descriptors.length == 1) { relatedClassPropertyType = descriptors[0].getPropertyType(); } } // establish relationship based on this type establishDomainClassRelationshipToType(property, relatedClassPropertyType); } private boolean isNotMappedToDifferentProperty(GrailsDomainClassProperty property, String relatedClassPropertyName, Map mappedBy) { String mappedByForRelation = (String) mappedBy.get(relatedClassPropertyName); if (mappedByForRelation == null) return true; if (!property.getName().equals(mappedByForRelation)) return false; return true; } private String findOneToManyThatMatchesType(DefaultGrailsDomainClassProperty property, Map relatedClassRelationships) { String relatedClassPropertyName = null; for (Object o : relatedClassRelationships.keySet()) { String currentKey = (String) o; Class<?> currentClass = (Class<?>) relatedClassRelationships.get(currentKey); if (property.getDomainClass().getClazz().getName().equals(currentClass.getName())) { relatedClassPropertyName = currentKey; break; } } return relatedClassPropertyName; } private void establishDomainClassRelationshipToType(DefaultGrailsDomainClassProperty property, Class<?> relatedClassPropertyType) { // uni-directional one-to-one if (relatedClassPropertyType == null) { if (hasOneMap.containsKey(property.getName())) { property.setHasOne(true); } property.setOneToOne(true); property.setBidirectional(false); } // bi-directional many-to-one else if (Collection.class.isAssignableFrom(relatedClassPropertyType) || Map.class.isAssignableFrom(relatedClassPropertyType)) { property.setManyToOne(true); property.setBidirectional(true); } // bi-directional one-to-one else if (DomainClassArtefactHandler.isDomainClass(relatedClassPropertyType)) { if (hasOneMap.containsKey(property.getName())) { property.setHasOne(true); } property.setOneToOne(true); if (!getClazz().equals(relatedClassPropertyType)) { property.setBidirectional(true); } } } public boolean isOwningClass(Class domainClass) { return owners.contains(domainClass); } /* (non-Javadoc) * @see org.codehaus.groovy.grails.domain.GrailsDomainClass#getProperties() */ public GrailsDomainClassProperty[] getProperties() { return properties; } /* (non-Javadoc) * @see org.codehaus.groovy.grails.domain.GrailsDomainClass#getIdentifier() */ public GrailsDomainClassProperty getIdentifier() { return identifier; } /* (non-Javadoc) * @see org.codehaus.groovy.grails.domain.GrailsDomainClass#getVersion() */ public GrailsDomainClassProperty getVersion() { return version; } /** * @see org.codehaus.groovy.grails.commons.GrailsDomainClass#getPersistantProperties() */ @Deprecated public GrailsDomainClassProperty[] getPersistantProperties() { return persistentProperties; } public GrailsDomainClassProperty[] getPersistentProperties() { return persistentProperties; } /* (non-Javadoc) * @see org.codehaus.groovy.grails.domain.GrailsDomainClass#getPropertyByName(java.lang.String) */ public GrailsDomainClassProperty getPropertyByName(String name) { GrailsDomainClassProperty persistentProperty = getPersistentProperty(name); if (persistentProperty == null) { throw new InvalidPropertyException( "No property found for name [" + name + "] for class [" + getClazz() + "]"); } return persistentProperty; } public GrailsDomainClassProperty getPersistentProperty(String name) { if (propertyMap.containsKey(name)) { return propertyMap.get(name); } int indexOfDot = name.indexOf('.'); if (indexOfDot > 0) { String basePropertyName = name.substring(0, indexOfDot); if (propertyMap.containsKey(basePropertyName)) { GrailsDomainClassProperty prop = propertyMap.get(basePropertyName); GrailsDomainClass referencedDomainClass = prop.getReferencedDomainClass(); if (referencedDomainClass != null) { String restOfPropertyName = name.substring(indexOfDot + 1); return referencedDomainClass.getPropertyByName(restOfPropertyName); } } } return null; } /* (non-Javadoc) * @see org.codehaus.groovy.grails.domain.GrailsDomainClass#getFieldName(java.lang.String) */ public String getFieldName(String propertyName) { return getPropertyByName(propertyName).getFieldName(); } /* (non-Javadoc) * @see org.codehaus.groovy.grails.commons.AbstractGrailsClass#getName() */ @Override public String getName() { return ClassUtils.getShortClassName(super.getName()); } /* (non-Javadoc) * @see org.codehaus.groovy.grails.domain.GrailsDomainClass#isOneToMany(java.lang.String) */ public boolean isOneToMany(String propertyName) { return getPropertyByName(propertyName).isOneToMany(); } /* (non-Javadoc) * @see org.codehaus.groovy.grails.domain.GrailsDomainClass#isManyToOne(java.lang.String) */ public boolean isManyToOne(String propertyName) { return getPropertyByName(propertyName).isManyToOne(); } /* (non-Javadoc) * @see org.codehaus.groovy.grails.commons.GrailsDomainClass#getRelationshipType(java.lang.String) */ public Class<?> getRelatedClassType(String propertyName) { return (Class<?>) relationshipMap.get(propertyName); } /* (non-Javadoc) * @see org.codehaus.groovy.grails.commons.GrailsDomainClass#getPropertyName() */ @Override public String getPropertyName() { return GrailsNameUtils.getPropertyNameRepresentation(getClazz()); } /* (non-Javadoc) * @see org.codehaus.groovy.grails.commons.GrailsDomainClass#isBidirectional() */ public boolean isBidirectional(String propertyName) { return getPropertyByName(propertyName).isBidirectional(); } /* (non-Javadoc) * @see org.codehaus.groovy.grails.commons.GrailsDomainClass#getConstraints() */ @SuppressWarnings("unchecked") public Map getConstrainedProperties() { if (constraints == null) { initializeConstraints(); } return Collections.unmodifiableMap(constraints); } private void initializeConstraints() { // process the constraints final ConstraintsEvaluator constraintsEvaluator = getConstraintsEvaluator(); constraints = constraintsEvaluator.evaluate(getClazz(), persistentProperties); } /* (non-Javadoc) * @see org.codehaus.groovy.grails.commons.GrailsDomainClass#getValidator() */ public Validator getValidator() { return validator; } /* (non-Javadoc) * @see org.codehaus.groovy.grails.commons.GrailsDomainClass#setValidator(Validator validator) */ public void setValidator(Validator validator) { this.validator = validator; } /* (non-Javadoc) * @see org.codehaus.groovy.grails.commons.GrailsDomainClass#getMappedBy() */ public String getMappingStrategy() { return mappingStrategy; } public boolean isRoot() { return root; } @SuppressWarnings("unchecked") public Set getSubClasses() { return subClasses; } public void refreshConstraints() { final ConstraintsEvaluator constraintEvaluator = getConstraintsEvaluator(); if (defaultConstraints != null) { constraints = constraintEvaluator.evaluate(getClazz(), persistentProperties); } else { constraints = constraintEvaluator.evaluate(getClazz(), persistentProperties); } // Embedded components have their own ComponentDomainClass instance which // won't be refreshed by the application. So, we have to do it here. for (GrailsDomainClassProperty property : persistentProperties) { if (property.isEmbedded()) { property.getComponent().refreshConstraints(); } } } ConstraintsEvaluator getConstraintsEvaluator() { if (grailsApplication != null && grailsApplication.getMainContext() != null) { final ApplicationContext context = grailsApplication.getMainContext(); if (context.containsBean(ConstraintsEvaluator.BEAN_NAME)) { return context.getBean(ConstraintsEvaluator.BEAN_NAME, ConstraintsEvaluator.class); } } return new DefaultConstraintEvaluator(defaultConstraints); } public Map getMappedBy() { return mappedBy; } public boolean hasPersistentProperty(String propertyName) { for (GrailsDomainClassProperty persistentProperty : persistentProperties) { if (persistentProperty.getName().equals(propertyName)) return true; } return false; } public void setMappingStrategy(String strategy) { mappingStrategy = strategy; } public void addComponent(GrailsDomainClass component) { components.add(component); } public List<GrailsDomainClass> getComponents() { return Collections.unmodifiableList(components); } public List<GrailsDomainClassProperty> getAssociations() { return associations; } }