blob: 88bd051a39c0e98120fd7f0f07bc8d32f2b38784 [file] [log] [blame]
package org.apache.jackrabbit.ocm.nodemanagement.impl;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.nodetype.NodeDefinitionTemplate;
import javax.jcr.nodetype.NodeTypeTemplate;
import javax.jcr.nodetype.PropertyDefinitionTemplate;
import javax.jcr.version.OnParentVersionAction;
import org.apache.jackrabbit.ocm.mapper.model.BeanDescriptor;
import org.apache.jackrabbit.ocm.mapper.model.ChildNodeDefDescriptor;
import org.apache.jackrabbit.ocm.mapper.model.ClassDescriptor;
import org.apache.jackrabbit.ocm.mapper.model.CollectionDescriptor;
import org.apache.jackrabbit.ocm.mapper.model.FieldDescriptor;
import org.apache.jackrabbit.ocm.mapper.model.MappingDescriptor;
import org.apache.jackrabbit.ocm.mapper.model.PropertyDefDescriptor;
import org.apache.jackrabbit.ocm.nodemanagement.NodeTypeManager;
import org.apache.jackrabbit.ocm.nodemanagement.exception.NamespaceCreationException;
import org.apache.jackrabbit.ocm.nodemanagement.exception.NodeTypeCreationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NodeTypeManagerImpl implements NodeTypeManager {
private static Logger log = LoggerFactory.getLogger(NodeTypeManagerImpl.class);
@Override
public void createNamespace(final Session session, final String namespace, final String namespaceUri) throws NamespaceCreationException {
if (session != null)
{
try
{
session.getWorkspace().getNamespaceRegistry().registerNamespace(namespace, namespaceUri);
log.info("Namespace created: " +
"{" + namespaceUri + "}" + namespace);
}
catch (Exception e)
{
throw new NamespaceCreationException(e);
}
}
}
@Override
public void createNodeTypes(final Session session, final MappingDescriptor mappingDescriptor) throws NodeTypeCreationException {
if (mappingDescriptor != null && mappingDescriptor.getClassDescriptorsByClassName().size() > 0)
{
final Collection classDescriptorObjects = mappingDescriptor.getClassDescriptorsByClassName().values();
final ClassDescriptor[] classDescriptors = (ClassDescriptor[])classDescriptorObjects.toArray(new ClassDescriptor[classDescriptorObjects.size()]);
createNodeTypes(session, classDescriptors);
}
else
{
throw new NodeTypeCreationException("The MappingDescriptor can't be null or empty.");
}
}
@Override
public void createNodeTypes(final Session session, final ClassDescriptor[] classDescriptors) throws NodeTypeCreationException {
if (classDescriptors != null && classDescriptors.length > 0)
{
log.info("Trying to create " + classDescriptors.length +
" JCR node types.");
for (int i = 0; i < classDescriptors.length; i++)
{
createSingleNodeType(session, classDescriptors[i]);
}
}
else
{
throw new NodeTypeCreationException("The ClassDescriptor can't be null or empty.");
}
}
@Override
public void createSingleNodeType(final Session session, final ClassDescriptor classDescriptor) throws NodeTypeCreationException {
try {
if (classDescriptor.getJcrType() != null &&
(classDescriptor.getJcrType().startsWith("nt:")
|| classDescriptor.getJcrType().startsWith("mix:"))) {
throw new NodeTypeCreationException("Namespace nt and mix are reserved namespaces. Please specify your own.");
}
if (checkSuperTypes(session.getWorkspace().getNodeTypeManager(),
classDescriptor.getJcrSuperTypes())) {
javax.jcr.nodetype.NodeTypeManager ntm = session.getWorkspace().getNodeTypeManager();
final NodeTypeTemplate ntt = ntm.createNodeTypeTemplate();
if (classDescriptor.getJcrType() == null) {
ntt.setName(classDescriptor.getClassName());
} else {
ntt.setName(classDescriptor.getJcrType());
}
ntt.setAbstract(classDescriptor.isAbstract());
if (classDescriptor.getJcrSuperTypes() != null && classDescriptor.getJcrSuperTypes().length() > 0) {
String[] superTypesArray = classDescriptor.getJcrSuperTypes().split(",");
//TODO combine the mixins here as well as supertypes
// Add classDescriptor.getJcrMixinTypes() to superTypesArray
for (String s : classDescriptor.getJcrMixinTypes()) {
System.out.println(s);
}
ntt.setDeclaredSuperTypeNames(superTypesArray);
}
// should we also support mixins to be created?
ntt.setMixin(false);
ntt.setQueryable(true);
ntt.setOrderableChildNodes(true);
final List nodeDefinitionTemplates = ntt.getNodeDefinitionTemplates();
final List propertyDefinitionTemplates = ntt.getPropertyDefinitionTemplates();
if (classDescriptor.getFieldDescriptors() != null) {
Iterator fieldIterator = classDescriptor.getFieldDescriptors().iterator();
while (fieldIterator.hasNext()) {
FieldDescriptor field = (FieldDescriptor) fieldIterator.next();
if (!field.isPath()) {
final PropertyDefinitionTemplate pdt = getPropertyDefinition(ntm, session.getValueFactory(), field);
// add the just created pdt to the nodetypetemplate
propertyDefinitionTemplates.add(pdt);
}
}
if (classDescriptor.getBeanDescriptors() != null) {
Iterator beanIterator = classDescriptor.getBeanDescriptors().iterator();
while (beanIterator.hasNext()) {
BeanDescriptor field = (BeanDescriptor) beanIterator.next();
if (this.isPropertyType(field.getJcrType())) {
final PropertyDefinitionTemplate pdt = getPropertyDefinition(ntm, session.getValueFactory(), field);
// add the just created pdt to the nodetypetemplate
propertyDefinitionTemplates.add(pdt);
} else {
final NodeDefinitionTemplate ndt = getNodeDefinition(ntm, session.getValueFactory(), field);
// add the just created pdt to the nodetypetemplate
nodeDefinitionTemplates.add(ndt);
}
}
}
if (classDescriptor.getCollectionDescriptors() != null) {
Iterator collectionIterator = classDescriptor.getCollectionDescriptors().iterator();
while (collectionIterator.hasNext()) {
CollectionDescriptor field = (CollectionDescriptor) collectionIterator.next();
if (this.isPropertyType(field.getJcrType())) {
final PropertyDefinitionTemplate pdt = getPropertyDefinition(ntm, session.getValueFactory(), field);
// add the just created pdt to the nodetypetemplate
propertyDefinitionTemplates.add(pdt);
} else {
final NodeDefinitionTemplate ndt = getNodeDefinition(ntm, session.getValueFactory(), field);
// add the just created pdt to the nodetypetemplate
nodeDefinitionTemplates.add(ndt);
}
}
}
ntm.registerNodeType(ntt, false);
log.info("Registered JCR node type '" + ntt.getName() +
"' for class '" + classDescriptor.getClassName() + "'");
}
} else {
throw new NodeTypeCreationException("JCR supertypes could not be resolved.");
}
} catch (Exception e) {
log.error("Could not create node types from class descriptor.", e);
throw new NodeTypeCreationException(e);
}
}
private NodeDefinitionTemplate getNodeDefinition(final javax.jcr.nodetype.NodeTypeManager ntm,
final ValueFactory valueFactory,
final ChildNodeDefDescriptor field) throws RepositoryException {
final NodeDefinitionTemplate ndt = ntm.createNodeDefinitionTemplate();
if (field.getJcrName() != null) {
ndt.setName(field.getJcrName());
} else {
ndt.setName("*");
}
int onParentVersion = OnParentVersionAction.IGNORE;
if (field.getJcrOnParentVersion() != null
&& field.getJcrOnParentVersion().length() > 0) {
onParentVersion = OnParentVersionAction.valueFromName(field.getJcrOnParentVersion());
}
ndt.setOnParentVersion(onParentVersion);
ndt.setSameNameSiblings(field.isJcrSameNameSiblings());
ndt.setAutoCreated(field.isJcrAutoCreated());
ndt.setDefaultPrimaryTypeName(field.getDefaultPrimaryType());
ndt.setMandatory(field.isJcrMandatory());
ndt.setProtected(field.isJcrProtected());
ndt.setRequiredPrimaryTypeNames(getJcrSuperTypes(field.getJcrType()));
return ndt;
}
private PropertyDefinitionTemplate getPropertyDefinition(final javax.jcr.nodetype.NodeTypeManager ntm,
final ValueFactory valueFactory,
final PropertyDefDescriptor field) throws RepositoryException {
final PropertyDefinitionTemplate pdt = ntm.createPropertyDefinitionTemplate();
if (field.getJcrName() != null) {
pdt.setName(field.getJcrName());
} else {
pdt.setName(field.getFieldName());
}
if (field.getJcrType() != null) {
try {
pdt.setRequiredType(PropertyType.valueFromName(field.getJcrType()));
} catch (IllegalArgumentException e) {
log.warn("Invalid property type '{}' for '{}'. Set default to String type", field.getJcrType(), field.getJcrName());
pdt.setRequiredType(PropertyType.STRING);
}
} else {
log.info("No property type set for {}. Setting 'String' type.", field.getJcrName());
pdt.setRequiredType(PropertyType.STRING);
}
int onParentVersion = OnParentVersionAction.IGNORE;
if (field.getJcrOnParentVersion() != null &&
field.getJcrOnParentVersion().length() > 0) {
onParentVersion = OnParentVersionAction.valueFromName(field.getJcrOnParentVersion());
}
pdt.setOnParentVersion(onParentVersion);
pdt.setAutoCreated(field.isJcrAutoCreated());
pdt.setAvailableQueryOperators(new String[0]);
pdt.setFullTextSearchable(true);
pdt.setMandatory(field.isJcrMandatory());
pdt.setMultiple(field.isJcrMultiple());
pdt.setOnParentVersion(onParentVersion);
pdt.setProtected(field.isJcrProtected());
pdt.setQueryOrderable(true);
if (field instanceof FieldDescriptor) {
FieldDescriptor f = (FieldDescriptor) field;
if (f.getJcrDefaultValue() != null) {
if (pdt.getRequiredType() == PropertyType.STRING) {
Value[] vals = {valueFactory.createValue(f.getJcrDefaultValue())};
pdt.setDefaultValues(vals);
} else {
log.warn("Can only set default value for String properties. Skip for field '{}'", field.getJcrName());
}
}
pdt.setValueConstraints(f.getJcrValueConstraints());
}
return pdt;
}
/** Checks if all JCR super types for a given node type exist.
*
* @param ntMgr NodeTypeManager
* @param superTypes Comma separated String with JCR node types
* @return returns <code>false</code> if one of the supertypes does not exist, otherwise returns <code>true</code>
*/
private boolean checkSuperTypes(javax.jcr.nodetype.NodeTypeManager ntMgr,
String superTypes)
{
boolean exists = true;
if (superTypes != null && superTypes.length() > 0)
{
String[] superTypesArray = superTypes.split(",");
log.debug("JCR super types found: " + superTypesArray.length);
for (int i = 0; i < superTypesArray.length; i++)
{
try
{
ntMgr.getNodeType(superTypesArray[i]);
}
catch (Exception e)
{
log.error("JCR super type '" + superTypesArray[i] + "' does not exist!");
exists = false;
break;
}
}
}
return exists;
}
public String[] getJcrSuperTypes(String superTypes)
{
return superTypes.split(",");
}
private boolean isPropertyType(String type)
{
return (type.equals(PropertyType.TYPENAME_BINARY) ||
type.equals(PropertyType.TYPENAME_BOOLEAN) ||
type.equals(PropertyType.TYPENAME_DATE) ||
type.equals(PropertyType.TYPENAME_DOUBLE) ||
type.equals(PropertyType.TYPENAME_LONG) ||
type.equals(PropertyType.TYPENAME_NAME) ||
type.equals(PropertyType.TYPENAME_PATH) ||
type.equals(PropertyType.TYPENAME_REFERENCE) ||
type.equals(PropertyType.TYPENAME_WEAKREFERENCE) ||
type.equals(PropertyType.TYPENAME_DECIMAL) ||
type.equals(PropertyType.TYPENAME_URI) ||
type.equals(PropertyType.TYPENAME_STRING));
}
}