Search in sources :

Example 6 with InternalComponentResources

use of org.apache.tapestry5.internal.InternalComponentResources in project tapestry-5 by apache.

the class BindParameterWorker method getEmbeddedComponentResourcesForPublishedParameter.

/**
 * Returns the {@link InternalComponentResources} of an embeddedComponent that contains the published parameter
 * publishedParameterName. This is basically a recursive search for published parameters.
 */
private InternalComponentResources getEmbeddedComponentResourcesForPublishedParameter(InternalComponentResources containerResources, String publishedParameterName) {
    List<InternalComponentResources> embeddedComponentResourcesList = CollectionFactory.newList();
    embeddedComponentResourcesList.add(containerResources);
    while (!embeddedComponentResourcesList.isEmpty()) {
        InternalComponentResources resources = embeddedComponentResourcesList.remove(0);
        ComponentModel containerComponentModel = resources.getComponentModel();
        for (String embeddedComponentId : containerComponentModel.getEmbeddedComponentIds()) {
            EmbeddedComponentModel embeddedComponentModel = containerComponentModel.getEmbeddedComponentModel(embeddedComponentId);
            InternalComponentResources embeddedComponentResources = (InternalComponentResources) resources.getEmbeddedComponent(embeddedComponentId).getComponentResources();
            /**
             * If the parameter is not a formal parameter, then the parameter must be a published parameter
             * of an embeddedComponent of the component we are currently examining.
             */
            if (embeddedComponentModel.getPublishedParameters().contains(publishedParameterName) && embeddedComponentResources.getComponentModel().isFormalParameter(publishedParameterName)) {
                return embeddedComponentResources;
            }
            embeddedComponentResourcesList.add(embeddedComponentResources);
        }
    }
    return null;
}
Also used : EmbeddedComponentModel(org.apache.tapestry5.model.EmbeddedComponentModel) InternalComponentResources(org.apache.tapestry5.internal.InternalComponentResources) ComponentModel(org.apache.tapestry5.model.ComponentModel) MutableComponentModel(org.apache.tapestry5.model.MutableComponentModel) EmbeddedComponentModel(org.apache.tapestry5.model.EmbeddedComponentModel)

Example 7 with InternalComponentResources

use of org.apache.tapestry5.internal.InternalComponentResources in project tapestry-5 by apache.

the class ParameterWorker method createComputedParameterConduit.

