Skip to content

Commit

Permalink
Merge pull request #5558 from mP1/feature/SpreadsheetTemplateContextT…
Browse files Browse the repository at this point in the history
…emplateContext

SpreadsheetTemplateContextTemplateContext
  • Loading branch information
mP1 authored Jan 13, 2025
2 parents e49bb4f + 94a2959 commit 638bac2
Show file tree
Hide file tree
Showing 9 changed files with 1,124 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/*
* Copyright 2019 Miroslav Pokorny (github.com/mP1)
*
* 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 walkingkooka.spreadsheet.template;

import walkingkooka.Cast;
import walkingkooka.datetime.DateTimeContext;
import walkingkooka.math.DecimalNumberContext;
import walkingkooka.spreadsheet.expression.SpreadsheetExpressionEvaluationContext;
import walkingkooka.spreadsheet.expression.SpreadsheetExpressionEvaluationContextDelegator;
import walkingkooka.spreadsheet.parser.SpreadsheetParserContext;
import walkingkooka.spreadsheet.parser.SpreadsheetParserContextDelegator;
import walkingkooka.template.TemplateValueName;
import walkingkooka.tree.expression.Expression;
import walkingkooka.tree.expression.ExpressionEvaluationContext;
import walkingkooka.tree.expression.ExpressionNumberKind;
import walkingkooka.tree.expression.ExpressionReference;
import walkingkooka.tree.expression.function.ExpressionFunction;

import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;

/**
* A {@link SpreadsheetTemplateContext} that sources values and functionality from {@link SpreadsheetParserContext},
* {@link SpreadsheetExpressionEvaluationContext} and template values from a {@link Function}.
*/
final class BasicSpreadsheetTemplateContext implements SpreadsheetTemplateContext,
SpreadsheetParserContextDelegator,
SpreadsheetExpressionEvaluationContextDelegator {

static BasicSpreadsheetTemplateContext with(final SpreadsheetParserContext spreadsheetParserContext,
final SpreadsheetExpressionEvaluationContext spreadsheetExpressionEvaluationContext,
final Function<TemplateValueName, Expression> nameToExpression) {
return new BasicSpreadsheetTemplateContext(
Objects.requireNonNull(spreadsheetParserContext, "spreadsheetParserContext"),
Objects.requireNonNull(spreadsheetExpressionEvaluationContext, "spreadsheetExpressionEvaluationContext"),
Objects.requireNonNull(nameToExpression, "nameToExpression")
);
}

private BasicSpreadsheetTemplateContext(final SpreadsheetParserContext spreadsheetParserContext,
final SpreadsheetExpressionEvaluationContext spreadsheetExpressionEvaluationContext,
final Function<TemplateValueName, Expression> nameToExpression) {
this.spreadsheetParserContext = spreadsheetParserContext;
this.spreadsheetExpressionEvaluationContext = spreadsheetExpressionEvaluationContext.enterScope(
this::reference
);
this.nameToExpression = nameToExpression;
}

// SpreadsheetParserContext.........................................................................................

@Override
public SpreadsheetParserContext spreadsheetParserContext() {
return this.spreadsheetParserContext;
}

private final SpreadsheetParserContext spreadsheetParserContext;

// ExpressionEvaluationContext......................................................................................

@Override
public Object evaluateExpression(final Expression expression) {
return expression.toValue(this);
}

@Override
public Object evaluateFunction(final ExpressionFunction<?, ? extends ExpressionEvaluationContext> function,
final List<Object> parameters) {
return function
.apply(
this.prepareParameters(
function,
parameters
),
Cast.to(this)
);
}

@Override
public Optional<Optional<Object>> reference(final ExpressionReference reference) {
Objects.requireNonNull(reference, "reference");

Optional<Optional<Object>> value;

// TemplateValueName gets passed into a SpreadsheetLabelName by SpreadsheetParsers#expression
if (reference instanceof TemplateValueName) {
final TemplateValueName templateValueName = (TemplateValueName) reference;

final Expression expression = this.nameToExpression.apply(templateValueName);
if(null == expression) {
throw new IllegalStateException("Missing expression for " + templateValueName);
}

value = Optional.of(
Optional.ofNullable(
this.evaluateExpression(expression)
)
);
} else {
value = Optional.empty(); // unknown references have no value
}

return value;
}

@Override
public SpreadsheetExpressionEvaluationContext spreadsheetExpressionEvaluationContext() {
return this.spreadsheetExpressionEvaluationContext;
}

private final SpreadsheetExpressionEvaluationContext spreadsheetExpressionEvaluationContext;

@Override
public ExpressionNumberKind expressionNumberKind() {
return this.spreadsheetParserContext.expressionNumberKind();
}

@Override
public Locale locale() {
return this.spreadsheetParserContext.locale();
}

@Override
public DateTimeContext dateTimeContext() {
return this.spreadsheetParserContext;
}

@Override
public DecimalNumberContext decimalNumberContext() {
return this.spreadsheetParserContext;
}

// templateValue....................................................................................................

@Override
public String templateValue(final TemplateValueName name) {
return this.convertOrFail(
this.evaluateExpression(
this.nameToExpression.apply(name)
),
String.class
);
}

private final Function<TemplateValueName, Expression> nameToExpression;

// toString.........................................................................................................

@Override
public String toString() {
return this.spreadsheetExpressionEvaluationContext +
" " +
this.spreadsheetParserContext +
" " +
this.nameToExpression;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* Copyright 2019 Miroslav Pokorny (github.com/mP1)
*
* 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 walkingkooka.spreadsheet.template;

import walkingkooka.Either;
import walkingkooka.convert.Converter;
import walkingkooka.net.AbsoluteUrl;
import walkingkooka.spreadsheet.SpreadsheetCell;
import walkingkooka.spreadsheet.convert.SpreadsheetConverterContext;
import walkingkooka.spreadsheet.meta.SpreadsheetMetadata;
import walkingkooka.spreadsheet.parser.FakeSpreadsheetParserContext;
import walkingkooka.spreadsheet.parser.SpreadsheetParserToken;
import walkingkooka.spreadsheet.reference.SpreadsheetCellReference;
import walkingkooka.spreadsheet.reference.SpreadsheetLabelName;
import walkingkooka.spreadsheet.reference.SpreadsheetSelection;
import walkingkooka.template.TemplateValueName;
import walkingkooka.text.CaseSensitivity;
import walkingkooka.text.cursor.TextCursor;
import walkingkooka.tree.expression.Expression;
import walkingkooka.tree.expression.ExpressionEvaluationContext;
import walkingkooka.tree.expression.ExpressionFunctionName;
import walkingkooka.tree.expression.ExpressionReference;
import walkingkooka.tree.expression.function.ExpressionFunction;
import walkingkooka.tree.expression.function.ExpressionFunctionParameter;

import java.util.List;
import java.util.Optional;

public class FakeSpreadsheetTemplateContext extends FakeSpreadsheetParserContext
implements SpreadsheetTemplateContext {

public FakeSpreadsheetTemplateContext() {
super();
}

@Override
public SpreadsheetParserToken parseFormula(final TextCursor formula) {
throw new UnsupportedOperationException();
}

@Override
public Optional<SpreadsheetCell> cell() {
throw new UnsupportedOperationException();
}

@Override
public Optional<SpreadsheetCell> loadCell(final SpreadsheetCellReference cell) {
throw new UnsupportedOperationException();
}

@Override
public AbsoluteUrl serverUrl() {
throw new UnsupportedOperationException();
}

@Override
public Converter<SpreadsheetConverterContext> converter() {
throw new UnsupportedOperationException();
}

@Override
public SpreadsheetMetadata spreadsheetMetadata() {
throw new UnsupportedOperationException();
}

@Override
public SpreadsheetSelection resolveLabel(final SpreadsheetLabelName labelName) {
throw new UnsupportedOperationException();
}

@Override
public Object evaluateExpression(final Expression expression) {
throw new UnsupportedOperationException();
}

@Override
public <T> T prepareParameter(final ExpressionFunctionParameter<T> parameter,
final Object value) {
throw new UnsupportedOperationException();
}

@Override
public Object evaluateFunction(final ExpressionFunction<?, ? extends ExpressionEvaluationContext> function,
final List<Object> values) {
throw new UnsupportedOperationException();
}

@Override
public Object handleException(final RuntimeException thrown) {
throw new UnsupportedOperationException();
}

@Override
public Optional<Optional<Object>> reference(final ExpressionReference reference) {
throw new UnsupportedOperationException();
}

@Override
public CaseSensitivity stringEqualsCaseSensitivity() {
throw new UnsupportedOperationException();
}

@Override
public long dateOffset() {
throw new UnsupportedOperationException();
}

@Override
public boolean canConvert(final Object value,
final Class<?> type) {
throw new UnsupportedOperationException();
}

@Override
public <T> Either<T, String> convert(final Object value,
final Class<T> type) {
throw new UnsupportedOperationException();
}

@Override
public boolean isPure(final ExpressionFunctionName name) {
throw new UnsupportedOperationException();
}

@Override
public ExpressionFunction<?, ExpressionEvaluationContext> expressionFunction(final ExpressionFunctionName name) {
throw new UnsupportedOperationException();
}

@Override
public String templateValue(final TemplateValueName name) {
throw new UnsupportedOperationException();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2019 Miroslav Pokorny (github.com/mP1)
*
* 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 walkingkooka.spreadsheet.template;

import walkingkooka.spreadsheet.expression.SpreadsheetExpressionEvaluationContext;
import walkingkooka.spreadsheet.parser.SpreadsheetParserContext;
import walkingkooka.template.TemplateValueName;

/**
* A Context that leverages Spreadsheet components to parse and render templates.
*/
public interface SpreadsheetTemplateContext extends SpreadsheetParserContext,
SpreadsheetExpressionEvaluationContext {

/**
* {@see TemplateContext#templateValue}
*/
String templateValue(final TemplateValueName name);
}
Loading

0 comments on commit 638bac2

Please sign in to comment.