blob: b5d22ab9fff5ac065e72061a054ad383c15726a6 [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.nifi.parameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ExpressionLanguageAwareParameterParser extends AbstractParameterParser implements ParameterParser {
private static final Logger logger = LoggerFactory.getLogger(ExpressionLanguageAwareParameterParser.class);
private static final char DOLLAR_SIGN = '$';
@Override
public ParameterTokenList parseTokens(final String input) {
if (input == null || input.isEmpty()) {
return new StandardParameterTokenList(input, Collections.emptyList());
}
final List<ParameterToken> tokens = new ArrayList<>();
int sequentialStartTags = 0;
boolean oddDollarCount = false;
char lastChar = 0;
int embeddedElCount = 0;
int expressionStart = -1;
for (int i=0; i < input.length(); i++) {
final char c = input.charAt(i);
switch (c) {
case START_TAG:
// If last character was a # character, then the previous character along with this character
// represent an escaped literal # character. Otherwise, this character potentially represents
// the start of a Parameter Reference.
sequentialStartTags++;
break;
case OPEN_BRACE:
if (oddDollarCount && lastChar == '$') {
if (embeddedElCount == 0) {
expressionStart = i - 1;
}
}
// Keep track of the number of opening curly braces that we are embedded within,
// if we are within an Expression. If we are outside of an Expression, we can just ignore
// curly braces. This allows us to ignore the first character if the value is something
// like: { ${abc} }
// However, we will count the curly braces if we have something like: ${ $${abc} }
if (expressionStart > -1) {
embeddedElCount++;
continue;
}
if (sequentialStartTags > 0) {
final ParameterToken token = parseParameterToken(input, i, sequentialStartTags, tokens);
// If we found a reference, skip 'i' to the end of the reference, since there can't be any other references before that point.
if (token != null) {
i = token.getEndOffset();
}
}
break;
case CLOSE_BRACE:
if (embeddedElCount <= 0) {
continue;
}
if (--embeddedElCount == 0) {
expressionStart = -1;
oddDollarCount = false;
}
break;
case DOLLAR_SIGN:
oddDollarCount = !oddDollarCount;
break;
default:
break;
}
if (c != START_TAG) {
sequentialStartTags = 0;
}
lastChar = c;
}
return new StandardParameterTokenList(input, tokens);
}
}