@SuppressWarnings("all")
private ComputedValue<FieldConduit<Object>> createComputedParameterConduit(final String parameterName, final String fieldTypeName, final Parameter annotation, final MethodHandle defaultMethodHandle) {
    boolean primitive = PlasticUtils.isPrimitive(fieldTypeName);
    final boolean allowNull = annotation.allowNull() && !primitive;
    return new ComputedValue<FieldConduit<Object>>() {

        public ParameterConduit get(InstanceContext context) {
            final InternalComponentResources icr = context.get(InternalComponentResources.class);
            final Class fieldType = classCache.forName(fieldTypeName);
            final PerThreadValue<ParameterState> stateValue = perThreadManager.createValue();
            return new ParameterConduit() {

                // Default value for parameter, computed *once* at
                // page load time.
                private Object defaultValue = classCache.defaultValueForType(fieldTypeName);

                private Binding parameterBinding;

                boolean loaded = false;

                private boolean invariant = false;

                {
                    // Inform the ComponentResources about the parameter conduit, so it can be
                    // shared with mixins.
                    icr.setParameterConduit(parameterName, this);
                    icr.getPageLifecycleCallbackHub().addPageLoadedCallback(new Runnable() {

                        public void run() {
                            load();
                        }
                    });
                }

                private ParameterState getState() {
                    ParameterState state = stateValue.get();
                    if (state == null) {
                        state = new ParameterState();
                        state.value = defaultValue;
                        stateValue.set(state);
                    }
                    return state;
                }

                private boolean isLoaded() {
                    return loaded;
                }

                public void set(Object instance, InstanceContext context, Object newValue) {
                    ParameterState state = getState();
                    if (!loaded) {
                        state.value = newValue;
                        defaultValue = newValue;
                        return;
                    }
                    // This will catch read-only or unbound parameters.
                    writeToBinding(newValue);
                    state.value = newValue;
                    // If caching is enabled for the parameter (the typical case) and the
                    // component is currently rendering, then the result
                    // can be cached in this ParameterConduit (until the component finishes
                    // rendering).
                    state.cached = annotation.cache() && icr.isRendering();
                }

                private Object readFromBinding() {
                    Object result;
                    try {
                        Object boundValue = parameterBinding.get();
                        result = typeCoercer.coerce(boundValue, fieldType);
                    } catch (RuntimeException ex) {
                        throw new TapestryException(String.format("Failure reading parameter '%s' of component %s: %s", parameterName, icr.getCompleteId(), ExceptionUtils.toMessage(ex)), parameterBinding, ex);
                    }
                    if (result == null && !allowNull) {
                        throw new TapestryException(String.format("Parameter '%s' of component %s is bound to null. This parameter is not allowed to be null.", parameterName, icr.getCompleteId()), parameterBinding, null);
                    }
                    return result;
                }

                private void writeToBinding(Object newValue) {
                    if (parameterBinding == null) {
                        return;
                    }
                    try {
                        Object coerced = typeCoercer.coerce(newValue, parameterBinding.getBindingType());
                        parameterBinding.set(coerced);
                    } catch (RuntimeException ex) {
                        throw new TapestryException(String.format("Failure writing parameter '%s' of component %s: %s", parameterName, icr.getCompleteId(), ExceptionUtils.toMessage(ex)), icr, ex);
                    }
                }

                public void reset() {
                    if (!invariant) {
                        getState().reset(defaultValue);
                    }
                }

                public void load() {
                    if (logger.isDebugEnabled()) {
                        logger.debug("{} loading parameter {}", icr.getCompleteId(), parameterName);
                    }
                    if (!icr.isBound(parameterName)) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("{} parameter {} not yet bound", icr.getCompleteId(), parameterName);
                        }
                        // Otherwise, construct a default binding, or use one provided from
                        // the component.
                        Binding binding = getDefaultBindingForParameter();
                        if (logger.isDebugEnabled()) {
                            logger.debug("{} parameter {} bound to default {}", icr.getCompleteId(), parameterName, binding);
                        }
                        if (binding != null) {
                            icr.bindParameter(parameterName, binding);
                        }
                    }
                    parameterBinding = icr.getBinding(parameterName);
                    loaded = true;
                    invariant = parameterBinding != null && parameterBinding.isInvariant();
                    getState().value = defaultValue;
                }

                public boolean isBound() {
                    return parameterBinding != null;
                }

                public Object get(Object instance, InstanceContext context) {
                    if (!isLoaded()) {
                        return defaultValue;
                    }
                    ParameterState state = getState();
                    if (state.cached || !isBound()) {
                        return state.value;
                    }
                    // Read the parameter's binding and cast it to the
                    // field's type.
                    Object result = readFromBinding();
                    if (invariant || (annotation.cache() && icr.isRendering())) {
                        state.value = result;
                        state.cached = true;
                    }
                    return result;
                }

                private Binding getDefaultBindingForParameter() {
                    if (InternalUtils.isNonBlank(annotation.value())) {
                        return bindingSource.newBinding("default " + parameterName, icr, annotation.defaultPrefix(), annotation.value());
                    }
                    if (annotation.autoconnect()) {
                        return defaultProvider.defaultBinding(parameterName, icr);
                    }
                    // Invoke the default method and install any value or Binding returned there.
                    invokeDefaultMethod();
                    return parameterBinding;
                }

                private void invokeDefaultMethod() {
                    if (defaultMethodHandle == null) {
                        return;
                    }
                    if (logger.isDebugEnabled()) {
                        logger.debug("{} invoking method {} to obtain default for parameter {}", icr.getCompleteId(), defaultMethodHandle, parameterName);
                    }
                    MethodInvocationResult result = defaultMethodHandle.invoke(icr.getComponent());
                    result.rethrow();
                    Object defaultValue = result.getReturnValue();
                    if (defaultValue == null) {
                        return;
                    }
                    if (defaultValue instanceof Binding) {
                        parameterBinding = (Binding) defaultValue;
                        return;
                    }
                    parameterBinding = new LiteralBinding(null, "default " + parameterName, defaultValue);
                }
            };
        }
    };
}
Also used : LiteralBinding(org.apache.tapestry5.internal.bindings.LiteralBinding) Binding(org.apache.tapestry5.Binding) LiteralBinding(org.apache.tapestry5.internal.bindings.LiteralBinding) InternalComponentResources(org.apache.tapestry5.internal.InternalComponentResources) TapestryException(org.apache.tapestry5.commons.internal.util.TapestryException)

Example 8 with InternalComponentResources

