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.xml;
018
019import static org.apache.juneau.commons.utils.CollectionUtils.*;
020import static org.apache.juneau.commons.utils.Shorts.*;
021
022import java.util.*;
023
024import org.apache.juneau.marshall.*;
025
026/**
027 * Metadata on classes specific to the XML serializers and parsers pulled from the {@link Xml @Xml} annotation on the
028 * class.
029 *
030 * <h5 class='section'>See Also:</h5><ul>
031 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/XmlSupport">XML</a>
032 * </ul>
033 */
034public class XmlClassMeta extends ExtendedClassMeta {
035
036   private final Namespace namespace;
037   private final XmlFormat format;
038   private final String childName;
039
040   /**
041    * Constructor.
042    *
043    * @param cm The class that this annotation is defined on.
044    *    <br>Can be <jk>null</jk> (no {@link Xml @Xml}/{@link XmlSchema @XmlSchema} annotations are looked up; namespace,
045    *    format, and child-name default accordingly).
046    * @param mp XML metadata provider (for finding information about other artifacts).
047    */
048   public XmlClassMeta(ClassMeta<?> cm, XmlMetaProvider mp) {
049      super(cm);
050      List<Xml> xmls = list();
051      List<XmlSchema> schemas = list();
052      if (nn(cm)) {
053         cm.forEachAnnotation(Xml.class, x -> true, xmls::add);
054         cm.forEachAnnotation(XmlSchema.class, x -> true, schemas::add);
055      }
056      this.namespace = XmlUtils.findNamespace(xmls, schemas);
057
058   String childNameTemp = null;
059   var formatValue = XmlFormat.DEFAULT;
060   for (var a : xmls) {
061      if (a.format() != XmlFormat.DEFAULT)
062         formatValue = a.format();
063      if (! a.childName().isEmpty())
064         childNameTemp = a.childName();
065   }
066   this.format = formatValue;
067   this.childName = childNameTemp;
068   }
069
070   /**
071    * Returns the XML namespace associated with this class.
072    *
073    * <p>
074    * Namespace is determined in the following order of {@link Xml#prefix() @Xml(prefix)} annotation:
075    * <ol>
076    *    <li>Class.
077    *    <li>Package.
078    *    <li>Superclasses.
079    *    <li>Superclass packages.
080    *    <li>Interfaces.
081    *    <li>Interface packages.
082    * </ol>
083    *
084    * @return The namespace associated with this class, or <jk>null</jk> if no namespace is associated with it.
085    */
086   public Namespace getNamespace() { return namespace; }
087
088   /**
089    * Returns the {@link Xml#childName() @Xml(childName)} annotation defined on the class.
090    *
091    * @return The value of the annotation, or <jk>null</jk> if not specified.
092    */
093   protected String getChildName() { return childName; }
094
095   /**
096    * Returns the {@link Xml#format() @Xml(format)} annotation defined on the class.
097    *
098    * @return The value of the annotation, or {@link XmlFormat#DEFAULT} if not specified.
099    */
100   protected XmlFormat getFormat() { return format; }
101}