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

io.vertigo.ui.impl.thymeleaf.components.FragmentUtil Maven / Gradle / Ivy

There is a newer version: 4.2.0
Show newest version
/**
 * vertigo - application development platform
 *
 * Copyright (C) 2013-2021, Vertigo.io, [email protected]
 *
 * 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 io.vertigo.ui.impl.thymeleaf.components;

import java.util.Map;

import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.engine.TemplateData;
import org.thymeleaf.engine.TemplateModel;
import org.thymeleaf.exceptions.TemplateInputException;
import org.thymeleaf.model.IModel;
import org.thymeleaf.processor.element.IElementModelStructureHandler;
import org.thymeleaf.standard.expression.Fragment;
import org.thymeleaf.standard.expression.FragmentExpression;
import org.thymeleaf.standard.expression.FragmentExpression.ExecutedFragmentExpression;
import org.thymeleaf.standard.expression.IStandardExpressionParser;
import org.thymeleaf.standard.expression.NoOpToken;
import org.thymeleaf.standard.expression.StandardExpressions;

public final class FragmentUtil {

	private FragmentUtil() {
		//private constructor for Helper
	}

	public static IModel getFragmentModel(final ITemplateContext context,
			final String attributeValue,
			final IElementModelStructureHandler structureHandler) {

		final Object fragmentObj = computeFragment(context, attributeValue);
		if (fragmentObj == null) {

			// If the Fragment result is null, this is an error. Note a NULL result is not the same as the result being the empty fragment
			// (~{})
			throw new TemplateInputException("Error resolving fragment: \"" + attributeValue + "\": " + "template or fragment could not be resolved");
		}

		final Fragment fragment = (Fragment) fragmentObj;

		final TemplateModel fragmentModel = fragment.getTemplateModel();
		final Map fragmentParameters = fragment.getParameters();

		/*
		 * APPLY THE FRAGMENT'S TEMPLATE RESOLUTION so that all code inside the fragment is executed with its own template resolution info (working
		 * as if it were a local variable)
		 */
		final TemplateData fragmentTemplateData = fragmentModel.getTemplateData();
		structureHandler.setTemplateData(fragmentTemplateData);

		/*
		 * APPLY THE FRAGMENT PARAMETERS AS LOCAL VARIABLES, perhaps after reshaping it according to the fragment signature
		 */
		if (fragmentParameters != null && fragmentParameters.size() > 0) {
			for (final Map.Entry fragmentParameterEntry : fragmentParameters.entrySet()) {
				structureHandler.setLocalVariable(fragmentParameterEntry.getKey(), fragmentParameterEntry.getValue());
			}
		}
		return fragmentModel;
	}

	private static Object computeFragment(final ITemplateContext context, final String input) {
		final IStandardExpressionParser expressionParser = StandardExpressions.getExpressionParser(context.getConfiguration());
		final FragmentExpression fragmentExpression = (FragmentExpression) expressionParser.parseExpression(context, input.trim());

		final ExecutedFragmentExpression executedFragmentExpression = FragmentExpression.createExecutedFragmentExpression(context, fragmentExpression);

		if (executedFragmentExpression.getFragmentSelectorExpressionResult() == null && executedFragmentExpression.getFragmentParameters() == null) {
			// We might be in the scenario that what we thought was a template name in fact was instead an expression
			// returning a Fragment itself, so we should simply return it
			final Object templateNameExpressionResult = executedFragmentExpression.getTemplateNameExpressionResult();
			if (templateNameExpressionResult != null) {
				if (templateNameExpressionResult instanceof Fragment) {
					return templateNameExpressionResult;
				}
				if (templateNameExpressionResult == NoOpToken.VALUE) {
					return NoOpToken.VALUE;
				}
			}
		}

		// Given this is a simple (originally unwrapped) fragment expression, we will consider the non-existence
		// of the fragment a failure. The reason we do this here instead of just waiting and seeing if we receive
		// a null and then failing is that, in order to receive such "null", the underlying resolution system would
		// have to execute a (potentially costly) resource.exists() call on the resolved resource.
		return FragmentExpression.resolveExecutedFragmentExpression(context, executedFragmentExpression, true);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy