/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 fr.openwide.core.wicket.more.model; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.wicket.markup.repeater.data.IDataProvider; import org.apache.wicket.model.AbstractPropertyModel; import org.apache.wicket.model.IModel; import org.bindgen.BindingRoot; import fr.openwide.core.wicket.more.markup.html.factory.AbstractDetachableFactory; import fr.openwide.core.wicket.more.markup.html.factory.IDetachableFactory; /** * An improved and simplified version of the BindingModel implementation of * wicket-bindgen. * * It is based on PropertyModel instead of using bindgen features because * bindgen behavior is not the same as Wicket one. Typically, when an * object is null in the path, Wicket tries to instantiate using the default * constructor which allows to have cost().quantity() working even if * cost property is null. * * @author igor.vaynberg * @author Open Wide * * @param <R> * type of object that is the root of the expression * @param <T> * type of object returned by the expression */ public class BindingModel<R, T> extends AbstractPropertyModel<T> { private static final long serialVersionUID = -4018038300151228083L; private static final String ROOT = "#root"; private final String propertyExpression; public static final <T, U> IDetachableFactory<IModel<T>, BindingModel<T, U>> factory(BindingRoot<? super T, ? extends U> binding) { final String propertyExpression = binding.getPath(); return new AbstractDetachableFactory<IModel<T>, BindingModel<T, U>>() { private static final long serialVersionUID = 1L; @Override public BindingModel<T, U> create(IModel<T> parameter) { return new BindingModel<T, U>(parameter, propertyExpression); } @Override public String toString() { return BindingModel.class.getSimpleName() + ".factory(" + propertyExpression + ")"; } }; } private BindingModel(Object root, String propertyExpression) { super(root); if (ROOT.equals(propertyExpression)) { this.propertyExpression = null; } else { this.propertyExpression = propertyExpression; } } /** * Convenience method to convert a {@link BindingRoot} into a * {@link BindingModel} * * @param <T> * @param binding * @return binding model for {@code binding} */ public static <R, T> BindingModel<R, T> of(IModel<? extends R> root, BindingRoot<R, T> binding) { return new BindingModel<R, T>(root, binding.getPath()); } /** * Convenience method to convert a {@link BindingRoot} into a * {@link BindingModel} * * @param <T> * @param binding * @return binding model for {@code binding} */ public static <R, T> BindingModel<R, T> of(IDataProvider<?> root, BindingRoot<R, T> binding) { return new BindingModel<R, T>(root, binding.getPath()); } @Override protected String propertyExpression() { return propertyExpression; } @Override public String toString() { return new ToStringBuilder(this) .append("root", getTarget()) .append("propertyExpression", getPropertyExpression()) .build(); } }