FileDocCategorySizeDatePackage
ModelValidator.javaAPI DocGlassfish v2 API91137Fri May 04 22:34:44 BST 2007com.sun.jdo.api.persistence.model.util

ModelValidator

public class ModelValidator extends Object
author
Rochelle Raccah
version
%I%

Fields Summary
private com.sun.jdo.api.persistence.model.Model
_model
This field holds the model object used for validation
private String
_className
This field holds the name of the class being validated
private ClassLoader
_classLoader
This field holds the class loader used to load class being validated (if available).
private ResourceBundle
_messages
I18N message handler
Constructors Summary
public ModelValidator(com.sun.jdo.api.persistence.model.Model model, String className, ResourceBundle bundle)

		this(model, className, null, bundle);
	
public ModelValidator(com.sun.jdo.api.persistence.model.Model model, String className, ClassLoader classLoader, ResourceBundle bundle)
Create a new model validator object.

param
model model object used for validation
param
className the name of the class being validated

		_model = model;
		_className = className;
		_classLoader = classLoader;
		_messages = bundle;
	
Methods Summary
private ModelValidationExceptionconstructClassException(java.lang.String className, java.lang.Object relatedField, java.lang.String keyBase)
Constructs a ModelValidationException for class validation tests using the supplied class name, related field, and key base.

param
className the name of the class which caused the problem
param
field the field object which caused the problem - may be null
param
keyBase the base key to be used for the i18n string
return
the ModelValidationException
see
#getOffendingObject
see
#getKey
see
#getArguments
see
#constructFieldException

		return constructClassException(ModelValidationException.ERROR, 
			className, relatedField, keyBase);
	
private ModelValidationExceptionconstructClassException(int errorType, java.lang.String className, java.lang.Object relatedField, java.lang.String keyBase)
Constructs a ModelValidationException for class validation tests using the supplied class name, related field, and key base.

