001 /*
002 * Copyright 2002-2008 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016 package org.springframework.binding.value.support;
017
018 import org.springframework.rules.closure.Closure;
019 import org.springframework.core.style.StylerUtils;
020 import org.springframework.util.Assert;
021
022 /**
023 * ValueModel adding a <code>refreshable</code> aspect. A {@link Closure} is
024 * given that may be executed using the {@link #refresh()} method or forced to
025 * be executed on every {@link #getValue()}. The given refresh Closure is used
026 * to set the value before reading it.
027 *
028 * @author Keith Donald
029 */
030 public class RefreshableValueHolder extends ValueHolder {
031 private final Closure refreshFunction;
032
033 private boolean alwaysRefresh;
034
035 /**
036 * Constructor supplying a refresh <code>Closure</code>. Refresh has to be triggered
037 * manually.
038 */
039 public RefreshableValueHolder(Closure refreshFunction) {
040 this(refreshFunction, false);
041 }
042
043 /**
044 * Constructor supplying a refresh <code>Closure</code> that allways has to be triggered
045 * when reading the value.
046 */
047 public RefreshableValueHolder(Closure refreshFunction, boolean alwaysRefresh) {
048 this(refreshFunction, alwaysRefresh, true);
049 }
050
051 /**
052 * Constructor supplying a refresh <code>Closure</code> that allways has to be triggered
053 * when reading the value. Additionally a refresh is triggered on construction.
054 */
055 public RefreshableValueHolder(Closure refreshFunction, boolean alwaysRefresh, boolean lazyInit) {
056 super();
057 Assert.notNull(refreshFunction, "The refresh callback cannot be null");
058 this.refreshFunction = refreshFunction;
059 this.alwaysRefresh = alwaysRefresh;
060 if (!lazyInit) {
061 refresh();
062 }
063 }
064
065 /**
066 * {@inheritDoc}
067 *
068 * If allwaysRefresh is set, this method will trigger refresh() each time it is executed.
069 */
070 public Object getValue() {
071 if (alwaysRefresh) {
072 refresh();
073 }
074 return super.getValue();
075 }
076
077 /**
078 * Refresh te value by executing the refresh <code>Closure</code>.
079 */
080 public void refresh() {
081 if (logger.isDebugEnabled()) {
082 logger.debug("Refreshing held value '" + StylerUtils.style(super.getValue()) + "'");
083 }
084 setValue(refreshFunction.call(null));
085 }
086 }