// ***************************************************************************************************************************
// * 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 org.apache.juneau;

import java.lang.reflect.*;
import java.util.*;

import org.apache.juneau.annotation.*;

/**
 * Represents a map of dictionary type names to bean classes that make up a bean dictionary.
 *
 * <p>
 * In general, this approach for defining dictionary names for classes is used when it's not possible to use the
 * {@link Bean#typeName() @Bean(typeName)} annotation.
 *
 * <h5 class='section'>Example:</h5>
 * <p class='bcode w800'>
 * 	<jc>// A bean dictionary map consisting of classes without @Bean(typeName) annotations</jc>
 * 	<jc>// that require type names to be explicitly specified.</jc>
 * 	<jk>public class</jk> MyBeanDictionaryMap <jk>extends</jk> BeanDictionaryMap {
 *
 * 		<jc>// Must provide a no-arg constructor!</jc>
 * 		<jk>public</jk> MyBeanDictionaryMap() {
 * 			addClass(<js>"MyBean"</js>, MyBean.<jk>class</jk>);
 * 			addClass(<js>"MyBeanArray"</js>, MyBean[].<jk>class</jk>);
 * 			addClass(<js>"StringArray"</js>, String[].<jk>class</jk>);
 * 			addClass(<js>"String2dArray"</js>, String[][].<jk>class</jk>);
 * 			addClass(<js>"IntArray"</js>, <jk>int</jk>[].<jk>class</jk>);
 * 			addClass(<js>"Int2dArray"</js>, <jk>int</jk>[][].<jk>class</jk>);
 * 			addClass(<js>"LinkedList"</js>, LinkedList.<jk>class</jk>);
 * 			addClass(<js>"TreeMap"</js>, TreeMap.<jk>class</jk>);
 * 			addCollectionClass(<js>"LinkedListOfInts"</js>, LinkedList.<jk>class</jk>, Integer.<jk>class</jk>);
 * 			addCollectionClass(<js>"LinkedListOfR1"</js>, LinkedList.<jk>class</jk>, R1.<jk>class</jk>);
 * 			addCollectionClass(<js>"LinkedListOfCalendar"</js>, LinkedList.<jk>class</jk>, Calendar.<jk>class</jk>);
 * 		}
 * 	}
 *
 * 	<jc>// Use it in a parser.</jc>
 * 	ReaderParser p = JsonParser
 * 		.<jsm>create</jsm>()
 * 		.beanDictionary(MyBeanDictionaryMap.<jk>class</jk>)
 * 		.build();
 * </p>
 *
 * <p>
 * Subclasses must implement a public no-arg constructor so that it can be instantiated by the bean context code.
 */
@SuppressWarnings("rawtypes")
public class BeanDictionaryMap extends LinkedHashMap<String,Object> {
	private static final long serialVersionUID = 1L;

	/**
	 * Constructor.
	 */
	protected BeanDictionaryMap() {}

	/**
	 * Add a dictionary name mapping for the specified class.
	 *
	 * @param typeName The dictionary name of the class.
	 * @param c The class represented by the dictionary name.
	 * @return This object (for method chaining).
	 */
	protected BeanDictionaryMap addClass(String typeName, Class<?> c) {
		put(typeName, c);
		return this;
	}

	/**
	 * Add a dictionary name mapping for the specified map class with the specified key and value classes.
	 *
	 * @param typeName The dictionary name of the class.
	 * @param mapClass The map implementation class.
	 * @param keyClass The key class.
	 * @param valueClass The value class.
	 * @return This object (for method chaining).
	 */
	protected BeanDictionaryMap addMapClass(String typeName, Class<? extends Map> mapClass, Object keyClass, Object valueClass) {
		assertValidParameter(keyClass);
		assertValidParameter(valueClass);
		put(typeName, new Object[]{mapClass, keyClass, valueClass});
		return this;
	}

	/**
	 * Add a dictionary name mapping for the specified collection class with the specified entry class.
	 *
	 * @param typeName The dictionary name of the class.
	 * @param collectionClass The collection implementation class.
	 * @param entryClass The entry class.
	 * @return This object (for method chaining).
	 */
	protected BeanDictionaryMap addCollectionClass(String typeName, Class<? extends Collection> collectionClass, Object entryClass) {
		assertValidParameter(entryClass);
		put(typeName, new Object[]{collectionClass, entryClass});
		return this;
	}

	private void assertValidParameter(Object o) {
		if (o != null) {
			if (o instanceof Class)
				return;
			if (o.getClass().isArray()) {
				for (int i = 0; i < Array.getLength(o); i++)
					assertValidParameter(Array.get(o, i));
				return;
			}
		}
		throw new BeanRuntimeException("Invalid object type passed to BeanDictionaryMap: ''{0}''.  Only objects of type Class or Object[] containing Class or Object[] objects can be used.");
	}
}
