/******************************************************************************* * Copyright (c) 2007, 2014 compeople AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * compeople AG - initial API and implementation *******************************************************************************/ package org.eclipse.riena.ui.ridgets.databinding; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import org.eclipse.core.databinding.conversion.Converter; import org.eclipse.core.databinding.conversion.IConverter; /** * Creates {@link IConverter}s that translate from type {@code K} to type * {@code L} and back. Conversion is done by mapping pairs of values of each * type to each other. * <p> * The factory is initially configured by invoking {@link #add(Object, Object)} * one or more times. This introduces the matching pairs of values. Afterwards * {@link #createFromToConverter()} will return an K-to-L converter and * {@link #createToFromConverter()} will return a L-to-K converter. * <p> * Here is an example that used the {@link ConverterFactory} to convert * {@code enum}-values to human-readable Strings: * * <pre> * private enum Answer { * YES, NO, MAYBE * } * // ... * ConverterFactory<?, ?> factory * = new ConverterFactory<Answer, String>(Answer.class, String.class); * fac.add(Answer.YES, "Yes") * .add(Answer.NO, "No") * .add(Answer.MAYBE, "Maybe") * .add(null, ""); * ridget.setModelToUIControlConverter(factory.createFromToConverter()); * ridget.setUIControlToModelConverter(factory.createToFromConverter()); * </pre> * * @see IConverter * @since 1.2 */ public final class ConverterFactory<K, L> { private final Class<K> fromType; private final Class<L> toType; private final Map<K, L> modelToUI; /** * Create a converter factory between two types * * @param fromType * the origin-type * @param toType * the destination-type */ public ConverterFactory(final Class<K> fromType, final Class<L> toType) { this.fromType = fromType; this.toType = toType; modelToUI = new HashMap<K, L>(); } /** * Create a conversion rule, mapping the {@code fromValue} to the * {@code toValue} and back. * * @param fromValue * the origin value * @param toValue * the destination value * @return this instance (fluent API) */ public ConverterFactory<K, L> add(final K fromValue, final L toValue) { modelToUI.put(fromValue, toValue); return this; } /** * Returns an {@link IConverter} that maps values of the origin-type * {@code K} to the destination-type {@code L}. * <p> * Value pairs must be introduced via the {@link #add(Object, Object)} * method. Unknown origin-values are mapped to {@code null}. * * @return an {@link IConverter}; never null */ public IConverter createFromToConverter() { return new Converter(fromType, toType) { public Object convert(final Object fromObject) { return modelToUI.get(fromObject); } }; } /** * Returns an {@link IConverter} that maps values of the destination-type * {@code L} to the origin-type {@code K}. * <p> * Value pairs must be introduced via the {@link #add(Object, Object)} * method. Unknown destination-values are mapped to {@code null}. * * @return an {@link IConverter}; never null */ public IConverter createToFromConverter() { return new Converter(toType, fromType) { public Object convert(final Object fromObject) { K result = null; final Iterator<Entry<K, L>> iter = modelToUI.entrySet().iterator(); while (result == null && iter.hasNext()) { final Entry<K, L> entry = iter.next(); if (entry.getValue().equals(fromObject)) { result = entry.getKey(); } } return result; } }; } }