/** 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;
}
}