blob: e2945f90e912ce47223d4caa8e2cbbbf66f06a92 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.jackrabbit.oak.query.ast;
import org.apache.jackrabbit.oak.api.PropertyValue;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.query.QueryImpl;
import org.apache.jackrabbit.oak.query.ValueConverter;
import org.jetbrains.annotations.NotNull;
/**
* The base class for all abstract syntax tree nodes.
*/
abstract class AstElement {
protected QueryImpl query;
abstract boolean accept(AstVisitor v);
protected String protect(Object expression) {
String str = expression.toString();
if (str.indexOf(' ') >= 0) {
return '(' + str + ')';
} else {
return str;
}
}
protected String quote(String pathOrName) {
pathOrName = pathOrName.replaceAll("]", "]]");
return '[' + pathOrName + ']';
}
protected String quoteJson(String string) {
return '"' + string.replaceAll("\"", "\"\"") + '"';
}
public void setQuery(QueryImpl query) {
this.query = query;
}
/**
* Normalize the property name (including namespace remapping).
* Asterisks are kept.
*
* @param propertyName the property name to normalize
* @return the normalized (oak-) property name
*/
protected String normalizePropertyName(String propertyName) {
// TODO normalize the path (remove superfluous ".." and "."
// where possible)
if (query == null) {
return propertyName;
}
if (propertyName == null) {
return null;
}
int slash = propertyName.indexOf('/');
if (slash < 0) {
return normalizeNonRelativePropertyName(propertyName);
}
// relative properties
String relativePath = PathUtils.getParentPath(propertyName);
if (relativePath.indexOf('*') >= 0) {
StringBuilder buff = new StringBuilder();
for (String p : PathUtils.elements(relativePath)) {
if (!p.equals("*")) {
p = query.getOakPath(p);
}
if (p.length() > 0) {
if (buff.length() > 0) {
buff.append('/');
}
buff.append(p);
}
}
relativePath = buff.toString();
} else {
relativePath = query.getOakPath(relativePath);
}
propertyName = PathUtils.getName(propertyName);
propertyName = normalizeNonRelativePropertyName(propertyName);
return PathUtils.concat(relativePath, propertyName);
}
private String normalizeNonRelativePropertyName(String propertyName) {
if (propertyName.equals("*")) {
return propertyName;
}
return query.getOakPath(propertyName);
}
/**
* Validate and normalize the path.
*
* @param path the path to validate
* @return the validated and normalized path
*/
protected String normalizePath(String path) {
// TODO normalize the path (remove superfluous ".." and "."
// where possible)
if (query == null) {
return path;
}
return query.getOakPath(path);
}
protected PropertyValue convertValueToType(PropertyValue v, PropertyValue targetType) {
if (targetType.count() == 0) {
return v;
}
int type = targetType.getType().tag();
if (v.getType().tag() == type) {
return v;
}
try {
return ValueConverter.convert(v, type, query.getNamePathMapper());
} catch (IllegalArgumentException e) {
// not possible to convert
return v;
}
}
/**
* Calculate the session local path (the path excluding the workspace name)
* if possible.
*
* @param path the absolute path
* @return the session local path, or null if not within this workspace
*/
protected String getLocalPath(String path) {
return path;
}
/**
* @return a clone of self. Default implementation in {@link AstElement} returns same reference
* to {@code this}.
*/
@NotNull
public AstElement copyOf() {
return this;
}
}