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.jsonschema;
018
019import static org.apache.juneau.commons.utils.CollectionUtils.*;
020import static org.apache.juneau.commons.utils.Shorts.*;
021import static org.apache.juneau.commons.utils.StringUtils.*;
022
023import java.util.*;
024
025import org.apache.juneau.commons.utils.*;
026import org.apache.juneau.marshall.collections.*;
027import org.apache.juneau.marshall.json5.*;
028import org.apache.juneau.marshall.parser.*;
029
030/**
031 * Utilities for working with the schema annotations.
032 *
033 * <h5 class='section'>See Also:</h5><ul>
034 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JsonSchemaDetails">JSON-Schema Support</a>
035 * </ul>
036 */
037public class SchemaUtils {
038
039   /**
040    * Prevents instantiation.
041    */
042   private SchemaUtils() {}
043
044   /**
045    * Joins an array of strings with newlines.
046    *
047    * @param s The arrays to join.  Must not be <jk>null</jk>.
048    * @return A new joined string.
049    */
050   public static String joinnl(String[]...s) {
051      for (var ss : s) {
052         if (ss.length != 0)
053            return StringUtils.joinnl(ss).trim();
054      }
055      return "";
056   }
057
058   /**
059    * Parses a generic object as JSON and converts it to an {@link JsonMap}.
060    *
061    * @param o The object to convert.  Can be <jk>null</jk> (returns a new empty {@link JsonMap}).
062    * @return
063    *    The parsed contents (a new empty {@link JsonMap} if {@code o} is <jk>null</jk> or an empty string),
064    *    never <jk>null</jk>.
065    * @throws ParseException Invalid JSON encountered.
066    */
067   public static JsonMap parseMap(Object o) throws ParseException {
068      if (o == null)
069         return new JsonMap();
070      if (o instanceof String[] o2)
071         o = joinnl(o2);
072      if (o instanceof String o2) {
073         var s = o2;
074         if (s.isEmpty())
075            return new JsonMap();
076         if (eqic("IGNORE", s))
077            return JsonMap.of("ignore", true);
078         if (! isProbablyJsonObject(s, true))
079            s = "{" + s + "}";
080         return new JsonMap(Json5Map.ofString(s));
081      }
082      if (o instanceof JsonMap o2)
083         return o2;
084      if (o instanceof MarshalledMap o2)
085         return new JsonMap(o2);
086      throw new ParseException("Unexpected data type '%s'.  Expected Map or String.", cn(o));
087   }
088
089   /**
090    * Concatenates and parses a string array as a JSON object.
091    *
092    * @param ss The array to concatenate and parse.  Must not be <jk>null</jk>.
093    * @return
094    *    The parsed contents (a new empty {@link JsonMap} if the array is empty or joins to an empty string),
095    *    never <jk>null</jk>.
096    * @throws ParseException Invalid JSON encountered.
097    */
098   public static JsonMap parseMap(String[] ss) throws ParseException {
099      if (ss.length == 0)
100         return new JsonMap();
101      String s = joinnl(ss);
102      if (s.isEmpty())
103         return new JsonMap();
104      if (! isProbablyJsonObject(s, true))
105         s = "{" + s + "}";
106      return new JsonMap(Json5Map.ofString(s));
107   }
108
109   /**
110    * Concatenates and parses a string array as JSON array or comma-delimited list.
111    *
112    * @param ss The array to concatenate and parse.  Must not be <jk>null</jk>.
113    * @return
114    *    The parsed contents (a new empty mutable {@link Set} if the array is empty or joins to an empty string),
115    *    never <jk>null</jk>.
116    * @throws ParseException Invalid JSON encountered.
117    */
118   public static Set<String> parseSet(String[] ss) throws ParseException {
119      Set<String> set = set();
120      if (ss.length == 0)
121         return set;
122      String s = joinnl(ss);
123      if (s.isEmpty())
124         return set;
125      Json5List.ofJson5OrCdl(s).forEach(x -> set.add(x.toString()));
126      return set;
127   }
128}