/*
* Copyright (C) 2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.services.jcr.impl.core.nodetype.registration;
import org.exoplatform.services.jcr.core.nodetype.NodeDefinitionData;
import org.exoplatform.services.jcr.core.nodetype.NodeTypeData;
import org.exoplatform.services.jcr.core.nodetype.NodeTypeDataImpl;
import org.exoplatform.services.jcr.core.nodetype.PropertyDefinitionData;
import org.exoplatform.services.jcr.datamodel.InternalQName;
import org.exoplatform.services.jcr.impl.Constants;
import java.util.LinkedList;
import java.util.List;
import javax.jcr.PropertyType;
import javax.jcr.version.OnParentVersionAction;
/**
* Created by The eXo Platform SAS. <br>
* This class is designed to build NodeTypeData instances 'bit by bit'. It
* serves as a container to store NodeType definition setting in the process of
* reading the stream. When instance of builder is created default parameters
* are assigned to internal fields. When method <b>build()</b> is invoked new
* NodeTypeData instance is created using parameters from internal fields. To
* define new child or new property method <b>
* newNodeDefinitionDataBuilder()</b> or <b> newPropertyDefinitionDataBuilder()
* </b> should be invoked. <b>Instances of returned Builders are automatically
* added to internal child or property lists.</b> If some builder is not used it
* should be removed from internal lists by using NodeTypeDataBuilder's method
* removeNodeDefinitionDataBuilder() or removePropertyDefinitionDataBuilder.
*
* @author <a href="mailto:nikolazius@gmail.com">Nikolay Zamosenchuk</a>
* @version $Id: $
*/
public class NodeTypeDataBuilder
{
private InternalQName name;
private InternalQName[] supertypes;
private boolean isMixin;
private boolean isOrderable;
private InternalQName primaryItemName;
private PropertyDefinitionData[] propertyDefinitions;
private NodeDefinitionData[] childNodeDefinitions;
private boolean isAbstract;
private boolean isQueryable = true;
private List<NodeDefinitionDataBuilder> nodeDefinitionDataBuilders;
private List<PropertyDefinitionDataBuilder> propertyDefinitionDataBuilders;
/**
* This subclass represents child builder. To create instance of this class
* you should call NodeTypeDataBuilder's method
* <b>newNodeDefinitionDataBuilder()</b>.
*/
public class NodeDefinitionDataBuilder
{
private InternalQName name;
private InternalQName declaringType;
private InternalQName defaultPrimaryType;
private InternalQName[] requiredPrimaryTypes;
private boolean isAutoCreated;
private int onParentVersion;
private boolean isProtected;
private boolean isMandatory;
private boolean allowsSameNameSiblings;
/**
* Constructor is private. Could to be invoked only by NodeTypeDataBuilder.
*
* @param declaringType
*/
private NodeDefinitionDataBuilder(InternalQName declaringType)
{
this.declaringType = declaringType;
this.defaultPrimaryType = null;
this.requiredPrimaryTypes = new InternalQName[]{Constants.NT_BASE};
this.isAutoCreated = false;
this.onParentVersion = OnParentVersionAction.COPY;
this.isProtected = false;
this.isMandatory = false;
this.allowsSameNameSiblings = false;
}
/**
* This method returns new instance of NodeDefinitionData using parameters
* stored in current instance. This method is called by
* <b>NodeTypeDataBuilder.build()</b> before creating NodeTypeData instance.
*
* @return instance of NodeDefinitionData
*/
private NodeDefinitionData build()
{
return new NodeDefinitionData(name, declaringType, isAutoCreated, isMandatory, onParentVersion, isProtected,
requiredPrimaryTypes, defaultPrimaryType, allowsSameNameSiblings);
}
public void setName(InternalQName name)
{
this.name = name;
}
public void setDefaultPrimaryType(InternalQName defaultPrimaryType)
{
this.defaultPrimaryType = defaultPrimaryType;
}
public void setRequiredPrimaryTypes(InternalQName[] requiredPrimaryTypes)
{
this.requiredPrimaryTypes = requiredPrimaryTypes;
}
public void setAutoCreated(boolean isAutoCreated)
{
this.isAutoCreated = isAutoCreated;
}
public void setOnParentVersion(int onParentVersion)
{
this.onParentVersion = onParentVersion;
}
public void setProtected(boolean isProtected)
{
this.isProtected = isProtected;
}
public void setMandatory(boolean isMandatory)
{
this.isMandatory = isMandatory;
}
public void setAllowsSameNameSiblings(boolean allowsSameNameSiblings)
{
this.allowsSameNameSiblings = allowsSameNameSiblings;
}
}
/**
* This subclass represents property builder. To create instance of this class
* you should call NodeTypeDataBuilder's method
* <b>newPropertyDefinitionDataBuilders()</b>.
*/
public class PropertyDefinitionDataBuilder
{
private InternalQName name;
private int requiredType;
private String[] valueConstraints;
private String[] defaultValues;
private boolean isAutoCreated;
private boolean isProtected;
private boolean isMandatory;
private boolean isMultiple;
private boolean isFullTextSearchable;
private boolean isQueryOrderable;
private String[] queryOperators;
private int onParentVersion;
private InternalQName declaringType;
/**
* Constructor is private. Could to be invoked only by NodeTypeDataBuilder.
*
* @param declaringType
*/
private PropertyDefinitionDataBuilder(InternalQName declaringType)
{
this.requiredType = PropertyType.STRING;
this.valueConstraints = null;
this.defaultValues = null;
this.isAutoCreated = false;
this.isProtected = false;
this.isMandatory = false;
this.isMultiple = false;
// this.isFullTextSearchable = true;
// this.isQueryOrderable = true;
// this.queryOperators = Operator.getAllQueryOperators();
this.onParentVersion = OnParentVersionAction.COPY;
this.declaringType = declaringType;
}
/**
* This method returns new instance of NodeDefinitionData using parameters
* stored in current instance. This method is called by
* <b>NodeTypeDataBuilder.build()</b> before creating NodeTypeData instance.
*
* @return instance of PropertyDefinitionData
*/
private PropertyDefinitionData build()
{
return new PropertyDefinitionData(name, declaringType, isAutoCreated, isMandatory, onParentVersion,
isProtected, requiredType, valueConstraints, defaultValues, isMultiple);
}
public void setName(InternalQName name)
{
this.name = name;
}
public void setRequiredType(int requiredType)
{
this.requiredType = requiredType;
}
public void setValueConstraints(String[] valueConstraints)
{
this.valueConstraints = valueConstraints;
}
public void setDefaultValues(String[] defaultValues)
{
this.defaultValues = defaultValues;
}
public void setAutoCreated(boolean isAutoCreated)
{
this.isAutoCreated = isAutoCreated;
}
public void setProtected(boolean isProtected)
{
this.isProtected = isProtected;
}
public void setMandatory(boolean isMandatory)
{
this.isMandatory = isMandatory;
}
public void setMultiple(boolean isMultiple)
{
this.isMultiple = isMultiple;
}
public void setFullTextSearchable(boolean fullTextSearchable)
{
this.isFullTextSearchable = fullTextSearchable;
}
public void setQueryOrderable(boolean isQueryOrderable)
{
this.isQueryOrderable = isQueryOrderable;
}
public void setQueryOperators(String[] queryOperators)
{
this.queryOperators = queryOperators;
}
public void setOnParentVersion(int onParentVersion)
{
this.onParentVersion = onParentVersion;
}
}
/**
* Creates new instance of NodeTypeData builder with default parameters.
*/
public NodeTypeDataBuilder()
{
this.isMixin = false;
this.isOrderable = false;
this.isAbstract = false;
this.isQueryable = true;
this.primaryItemName = null;
this.supertypes = new InternalQName[]{Constants.NT_BASE};
this.propertyDefinitions = new PropertyDefinitionData[0];
this.childNodeDefinitions = new NodeDefinitionData[0];
this.nodeDefinitionDataBuilders = new LinkedList<NodeDefinitionDataBuilder>();
this.propertyDefinitionDataBuilders = new LinkedList<PropertyDefinitionDataBuilder>();
}
/**
* Creates child builder. This builder is automatically added to list of child
* builders in order to fill nodetType's child declaration array. If this
* instance is not used, it should be removed from internal list by calling
* NodeTypeData's method <b>removeNodeDefinitionDataBuilder()</b>.
*
* @return new NodeDefinitionBuilder
*/
public NodeDefinitionDataBuilder newNodeDefinitionDataBuilder()
{
NodeDefinitionDataBuilder child = new NodeDefinitionDataBuilder(this.name);
this.nodeDefinitionDataBuilders.add(child);
return child;
}
/**
* Creates property builder. This builder is automatically added to list of
* property builders in order to fill nodetType's property declaration array.
* If this instance is not used, it should be removed from internal list by
* calling NodeTypeData's method <b>removePropertyDefinitionDataBuilder()</b>.
*
* @return new NodeDefinitionBuilder
*/
public PropertyDefinitionDataBuilder newPropertyDefinitionDataBuilder()
{
PropertyDefinitionDataBuilder property = new PropertyDefinitionDataBuilder(this.name);
this.propertyDefinitionDataBuilders.add(property);
return property;
}
/**
* Removes given NodeDefinitionDataBuilder from internal list of NodeType's
* children.
*
* @param childBuilder
* @return result flag
*/
public boolean removeNodeDefinitionDataBuilder(NodeDefinitionDataBuilder childBuilder)
{
return nodeDefinitionDataBuilders.remove(childBuilder);
}
/**
* Removes given PropertyDefinitionDataBuilder from internal list of
* NodeType's properties.
*
* @param propertyBuilder
* @return result flag
*/
public boolean removePropertyDefinitionDataBuilder(PropertyDefinitionDataBuilder propertyBuilder)
{
return propertyDefinitionDataBuilders.remove(propertyBuilder);
}
/**
* Creates instance of NodeTypeData using parameters stored in this object.
*
* @return NodeTypeData
*/
public NodeTypeData build()
{
if (nodeDefinitionDataBuilders.size() > 0)
{
childNodeDefinitions = new NodeDefinitionData[nodeDefinitionDataBuilders.size()];
for (int i = 0; i < childNodeDefinitions.length; i++)
{
childNodeDefinitions[i] = nodeDefinitionDataBuilders.get(i).build();
}
}
if (propertyDefinitionDataBuilders.size() > 0)
{
propertyDefinitions = new PropertyDefinitionData[propertyDefinitionDataBuilders.size()];
for (int i = 0; i < propertyDefinitions.length; i++)
{
propertyDefinitions[i] = propertyDefinitionDataBuilders.get(i).build();
}
}
return new NodeTypeDataImpl(name, primaryItemName, isMixin, isOrderable, supertypes,
propertyDefinitions, childNodeDefinitions);
}
public void setName(InternalQName name)
{
this.name = name;
}
public void setSupertypes(InternalQName[] supertypes)
{
this.supertypes = supertypes;
}
public void setMixin(boolean isMixin)
{
this.isMixin = isMixin;
}
public void setOrderable(boolean isOrderable)
{
this.isOrderable = isOrderable;
}
public void setPrimaryItemName(InternalQName primaryItemName)
{
this.primaryItemName = primaryItemName;
}
public void setAbstract(boolean isAbstract)
{
this.isAbstract = isAbstract;
}
public void setQueryable(boolean isQueryable)
{
this.isQueryable = isQueryable;
}
}