All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.plexus.interpolation.fixed.FixedStringSearchInterpolator Maven / Gradle / Ivy

There is a newer version: 3.0.0-alpha-3
Show newest version
package org.codehaus.plexus.interpolation.fixed;

/*
 * Copyright 2014 The Codehaus Foundation.
 *
 * 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.
 */

import java.util.ArrayList;
import java.util.List;

import org.codehaus.plexus.interpolation.BasicInterpolator;
import org.codehaus.plexus.interpolation.InterpolationException;
import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
import org.codehaus.plexus.interpolation.RecursionInterceptor;

/**
 * 

* A fixed string search interpolator is permanently bound to a given set of value sources, * an is totally fixed and stateless over these value sources.

*

The fixed interpolator is also a #StatelessValueSource and can be used as a source * for a different fixed interpolator, creating a scope chain.

*

Once constructed, this interpolator will always point to the same set of objects (value sources), * in such a way that if the underlying object is fixed, expressions will always * evaluate to the same result.

*

The fixed interpolator can be shared among different clients and is thread safe to * the extent the underlying value sources can be accessed safely. * Since interpolation expressions cannot modify the objects, thread safety concerns * this will normally be limited to safe publication and memory model visibility of * underlying objects.

*

The fixed interpolator can be a valuesource

*/ public class FixedStringSearchInterpolator implements FixedValueSource { private final FixedValueSource[] valueSources; private final InterpolationPostProcessor postProcessor; public static final String DEFAULT_START_EXPR = "${"; public static final String DEFAULT_END_EXPR = "}"; private final String startExpr; private final String endExpr; private final String escapeString; private FixedStringSearchInterpolator( String startExpr, String endExpr, String escapeString, InterpolationPostProcessor postProcessor, FixedValueSource... valueSources) { this.startExpr = startExpr; this.endExpr = endExpr; this.escapeString = escapeString; if (valueSources == null) { throw new IllegalArgumentException("valueSources cannot be null"); } for (int i = 0; i < valueSources.length; i++) { if (valueSources[i] == null) { throw new IllegalArgumentException("valueSources[" + i + "] is null"); } } this.valueSources = valueSources; this.postProcessor = postProcessor; } public static FixedStringSearchInterpolator create( String startExpr, String endExpr, FixedValueSource... valueSources) { return new FixedStringSearchInterpolator(startExpr, endExpr, null, null, valueSources); } public static FixedStringSearchInterpolator create(FixedValueSource... valueSources) { return new FixedStringSearchInterpolator(DEFAULT_START_EXPR, DEFAULT_END_EXPR, null, null, valueSources); } public static FixedStringSearchInterpolator createWithPermittedNulls(FixedValueSource... valueSources) { List nonnulls = new ArrayList(); for (FixedValueSource item : valueSources) { if (item != null) nonnulls.add(item); } return new FixedStringSearchInterpolator( DEFAULT_START_EXPR, DEFAULT_END_EXPR, null, null, nonnulls.toArray(new FixedValueSource[nonnulls.size()])); } public FixedStringSearchInterpolator withExpressionMarkers(String startExpr, String endExpr) { return new FixedStringSearchInterpolator(startExpr, endExpr, escapeString, postProcessor, valueSources); } public FixedStringSearchInterpolator withPostProcessor(InterpolationPostProcessor postProcessor) { return new FixedStringSearchInterpolator(startExpr, endExpr, escapeString, postProcessor, valueSources); } public FixedStringSearchInterpolator withEscapeString(String escapeString) { return new FixedStringSearchInterpolator(startExpr, endExpr, escapeString, postProcessor, valueSources); } public String interpolate(String input) throws InterpolationCycleException { return interpolate(input, new InterpolationState()); } public static FixedStringSearchInterpolator empty() { return create(); } // Find out how to return null when we cannot interpolate this expression // At this point we should always be a ${expr} public Object getValue(String realExpr, InterpolationState interpolationState) { interpolationState.recursionInterceptor.expressionResolutionStarted(realExpr); try { Object value = null; for (FixedValueSource valueSource : valueSources) { value = valueSource.getValue(realExpr, interpolationState); if (value != null) { break; } } if (value != null) { if (interpolationState.root != null) { value = interpolationState.root.interpolate(String.valueOf(value), interpolationState); } return String.valueOf(value); } else { return null; } } finally { interpolationState.recursionInterceptor.expressionResolutionFinished(realExpr); } } public BasicInterpolator asBasicInterpolator() { final InterpolationState is = new InterpolationState(); return new BasicInterpolator() { public String interpolate(String input) throws InterpolationException { return FixedStringSearchInterpolator.this.interpolate(input, is); } public String interpolate(String input, RecursionInterceptor recursionInterceptor) throws InterpolationException { is.setRecursionInterceptor(recursionInterceptor); return FixedStringSearchInterpolator.this.interpolate(input, is); } }; } public String interpolate(String input, InterpolationState interpolationState) throws InterpolationCycleException { if (interpolationState.root == null) { interpolationState.root = this; } if (input == null) { // return empty String to prevent NPE too return ""; } StringBuilder result = new StringBuilder(input.length() * 2); int startIdx; int endIdx = -1; while ((startIdx = input.indexOf(startExpr, endIdx + 1)) > -1) { result.append(input, endIdx + 1, startIdx); endIdx = input.indexOf(endExpr, startIdx + 1); if (endIdx < 0) { break; } final String wholeExpr = input.substring(startIdx, endIdx + endExpr.length()); String realExpr = wholeExpr.substring(startExpr.length(), wholeExpr.length() - endExpr.length()); if (startIdx >= 0 && escapeString != null && escapeString.length() > 0) { int startEscapeIdx = startIdx == 0 ? 0 : startIdx - escapeString.length(); if (startEscapeIdx >= 0) { String escape = input.substring(startEscapeIdx, startIdx); if (escapeString.equals(escape)) { result.append(wholeExpr); result.replace(startEscapeIdx, startEscapeIdx + escapeString.length(), ""); continue; } } } boolean resolved = false; if (!interpolationState.unresolvable.contains(wholeExpr)) { if (realExpr.startsWith(".")) { realExpr = realExpr.substring(1); } if (interpolationState.recursionInterceptor.hasRecursiveExpression(realExpr)) { throw new InterpolationCycleException(interpolationState.recursionInterceptor, realExpr, wholeExpr); } Object value = getValue(realExpr, interpolationState); if (value != null) { value = interpolate(String.valueOf(value), interpolationState); if (postProcessor != null) { Object newVal = postProcessor.execute(realExpr, value); if (newVal != null) { value = newVal; } } result.append(String.valueOf(value)); resolved = true; } else { interpolationState.unresolvable.add(wholeExpr); } } if (!resolved) { result.append(wholeExpr); } if (endIdx > -1) { endIdx += endExpr.length() - 1; } } if (endIdx == -1 && startIdx > -1) { result.append(input, startIdx, input.length()); } else if (endIdx < input.length()) { result.append(input, endIdx + 1, input.length()); } return result.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy