/*
 * Java Genetic Algorithm Library (@__identifier__@).
 * Copyright (c) @__year__@ Franz Wilhelmstötter
 *
 * 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.
 *
 * Author:
 *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
 */
package org.jenetics.internal.util;

import static java.util.Objects.requireNonNull;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.xml.bind.DataBindingException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;

import org.jenetics.util.ISeq;

/**
 * Caches the JAXB classes and lets you add additional one.
 *
 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
 * @version !__version__!
 * @since !__version__!
 */
public final class JAXBContextCache {
	private JAXBContextCache() {require.noInstance();}

	private static final List<Class<?>> CLASSES = new ArrayList<>();
	static {
		addPackage("org.jenetics");
		addPackage("org.jenetics.engine");
		addPackage("org.jenetics.internal.util");
	}

	private static JAXBContext _context;

	public static synchronized JAXBContext context() {
		if (_context == null) {
			try {
				_context = JAXBContext
					.newInstance(CLASSES.toArray(new Class<?>[CLASSES.size()]));
			} catch (JAXBException e) {
				throw new DataBindingException(
					"Something went wrong while creating JAXBContext.", e
				);
			}
		}

		return _context;
	}

	public static synchronized void addPackage(final String pkg) {
		requireNonNull(pkg);

		final List<Class<?>> classes = jaxbClasses(pkg);
		if (!classes.isEmpty()) {
			_context = null;
			CLASSES.addAll(jaxbClasses(pkg));
		}
	}

	public static synchronized void addClass(final Class<?> cls) {
		requireNonNull(cls);

		_context = null;
		CLASSES.add(cls);
	}

	@SuppressWarnings("unchecked")
	private static List<Class<?>> jaxbClasses(final String pkg) {
		try {
			final Field field = Class
				.forName(pkg + ".jaxb")
				.getField("CLASSES");
			field.setAccessible(true);

			return ((ISeq<Class<?>>)field.get(null)).asList();
		} catch (ReflectiveOperationException e) {
			return Collections.emptyList();
		}
	}
}

@@ -869,24 +869,22 @@
 va.util.
-ArrayLis
+HashSe
 t;%0Aimpor
@@ -899,41 +899,10 @@
 til.
-Collections;%0Aimport java.util.Lis
+Se
 t;%0A%0A
@@ -1362,27 +1362,26 @@
 tatic final 
-Lis
+Se
 t%3CClass%3C?%3E%3E 
@@ -1398,16 +1398,14 @@
 new 
-ArrayLis
+HashSe
 t%3C%3E(
@@ -1985,40 +1985,16 @@
 ) %7B%0A
-%09%09requireNonNull(pkg);%0A%0A
 %09%09final 
 List
@@ -1989,20 +1989,20 @@
 %09%09final 
-List
+ISeq
 %3CClass%3C?
@@ -2030,17 +2030,96 @@
 ses(pkg)
-;
+.stream()%0A%09%09%09.filter(cls -%3E !CLASSES.contains(cls))%0A%09%09%09.collect(ISeq.toISeq());%0A
 %0A%09%09if (!
@@ -2177,31 +2177,31 @@
 .addAll(
-jaxbC
+c
 lasses
-(pkg
+.asList(
 ));%0A%09%09%7D%0A
@@ -2292,16 +2292,49 @@
 (cls);%0A%0A
+%09%09if (!CLASSES.contains(cls)) %7B%0A%09
 %09%09_conte
@@ -2346,16 +2346,17 @@
 null;%0A%09%09
+%09
 CLASSES.
@@ -2365,16 +2365,20 @@
 d(cls);%0A
+%09%09%7D%0A
 %09%7D%0A%0A%09@Su
@@ -2421,20 +2421,20 @@
  static 
-List
+ISeq
 %3CClass%3C?
@@ -2468,16 +2468,40 @@
  pkg) %7B%0A
+%09%09requireNonNull(pkg);%0A%0A
 %09%09try %7B%0A
@@ -2624,17 +2624,16 @@
 %09return 
-(
 (ISeq%3CCl
@@ -2659,18 +2659,8 @@
 ull)
-).asList()
 ;%0A%09%09
@@ -2716,29 +2716,18 @@
 urn 
-Collections
+ISeq
 .empty
-List
 ();%0A

Improve 'JAXBContextCache'.