/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco 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 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Alfresco. If not, see .
* #L%
*/
package org.alfresco.repo.virtual.config;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* A String name or qname path expression that resolves to a {@link NodeRef}.
* The given name or qname path is relative to a {@link NodeRefContext}
* repository location. The default context is set to
* {@link CompanyHomeContext#COMPANY_HOME_CONTEXT_NAME}. Other contexts can be
* set using their name with {@link #setContext(String)}.
* The set path is automatically detected and checked for consistency.
*/
public class NodeRefPathExpression implements NodeRefExpression
{
private static final String NAMESPACE_DELIMITER = ":";
private static final String PATH_DELIMITER = "/";
private Map contexts = new HashMap();
private NodeRefResolver resolver;
private String context = CompanyHomeContext.COMPANY_HOME_CONTEXT_NAME;
private String[] createNamePath;
private String[] namePath;
private String[] qNamePath;
public NodeRefPathExpression(NodeRefResolver resolver, Map contexts)
{
this(resolver,
contexts,
CompanyHomeContext.COMPANY_HOME_CONTEXT_NAME,
null);
}
public NodeRefPathExpression(NodeRefResolver resolver, Map contexts, String context,
String path)
{
super();
this.resolver = resolver;
this.contexts = contexts;
this.context = context;
setPath(path);
}
public void setContext(String context)
{
this.context = context;
}
public void setCreatedPathName(String createNamePath)
{
this.createNamePath = createNamePath.split(",");
}
/**
* Path setter.
* The type of path is automatically detected and checked for consistency.
*
* @param path the string path to be resolved later
* @throws AlfrescoRuntimeException if the given path is inconsistent (i.e.
* a combination of qnames and names)
*/
public void setPath(String path) throws AlfrescoRuntimeException
{
String[] pathElements = splitAndNormalizePath(path);
if (isQNamePath(pathElements))
{
this.qNamePath = pathElements;
}
else if (isNamePath(pathElements))
{
this.namePath = pathElements;
}
else
{
throw new AlfrescoRuntimeException("Invalid path format : " + path);
}
}
private boolean isQNamePath(String[] pathElements)
{
for (int i = 0; i < pathElements.length; i++)
{
if (!pathElements[i].contains(NAMESPACE_DELIMITER))
{
return false;
}
}
return true;
}
private boolean isNamePath(String[] pathElements)
{
for (int i = 0; i < pathElements.length; i++)
{
if (pathElements[i].contains(NAMESPACE_DELIMITER))
{
return false;
}
}
return true;
}
public static String[] splitAndNormalizePath(String path)
{
if (path == null || path.trim().length() == 0)
{
return new String[] {};
}
String[] splitPath = path.split(PATH_DELIMITER);
// remove blank entries resulted from misplaced delimiters
int shift = 0;
for (int i = 0; i < splitPath.length; i++)
{
if (splitPath[i] == null || splitPath[i].trim().isEmpty())
{
shift++;
}
else if (shift > 0)
{
splitPath[i - shift] = splitPath[i];
}
}
if (shift > 0)
{
String[] noBlanksSplitPath = new String[splitPath.length - shift];
if (noBlanksSplitPath.length > 0)
{
System.arraycopy(splitPath,
0,
noBlanksSplitPath,
0,
noBlanksSplitPath.length);
}
splitPath = noBlanksSplitPath;
}
return splitPath;
}
@Override
public NodeRef resolve()
{
NodeRefContext theContext = contexts.get(context);
if (this.namePath != null)
{
return theContext.resolveNamePath(this.namePath,
resolver);
}
else
{
return theContext.resolveQNamePath(this.qNamePath,
resolver);
}
}
@Override
public NodeRef resolve(boolean createIfNotFound)
{
NodeRef nodeRef = resolve();
if (nodeRef == null && createIfNotFound)
{
NodeRefContext theContext = contexts.get(context);
if (this.namePath != null)
{
return theContext.createNamePath(this.namePath,
resolver);
}
else
{
return theContext.createQNamePath(this.qNamePath,
this.createNamePath,
resolver);
}
}
return nodeRef;
}
@Override
public String toString()
{
StringBuilder pathString = new StringBuilder();
pathString.append("<");
pathString.append(this.context);
pathString.append(">/");
if (this.namePath != null)
{
pathString.append(Arrays.toString(this.namePath));
}
if (this.qNamePath != null)
{
pathString.append(Arrays.toString(this.qNamePath));
}
return "";
}
}