/*
* Copyright 2015 Martin Kouba
*
* 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 org.trimou.engine.resolver;
import org.trimou.engine.config.EngineConfigurationKey;
/**
* An enhanced resolver should be able to create a {@link Hint} for a
* sucessfully resolved context object and name.
*
* <p>
* Note that hints may not always give better results. E.g. if we have a tag
* <code>{{foo.bar}}</code> and first we pass data where foo is resolved as a
* map and then another data where foo is resolved as an integer, the hint
* created for the map will not work for integer. In this case, the hint should
* inform that it's not applicable and the resolver chain will be used to
* resolve the value.
* </p>
*
* <p>
* {@link EngineConfigurationKey#RESOLVER_HINTS_ENABLED} can be used to disable
* the hints entirely.
* </p>
*
* @author Martin Kouba
* @see EngineConfigurationKey#RESOLVER_HINTS_ENABLED
*/
public interface EnhancedResolver extends Resolver {
/**
* This method may only be called right after the
* {@link #resolve(Object, String, ResolutionContext)} of the same resolver
* returns a non-null value. The parameters must be the same.
*
* <p>
* The created hint is currently only used to skip the resolver chain for
* the first part of a key of a variable tag, i.e. <code>foo</code> for
* <code>{{foo}}</code> or <code>{{foo.bar}}</code>.
* </p>
*
* <p>
* This method must not return <code>null</code>.
* </p>
*
* @param contextObject
* @param name
* @param context
* @return the hint
* @see Hints#INAPPLICABLE_HINT
*/
Hint createHint(Object contextObject, String name, ResolutionContext context);
/**
* A hint could be used to skip the resolver chain for a part of the key of
* a specific tag. The hint can only be used for the same tag for which the
* context object and name were resolved. However, the resolver is permitted
* to reuse a hint instance.
*
* <p>
* Implementations must be thread-safe.
* </p>
*
* @author Martin Kouba
* @see EnhancedResolver#createHint(Object, String)
* @see Hints#INAPPLICABLE_HINT
*/
interface Hint {
/**
* Note that the runtime class of the context object may be different
* than the class used to create the hint.
*
* <p>
* If a hint is not applicable it should return <code>null</code> and
* the resolver chain will be used to resolve the value.
* </p>
*
* @param contextObject
* The current context object, may be <code>null</code>
* @param name
* The name (the key or its part) is never <code>null</code>
* @param context
* The resolution context
* @return the resolved object or <code>null</code>
*/
Object resolve(Object contextObject, String name,
ResolutionContext context);
}
}