@Override
public FieldType createOrUpdateFieldType(FieldType fieldType) throws RepositoryException, InterruptedException {
ArgumentValidator.notNull(fieldType, "fieldType");
if (fieldType.getId() == null && fieldType.getName() == null) {
throw new TypeException("No ID or name specified in the field type to create-or-update.");
}
if (fieldType.getId() != null && fieldType.getName() != null) {
// If the ID is specified, we can assume it is a field type which is supposed to exist already
// so we call update. We also require the name to be specified, since the name is the only
// property of field type which can be updated, so otherwise it makes no sense to call update
// (update will throw an exception in that case).
return updateFieldType(fieldType);
} else if (fieldType.getId() != null) {
// There's nothing to update or create: just fetch the field type, check its state corresponds
// and return it
FieldType latestFieldType = getFieldTypeByIdWithoutCache(fieldType.getId());
// don't modify input object
FieldType newFieldType = fieldType.clone();
copyUnspecifiedFields(newFieldType, latestFieldType);
checkImmutableFieldsCorrespond(newFieldType, latestFieldType);
// The supplied name was null, so no need to check if it corresponds
return latestFieldType;
} else { // if (fieldType.getName() != null) {
int attempts;
for (attempts = 0; attempts < 3; attempts++) {
FieldType existingFieldType = schemaCache.getFieldTypeByNameReturnNull(fieldType.getName());
if (existingFieldType != null) {
// Field types cannot be deleted so there is no possibility that it would have been deleted
// in the meantime.
FieldType latestFieldType = getFieldTypeByIdWithoutCache(existingFieldType.getId());
if (!latestFieldType.getName().equals(fieldType.getName())) {
// Between what we got from the cache and from the persistent storage, the name could
// be different if the cache was out of date. In such case, we could loop a few times
// before giving up, but for now just throwing an exception since this is not expected
// to occur much
throw new TypeException("Field type create-or-update: id-name mapping in cache different" +
" than what is stored. This is not a user error, just retry please.");
}
// don't modify input object
FieldType newFieldType = fieldType.clone();
copyUnspecifiedFields(newFieldType, latestFieldType);
checkImmutableFieldsCorrespond(newFieldType, latestFieldType);
return latestFieldType;
} else {
try {
return createFieldType(fieldType);
} catch (FieldTypeExistsException e) {
// someone created the field type since we checked, we try again
}
}
}
throw new TypeException("Field type create-or-update failed after " + attempts +
" attempts, toggling between create and exists mode: this should be impossible" +
"since field types cannot be deleted.");
}
}