All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.tuple.TupleBuilder Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2013-2016 the original author or authors.
 *
 * 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.springframework.tuple;

import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.util.Assert;

/**
 * Builder class to create Tuple instances.
 * 
 * Default Locale is US for NumberFormat and default DatePattern is "yyyy-MM-dd"
 *
 * Note: Using a custom conversion service that is instance based (not configured
 * as a singleton) will have significant performance impacts.
 * 
 * @author Mark Pollack
 * @author David Turanski
 * @author Michael Minella
 * @author Gunnar Hillert
 */
public class TupleBuilder {

	private List names = new ArrayList<>();

	private List values = new ArrayList<>();

	private final boolean mutable;

	private ConfigurableConversionService customConversionService = null;

	private final static String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";

	private final static Locale DEFAULT_LOCALE = Locale.US;

	private static final ConfigurableConversionService defaultConversionService;

	private static Converter tupleToStringConverter = new TupleToJsonStringConverter();

	private static Converter stringToTupleConverter = new JsonStringToTupleConverter();

	static {
		defaultConversionService = new DefaultTupleConversionService();
		defaultConversionService.addConverterFactory(new LocaleAwareStringToNumberConverterFactory(NumberFormat
				.getInstance(DEFAULT_LOCALE)));
		DateFormat dateFormat = new SimpleDateFormat(DEFAULT_DATE_PATTERN);
		dateFormat.setLenient(false);
		defaultConversionService.addConverter(new StringToDateConverter(dateFormat));
	}

	/**
	 * Return a new builder that will create immutable Tuples.
	 */
	public static TupleBuilder mutableTuple() {
		return new TupleBuilder(true);
	}

	/**
	 * Return a new builder that will create {@link MutableTuple}.
	 */
	public static TupleBuilder tuple() {
		return new TupleBuilder(false);
	}

	/**
	 * Creates a builder that will create immutable Tuples.
	 */
	public TupleBuilder() {
		this(false);
	}

	private TupleBuilder(boolean mutable) {
		this.mutable = mutable;
	}

	public Tuple of(String k1, Object v1) {
		return newTuple(namesOf(k1), valuesOf(v1));
	}

	public Tuple of(String k1, Object v1, String k2, Object v2) {
		addEntry(k1, v1);
		addEntry(k2, v2);
		return build();
	}

	public Tuple of(String k1, Object v1, String k2, Object v2, String k3, Object v3) {
		addEntry(k1, v1);
		addEntry(k2, v2);
		addEntry(k3, v3);
		return build();
	}

	public Tuple of(String k1, Object v1, String k2, Object v2, String k3, Object v3, String k4, Object v4) {
		addEntry(k1, v1);
		addEntry(k2, v2);
		addEntry(k3, v3);
		addEntry(k4, v4);
		return build();
	}

	public Tuple ofNamesAndValues(List names, List values) {
		this.names = names;
		this.values = values;
		return build();
	}

	public TupleBuilder put(String k1, Object v1) {
		addEntry(k1, v1);
		return this;
	}

	/**
	 * Add all names and values of the tuple to the built tuple.
	 * @param tuple names and value to add to the tuple being built
	 * @return builder to continue creating a new tuple instance
	 */
	public TupleBuilder putAll(Tuple tuple) {
		for (int i = 0; i < tuple.size(); i++) {
			Object value = tuple.getValues().get(i);
			String name = tuple.getFieldNames().get(i);
			addEntry(name, value);
		}
		return this;
	}

	public Tuple build() {
		return newTuple(names, values);
	}

	public static Tuple fromString(String source) {
		return stringToTupleConverter.convert(source);
	}

	public TupleBuilder setConfigurableConversionService(ConfigurableConversionService formattingConversionService) {
		Assert.notNull(formattingConversionService);
		this.customConversionService = formattingConversionService;
		return this;
	}

	public ConversionServiceBuilder setFormats(Locale locale, DateFormat dateFormat) {
		return new ConversionServiceBuilder(this, locale, dateFormat);
	}

	void addEntry(String k1, Object v1) {
		names.add(k1);
		values.add(v1);
	}

	static List valuesOf(Object v1) {
		ArrayList values = new ArrayList<>();
		values.add(v1);
		return Collections.unmodifiableList(values);
	}

	static List namesOf(String k1) {
		List fields = new ArrayList<>(1);
		fields.add(k1);
		return Collections.unmodifiableList(fields);

	}

	protected Tuple newTuple(List names, List values) {
		DefaultTuple tuple;

		ConfigurableConversionService conversionService = customConversionService != null ? customConversionService : defaultConversionService;
		tuple = mutable
				? new DefaultMutableTuple(names, values, conversionService)
				: new DefaultTuple(names, values, conversionService);
		tuple.setTupleToStringConverter(tupleToStringConverter);
		return tuple;
	}

	/**
	 * Provides the ability to inject a {@link ConfigurableConversionService} as a way to
	 * customize conversion behavior in the built {@link Tuple}.
	 *
	 * @author Michael Minella
	 */
	public static class ConversionServiceBuilder {

		private TupleBuilder builder;

		private Locale locale;

		private DateFormat dateFormat;

		ConversionServiceBuilder(TupleBuilder builder, Locale locale, DateFormat dateFormat) {
			this.builder = builder;
			this.locale = locale;
			this.dateFormat = dateFormat;
		}

		public TupleBuilder setConfigurableConversionService(ConfigurableConversionService formattingConversionService) {
			Assert.notNull(formattingConversionService);

			if (locale != null) {
				formattingConversionService.addConverterFactory(new LocaleAwareStringToNumberConverterFactory(NumberFormat
						.getInstance(locale)));
			}

			if (dateFormat != null) {
				formattingConversionService.addConverter(new StringToDateConverter(dateFormat));
			}

			builder.setConfigurableConversionService(formattingConversionService);

			return builder;
		}
	}
}