/*
* Copyright (c) 2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wso2.carbon.registry.jcr.nodetype;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.registry.jcr.util.RegistryNodeTypeUtil;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.nodetype.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class RegistryNodeType implements NodeType {
private NodeTypeTemplate ntd;
private NodeTypeManager nodeTypeManager;
private static Log log = LogFactory.getLog(RegistryNodeType.class);
public static final String UNDEFINED_NODE_NAME = "*";
public RegistryNodeType(NodeTypeDefinition ntd, NodeTypeManager nodeTypeManager) {
this.ntd = (RegistryNodeTypeTemplate) ntd;
this.nodeTypeManager = nodeTypeManager;
}
public NodeType[] getSupertypes() {
Set<NodeType> nodeTypeList = new HashSet<NodeType>();
try {
for (String ntName : ntd.getDeclaredSupertypeNames()) {
nodeTypeList.add(nodeTypeManager.getNodeType(ntName));
}
// if no super types, at least return nt:base
if (nodeTypeList.size() == 0 && (!ntd.isMixin()) &&
!ntd.getName().equals("nt:base")) {
nodeTypeList.add(nodeTypeManager.getNodeType("nt:base"));
}
} catch (RepositoryException e) {
log.error("Registry Error while getting super types " + e.getMessage());
}
return nodeTypeList.toArray(new NodeType[0]);
}
public NodeType[] getDeclaredSupertypes() {
return getSupertypes(); // Assume one level of inheritance
}
public NodeTypeIterator getSubtypes() {
Set<NodeType> nodeTypeList = new HashSet<NodeType>();
List nttList = ntd.getNodeDefinitionTemplates();
if (nttList.size() != 0) {
for (Object ntt : nttList) {
String ntName = ((NodeDefinition) ntt).getName();
try {
nodeTypeList.add(nodeTypeManager.getNodeType(ntName));
} catch (RepositoryException e) {
log.error("Registry Error while getting super types " + e.getMessage());
}
}
}
return new RegistryNodeTypeIterator(nodeTypeList);
}
public NodeTypeIterator getDeclaredSubtypes() {
return getSubtypes(); // Assume one level of inheritance
}
public boolean isNodeType(String s) {
if ("nt:base".equals(s)) {
return true;
}
boolean isNodetype = ntd.getName().equals(s); //TODO MUST check bottom-up in a nodetype tree to check isNodetype
if (!isNodetype) {
for (String ntsuper : ntd.getDeclaredSupertypeNames()) {
if (s.equals(ntsuper)) {
isNodetype = true;
break;
}
}
}
return isNodetype;
}
private void addPrimaryTypePropIfNotExists(PropertyDefinition[] pdfs) throws RepositoryException {
// check and add primary type as property
boolean hasPrimaryTypeProp = false;
for (PropertyDefinition pd : pdfs) {
if (pd.getName().equals("jcr:primaryType")) {
hasPrimaryTypeProp = true;
}
}
if (!hasPrimaryTypeProp) {
ntd.getPropertyDefinitionTemplates().add(RegistryNodeTypeUtil.
createJCRPrimaryTypeProperty(nodeTypeManager, ntd.getName()));
}
}
public PropertyDefinition[] getPropertyDefinitions() {
PropertyDefinition[] pdfs;
List<PropertyDefinition> pdList = null;
if (ntd != null) {
try {
pdfs = ntd.getDeclaredPropertyDefinitions();
addPrimaryTypePropIfNotExists(pdfs);
} catch (RepositoryException e) {
// TODO Log Error
}
return ntd.getDeclaredPropertyDefinitions();
} else {
return new PropertyDefinition[0];
}
}
public NodeDefinition[] getChildNodeDefinitions() {
if (ntd != null) {
return ntd.getDeclaredChildNodeDefinitions();
} else {
return new NodeDefinition[0];
}
}
public boolean canSetProperty(String s, Value value) {
if (value == null) {
return canRemoveItem(s);
}
PropertyDefinition property = getMatchingPropDef(ntd.getDeclaredPropertyDefinitions(), value.getType(), s, false);
int TYPE = property.getRequiredType();
if (property.isProtected()) {
return false;
}
switch (TYPE) {
case PropertyType.BINARY:
if (validateBinaryPropertyCanSet(value, property)) {
return true;
}
break;
case PropertyType.DATE:
if (validateDatePropertyCanSet(value, property)) {
return true;
}
break;
case PropertyType.PATH:
if (validatePathPropertyCanSet(value, property)) {
return true;
}
break;
case PropertyType.STRING:
return true;
case PropertyType.BOOLEAN:
return true;
case PropertyType.DOUBLE:
return true;
case PropertyType.LONG:
return true;
case PropertyType.NAME:
return true;
default:
break;
}
// if ((pd != null) && (pd.getName().equals(s)) &&
// (value.getType() == pd.getRequiredType())) {
// return true;
// }
return false;
}
private PropertyDefinition getMatchingPropDef(PropertyDefinition[] pdfs, int type, String name, boolean isMultiValued) {
for (PropertyDefinition pd : pdfs) {
int reqType = pd.getRequiredType();
if ((name.equals(pd.getName())
&& (isMultiValued == pd.isMultiple())
// || reqType == PropertyType.UNDEFINED
// || type == PropertyType.UNDEFINED)))
)) {
return pd;
}
}
return null;
}
private boolean validateBinaryPropertyCanSet(Value value, PropertyDefinition pd) {
if ((value.getType() == PropertyType.STRING
|| value.getType() == PropertyType.BINARY
|| value.getType() == PropertyType.DOUBLE
|| value.getType() == PropertyType.DATE
|| value.getType() == PropertyType.LONG
|| value.getType() == PropertyType.BOOLEAN
|| value.getType() == PropertyType.NAME
|| value.getType() == PropertyType.PATH)) {
return true;
}
return false;
}
private boolean isPathInFormat(Value value) {
//TODO add more special characters to validate a path
try {
String path = value.getString();
if (!"".equals(path)
&& (path.contains(":")
|| path.contains(",")
|| path.contains("%")
|| path.contains("^")
|| path.contains("*")
|| path.contains("(")
|| path.contains(")")
)) {
return false;
}
} catch (RepositoryException e) {
return true;
}
return true;
}
private boolean isDateInFormat(Value value) {
try {
if (value.getString().contains("time=")) {
return true;
}
} catch (RepositoryException e) {
return false;
}
return false;
}
//TODO add simple date format chek also
public boolean isValidDate(String inDate) {
if (inDate == null)
return false;
//set the format to use as a constructor argument
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
if (inDate.trim().length() != dateFormat.toPattern().length())
return false;
dateFormat.setLenient(false);
try {
//parse the inDate parameter
dateFormat.parse(inDate.trim());
} catch (ParseException pe) {
return false;
}
return true;
}
private boolean validatePathPropertyCanSet(Value value, PropertyDefinition pd) {
if (value.getType() == PropertyType.NAME
|| value.getType() == PropertyType.PATH
) {
return true;
}
if (value.getType() == PropertyType.DOUBLE
|| value.getType() == PropertyType.BOOLEAN
|| value.getType() == PropertyType.LONG) {
return false;
}
if (value.getType() != PropertyType.PATH) {
if (isPathInFormat(value)) {
return true;
}
}
return false;
}
private boolean validateDatePropertyCanSet(Value value, PropertyDefinition pd) {
if (value.getType() == PropertyType.DOUBLE
|| value.getType() == PropertyType.DATE
|| value.getType() == PropertyType.LONG) {
return true;
}
if (value.getType() != PropertyType.DATE) {
if (isDateInFormat(value)) {
return true;
}
}
return false;
}
private boolean validateBooleanPropertyCanSet(Value value) {
for (Object o : ntd.getPropertyDefinitionTemplates()) {
PropertyDefinitionTemplate pd = (PropertyDefinitionTemplate) o;
if ((pd.getRequiredType() == PropertyType.BINARY) && (
value.getType() == PropertyType.STRING
|| value.getType() == PropertyType.DOUBLE
|| value.getType() == PropertyType.DATE
|| value.getType() == PropertyType.LONG
|| value.getType() == PropertyType.BOOLEAN
|| value.getType() == PropertyType.NAME
|| value.getType() == PropertyType.PATH)) {
return true;
}
}
return false;
}
private boolean isPropertyProtected(String propName) {
for (Object o : ntd.getPropertyDefinitionTemplates()) {
PropertyDefinitionTemplate pd = (PropertyDefinitionTemplate) o;
if ((pd != null) && (pd.getName().equals(propName)) && (pd.isProtected())) {
return true;
}
}
return false;
}
private boolean validatePropertyIsMultiple(String propName) {
for (Object o : ntd.getPropertyDefinitionTemplates()) {
PropertyDefinitionTemplate pd = (PropertyDefinitionTemplate) o;
if ((pd != null) && (pd.getName().equals(propName)) && (!pd.isMultiple())) {
return false;
}
}
return true;
}
public boolean canSetProperty(String s, Value[] values) {
//return false if the property is not multiple
if (!validatePropertyIsMultiple(s)) {
return false;
}
if (isPropertyProtected(s)) {
return false;
}
for (Value value : values) {
if (!canSetProperty(s, value)) {
return false;
}
}
return true;
}
public boolean canAddChildNode(String s) { //TODO
//return false if the match child def not have a default primary type
for (NodeDefinition nd : getChildNodeDefinitions()) {
if (s.equals(nd.getName()) && nd.getDefaultPrimaryTypeName() != null) {
return true;
}
}
// true if resedual child defs has a non null primary type for a undefined child name
if (!isChildNameInDefList(s)) {
for (NodeDefinition nd : getChildNodeDefinitions()) {
if (nd.getDefaultPrimaryTypeName() != null) {
return true;
}
}
}
if (!isChildNameInDefList(s)) {
return false;
}
return false;
}
public boolean canAddChildNode(String s, String s1) { //TODO
// s- ChildNode name
// s1 = nodeType name
//Cannot add child for Mixin types
if (s1.startsWith("mix")) {
return false;
}
if (checkOnlyNodeNameUndefinedRule(s1)) {
return true;
}
if (!isChildNameInDefList(s)) {
return false;
}
for (NodeDefinition nd : getChildNodeDefinitions()) {
if (nd.getName().equals(s) && (isReqTypesContainsNodeType(nd, s1))) {
return true;
}
}
return false;
}
private boolean checkOnlyNodeNameUndefinedRule(String s1) {
// if child node name is undefined and still if nodetype of a child node def matches will return true
for (NodeDefinition nd : getChildNodeDefinitions()) {
if (isReqTypesContainsNodeType(nd, s1)) {
return true;
}
}
return false;
}
private boolean isReqTypesContainsNodeType(NodeDefinition nd, String s1) {
//Also check NTBase Cannot Be Added
for (String name : nd.getRequiredPrimaryTypeNames()) {
if ((!"nt:base".equals(s1)) &&
("nt:unstructured".equals(s1) || name.equals(s1))) {
return true;
}
}
return false;
}
private boolean checkNTBaseCannotAdded(String ntUnstr, String name) {
if (ntUnstr.equals("nt:unstructured") && "nt:base".equals(name)) {
return true;
} else {
return false;
}
}
private boolean isChildNameInDefList(String name) {
for (NodeDefinition nd : getChildNodeDefinitions()) {
if (name.equals(nd.getName())) {
return true;
}
}
return false;
}
public boolean canRemoveItem(String s) {
boolean canRemove = true;
// check mandatory /protected properties
for (Object pdt : ntd.getPropertyDefinitionTemplates()) {
if (((PropertyDefinition) pdt).getName().equals(s)) {
if (((PropertyDefinition) pdt).isMandatory()
|| ((PropertyDefinition) pdt).isProtected()) {
canRemove = false;
return canRemove;
}
}
}
// check mandatory /protected child items
for (NodeDefinition nd : ntd.getDeclaredChildNodeDefinitions()) {
if (nd.getName().equals(s)) {
if (nd.isMandatory() || nd.isProtected()) {
canRemove = false;
return canRemove;
}
}
}
return canRemove;
}
public boolean canRemoveNode(String s) {
boolean canRemoveNd = true;
Iterator it = ntd.getNodeDefinitionTemplates().iterator();
NodeDefinition nd = null;
while (it.hasNext()) {
nd = (NodeDefinitionTemplate) it.next();
if ((nd != null) && (nd.getName().equals(s)) &&
(nd.isProtected() || nd.isMandatory())) {
canRemoveNd = false;
return canRemoveNd;
}
}
return canRemoveNd;
}
public boolean canRemoveProperty(String s) {
boolean canRemovePrp = true;
Iterator it = ntd.getPropertyDefinitionTemplates().iterator();
PropertyDefinition pd = null;
while (it.hasNext()) {
pd = (PropertyDefinitionTemplate) it.next();
if (((pd != null) && pd.getName().equals(s) &&
(pd.isProtected() || pd.isMandatory()))) {
canRemovePrp = false;
return canRemovePrp;
}
}
return canRemovePrp;
}
public String getName() {
return ntd.getName();
}
public String[] getDeclaredSupertypeNames() {
return ntd.getDeclaredSupertypeNames();
}
public boolean isAbstract() {
return ntd.isAbstract();
}
public boolean isMixin() {
return ntd.isMixin();
}
public boolean hasOrderableChildNodes() {
return ntd.hasOrderableChildNodes();
}
public boolean isQueryable() {
return ntd.isQueryable();
}
public String getPrimaryItemName() {
return ntd.getPrimaryItemName();
}
public PropertyDefinition[] getDeclaredPropertyDefinitions() {
return ntd.getDeclaredPropertyDefinitions();
}
public NodeDefinition[] getDeclaredChildNodeDefinitions() {
return ntd.getDeclaredChildNodeDefinitions();
}
public NodeTypeTemplate getDefinition() { // Non JCR method
return (NodeTypeTemplate) ntd;
}
}