/* 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.activiti.workflow.simple.alfresco.conversion.script;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.activiti.workflow.simple.alfresco.conversion.AlfrescoConversionConstants;
import org.activiti.workflow.simple.alfresco.conversion.AlfrescoConversionUtil;
import org.activiti.workflow.simple.alfresco.model.M2Model;
import org.activiti.workflow.simple.alfresco.model.M2Namespace;
import org.activiti.workflow.simple.definition.form.FormPropertyDefinition;
import org.activiti.workflow.simple.exception.SimpleWorkflowException;
/**
* A builder to create property-references that are resolved at conversion-time to reference
* the correct fully-qualified property name, based on the "simple" name given in the {@link FormPropertyDefinition}.
*
* @author Frederik Heremans
*/
public class PropertyReference {
protected static final String REFERENCE_PREFIX = "{{";
protected static final String REFERENCE_SUFFIX = "}}";
protected static final String USERNAME_REFERENCE_EXPRESSION ="$'{'{0}.properties.userName'}'";
protected static final String GROUPNAME_REFERENCE_EXPRESSION ="$'{'{0}.properties.authorityName'}'";
protected static final String REFERENCE_EXPRESSION ="$'{'{0}'}'";
protected static final Pattern REFERENCE_EXPRESSION_PATTERN = Pattern.compile("\\{\\{[^\\{](.*?)\\}\\}");
protected String propertyName;
protected String additionalProperties;
protected boolean isPrefixed = false;
public PropertyReference(String propertyName) {
this(propertyName, null);
}
public PropertyReference(String propertyName, String additionalProperties) {
this.propertyName = propertyName;
this.additionalProperties = additionalProperties;
if(additionalProperties != null && additionalProperties.isEmpty()) {
this.additionalProperties = null;
}
isPrefixed = propertyName != null && propertyName.contains(":");
}
public String getPlaceholder() {
return REFERENCE_PREFIX + propertyName + REFERENCE_SUFFIX;
}
public String getPropertyName() {
return propertyName;
}
public String getUsernameReferenceExpression(String namespacePrefix) {
String qualifiedName = getQualifiedName(namespacePrefix);
return MessageFormat.format(USERNAME_REFERENCE_EXPRESSION, getVariableName(qualifiedName));
}
public String getGroupReferenceExpression(String namespacePrefix) {
String qualifiedName = getQualifiedName(namespacePrefix);
return MessageFormat.format(GROUPNAME_REFERENCE_EXPRESSION, getVariableName(qualifiedName));
}
public String getPropertyReferenceExpression(String namespacePrefix) {
String qualifiedName = getQualifiedName(namespacePrefix);
return MessageFormat.format(REFERENCE_EXPRESSION, getVariableName(qualifiedName));
}
public String getVariableReference(String namespacePrefix) {
String qualifiedName = getQualifiedName(namespacePrefix);
return getVariableName(qualifiedName);
}
public void validate(M2Model model) {
String namespacePrefix = model.getNamespaces().get(0).getPrefix();
boolean valid = false;
if(propertyName.contains(":")) {
// Already prefixed. Check if we import that namespace...
for(M2Namespace imported : model.getImports()) {
if(propertyName.startsWith(imported.getPrefix())) {
valid = true;
break;
}
}
if(!valid && !propertyName.startsWith(AlfrescoConversionConstants.WORKFLOW_NAMESPACE.getPrefix()) &&
!propertyName.startsWith(AlfrescoConversionConstants.BPM_NAMESPACE.getPrefix())) {
throw new SimpleWorkflowException("Property reference: " + this.getPlaceholder() + " references a property for a namespace that is not imported in the BPM-model");
} else {
valid = true;
}
}
if(!valid && !model.isContainedInModel(getQualifiedName(namespacePrefix))) {
throw new SimpleWorkflowException("Property reference: " + this.getPlaceholder() + " does not reference an existing property.");
}
}
public static boolean isPropertyReference(String value) {
return value != null && value.startsWith(REFERENCE_PREFIX)
&& value.endsWith(REFERENCE_SUFFIX);
}
public static boolean containsPropertyReference(String value) {
if(value == null) {
return false;
}
return value != null && value.indexOf(REFERENCE_PREFIX) >= 0
&& value.indexOf(REFERENCE_SUFFIX) >= 0;
}
public static String replaceAllPropertyReferencesInString(String refrence, String namespacePrefix, List<PropertyReference> foundReferences, boolean wrapAsExpression) {
String newValue = refrence;
List<String> references = new ArrayList<String>();
Matcher regexMatcher = REFERENCE_EXPRESSION_PATTERN.matcher(refrence);
while (regexMatcher.find()) {
references.add(regexMatcher.group());
}
if(!references.isEmpty()) {
PropertyReference ref = null;
for(String reference : references) {
ref = PropertyReference.createReference(reference);
if(ref != null) {
foundReferences.add(ref);
if(wrapAsExpression) {
newValue = newValue.replace(reference, ref.getPropertyReferenceExpression(namespacePrefix));
} else {
newValue = newValue.replace(reference, ref.getVariableReference(namespacePrefix));
}
}
}
}
return newValue;
}
/**
* @return a {@link PropertyReference} based on the given placeholder string. Returns null in case
* the given string is not a valid property reference.
*/
public static PropertyReference createReference(String referenceString) {
PropertyReference ref = null;
if(isPropertyReference(referenceString)) {
String raw = referenceString.replace(REFERENCE_PREFIX, "").replace(REFERENCE_SUFFIX, "");
if(raw.contains(".")) {
String additional = null;
String propertyName = raw;
int indexOf = raw.indexOf(".");
if(indexOf > 0) {
propertyName = raw.substring(0, indexOf);
additional = raw.substring(indexOf + 1);
}
ref = new PropertyReference(propertyName, additional);
} else {
ref = new PropertyReference(raw);
}
}
return ref;
}
protected String getVariableName(String propertyName) {
if(propertyName != null) {
if(additionalProperties != null) {
return propertyName.replace(':', '_') + "." + additionalProperties;
} else {
return propertyName.replace(':', '_');
}
}
return null;
}
protected String getQualifiedName(String namespacePrefix) {
String qualifiedName = null;
if(isPrefixed) {
qualifiedName = propertyName;
} else {
qualifiedName = AlfrescoConversionUtil.getQualifiedName(namespacePrefix, propertyName);
}
return qualifiedName;
}
}