jaxb.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-3.5.0).
003  * Copyright (c) 2007-2016 Franz Wilhelmstötter
004  *
005  * Licensed under the Apache License, Version 2.0 (the "License");
006  * you may not use this file except in compliance with the License.
007  * You may obtain a copy of the License at
008  *
009  *      http://www.apache.org/licenses/LICENSE-2.0
010  *
011  * Unless required by applicable law or agreed to in writing, software
012  * distributed under the License is distributed on an "AS IS" BASIS,
013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014  * See the License for the specific language governing permissions and
015  * limitations under the License.
016  *
017  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019  */
020 package org.jenetics.internal.util;
021 
022 import static org.jenetics.internal.util.reflect.classOf;
023 import static org.jenetics.internal.util.reflect.innerClasses;
024 
025 import java.util.concurrent.ConcurrentHashMap;
026 import java.util.concurrent.ConcurrentMap;
027 import java.util.function.Function;
028 
029 import javax.xml.bind.annotation.adapters.XmlAdapter;
030 
031 import org.jenetics.internal.util.model.CharacterModel;
032 
033 /**
034  * JAXB helper methods.
035  *
036  * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
037  * @version 1.6
038  * @since 2.0
039  */
040 public class jaxb {
041     private jaxb() {require.noInstance();}
042 
043     private static final XmlAdapter<Object, Object> IDENTITY_ADAPTER =
044         new XmlAdapter<Object, Object>() {
045             @Override public Object unmarshal(final Object value) {
046                 return value;
047             }
048             @Override public Object marshal(final Object value) {
049                 return value;
050             }
051         };
052 
053     private static final ConcurrentMap<Class<?>, XmlAdapter<?, ?>> ADAPTERS =
054         new ConcurrentHashMap<>();
055 
056     static {
057         ADAPTERS.put(Character.class, CharacterModel.ADAPTER);
058         ADAPTERS.put(CharacterModel.class, CharacterModel.ADAPTER);
059     }
060 
061     /**
062      * Return the an {@code XmlAdapter} for the given {@code vale}. If no
063      * adapter could be found, and identity adapter is returned.
064      *
065      * @param value the object for which to find an {@code XmlAdapter}
066      * @return the {@code XmlAdapter} for the given object, or an identity
067      *         adapter if no one can be found.
068      */
069     @SuppressWarnings("unchecked")
070     public static XmlAdapter<Object, Object> adapterFor(final Object value) {
071         return (XmlAdapter<Object, Object>)ADAPTERS
072             .computeIfAbsent(classOf(value), jaxb::newXmlAdapter);
073     }
074 
075     private static XmlAdapter<Object, Object> newXmlAdapter(final Class<?> cls) {
076         return innerClasses(cls)
077             .filter(XmlAdapter.class::isAssignableFrom)
078             .findFirst()
079             .flatMap(reflect::<XmlAdapter<Object, Object>>newInstance)
080             .orElse(IDENTITY_ADAPTER);
081     }
082 
083     /**
084      * Shorthand for {@code adapterFor(value).marshal(value)}
085      */
086     public static Object marshal(final Object value) throws Exception {
087         return adapterFor(value).marshal(value);
088     }
089 
090     /**
091      * Shorthand for {@code adapterFor(value).unmarshal(value)}
092      */
093     public static Object unmarshal(final Object value) throws Exception {
094         return adapterFor(value).unmarshal(value);
095     }
096 
097     /**
098      * Return a marshaller function from the given
099      * {@link javax.xml.bind.annotation.adapters.XmlAdapter}.
100      *
101      * @param a the adapter used by the marshaller function.
102      * @return the marshaller function
103      */
104     public static <V, B> Function<B, V> Marshaller(final XmlAdapter<V, B> a) {
105         return value -> {
106             try {
107                 return a.marshal(value);
108             } catch (Exception e) {
109                 throw new RuntimeException(e);
110             }
111         };
112     }
113 
114     /**
115      * Return a unmarshaller function from the given
116      * {@link javax.xml.bind.annotation.adapters.XmlAdapter}.
117      *
118      * @param a the adapter used by the unmarshaller function.
119      * @return the unmarshaller function
120      */
121     public static <V, B> Function<V, B> Unmarshaller(final XmlAdapter<V, B> a) {
122         return value -> {
123             try {
124                 return a.unmarshal(value);
125             } catch (Exception e) {
126                 throw new RuntimeException(e);
127             }
128         };
129     }
130 
131     /**
132      * Return a marshaller function for the given object.
133      *
134      * @param value the value to marshal
135      * @return the marshaller function
136      */
137     public static Function<Object, Object> Marshaller(final Object value) {
138         return Marshaller(adapterFor(value));
139     }
140 
141     /**
142      * Return a unmarshaller function for the given object.
143      *
144      * @param value the value to unmarshal
145      * @return the unmarshaller function
146      */
147     public static Function<Object, Object> Unmarshaller(final Object value)  {
148         return Unmarshaller(jaxb.adapterFor(value));
149     }
150 
151 }