001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  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 */
017package org.apache.juneau.marshall.swap.spi;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020
021import java.net.*;
022import java.time.*;
023import java.util.*;
024import java.util.concurrent.*;
025import java.util.regex.*;
026
027import org.apache.juneau.commons.reflect.*;
028import org.apache.juneau.marshall.*;
029import org.apache.juneau.marshall.swaps.*;
030
031/**
032 * Maintain the list of default swaps used by all serializers and parsers.
033 *
034 * <h5 class='section'>See Also:</h5><ul>
035 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Swaps">Swap</a>
036 * </ul>
037 */
038public class DefaultSwaps {
039
040   /**
041    * Prevents instantiation.
042    */
043   private DefaultSwaps() {}
044
045   private static final Map<Class<?>,ObjectSwap<?,?>> SWAPS = new ConcurrentHashMap<>();
046   static {
047      SWAPS.put(Locale.class, new StringSwap<Locale>() {
048         @Override public String swap(MarshallingSession s, Locale o) {
049            return s.getMarshallingContext().getLocaleFormat().format(o);
050         }
051         @Override public Locale unswap(MarshallingSession s, String o, ClassMeta<?> hint) {
052            return s.getMarshallingContext().getLocaleFormat().parse(o);
053         }
054      });
055      SWAPS.put(StackTraceElement.class, new StackTraceElementSwap());
056      SWAPS.put(TimeZone.class, new StringSwap<TimeZone>() {
057         @Override public String swap(MarshallingSession s, TimeZone o) {
058            return s.getMarshallingContext().getTimeZoneFormat().format(o);
059         }
060         @Override public TimeZone unswap(MarshallingSession s, String o, ClassMeta<?> hint) {
061            return TimeZoneFormat.parseTimeZone(o);
062         }
063      });
064      SWAPS.put(ZoneId.class, new StringSwap<ZoneId>() {
065         @Override public String swap(MarshallingSession s, ZoneId o) {
066            return s.getMarshallingContext().getTimeZoneFormat().format(o);
067         }
068         @Override public ZoneId unswap(MarshallingSession s, String o, ClassMeta<?> hint) {
069            return TimeZoneFormat.parseZoneId(o);
070         }
071      });
072      SWAPS.put(Currency.class, new StringSwap<Currency>() {
073         @Override public String swap(MarshallingSession s, Currency o) {
074            return CurrencyFormat.format(o, s.getMarshallingContext().getCurrencyFormat(), s.getLocale());
075         }
076         @Override public Currency unswap(MarshallingSession s, String o, ClassMeta<?> hint) {
077            return CurrencyFormat.parse(o, s.getMarshallingContext().getCurrencyFormat(), s.getLocale());
078         }
079      });
080      SWAPS.put(MatchResult.class, new MatchResultSwap());
081      SWAPS.put(URL.class, new UrlSwap());
082      SWAPS.put(byte[].class, new BinarySwap());
083      SWAPS.put(Class.class, new ClassFormatSwap());
084   }
085
086   /**
087    * Find the default ObjectSwap for the specified class.
088    *
089    * @param ci The class to find the swap for. Must not be <jk>null</jk>.
090    * @return The matched swap, or <jk>null</jk> if it couldn't be found.
091    */
092   @SuppressWarnings({
093      "java:S1452"  // Wildcard required - ObjectSwap<?,?> for heterogeneous default swap types
094   })
095   public static ObjectSwap<?,?> find(ClassInfo ci) {
096      var ci2 = ci.getAllParents().stream().filter(x -> nn(SWAPS.get(x.inner()))).findFirst().orElse(null);
097      return ci2 == null ? null : SWAPS.get(ci2.inner());
098   }
099}