/**
* Copyright (C) 2015 Valkyrie RCP
*
* 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.valkyriercp.binding.form.support;
import org.springframework.binding.collection.AbstractCachingMapDecorator;
import org.springframework.util.Assert;
import org.valkyriercp.binding.form.FieldFace;
import org.valkyriercp.binding.form.FieldFaceSource;
import java.util.HashMap;
import java.util.Map;
/**
* A convenience superclass for FieldFaceSource's that require caching to improve the performance of FieldFace lookup.
*
* <p>
* FieldFace retrieval is delegated to subclasses using the {@link #loadFieldFace(String, Object)} method.
*
* @author Oliver Hutchison
* @author Mathias Broekelmann
*/
public abstract class CachingFieldFaceSource implements FieldFaceSource {
private static final Object DEFAULT_CONTEXT = new Object();
/*
* A cache with context keys and Map from field to FieldFace values. The keys are held with week references so this
* class will not prevent GC of context instances.
*/
private final AbstractCachingMapDecorator cachedFieldFaceDescriptors = new AbstractCachingMapDecorator(true) {
public Object create(Object key) {
return new HashMap();
}
};
protected CachingFieldFaceSource() {
}
public FieldFace getFieldFace(String field) {
return getFieldFace(field, null);
}
public FieldFace getFieldFace(final String field, final Object context) {
Map faceDescriptors = (Map) cachedFieldFaceDescriptors.get(context == null ? DEFAULT_CONTEXT : context);
FieldFace fieldFaceDescriptor = (FieldFace) faceDescriptors.get(field);
if (fieldFaceDescriptor == null) {
fieldFaceDescriptor = loadFieldFace(field, context);
Assert.notNull(fieldFaceDescriptor, "FieldFace must not be null.");
faceDescriptors.put(field, fieldFaceDescriptor);
}
return fieldFaceDescriptor;
}
/**
* Loads the FieldFace for the given field path and context id. This value will be cached so performance need not be
* a concern of this method.
*
* @param field
* the form field path
* @param context
* optional context for which the FieldFace is being resolved
* @return the FieldFace for the given context id (never null).
*/
protected abstract FieldFace loadFieldFace(String field, Object context);
}