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.jena;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020
021import java.util.*;
022
023import org.apache.juneau.marshall.xml.*;
024
025/**
026 * Utility classes.
027 *
028 * <h5 class='section'>See Also:</h5><ul>
029 *    <li class='link'>{doc jmr.RdfDetails}
030
031 * </ul>
032 */
033public class RdfUtils {
034
035   private RdfUtils() {}
036
037   /**
038    * Find the namespace given a list of <ja>@Rdf</ja> and <ja>@RdfSchema</ja> annotations.
039    *
040    * <p>
041    * The annotations should be a child-to-parent ordering of annotations found on a class or method.
042    *
043    * @param rdfs The <c>@Rdf</c> annotations to search.
044    *    Must not be <jk>null</jk>.
045    * @param schemas The list of known RDF schemas.
046    *    Must not be <jk>null</jk>.
047    * @return The resolved namespace, or <jk>null</jk> if the namespace could not be resolved.
048    */
049   public static Namespace findNamespace(List<Rdf> rdfs, List<RdfSchema> schemas) {
050
051      for (var rdf : rdfs) {
052         var ns = findNamespace(rdf.prefix(), rdf.namespace(), rdfs, schemas);
053         if (nn(ns))
054            return ns;
055      }
056
057      for (var schema : schemas) {
058         var ns = findNamespace(schema.prefix(), schema.namespace(), null, schemas);
059         if (nn(ns))
060            return ns;
061      }
062
063      return null;
064   }
065
066   @SuppressWarnings({
067      "java:S3776" // Cognitive complexity acceptable for exhaustive RDF namespace resolution across annotation hierarchies
068   })
069   private static Namespace findNamespace(String prefix, String ns, List<Rdf> rdfs, List<RdfSchema> schemas) {
070
071      // If both prefix and namespace specified, use that Namespace mapping.
072      if (! (prefix.isEmpty() || ns.isEmpty()))
073         return Namespace.of(prefix, ns);
074
075      // If only prefix specified, need to search for namespaceURI.
076      if (! prefix.isEmpty()) {
077         if (nn(rdfs))
078            for (var rdf2 : rdfs)
079               if (rdf2.prefix().equals(prefix) && ! rdf2.namespace().isEmpty())
080                  return Namespace.of(prefix, rdf2.namespace());
081         for (var schema : schemas) {
082            if (schema.prefix().equals(prefix) && ! schema.namespace().isEmpty())
083               return Namespace.of(prefix, schema.namespace());
084            for (var rdfNs : schema.rdfNs())
085               if (rdfNs.prefix().equals(prefix))
086                  return Namespace.of(prefix, rdfNs.namespaceURI());
087         }
088         throw brex("Found @Rdf.prefix annotation with no matching URI.  prefix='" + prefix + "'");
089      }
090
091      // If only namespaceURI specified, need to search for prefix.
092      if (! ns.isEmpty()) {
093         if (nn(rdfs))
094            for (var rdf2 : rdfs)
095               if (rdf2.namespace().equals(ns) && ! rdf2.prefix().isEmpty())
096                  return Namespace.of(rdf2.prefix(), ns);
097         for (var schema : schemas) {
098            if (schema.namespace().equals(ns) && ! schema.prefix().isEmpty())
099               return Namespace.of(schema.prefix(), ns);
100            for (var rdfNs : schema.rdfNs())
101               if (rdfNs.namespaceURI().equals(ns))
102                  return Namespace.of(rdfNs.prefix(), ns);
103         }
104      }
105
106      return null;
107   }
108}