use of org.apache.tapestry5.internal.InternalComponentResources in project tapestry-5 by apache.

the class ComponentPageElementImpl method bindMixinParameter.

public void bindMixinParameter(String mixinId, String parameterName, Binding binding) {
    InternalComponentResources mixinResources = NamedSet.get(mixinIdToComponentResources, mixinId);
    mixinResources.bindParameter(parameterName, binding);
}
Also used : InternalComponentResources(org.apache.tapestry5.internal.InternalComponentResources)

Example 9 with InternalComponentResources

use of org.apache.tapestry5.internal.InternalComponentResources in project tapestry-5 by apache.

the class InternalComponentResourcesImplTest method add_page_lifecycle_listener.

@Test
public void add_page_lifecycle_listener() {
    Component component = mockComponent();
    Instantiator ins = mockInstantiator(component);
    ComponentModel model = mockComponentModel();
    ComponentPageElement element = mockComponentPageElement();
    Page page = mockPage();
    PageLifecycleListener listener = newMock(PageLifecycleListener.class);
    train_getModel(ins, model);
    page.addLifecycleListener(listener);
    replay();
    InternalComponentResources resources = new InternalComponentResourcesImpl(page, element, null, null, null, null, ins, false);
    resources.addPageLifecycleListener(listener);
    verify();
}
Also used : PageLifecycleListener(org.apache.tapestry5.runtime.PageLifecycleListener) InternalComponentResources(org.apache.tapestry5.internal.InternalComponentResources) ComponentModel(org.apache.tapestry5.model.ComponentModel) Instantiator(org.apache.tapestry5.internal.services.Instantiator) Component(org.apache.tapestry5.runtime.Component) Test(org.testng.annotations.Test)

Example 10 with InternalComponentResources

use of org.apache.tapestry5.internal.InternalComponentResources in project tapestry-5 by apache.

the class InternalComponentResourcesImplTest method post_render_cleanup_removes_all_variables.

@Test
public void post_render_cleanup_removes_all_variables() {
    Component component = mockComponent();
    Instantiator ins = mockInstantiator(component);
    ComponentModel model = mockComponentModel();
    train_getModel(ins, model);
    replay();
    InternalComponentResources resources = new InternalComponentResourcesImpl(null, null, null, elementResources, "Foo.bar", null, ins, false);
    resources.storeRenderVariable("fred", "FRED");
    resources.storeRenderVariable("barney", "BARNEY");
    resources.postRenderCleanup();
    try {
        resources.getRenderVariable("fred");
        unreachable();
    } catch (IllegalArgumentException ex) {
        assertEquals(ex.getMessage(), "Component Foo.bar does not contain a stored render variable with name 'fred'.  Stored render variables: (none).");
    }
    verify();
}
Also used : InternalComponentResources(org.apache.tapestry5.internal.InternalComponentResources) ComponentModel(org.apache.tapestry5.model.ComponentModel) Instantiator(org.apache.tapestry5.internal.services.Instantiator) Component(org.apache.tapestry5.runtime.Component) Test(org.testng.annotations.Test)

Aggregations

InternalComponentResources (org.apache.tapestry5.internal.InternalComponentResources)22 Test (org.testng.annotations.Test)10 ComponentModel (org.apache.tapestry5.model.ComponentModel)9 Component (org.apache.tapestry5.runtime.Component)8 Instantiator (org.apache.tapestry5.internal.services.Instantiator)7 Binding (org.apache.tapestry5.Binding)5 TypeCoercer (org.apache.tapestry5.commons.services.TypeCoercer)4 InternalPropBinding (org.apache.tapestry5.internal.bindings.InternalPropBinding)4 MarkupWriter (org.apache.tapestry5.MarkupWriter)3 Request (org.apache.tapestry5.http.services.Request)3 ValueEncoderSource (org.apache.tapestry5.services.ValueEncoderSource)3 Messages (org.apache.tapestry5.commons.Messages)2 TapestryException (org.apache.tapestry5.commons.internal.util.TapestryException)2 Platform (org.apache.tapestry5.corelib.components.SelectTest.Platform)2 LiteralBinding (org.apache.tapestry5.internal.bindings.LiteralBinding)2 ParameterModel (org.apache.tapestry5.model.ParameterModel)2 EnumSelectModel (org.apache.tapestry5.util.EnumSelectModel)2 ComponentResources (org.apache.tapestry5.ComponentResources)1 EventContext (org.apache.tapestry5.EventContext)1 Persist (org.apache.tapestry5.annotations.Persist)1