param
errorType the type of error -- one of {@link ModelValidationException#ERROR} or {@link ModelValidationException#WARNING}.
param
className the name of the class which caused the problem
param
field the field object which caused the problem - may be null
param
keyBase the base key to be used for the i18n string
return
the ModelValidationException
see
#getOffendingObject
see
#getKey
see
#getArguments
see
#constructFieldException

		return new ModelValidationException(errorType, 
			getOffendingObject(relatedField), I18NHelper.getMessage(
			getMessages(), getKey(keyBase, relatedField), 
			getArguments(className, relatedField)));
	
private ModelValidationExceptionconstructFieldException(java.lang.String fieldName, java.lang.String key)
Constructs a ModelValidationException for field validation tests using the supplied field name and key.

param
fieldName the name of the field which caused the problem
param
keyBase the base key to be used for the i18n string
return
the ModelValidationException
see
#constructClassException

		return constructFieldException(ModelValidationException.ERROR, 
			fieldName, key);
	
private ModelValidationExceptionconstructFieldException(int errorType, java.lang.String fieldName, java.lang.String key)
Constructs a ModelValidationException for field validation tests using the supplied field name and key.

param
errorType the type of error -- one of {@link ModelValidationException#ERROR} or {@link ModelValidationException#WARNING}.
param
fieldName the name of the field which caused the problem
param
keyBase the base key to be used for the i18n string
return
the ModelValidationException
see
#constructClassException

		return new ModelValidationException(errorType, 
			getModel().getField(getClassName(), fieldName), 
			I18NHelper.getMessage(getMessages(), key, fieldName));
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateClassExistenceComponent(java.lang.String className, PersistenceFieldElement relatedField)
Create a validation component which can check whether the class exists.

param
className the class whose existence is being checked
param
relatedField the relationship field whose class is being checked, may be null in which case we are probably checking the same class as the validator is checking overall
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				if ((className == null) || 
					!getModel().hasClass(className, getClassLoader()))
				{
					throw constructClassException(className, relatedField, 
						"util.validation.class_not_found");		//NOI18N
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateClassExistenceComponent(java.lang.String className)
Create a validation component which can check whether the class exists.

param
className the class whose existence is being checked
return
the validation component

		return createClassExistenceComponent(className, null);
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateClassMappingComponent(PersistenceClassElement persistenceClass)
Create a validation component which can check whether the class is unmapped.

param
persistenceClass the class whose mapping is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				PersistenceFieldElement[] fields = persistenceClass.getFields();
				String className = getClassName();

				if ((fields == null) || fields.length == 0)
				{
					throw constructClassException(
						ModelValidationException.WARNING, className, null, 
						"util.validation.class_no_fields");		//NOI18N
				}
				else	// has fields, check for primary table
				{
					MappingClassElement mappingClass = 
						getMappingClass(className);

					if ((mappingClass == null) || 
						(mappingClass.getTables().size() == 0))
					{
						throw constructClassException(
							ModelValidationException.WARNING, className, null, 
							"util.validation.class_not_mapped");		//NOI18N
					}
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateClassPersistenceComponent(java.lang.String className, PersistenceFieldElement relatedField)
Create a validation component which can check the class persistence.

param
className the class whose persistence is being checked
param
relatedField the relationship field whose class is being checked, may be null in which case we are probably checking the same class as the validator is checking overall
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				Model model = getModel();
	
				if ((className != null) && 
					 model.hasClass(className, getClassLoader()))
				{
					String key = null;

					if (!isPersistent(className))
						key = "util.validation.class_not_persistence_capable";//NOI18N
					else if (!model.isPersistenceCapableAllowed(className))
						key = "util.validation.class_not_allowed";//NOI18N

					if (key != null)
					{
						throw constructClassException(
							className, relatedField, key);
					}
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateClassPersistenceComponent(java.lang.String className)
Create a validation component which can check the class persistence.

param
className the class whose persistence is being checked
return
the validation component

		return createClassPersistenceComponent(className, null);
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateCollectionClassComponent(RelationshipElement field)
Create a validation component which can check whether the collection class is valid given the relationship field type.

param
field the relationship whose collection class is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				String className = getClassName();
				String fieldName = field.getName();

				if (isCollection(className, fieldName))
				{
					Model model = getModel();
					String collectionClass = field.getCollectionClass();
					String fieldType = model.getFieldType(className, fieldName);
					boolean missingCollectionClass = 
						StringHelper.isEmpty(collectionClass);

					if (!missingCollectionClass && 
						!model.getSupportedCollectionClasses(fieldType).
						contains(collectionClass))
					{
						throw constructFieldException(fieldName, 
							"util.validation.collection_class_invalid");//NOI18N
					}
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateColumnExistenceComponent(java.lang.String columnName)
Create a validation component which can check whether the given column exists.

param
columnName the column whose existence is being checked
return
the validation component

		return createColumnExistenceComponent(columnName, null);
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateColumnExistenceComponent(java.lang.String columnName, MappingFieldElement relatedField)
Create a validation component which can check whether the given column or column pair exists.

param
columnName the column or pair whose existence is being checked
param
relatedField the field whose class' column is being checked, may be null in which case we are probably checking the same secondary table setup
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				if (columnName != null)
				{
					String className = getClassName();
					String absoluteName = NameUtil.getAbsoluteMemberName(
						getSchemaForClass(className), columnName);
					TableElement table = TableElement.forName(
						NameUtil.getTableName(absoluteName));
					boolean foundTable = (table != null);
					DBMemberElement columnElement = ((foundTable) ? 
						table.getMember(DBIdentifier.create(absoluteName)) :
						null);
					boolean noRelated = (relatedField == null);

					if (foundTable)
					{
						boolean isRelationship = 
							(!noRelated && isRelationship(relatedField));
						boolean noColumn = (columnElement == null);

						if (!isRelationship && noColumn)
						{
							Object[] args = (noRelated) ? 
								new Object[]{columnName, className} : 
								new Object[]{columnName, relatedField, 
								className};

							throw new ModelValidationException(
								ModelValidationException.WARNING, 
								getOffendingObject(relatedField),
								I18NHelper.getMessage(getMessages(), getKey(
									"util.validation.column_not_found", //NOI18N
									relatedField), args));
						}
						else if (isRelationship && 
							(noColumn || !isPairComplete(columnElement)))
						{
							throw new ModelValidationException(
								ModelValidationException.WARNING, 
								getOffendingObject(relatedField),
								I18NHelper.getMessage(getMessages(), 
									"util.validation.column_invalid", //NOI18N
									new Object[]{columnName, relatedField, 
									className}));
						}
					}
				}
			}
			private boolean isPairComplete (DBMemberElement member)
			{
				return ((member instanceof ColumnPairElement) &&  
					(((ColumnPairElement)member).getLocalColumn() != null) && 
					(((ColumnPairElement)member).getReferencedColumn() 
					!= null));
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateColumnOverlapComponent(MappingFieldElement field)
Create a validation component which can check whether the field is one of a set mapped to overlapping columns

param
field the field whose column mapping is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				MappingClassElement mappingClass = field.getDeclaringClass();
				Iterator iterator = mappingClass.getFields().iterator();
				ArrayList myColumns = field.getColumns();

				while (iterator.hasNext())
				{
					MappingFieldElement testField =
						(MappingFieldElement)iterator.next();

					if (!testField.equals(field) && !isRelationship(testField) 
						&& isPartialMatch(myColumns, testField.getColumns()))
					{
						String fieldName = field.getName();

						throw new ModelValidationException(getModel().getField(
							getClassName(), fieldName), 
							I18NHelper.getMessage(getMessages(), 
							"util.validation.field_mapping_invalid", //NOI18N
							new Object[]{fieldName, testField.getName()}));
					}
				}
			}
			private boolean isPartialMatch (ArrayList columns1, 
				ArrayList columns2)
			{
				int count = columns1.size();

				if (count > 0)
				{
					ArrayList difference = getDifference(columns1, columns2);

					return (!difference.isEmpty() && 
						(columns2.size() != difference.size()));
				}

				return false;
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateElementClassComponent(RelationshipElement field)
Create a validation component which can check whether the relationship is mapped to columns even though the element class is null.

param
field the relationship whose element class is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				String className = getClassName();
				String fieldName = field.getName();

				if (isCollection(className, fieldName))
				{
					String elementClass = field.getElementClass();

					if (StringHelper.isEmpty(elementClass))
					{
						MappingClassElement mappingClass = 
							getMappingClass(className);
						MappingFieldElement mappingElement = 
							((mappingClass != null) ? 
							mappingClass.getField(fieldName) : null);

						if ((mappingElement != null) && 
							(mappingElement.getColumns().size() > 0))
						{
							throw constructFieldException(fieldName, 
								"util.validation.element_class_not_found");//NOI18N
						}
					}
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateFieldBlobMappingComponent(PersistenceFieldElement field)
Create a validation component which can check whether the field is mapped to a blob type and if so, whether it is a key field or belongs to the default fetch group. Note that it's somewhat important to check for the key field first because if a field is key, its fetch group value in the model is ignored.

param
field the field whose mapping/key field/fetch group consistency is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				String className = getClassName();
				String fieldName = field.getName();
				MappingClassElement mappingClass = getMappingClass(className);
				MappingFieldElement mappingField = ((mappingClass != null) ? 
					mappingClass.getField(fieldName) : null);

				if (mappingField != null)
				{
					boolean isKey = field.isKey();

 					if (isKey || (MappingFieldElement.GROUP_DEFAULT == 
						mappingField.getFetchGroup()))
					{
						if (isMappedToBlob(mappingField, 
							getSchemaForClass(className)))
						{
							throw constructFieldException(fieldName, (isKey ? 
								"util.validation.field_key_field_not_allowed" : //NOI18N
								"util.validation.field_fetch_group_not_allowed")); // NOI18N
						}
					}
				}
			}
			private boolean isMappedToBlob (MappingFieldElement mappingField, 
				String schema)
			{
				if (mappingField instanceof MappingRelationshipElement)
				{
					return isMappedToBlob(
						(MappingRelationshipElement)mappingField, schema);
				}
				else
				{
					Iterator iterator = mappingField.getColumns().iterator();

					while (iterator.hasNext())
					{
						String absoluteName = NameUtil.getAbsoluteMemberName(
							schema, (String)iterator.next());
						TableElement table = TableElement.forName(
							NameUtil.getTableName(absoluteName));
						ColumnElement columnElement = ((table != null) ?
							(ColumnElement)table.getMember(
							DBIdentifier.create(absoluteName)) : null);

						if (isMappedToBlob(columnElement))
							return true;
					}
				}

				return false;
			}
			private boolean isMappedToBlob (MappingRelationshipElement rel, 
				String schema)
			{
				Iterator iterator = rel.getColumns().iterator();

				while (iterator.hasNext())
				{
					ColumnPairElement pair = 
						getPair((String)iterator.next(), schema);

					if (isMappedToBlob(pair))
						return true;
				}

				// now check join columns
				iterator = rel.getAssociatedColumns().iterator();
				while (iterator.hasNext())
				{
					ColumnPairElement pair = 
						getPair((String)iterator.next(), schema);

					if (isMappedToBlob(pair))
						return true;
				}

				return false;
			}
			private boolean isMappedToBlob (ColumnPairElement pair)
			{
				return ((pair == null) ? false : 
					isMappedToBlob(pair.getLocalColumn()) && 
					isMappedToBlob(pair.getReferencedColumn()));
			}
			private boolean isMappedToBlob (ColumnElement column)
			{
				return ((column != null) && 
					SQLTypeUtil.isBlob(column.getType()));
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateFieldCardinalityComponent(PersistenceFieldElement field)
Create a validation component which can check whether the cardinality bounds are semantically valid given the relationship field type.

param
field the relationship whose cardinality bounds are being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				if (isLegalRelationship(field))
				{
					RelationshipElement relationship =
						(RelationshipElement)field;
					String fieldName = field.getName();
					boolean nonCollectionRelationship = 
						!isCollection(getClassName(), fieldName);
					int upperBound = (nonCollectionRelationship ?
						1 : relationship.getUpperBound());
					int lowerBound = relationship.getLowerBound();
					MappingRelationshipElement mapping = null;

					if ((lowerBound < 0) || (upperBound <= 0) || 
						(lowerBound > upperBound))
					{
						throw constructFieldException(fieldName, 
							"util.validation.cardinality_invalid");	//NOI18N
					}

					// now check specific lower bound requirements imposed
					// by the mapping
					mapping = getMappingRelationship(relationship);
					if (nonCollectionRelationship && (lowerBound != 1) && 
						(mapping != null) && !isJoin(mapping))
					{
						// If the non-collection relationship field is exactly
						// mapped to a FK, we need to check the nullability
						// of the columns. If there are any non-nullable
						// columns the lower bound must be 1.
						ForeignKeyElement fk = getMatchingFK(mapping);

						if ((fk != null) && hasNonNullableColumn(fk))
						{
							throw constructFieldException(fieldName,
								"util.validation.lower_bound_invalid"); //NOI18N
						}
					}
				}
			}

			/** Returns <code>true</code> if the specified FK has at least
			 * one non-nullable column. Please note that the caller is
			 * responsible for passing a non-null fk argument.
			 */
			private boolean hasNonNullableColumn (ForeignKeyElement fk)
			{
				ColumnElement[] localColumns = fk.getLocalColumns();
				int count = ((localColumns != null) ? localColumns.length : 0);
				
				for (int i = 0; i < count; i++)
				{
					if (!localColumns[i].isNullable())
						return true;
				}

				return false;
			}

			/** Checks whether the specified relationship is exactly mapped
			 * to a FK. If yes, the method returns the matching FK. If not, 
			 * it returns <code>null</code>. Please note that the caller is
			 * responsible for passing a non-null mapping argument.
			 */
 			private ForeignKeyElement getMatchingFK (
				MappingRelationshipElement mapping)
			{
				MappingClassElement mappingClass = mapping.
					getDeclaringClass();
				String databaseRoot = getSchemaForClass(getClassName());
				List pairNames = mapping.getColumns();
				List tables = mappingClass.getTables();
					
				if (tables != null)
				{
					for (Iterator i = tables.iterator(); i.hasNext();)
					{
						String tableName = ((MappingTableElement)i.next()).
							getName();
						TableElement table = getTable(tableName, databaseRoot);
						ForeignKeyElement fk = getMatchingFK(pairNames, table);
						
						if (fk != null)
							return fk;
					}
				}

				return null;
			}

			/** Checks whether the specified TableElement has a FK that
			 * exactly matches the list of column pair names. 
			 * @return the matching FK if it exactly matches the list 
			 * of column pairs; <code>null</code> otherwise. 
			 */
			private ForeignKeyElement getMatchingFK (List pairNames, 
				TableElement table)
			{
				ForeignKeyElement[] foreignKeys = (table != null) ? 
					table.getForeignKeys() : null;
				int count = ((foreignKeys != null) ? foreignKeys.length : 0);

				for (int i = 0; i < count; i++)
				{
					if (matchesFK(pairNames, foreignKeys[i]))
						return foreignKeys[i];
				}

				return null;
			}

			/** Returns <code>true</code> if the specified list of column
			 * pair names matches exactly the specified FK. 
			 */
			private boolean matchesFK (List pairNames, 
				ForeignKeyElement foreignKey)
			{
				ColumnPairElement[] fkPairs = foreignKey.getColumnPairs();
				int fkCount = ((fkPairs != null) ? fkPairs.length : 0);
				int count = ((pairNames != null) ? pairNames.size() : 0);

				// First check whether the list of fk column pairs has the 
				// same size than the specified list of columns.
				if (fkCount == count) 
				{
					// Now check whether each fk column is included in the
					// specified list of columns.
					for (int i = 0; i < fkCount; i++)
					{
						String fkPairName = NameUtil.getRelativeMemberName(
							fkPairs[i].getName().getFullName());

						if (!pairNames.contains(fkPairName))
							return false;
					}

					return true;
				}

				return false;
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateFieldConsistencyComponent(PersistenceFieldElement field)
Create a validation component which can check whether the field is consistent (field in both models or relationship in both).

param
field the field whose consistency is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				String fieldName = field.getName();
				String className = getClassName();
				boolean isLegallyPersistent = 
					isPersistentAllowed(className, fieldName);

				if (isLegallyPersistent)
				{
					MappingClassElement mappingClass = 
						getMappingClass(className);
					MappingFieldElement mappingElement = 
						((mappingClass != null) ? 
						mappingClass.getField(fieldName) : null);

					if (mappingElement != null)
					{
						boolean jdoIsRelationship = isLegalRelationship(field);

						if (jdoIsRelationship != isRelationship(mappingElement))
						{
							throw constructFieldException(fieldName, 
								"util.validation.field_type_inconsistent");	//NOI18N
						}
					}
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateFieldConsistencyComponent(MappingFieldElement field)
Create a validation component which can check whether the field is consistent (if in mapping model but not jdo, it is a problem).

param
field the field whose consistency is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				if (field != null)
				{
					String fieldName = field.getName();
					PersistenceClassElement persistenceClass = 
						getPersistenceClass(getClassName());
					PersistenceFieldElement persistenceElement = 
						((persistenceClass != null) ? 
						persistenceClass.getField(fieldName) : null);

					if (persistenceElement == null)
					{
						throw constructFieldException(fieldName, 
							"util.validation.field_model_inconsistent");//NOI18N
					}
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateFieldDefaultFetchGroupComponent(MappingFieldElement field)
Create a validation component which can check whether the field is part of a managed (multiple fields to same column) group and in an illegal fetch group. If the field is in one of these groups, it is not allowed to be in the default fetch group.

param
field the field whose fetch group is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				if (field != null)
				{
					String fieldName = field.getName();
					PersistenceClassElement persistenceClass = 
						getPersistenceClass(getClassName());
					PersistenceFieldElement pElement = 
						((persistenceClass != null) ? 
						persistenceClass.getField(fieldName) : null);

					if ((pElement != null) && !pElement.isKey() && 
						(MappingFieldElement.GROUP_DEFAULT == 
						field.getFetchGroup()))
					{
						MappingClassElement mappingClass = 
							field.getDeclaringClass();
						boolean isVersionField = 
							((MappingClassElement.VERSION_CONSISTENCY == 
								mappingClass.getConsistencyLevel()) &&
								field.isVersion());
						Iterator iterator = mappingClass.getFields().iterator();
						String exceptionKey = (!isVersionField ?
							"util.validation.field_fetch_group_invalid"://NOI18N
							"util.validation.version_field_column_invalid");//NOI18N

						/* rules: 
						 *	primitive, primitive -> error if exact match of 
						 *		columns
						 *	primitive, relationship OR
						 *	relationship, primitive -> error if non-collection
						 *		relationship and none of the relationship's 
						 *		columns are PK columns and any are present in 
						 *		the primitive's list
						 *	relationship, relationship -> error if exact 
						 *		match of mapping (local, join, associated), 
						 *		but order is not important
						 */
						while (iterator.hasNext())
						{
							MappingFieldElement testField =
								(MappingFieldElement)iterator.next();

							if (isManaged(field, testField) || 
								isManaged(testField, field))
							{
								throw constructFieldException(
									fieldName, exceptionKey);
							}
							else if (!testField.equals(field) && isExactMatch(
								field, testField))
							{
								throw constructFieldException(
									fieldName, exceptionKey);
							}
						}
					}
				}
			}
			private boolean isManaged (MappingFieldElement primField, 
				MappingFieldElement relField)				
			{
				String className = getClassName();

				if (!isRelationship(primField) && isRelationship(relField) && 
					!isCollection(className, relField.getName()))
				{
					ArrayList columns = primField.getColumns();
					Iterator iterator = relField.getColumns().iterator();
					String databaseRoot = getSchemaForClass(className);

					while (iterator.hasNext())
					{
						if (!testColumn(getLocalColumn((String)iterator.next(), 
							databaseRoot), columns))
						{
							return true;
						}
					}
				}

				return false;
			}
			private boolean testColumn (ColumnElement column, 
				ArrayList masterList)
			{
				if ((column != null) && !isPrimaryKeyColumn(column))
				{
					return !masterList.contains(NameUtil.
						getRelativeMemberName(column.getName().getFullName()));
				}

				return true;
			}
			private ColumnElement getLocalColumn (String pairName, 
				String databaseRoot)
			{
				ColumnPairElement pair = getPair(pairName, databaseRoot);

				return ((pair != null) ? pair.getLocalColumn() : null);
			}
			private boolean isPrimaryKeyColumn (ColumnElement column)
			{
				if (column != null)
				{
					KeyElement key = column.getDeclaringTable().getPrimaryKey();

					return ((key != null) && 
						(key.getColumn(column.getName()) != null));
				}

				return false;
			}
			private boolean isExactMatch (ArrayList columns1, 
				ArrayList columns2)
			{
				int count = columns1.size();

				if ((count > 0) && (count == columns2.size()))
					return getDifference(columns1, columns2).isEmpty();

				return false;
			}
			private boolean isExactMatch (MappingFieldElement field1, 
				MappingFieldElement field2)
			{
				boolean field1IsRel = isRelationship(field1);
				boolean match = false;

				// both primitives, or both relationships
				if (field1IsRel == isRelationship(field2))
				{
					match = isExactMatch(field1.getColumns(), 
						field2.getColumns());

					if (match && field1IsRel)
					{
						MappingRelationshipElement rel1 =
							(MappingRelationshipElement)field1;
						MappingRelationshipElement rel2 =
							(MappingRelationshipElement)field2;
						boolean field1IsJoin = isJoin(rel1);

						// both join relationships or both direct
						if (field1IsJoin == isJoin(rel2))
						{
							if (field1IsJoin)
							{
								match = isExactMatch(
									rel1.getAssociatedColumns(), 
									rel2.getAssociatedColumns());
							}
						}
						else
							match = false;
					}
				}
				
				return match;
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateFieldExistenceComponent(java.lang.String fieldName)
Create a validation component which can check whether the field exists.

param
fieldName the field whose existence is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				if (!getModel().hasField(getClassName(), fieldName))
				{
					throw constructFieldException(fieldName, 
						"util.validation.field_not_found");			//NOI18N
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateFieldExistenceComponent(java.lang.Object field)
Create a validation component which can check whether the field exists.

param
field the field whose existence is being checked
return
the validation component

		return createFieldExistenceComponent(field.toString());
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateFieldMappingComponent(PersistenceFieldElement field)
Create a validation component which can check whether the field is unmapped.

param
field the field whose mapping is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				String fieldName = field.getName();
				MappingClassElement mappingClass = 
					getMappingClass(getClassName());
 
				if ((mappingClass != null) && 
					(mappingClass.getTables().size() > 0))
				{
					MappingFieldElement mappingField = 
						mappingClass.getField(fieldName);

					if ((mappingField == null) || 
						(mappingField.getColumns().size() == 0))
					{
						throw constructFieldException(
							ModelValidationException.WARNING, fieldName, 
							"util.validation.field_not_mapped");	//NOI18N
					}
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateFieldPersistenceComponent(PersistenceFieldElement field)
Create a validation component which can check whether the field is persistent.

param
field the field whose persistence is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				boolean isPersistent = (PersistenceFieldElement.PERSISTENT == 
					field.getPersistenceType());
				String fieldName = field.getName();

				if (isPersistent && 
					!isPersistentAllowed(getClassName(), fieldName))
				{
					throw constructFieldException(fieldName, 
						"util.validation.field_persistent_not_allowed");//NOI18N
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateFieldPersistenceTypeComponent(PersistenceFieldElement field)
Create a validation component which can check the persistence type of the field (whether it is a relationship or not).

param
field the field whose persistence type is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				String fieldName = field.getName();
				String className = getClassName();
				boolean isLegallyPersistent = 
					isPersistentAllowed(className, fieldName);

				if (isLegallyPersistent)
				{
					boolean isRelationship = isRelationship(field);
					boolean mustBeRelationship = shouldBeRelationship(field);

					if (isRelationship && !mustBeRelationship)
					{
						throw constructFieldException(fieldName, 
							"util.validation.field_relationship_not_allowed");//NOI18N
					}
					else if (!isRelationship && mustBeRelationship)
					{
						throw constructFieldException(fieldName, 
							"util.validation.field_type_not_allowed");	//NOI18N
					}
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateInverseFieldComponent(RelationshipElement field)
Create a validation component which can check whether the inverse of the inverse of the relationship is the relationship itself.

param
field the relationship whose inverse relationship is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				Model model = getModel();
				RelationshipElement inverse = 
					field.getInverseRelationship(model);
				RelationshipElement inverseInverse = ((inverse != null) ? 
					inverse.getInverseRelationship(model) : null);

				if ((inverse != null) && 
					(!field.equals(inverseInverse) || (inverseInverse == null)))
				{
					String fieldName = field.getName();

					throw new ModelValidationException(
						model.getField(getClassName(), fieldName), 
						I18NHelper.getMessage(getMessages(), 
						"util.validation.inverse_field_invalid", //NOI18N
						new Object[]{fieldName, inverse.getName()}));
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateInverseMappingComponent(RelationshipElement field)
Create a validation component which can check whether the mapping of the relationship and the mapping of its inverse are inverses of each other.

param
field the relationship whose inverse relationship is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				Model model = getModel();
				RelationshipElement inverse = 
					field.getInverseRelationship(model);

				if ((inverse != null) && !isInverseMapping(field, inverse))
				{
					String fieldName = field.getName();

					throw new ModelValidationException(
						model.getField(getClassName(), fieldName), 
						I18NHelper.getMessage(getMessages(), 
						"util.validation.inverse_mapping_mismatch", //NOI18N
						new Object[]{fieldName, inverse.getName()}));
				}
			}
			private boolean hasMappingRows (MappingRelationshipElement field2)
			{
				if (field2 != null)
				{
					ArrayList columns = field2.getColumns();
					
					return ((columns != null) && !columns.isEmpty());
				}

				return false;
			}
			private boolean isInverseMapping (RelationshipElement jdoField1,
				RelationshipElement jdoField2)
			{
				MappingRelationshipElement field1 = 
					getMappingRelationship(jdoField1);
				MappingRelationshipElement field2 = 
					getMappingRelationship(jdoField2);
				boolean field1HasMapping = hasMappingRows(field1);
				boolean field2HasMapping = hasMappingRows(field2);

				// if both have rows, they must be exact inverses
				if (field1HasMapping && field2HasMapping)
				{
					boolean field1IsJoin = isJoin(field1);

					if (field1IsJoin == isJoin(field2))
					{
						ArrayList pairs1 = field1.getColumns();
						ArrayList pairs2 = field2.getColumns();

						return ((!field1IsJoin) ? isInverse(pairs1, pairs2) :
							(isInverse(pairs1, 
							field2.getAssociatedColumns()) && 
							isInverse(field1.getAssociatedColumns(), pairs2)));
					}

					return false;
				}

				// if neither have rows that's fine
				return (field1HasMapping == field2HasMapping);
			}
			private boolean isInverse (ArrayList pairs1, ArrayList pairs2)
			{
				int i, size1 = pairs1.size(), size2 = pairs2.size();

				if (size1 == size2)
				{
					for (i = 0; i < size1; i++)
					{
						String nextPair = (String)pairs1.get(i);
						String inversePair = (String)pairs2.get(i);
						int semicolonIndex1 = nextPair.indexOf(';");
						int semicolonIndex2 = inversePair.indexOf(';");

						if (((semicolonIndex1 == -1) || (semicolonIndex2 == -1))
							|| (!nextPair.substring(0, semicolonIndex1).equals(
							inversePair.substring(semicolonIndex2 + 1)) || 
							!nextPair.substring(semicolonIndex1 + 1).equals(
							inversePair.substring(0, semicolonIndex2))))
						{
							return false;
						}
					}

					return true;
				}

				return false;
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateKeyClassComponent(java.lang.String className)
Create a validation component which can check whether the key class of the persistence capable class is valid. This includes:
  • The key class must be public.
  • The key class must implement Serializable.
  • If the key class is an inner class, it must be static.
  • The key class must have a public constructor, which might be the default constructor or a no-arg constructor.
  • The field types of all non-static fields in the key class must be of valid types.
  • All serializable non-static fields in the key class must be public.
  • The names of the non-static fields in the key class must include the names of the primary key fields in the JDO class, and the types of the common fields must be identical
  • The key class must redefine equals and hashCode.

		return new ValidationComponent ()
		{
			/** The class element of the key class */
			private Object keyClass;

			/** The fully qualified name of the key class */
			private String keyClassName;

			public void validate () throws ModelValidationException
			{
				// checks the key class name
				keyClassName = validateKeyClassName(className);
				// initilialize keyClass field 
				keyClass = getModel().getClass(keyClassName, getClassLoader());
				validateClass();
				validateConstructor();
				validateFields();
				validateMethods();
			}

			/** Helper method validating the key class itself: 
			 * public, serializable, static.
			 */
			private void validateClass () throws ModelValidationException
			{
				Model model = getModel();
				int modifiers = model.getModifiersForClass(keyClassName);
				boolean hasKeyClassName = !StringHelper.isEmpty(keyClassName);
				boolean isInnerClass = 
					(hasKeyClassName && (keyClassName.indexOf('$") != -1));
				String pcClassName = getClassName();

				// check for key class existence
				if (keyClass == null)
				{
					throw new ModelValidationException(
						ModelValidationException.WARNING,
						model.getClass(pcClassName),
						I18NHelper.getMessage(getMessages(), 
						"util.validation.key_class_missing", //NOI18N
						keyClassName, pcClassName));
				}

				// check for public class modifier
				if (!Modifier.isPublic(modifiers))
				{
					throw new ModelValidationException(keyClass,
						I18NHelper.getMessage(getMessages(), 
						"util.validation.key_class_public", //NOI18N
						keyClassName, pcClassName));
				}
				
				// check for Serializable
				/* This check is disabled because of Boston backward 
				   compatibility. In Boston there was no requirement for a 
				   key class being serializable, thus key classes from pc 
				   classes mapped with boston are not serializable.

				if (!model.implementsInterface(keyClass, 
					"java.io.Serializable")) //NOI18N
				{
					throw new ModelValidationException(keyClass,
						I18NHelper.getMessage(getMessages(), 
						"util.validation.key_class_serializable", //NOI18N
						keyClassName, pcClassName));
				}
				*/

				// if inner class it must be static
				if (isInnerClass && !Modifier.isStatic(modifiers))
				{
					throw new ModelValidationException(keyClass,
						I18NHelper.getMessage(getMessages(), 
						"util.validation.key_class_static", //NOI18N
						keyClassName, pcClassName));
				}
			}

			/** Helper method validating the fields of the key class.
			 */
			private void validateFields () throws ModelValidationException
			{
				String pcClassName = getClassName();
				Model model = getModel();
				// check for valid typed public non-static fields
				List keyClassFieldNames = model.getAllFields(keyClassName);
				Map keyFields = getKeyFields();

				for (Iterator i = keyClassFieldNames.iterator(); i.hasNext();)
				{
					String keyClassFieldName = (String)i.next();
					Object keyClassField = 
						getKeyClassField(keyClassName, keyClassFieldName);
					int keyClassFieldModifiers = 
						model.getModifiers(keyClassField);
					String keyClassFieldType = model.getType(keyClassField);
					Object keyField = keyFields.get(keyClassFieldName);

					if (Modifier.isStatic(keyClassFieldModifiers))
						// we are not interested in static fields
						continue;

					if (!model.isValidKeyType(keyClassName, keyClassFieldName))
					{
						throw new ModelValidationException(keyClassField,
							I18NHelper.getMessage(getMessages(), 
							"util.validation.key_field_type_invalid", //NOI18N
							keyClassFieldName, keyClassName));
					}
					
					if (!Modifier.isPublic(keyClassFieldModifiers))
					{
						throw new ModelValidationException(keyClassField,
							I18NHelper.getMessage(getMessages(), 
							"util.validation.key_field_public", //NOI18N
							keyClassFieldName, keyClassName));
					}

					if (keyField == null)
						continue;
					
					if (!keyClassFieldType.equals(model.getType(keyField)))
					{
						throw new ModelValidationException(keyClassField,
							I18NHelper.getMessage(getMessages(), 
							"util.validation.key_field_type_mismatch", //NOI18N
							keyClassFieldName, keyClassName, pcClassName));
					}

					// remove handled keyField from the list of keyFields
					keyFields.remove(keyClassFieldName);
				}

				// check whether there are any unhandled key fields
				if (!keyFields.isEmpty())
				{
					Object pcClass = model.getClass(pcClassName);
					String fieldNames = StringHelper.arrayToSeparatedList(
						new ArrayList(keyFields.keySet()));

					throw new ModelValidationException(pcClass,
						I18NHelper.getMessage(getMessages(), 
						"util.validation.key_field_missing", //NOI18N
						pcClassName, keyClassName, fieldNames));
				}
			}

			/** Helper method validating the key class constructors.
			 */
			private void validateConstructor () throws ModelValidationException
			{
				// no constructor or no arg constructor
				Model model = getModel();
				boolean hasConstr = model.hasConstructor(keyClassName);
				Object noArgConstr = 
					model.getConstructor(keyClassName, Model.NO_ARGS);
				int modifiers = model.getModifiers(noArgConstr);

				if (hasConstr && 
					((noArgConstr == null) || !Modifier.isPublic(modifiers)))
				{
					throw new ModelValidationException(keyClass,
						I18NHelper.getMessage(getMessages(), 
						"util.validation.key_class_constructor", //NOI18N
						keyClassName, getClassName()));
				}
			}

			/** Helper method validating the key class methods.
			 */
			private void validateMethods () throws ModelValidationException
			{
				Model model = getModel();
				Object equalsMethod = getNonObjectMethod(keyClassName, 
					"equals", Model.EQUALS_ARGS); //NOI18N
				Object hashCodeMethod = getNonObjectMethod(keyClassName, 
					"hashCode", Model.NO_ARGS); //NOI18N

				// check equals method
				if (!matchesMethod(equalsMethod, Modifier.PUBLIC,
					0, "boolean")) //NOI18N
				{
					throw new ModelValidationException(keyClass,
						I18NHelper.getMessage(getMessages(), 
						"util.validation.key_class_equals", //NOI18N
						keyClassName, getClassName()));
				}
				
				// check hashCode method
				if (!matchesMethod(hashCodeMethod, Modifier.PUBLIC,
					0, "int")) //NOI18N
				{
					throw new ModelValidationException(keyClass,
						I18NHelper.getMessage(getMessages(), 
						"util.validation.key_class_hashcode", //NOI18N
						keyClassName, getClassName()));
				}
			}
			
			/** Helper method validating the name of the key class.
			 */
			private String validateKeyClassName (String keyClassName) 
				throws ModelValidationException
			{
				String pcClassName = getClassName();
				Model model = getModel();
				boolean hasKeyClassName = !StringHelper.isEmpty(keyClassName);
				boolean hasPrefix;
				String nameSuffix;
				boolean isOIDNameSuffix;

				// check for existence of key class name
				if (!hasKeyClassName)
				{
					throw new ModelValidationException(
						ModelValidationException.WARNING,
						model.getClass(pcClassName),
						I18NHelper.getMessage(getMessages(), 
						"util.validation.key_class_unset", //NOI18N
						pcClassName));
				}

				keyClassName = keyClassName.trim();
				hasPrefix = keyClassName.startsWith(pcClassName);
				nameSuffix = (hasPrefix ? 
				   keyClassName.substring(pcClassName.length()) : keyClassName);
				isOIDNameSuffix = 
					(nameSuffix.equalsIgnoreCase(".OID") || // NOI18N
					 nameSuffix.equalsIgnoreCase("$OID")); // NOI18N

				if (!hasPrefix || 
					(!nameSuffix.equalsIgnoreCase("Key") && 	// NOI18N
					 !isOIDNameSuffix))
				{
					Object pcClass = getModel().getClass(pcClassName);
					throw new ModelValidationException(pcClass,
						I18NHelper.getMessage(getMessages(),
						"util.validation.key_class_invalid", //NOI18N
						keyClassName, pcClassName));
				}
				if (isOIDNameSuffix)
				{
					StringBuffer buf = new StringBuffer(keyClassName);
					buf.setCharAt(keyClassName.length() - 4, '$");
					return buf.toString();  
				}
				return keyClassName;
			}

			// helper method which returns a field object from the 
			// given class or one of its superclasses
			private Object getKeyClassField (String keyClassName, 
				String keyClassFieldName)
			{
				Model model = getModel();
				Object keyClassField = 
					model.getField(keyClassName, keyClassFieldName);

				if (keyClassField == null)	// this is an inherited field
				{
					keyClassField = model.getInheritedField(
						keyClassName, keyClassFieldName);
				}

				return keyClassField;
			}

			/** Helper method returning the key fields of the pc class as a map.
			 */
			private Map getKeyFields ()
			{
				Model model = getModel();
				String pcClassName = getClassName();
				PersistenceClassElement pce = 
					model.getPersistenceClass(pcClassName);
				PersistenceFieldElement[] fields = pce.getFields();
				Map keyFields = new HashMap();

				if (fields != null)
				{
					for (int i = 0; i < fields.length; i++)
					{
						PersistenceFieldElement pfe = fields[i];
						if (pfe.isKey())
						{
							String name = pfe.getName();
							keyFields.put(name, 
								model.getField(pcClassName, name));
						}
					}
				}
				
				return keyFields;
			}
			// helper method which returns a method object from the 
			// given class or one of its superclasses provided it
			// is not java.lang.Object
			private Object getNonObjectMethod (String className, 
				String methodName, String[] argTypeNames)
			{
				Model model = getModel();
				Object method = 
					model.getMethod(className, methodName, argTypeNames);

				if (method == null)	// look for an inherited method
				{
					method = model.getInheritedMethod(
						className, methodName, argTypeNames);

					if ((method != null) && model.getDeclaringClass(method).
						equals("java.lang.Object"))		// NOI18N
					{
						method = null;
					}
				}

				return method;
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateKeyColumnMappingComponent(PersistenceClassElement persistenceClass)
Create a validation component which can check whether the class contains field mappings for all primary key columns.

param
persistenceClass the class whose mapping is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				String className = getClassName();
				MappingClassElement mappingClass = getMappingClass(className);

				if (mappingClass != null)
				{
					List tables = mappingClass.getTables();

					if (tables.size() > 0)
					{
						String tableName = 
							((MappingTableElement)tables.get(0)).getName();
						TableElement table = getTable(tableName, 
							getSchemaForClass(className));
						List columns = getUnmappedColumnNames(
							((table != null) ? table.getPrimaryKey() : null), 
							mappingClass);

						if ((columns != null) && (columns.size() > 0))
						{
							throw new ModelValidationException(
								ModelValidationException.WARNING, 
								getOffendingObject(null),
								I18NHelper.getMessage(getMessages(), 
								"util.validation.class_key_column_missing", //NOI18N
								className, tableName, 
								StringHelper.arrayToSeparatedList(columns)));
						}
					}
				}
			}
			private List getUnmappedColumnNames (KeyElement primaryKey, 
				MappingClassElement mappingClass)
			{
				List unmappedColumns = null;

				if (primaryKey != null)	// check if primary table has a pk
				{
					ColumnElement[] columns = primaryKey.getColumns();
					int count = ((columns != null) ? columns.length : 0);

					// all columns in the pk should be mapped to key fields
					if (count > 0)
					{
						List mappingFields = mappingClass.getFields();
						Iterator iterator = mappingFields.iterator();

						unmappedColumns = getRelativeColumnNames(columns);

						while (iterator.hasNext())
						{
							MappingFieldElement field = 
								(MappingFieldElement)iterator.next();

							if (isKeyField(field))
								unmappedColumns.removeAll(field.getColumns());
						}
					}
				}

				return unmappedColumns;
			}
			private List getRelativeColumnNames (ColumnElement[] columns)
			{
				int i, count = ((columns != null) ? columns.length : 0);
				List columnNames = new ArrayList(count);
								
				for (i = 0; i < count; i++)
				{
					columnNames.add(NameUtil.getRelativeMemberName(
						columns[i].getName().getFullName()));
				}

				return columnNames;
			}
			private boolean isKeyField (MappingFieldElement field)
			{
				PersistenceFieldElement persistenceField = 
					persistenceClass.getField(field.getName());

				return ((persistenceField != null) && persistenceField.isKey());
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreatePrimaryTableComponent(MappingTableElement primaryTable)
Create a validation component which can check whether the class is mapped to tables even though the schema is null or the class is mapped to a primary table without a primary key.

param
primaryTable the primary table for the class
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				if (primaryTable != null)
				{
					String className = getClassName();
					String schemaName = getSchemaForClass(className);

					if (schemaName == null)
					{
						throw constructClassException(className, null, 
							"util.validation.schema_not_set");		//NOI18N
					}
					else
					{
						String tableName = primaryTable.getName();
						TableElement table = getTable(tableName, schemaName);

						if ((table != null) && (table.getPrimaryKey() == null))
						{ 
							throw new ModelValidationException(
								getOffendingObject(null),
								I18NHelper.getMessage(getMessages(), 
									"util.validation.table_no_primarykey", //NOI18N
									new Object[]{tableName, className}));
						}
					}
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateRelatedClassMatchesComponent(RelationshipElement field)
Create a validation component which can check whether the inverse of the relationship belongs to the related class (type or element class depending on cardinality).

param
field the relationship whose inverse relationship is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				String inverseName = 
					field.getInverseRelationshipName();

				if (!StringHelper.isEmpty(inverseName))
				{
					Model model = getModel();
					RelationshipElement inverse = 
						field.getInverseRelationship(model);

					if (inverse == null) // no such field in that related class
					{
						String relatedClass = getRelatedClass(field);
						String fieldName = field.getName();
						String key = ((relatedClass != null) ? 
							"util.validation.related_class_mismatch" : //NOI18N
							"util.validation.related_class_not_found");//NOI18N
						Object[] args = ((relatedClass != null) ? 
							new Object[]{fieldName, inverseName, relatedClass}
							: new Object[]{fieldName, inverseName});
							
						throw new ModelValidationException(
							model.getField(getClassName(), fieldName), 
							I18NHelper.getMessage(getMessages(), key, args));
					}
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateRelatedSchemaMatchesComponent(java.lang.String relatedClass, PersistenceFieldElement relatedField)
Create a validation component which can check whether the schema of the related class matches that of the class we are checking.

param
relatedClass the class whose schema is being checked
param
relatedField the relationship field whose schema is being compared
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				if (relatedClass != null)
				{
					String className = getClassName();
					String mySchema = getSchemaForClass(className);
					String relatedSchema = getSchemaForClass(relatedClass);

					if ((mySchema != null) && (relatedSchema != null) && 
						!(relatedSchema.equals(mySchema)))
					{
						String fieldName = relatedField.getName();

						throw new ModelValidationException(
							getModel().getField(className, fieldName), 
							I18NHelper.getMessage(getMessages(), 
							"util.validation.schema_mismatch", //NOI18N
							new Object[]{className, relatedClass, fieldName}));
					}
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateRelatedTableMatchesComponent(java.lang.String relatedClass, PersistenceFieldElement relatedField, java.util.List tableNames, java.lang.String pairName)
Create a validation component which can check whether any of the supplied tables of the related class (which includes primary and secondary tables) contains the table of the column stored in the relationship definition.

param
relatedClass the class whose table is being checked
param
relatedField the relationship field whose table is being compared
param
tableNames the list of names of the tables we expect the column to match
param
pairName the name of the pair whose reference column is to be checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				ColumnPairElement pair = getPair(pairName, 
					getSchemaForClass(relatedClass));

				if (pair != null)
				{
					ColumnElement column = pair.getReferencedColumn();

					if (!matchesTable(tableNames, column))
					{
						String fieldName = relatedField.getName();

						throw new ModelValidationException(
							getModel().getField(getClassName(), fieldName), 
							I18NHelper.getMessage(getMessages(), 
							getKey(
							"util.validation.table_mismatch", //NOI18N
							relatedField),
							new Object[]{column.getName().getFullName(),
							fieldName, relatedClass}));
					}
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateSchemaExistenceComponent(java.lang.String className)
Create a validation component which can check whether the schema of the given class exists.

param
className the class whose mapped schema's existence is being checked
return
the validation component

		return createSchemaExistenceComponent(className, null);
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateSchemaExistenceComponent(java.lang.String className, PersistenceFieldElement relatedField)
Create a validation component which can check whether the schema of the given class exists.

param
className the class whose mapped schema's existence is being checked
param
relatedField the relationship field whose class' mapped schema is being checked, may be null in which case we are probably checking the same class as the validator is checking overall
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				String schemaName = getSchemaForClass(className);

				if ((schemaName != null) && 
					(SchemaElement.forName(schemaName) == null))
				{
					Object[] args = (relatedField == null) ? 
						new Object[]{schemaName, className} : 
						new Object[]{schemaName, className, relatedField};

					throw new ModelValidationException(
						ModelValidationException.WARNING, 
						getOffendingObject(relatedField),
						I18NHelper.getMessage(getMessages(), getKey(
							"util.validation.schema_not_found", //NOI18N
							relatedField), args));
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateSerializableClassComponent(java.lang.String className)
Create a validation component which can check that the persistence capable class implement methods readObject and writeObject, if the class implements the intreface java.io.Serializable

param
className the class whose methods are checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				Model model = getModel();
				Object pcClass = null;

				if (className == null)
					return;
				pcClass = model.getClass(className);
				if (pcClass == null)
					return;

				if (model.implementsInterface(pcClass, "java.io.Serializable")) //NOI18N
				{
					// check readObject method
					Object readMethod = model.getMethod(className, 
						"readObject", Model.READ_OBJECT_ARGS); //NOI18N

					if (!matchesMethod(readMethod, Modifier.PRIVATE,
						Modifier.SYNCHRONIZED, "void")) // NOI18N
					{
						throw new ModelValidationException(pcClass,
							I18NHelper.getMessage(getMessages(),
							"util.validation.class_readobject", //NOI18N
							className));
					}
					
					// check writeObject method
					Object writeMethod = model.getMethod(className, 
						"writeObject", Model.WRITE_OBJECT_ARGS); //NOI18N

					if (!matchesMethod(writeMethod, Modifier.PRIVATE,
						Modifier.SYNCHRONIZED, "void")) // NOI18N
					{
						throw new ModelValidationException(pcClass,
							I18NHelper.getMessage(getMessages(),
							"util.validation.class_writeobject", //NOI18N
							className));
					}
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateTableExistenceComponent(java.lang.String tableName)
Create a validation component which can check whether the given table exists.

param
tableName the table whose existence is being checked
return
the validation component

		return createTableExistenceComponent(tableName, null);
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateTableExistenceComponent(java.lang.String tableName, PersistenceFieldElement relatedField)
Create a validation component which can check whether the given table exists.

param
tableName the table whose existence is being checked
param
relatedField the relationship field whose class' table is being checked, may be null in which case we are probably checking the same class as the validator is checking overall
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				if (tableName != null)
				{
					String className = getClassName();
					boolean noRelated = (relatedField == null);
					TableElement table = getTable(tableName,
						getSchemaForClass((noRelated ? className : 
						getRelatedClass(relatedField))));

					if (table == null)
					{
						Object[] args = noRelated ? 
							new Object[]{tableName, className} : 
							new Object[]{tableName, relatedField};

						throw new ModelValidationException(
							ModelValidationException.WARNING, 
							getOffendingObject(relatedField),
							I18NHelper.getMessage(getMessages(), getKey(
								"util.validation.table_not_found", //NOI18N
								relatedField), args));
					}
				}
			}
		};
	
protected com.sun.jdo.api.persistence.model.util.ModelValidator$ValidationComponentcreateVersionConsistencyComponent(MappingClassElement mappingClass)
Create a validation component which checks whether the rules for version consistency are followed. This includes:
  • There must be exactly one version field defined.
  • The version field must not be a relationship.
  • The version field must not be a key field.
  • The version field must be of java type (primitive) long.
  • The version field must be in the default fetch group.
  • The version field must be mapped to exactly 1 column from the primary table.
  • The column to which the version field is mapped must be of a numeric type and non-nullable.
  • The column to which the version field is mapped must not be a PK or FK column.

param
mappingClass the mapping class element whose consistency is being checked
return
the validation component

		return new ValidationComponent ()
		{
			public void validate () throws ModelValidationException
			{
				// only bother to check for classes with version consistency
				if (MappingClassElement.VERSION_CONSISTENCY == 
					mappingClass.getConsistencyLevel())
				{
					MappingFieldElement versionField =
						 validateVersionFieldExistence();
					String className = mappingClass.getName();
					String fieldName = versionField.getName();
					String columnName = null;
					ColumnElement column = null;

					if (versionField instanceof MappingRelationshipElement)
					{
						throw constructFieldException(fieldName, 
							"util.validation.version_field_relationship_not_allowed");//NOI18N
					}
					else if (MappingFieldElement.GROUP_DEFAULT != 
						versionField.getFetchGroup()) // must be in DFG
					{
						throw constructFieldException(fieldName, 
							"util.validation.version_field_fetch_group_invalid");//NOI18N
					}

					validatePersistenceFieldAttributes(className, fieldName);
					columnName = validateVersionFieldMapping(versionField);
					column = validateTableMatch(className, fieldName, columnName);
					validateColumnAttributes(className, fieldName, column);
				}
			}
			/** Helper method validating the existence of the exactly one 
			 * version field.
			 */
			private MappingFieldElement validateVersionFieldExistence () 
				throws ModelValidationException
			{
				List versionFields = mappingClass.getVersionFields();

				// must have exactly 1 version field (for this release)
				if (versionFields.size() != 1)
				{
					throw constructClassException(mappingClass.getName(), 
						null, "util.validation.version_field_cardinality");	//NOI18N
				}

				return (MappingFieldElement)versionFields.get(0);
			}
			/** Helper method validating the attributes of the field in the  
			 * jdo model which corresponds to the version field.
			 */
			private void validatePersistenceFieldAttributes (String className, 
				String fieldName) throws ModelValidationException
			{
				Class fieldType = JavaTypeHelper.getPrimitiveClass(
					getModel().getFieldType(className, fieldName));
				String keyName = null;

				// must not be a key field
				if (getPersistenceClass(className).getField(fieldName).isKey())
					keyName = "util.validation.version_field_key_field_not_allowed";//NOI18N
				else if (Long.TYPE != fieldType)	// must be type long
					keyName = "util.validation.version_field_type_not_allowed";//NOI18N

				if (keyName != null)
					throw constructFieldException(fieldName, keyName);
			}
			/** Helper method validating the column name of the  
			 * version field mapping.
			 */
			private String validateVersionFieldMapping (
				MappingFieldElement versionField) 
				throws ModelValidationException
			{
				List columns = versionField.getColumns();

				// must be mapped to exactly 1 column (for this release)
				if (columns.size() != 1)
				{
					throw constructFieldException(versionField.getName(), 
						"util.validation.version_field_not_mapped");	//NOI18N
				}

				return (String)columns.get(0);
			}
			/** Helper method validating the column mapping of the version 
			 * field is from the primary table.
			 */
			private ColumnElement validateTableMatch (String className, 
				String fieldName, String columnName) 
				throws ModelValidationException
			{
				String schema = getSchemaForClass(className);
				String absoluteName = 
					NameUtil.getAbsoluteMemberName(schema, columnName);
				TableElement table = 
					TableElement.forName(NameUtil.getTableName(absoluteName));
				String primaryName = ((MappingTableElement)mappingClass.
					getTables().get(0)).getName();
				TableElement pTable = getTable(primaryName, schema);

				// column must be from the PT
				if (table != pTable)
				{
					throw new ModelValidationException(
						getModel().getField(className, fieldName), 
						I18NHelper.getMessage(getMessages(), 
						"util.validation.version_field_table_mismatch", //NOI18N
						new Object[]{columnName, fieldName, className}));
				}

				return ((table != null) ? (ColumnElement)table.getMember(
					DBIdentifier.create(absoluteName)) : null);
			}
			/** Helper method validating the attributes of the column of the  
			 * version field mapping.
			 */
			private void validateColumnAttributes (String className, 
				String fieldName, ColumnElement column)
				throws ModelValidationException
			{
				String keyName = null;

				// column must be numeric type and non-nullable
				if (column.isNullable() || !column.isNumericType())
					keyName = "util.validation.version_field_column_type_invalid";		// NOI18N
				else	// column must be non-PK and non-FK column
				{
					TableElement table = column.getDeclaringTable();
					UniqueKeyElement[] uks = table.getUniqueKeys();
					ForeignKeyElement[] fks = table.getForeignKeys();
					int i, count = ((uks != null) ? uks.length : 0);

					for (i = 0; i < count; i++)
					{
						UniqueKeyElement uk = uks[i];

						if (uk.isPrimaryKey() && Arrays.asList(
							uk.getColumns()).contains(column))
						{
							keyName = "util.validation.version_field_column_pk_invalid";		// NOI18N
							break;
						}
					}

					count = ((fks != null) ? fks.length : 0);
					for (i = 0; i < count; i++)
					{
						ForeignKeyElement fk = fks[i];

						if (Arrays.asList(fk.getLocalColumns()).
							contains(column))
						{
							keyName = "util.validation.version_field_column_fk_invalid";		// NOI18N
							break;
						}
					}
				}

				if (keyName != null)
				{
					throw new ModelValidationException(
						getModel().getField(className, fieldName), 
						I18NHelper.getMessage(getMessages(), keyName, 
						new Object[]{column.getName(), fieldName, className}));
				}
			}
		};
	
private MappingReferenceKeyElementfindReferenceKey(MappingTableElement primaryTable, MappingTableElement secondaryTable)

		if ((primaryTable != null) && (secondaryTable != null))
		{
			Iterator iterator = primaryTable.getReferencingKeys().iterator();

			while (iterator.hasNext())
			{
				MappingReferenceKeyElement testKey = 
					(MappingReferenceKeyElement)iterator.next();

				if (testKey.getTable().equals(secondaryTable))
					return testKey;
			}
		}

		return null;
	
public java.util.CollectionfullValidationCheck()
Main method used for validating the combination of java (or class) information and mapping/jdo information by running through the full validation check and returning a collection of ModelValidationExceptions containing any errors or warnings encountered.

return
a collection of ModelValidationExceptions containing any errors or warnings encountered. If no errors or warnings were encountered, the collection will be empty, not null.
see
#getFullValidationList

		ArrayList list = new ArrayList();
		Iterator iterator = getFullValidationList().iterator();

		while (iterator.hasNext())
		{
			try
			{
				((ValidationComponent)iterator.next()).validate();
			}
			catch (ModelValidationException e)
			{
				list.add(e);
			}
		}

		return Collections.unmodifiableCollection(list);
	
private java.lang.Object[]getArguments(java.lang.String className, java.lang.Object field)
Computes the arguments for the i18n string to be used in the construction of a ModelValidationException as follows: if a non-null field is supplied, an array containing the supplied className and field is returned, otherwise, an array containing only the supplied className is returned.

param
className the name of the class which caused the problem
param
field the field object which caused the problem - may be null
return
the argument array

		return ((field == null) ? new Object[]{className} : 
			new Object[]{className, field});
	
public java.util.CollectiongetBasicValidationList()
Computes and returns a collection of ValidationComponents representing the tests to be performed during parse.

return
a collection of ValidationComponents representing the tests to be performed during parse.
see
#getDatabaseValidationList
see
#getFieldsValidationList
see
#getFullValidationList

		ArrayList list = new ArrayList();
		String className = getClassName();

		list.add(createClassExistenceComponent(className));
		list.add(createClassPersistenceComponent(className));

		list.addAll(getDatabaseValidationList());
		list.addAll(getFieldsValidationList());

		return Collections.unmodifiableCollection(list);
	
public java.lang.ClassLoadergetClassLoader()
Get the class loader used to load the class being validated.

return
the class loader of the class being validated

 return _classLoader; 
public java.lang.StringgetClassName()
Get the name of the class being validated.

return
the name of the class being validated

 return _className; 
private java.util.CollectiongetDatabaseValidationList()
Computes and returns a collection of ValidationComponents representing the database tests to be performed.

return
a collection of ValidationComponents representing the database tests to be performed.

		ArrayList list = new ArrayList();
		String className = getClassName();
		MappingClassElement mappingClass = getMappingClass(className);

		if (mappingClass != null)
		{
			ArrayList tables = mappingClass.getTables();
			int i, count = ((tables != null) ? tables.size() : 0);
			MappingTableElement primaryTable = null;
			Iterator iterator = null;

			list.add(createSchemaExistenceComponent(className));

			for (i = 0; i < count; i++)
			{
				MappingTableElement nextTable = 
					(MappingTableElement)tables.get(i);

				list.add(createTableExistenceComponent(nextTable.getTable()));

				if (i == 0)
				{
					primaryTable = nextTable;
					list.add(createPrimaryTableComponent(primaryTable));
				}
				else
				{
					MappingReferenceKeyElement referenceKey = 
						findReferenceKey(primaryTable, nextTable);

					if (referenceKey != null)
					{
						iterator = referenceKey.getColumnPairNames().iterator();
						while (iterator.hasNext())
						{
							list.add(createColumnExistenceComponent(
								(String)iterator.next()));
						}
					}
				}
			}

			list.add(createVersionConsistencyComponent(mappingClass));

			iterator = mappingClass.getFields().iterator();
			while (iterator.hasNext())
			{
				MappingFieldElement nextField = 
					(MappingFieldElement)iterator.next();
				ArrayList allColumns = new ArrayList();
				Iterator columnIterator = null;

				if (isRelationship(nextField))
				{
					allColumns.addAll(((MappingRelationshipElement)nextField).
						getAssociatedColumns());
				}

				allColumns.addAll(nextField.getColumns());

				columnIterator = allColumns.iterator();
				while (columnIterator.hasNext())
				{
					list.add(createColumnExistenceComponent(
						(String)columnIterator.next(), nextField));
				}
			}
		}

		return list;
	
private java.util.ArrayListgetDifference(java.util.ArrayList columns1, java.util.ArrayList columns2)

		ArrayList differenceColumns = new ArrayList(columns2);

		differenceColumns.removeAll(columns1);

		return differenceColumns;
	
private java.util.CollectiongetFieldsValidationList()
Computes and returns a collection of ValidationComponents representing the field and relationship tests to be performed.

return
a collection of ValidationComponents representing the field and relationship tests to be performed.

		ArrayList list = new ArrayList();
		Model model = getModel();
		String className = getClassName();
		PersistenceClassElement persistenceClass = 
			getPersistenceClass(className);

		if (persistenceClass != null)
		{
			PersistenceFieldElement[] fields = persistenceClass.getFields();
			int i, count = ((fields != null) ? fields.length : 0);
			Iterator iterator = 
				getMappingClass(className).getFields().iterator();

			for (i = 0; i < count; i++)
			{
				PersistenceFieldElement field = fields[i];

				list.add(createFieldExistenceComponent(field));

				// even though this is really the validation step, we 
				// only want to add the others if the field exists
				if (model.hasField(className, field.getName()))
				{
					list.add(createFieldPersistenceComponent(field));
					list.add(createFieldPersistenceTypeComponent(field));
					list.add(createFieldConsistencyComponent(field));

					if (isLegalRelationship(field))
					{
						RelationshipElement rel = (RelationshipElement)field;

						/* user modifiable collection class not yet supported
						list.add(createCollectionClassComponent(rel));*/
						list.add(createElementClassComponent(rel));
						list.add(createRelatedClassMatchesComponent(rel));
					}
				}
			}

			while (iterator.hasNext())
			{
				MappingFieldElement field = 
					(MappingFieldElement)iterator.next();
				String fieldName = field.getName();

				// only check this if it is not in the jdo model
				if (persistenceClass.getField(fieldName) == null)
				{
					list.add(createFieldExistenceComponent(field));

					// even though this is really the validation step, we 
					// only want to add the others if the field exists
					if (model.hasField(className, fieldName))
						list.add(createFieldConsistencyComponent(field));
				}

				if (!isRelationship(field))
					list.add(createColumnOverlapComponent(field));

				// preliminary fix for CR6239630
				if (Boolean.getBoolean("AllowManagedFieldsInDefaultFetchGroup")) // NOI18N
		 		{
                                    // Do nothing - AllowManagedFieldsInDefaultFetchGroup: 
                                    // disabled single model validation test; 
                                    // may use checked read/write access to managed fields
				}
				else
				{
					list.add(createFieldDefaultFetchGroupComponent(field));
				}
			}
		}

		return list;
	
public java.util.CollectiongetFullValidationList()
Computes and returns a collection of ValidationComponents representing the tests to be performed during validation. These include all those in the basic list plus those which check cardinality and the related classes in more detail.

return
a collection of ValidationComponents representing the tests to be performed during validation.
see
#getRelatedClassValidationList
see
#getBasicValidationList

		ArrayList list = new ArrayList(getBasicValidationList());
		String className = getClassName();
		PersistenceClassElement persistenceClass = 
			getPersistenceClass(className);

		if (persistenceClass != null)
		{
			PersistenceFieldElement[] fields = persistenceClass.getFields();
			int i, count = ((fields != null) ? fields.length : 0);

			list.add(createSerializableClassComponent(className));
			list.add(createKeyClassComponent(persistenceClass.getKeyClass()));
			list.add(createClassMappingComponent(persistenceClass));
			list.add(createKeyColumnMappingComponent(persistenceClass));

			for (i = 0; i < count; i++)
			{
				PersistenceFieldElement field = fields[i];

				list.add(createFieldCardinalityComponent(field));
				list.add(createFieldMappingComponent(field));
				list.add(createFieldBlobMappingComponent(field));
				list.addAll(getRelatedClassValidationList(field));
			}
		}

		return Collections.unmodifiableCollection(list);
	
private java.lang.StringgetKey(java.lang.String keyBase, java.lang.Object field)
Computes the key for the i18n string to be used in the construction of a ModelValidationException as follows: if a non-null field is supplied, "_related" is appending to the supplied key base, otherwise, the key base is returned as is.

param
keyBase the base key to be used for the i18n string
param
field the field object which caused the problem - may be null
return
the key

		return ((field == null) ? keyBase : (keyBase + "_related"));	//NOI18N
	
private MappingClassElementgetMappingClass(java.lang.String className)
Convenience method to call Model.getMappingClass.

		return getModel().getMappingClass(className, getClassLoader());
	
private MappingRelationshipElementgetMappingRelationship(RelationshipElement jdoElement)

		MappingRelationshipElement mappingElement = null;

		if (jdoElement != null)
		{
			MappingClassElement mappingClass = getMappingClass(
				jdoElement.getDeclaringClass().getName());

			if (mappingClass != null)
			{
				MappingFieldElement fieldElement =
					mappingClass.getField(jdoElement.getName());

				if (isRelationship(fieldElement))
					mappingElement = (MappingRelationshipElement)fieldElement;
			}
		}

		return mappingElement;
	
protected java.util.ResourceBundlegetMessages()

return
I18N message handler for this element

 return _messages; 
public com.sun.jdo.api.persistence.model.ModelgetModel()
Get the model object used for validation.

return
the model object used for validation

 return _model; 
private java.lang.ObjectgetOffendingObject(java.lang.Object field)
Computes the offending object to be used in the construction of a ModelValidationException as follows: if a non-null field is supplied, the corresponding org.openide.src.FieldElement is returned, otherwise, corresponding org.openide.src.ClassElement is returned.

param
field the field object which caused the problem - may be null
return
the offending object

		return ((field == null) ? 
			getModel().getClass(getClassName(), getClassLoader()) :
			getModel().getField(getClassName(), field.toString()));
	
private ColumnPairElementgetPair(java.lang.String pairName, java.lang.String databaseRoot)

		String absoluteName = NameUtil.getAbsoluteMemberName(
			databaseRoot, pairName);
		TableElement tableElement = TableElement.forName(
			NameUtil.getTableName(absoluteName));
		DBMemberElement pair = ((tableElement == null) ? null :
			tableElement.getMember(DBIdentifier.create(absoluteName)));

		return ((pair instanceof ColumnPairElement) ? 
			((ColumnPairElement)pair) : null);
	
private PersistenceClassElementgetPersistenceClass(java.lang.String className)
Convenience method to call Model.getPersistenceClass.

		return getModel().getPersistenceClass(className, getClassLoader());
	
private java.lang.StringgetRelatedClass(PersistenceFieldElement field)

		if (isLegalRelationship(field))
			return getModel().getRelatedClass((RelationshipElement)field);

		return null;
	
private java.util.CollectiongetRelatedClassValidationList(PersistenceFieldElement field)
Computes and returns a collection of ValidationComponents representing the related class tests to be performed. Right now, these are only included as part of full validation, as they may be somewhat time intensive since they compute information about other classes as well as this class.

return
a collection of ValidationComponents representing the related class tests to be performed.

		String relatedClass = getRelatedClass(field);
		ArrayList list = new ArrayList();

		// even though this is really already included in the validation 
		// step, we only want to add the extra steps if the field exists
		if ((relatedClass != null) && 
			getModel().hasField(getClassName(), field.getName()))
		{
			MappingClassElement relatedClassElement = 
				getMappingClass(relatedClass);

			list.add(createClassExistenceComponent(relatedClass, field));
			list.add(createClassPersistenceComponent(relatedClass, field));
			list.add(createSchemaExistenceComponent(relatedClass, field));
			list.add(createRelatedSchemaMatchesComponent(relatedClass, field));

			if (relatedClassElement != null)
			{
				ArrayList tables = relatedClassElement.getTables();
				MappingTableElement primaryTable = null;
				boolean hasTables = ((tables != null) && (tables.size() > 0));

				if (hasTables)
				{
					primaryTable = (MappingTableElement)tables.get(0);
					list.add(createTableExistenceComponent(
						primaryTable.getTable(), field));
				}

				if (isRelationship(field))
				{
					RelationshipElement relElement = (RelationshipElement)field;
					Object rel = getMappingClass(getClassName()).
						getField(field.getName());

					list.add(createInverseFieldComponent(relElement));
					list.add(createInverseMappingComponent(relElement));

					// verify that the columns from the primary table 
					// of the related class are actually from that table
					// since it could have been changed
					if ((rel != null) && isRelationship(rel))
					{
						MappingRelationshipElement relationship = 
							(MappingRelationshipElement)rel;
						ArrayList columns = 
							relationship.getAssociatedColumns();
						Iterator iterator = null;

						if ((columns == null) || (columns.size() == 0))
							columns = relationship.getColumns();

						if (columns != null)
						{
							List tableNames = new ArrayList();

							if (hasTables)
							{
								Iterator tableIterator = tables.iterator();

								while (tableIterator.hasNext())
								{
									tableNames.add(((MappingTableElement)
										tableIterator.next()).getName());
								}
							}

							iterator = columns.iterator();

							while (iterator.hasNext())
							{
								list.add(createRelatedTableMatchesComponent(
									relatedClass, field, tableNames, 
									(String)iterator.next()));
							}
						}
					}
				}
			}
		}

		return list;
	
private java.lang.StringgetSchemaForClass(java.lang.String className)

		MappingClassElement mappingClass = getMappingClass(className);
		String schema = ((mappingClass != null) ? 
			mappingClass.getDatabaseRoot() : null);

		return (StringHelper.isEmpty(schema) ? null : schema.trim());
	
private TableElementgetTable(java.lang.String tableName, java.lang.String databaseRoot)

		String absoluteName = NameUtil.getAbsoluteTableName(databaseRoot,
			tableName);
		return TableElement.forName(absoluteName);
	
private booleanisCollection(java.lang.String className, java.lang.String fieldName)

		Model model = getModel();

		return model.isCollection(model.getFieldType(className, fieldName));
	
private booleanisJoin(MappingRelationshipElement field)

		if (field != null)
		{
			ArrayList columns = field.getAssociatedColumns();
			
			return ((columns != null) && !columns.isEmpty());
		}
		
		return false;
	
private booleanisLegalRelationship(PersistenceFieldElement field)

		return (isRelationship(field) ? shouldBeRelationship(field) : false);
	
private booleanisPersistent(java.lang.String className)
Convenience method to call Model.isPersistent

		return getModel().isPersistent(className, getClassLoader());
	
private booleanisPersistentAllowed(java.lang.String className, java.lang.String fieldName)
Convenience method to call Model.isPersistentAllowed

		return getModel().isPersistentAllowed(className, getClassLoader(), 
			fieldName);
	
private booleanisRelationship(java.lang.Object field)

		return ((field instanceof RelationshipElement) || 
			(field instanceof MappingRelationshipElement));
	
private booleanmatchesMethod(java.lang.Object method, int expectedModifiers, int optionalModifiers, java.lang.String expectedReturnType)
Checks whether the specified method element exists and if so whether it has the expected modifiers and the expected return type.

param
method the method element to be checked
param
expectedModifiers the modifiers the method should have
param
optionalModifiers additional modifiers the method might have
param
expectedReturnType the return type the method should have
return
true if the method matches, false otherwise.

		boolean matches = false;  

		if (method != null)
		{
			Model model = getModel();
			int modifiers = model.getModifiers(method);

			matches = (((modifiers == expectedModifiers) || 
				(modifiers == (expectedModifiers | optionalModifiers))) &&
				expectedReturnType.equals(model.getType(method)));
		}

		return matches;
	
private booleanmatchesTable(java.util.List tableNames, ColumnElement column)
Check if the table of the column matches one of the list of tables.

param
tableNames A list of table names in which to check for a match
param
column A ColumnElement object to be checked
return
true if the column belongs to a table found in the supplied list of table names, false otherwise

	
		return ((column == null) ? true : tableNames.contains(
			column.getDeclaringTable().getName().getName()));
	
public booleanparseCheck()
Main method used for parsing the combination of java (or class) information and mapping/jdo information by running through a subset of the full validation check and aborting (and returning false at the first error or warning.

return
true if no errors or warnings occur, false otherwise.
see
#getBasicValidationList

		Iterator iterator = getBasicValidationList().iterator();

		try
		{
			while (iterator.hasNext())
				((ValidationComponent)iterator.next()).validate();
		}
		catch (ModelValidationException e)
		{
			LogHelperModel.getLogger().log(Logger.FINER, 
				"model.parse_error", e);	// NOI18N

			return false;
		}

		return true;
	
private booleanshouldBeRelationship(PersistenceFieldElement field)

		Model model = getModel();
		String fieldType = model.getFieldType(getClassName(), field.getName());

		return (isPersistent(fieldType) || model.isCollection(fieldType));