001/*
002 * ============================================================================
003 *  Copyright © 2002-2020 by Thomas Thrien.
004 *  All Rights Reserved.
005 * ============================================================================
006 *  Licensed to the public under the agreements of the GNU Lesser General Public
007 *  License, version 3.0 (the "License"). You may obtain a copy of the License at
008 *
009 *       http://www.gnu.org/licenses/lgpl.html
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, WITHOUT
013 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014 *  License for the specific language governing permissions and limitations
015 *  under the License.
016 */
017
018package org.tquadrat.foundation.xml.parse;
019
020import static java.util.Collections.emptyList;
021import static java.util.Collections.emptySet;
022import static org.apiguardian.api.API.Status.STABLE;
023
024import java.net.URI;
025import java.util.Collection;
026import java.util.List;
027import java.util.Optional;
028import java.util.Set;
029
030import org.apiguardian.api.API;
031import org.tquadrat.foundation.annotation.ClassVersion;
032
033/**
034 *  An attribute.
035 *
036 *  @param  qName   The XML qualified (prefixed) name for the attribute.
037 *  @param  localName   An instance of
038 *      {@link Optional}
039 *      that holds the local name for the attribute; will be
040 *      {@linkplain Optional#empty() empty} if Namespace processing is not
041 *      being performed.
042 *  @param  uri An instance
043 *      {@link Optional}
044 *      that holds the Namespace URI for the attribute; will be
045 *      {@linkplain Optional#empty() empty} if  none is available.
046 *  @param  type    The attribute type. If the parser has not read a
047 *      declaration for the attribute, or if the parser does not report
048 *      attribute types, then it must return the value
049 *      {@link Type#CDATA CDATA}
050 *      as stated in the XML 1.0 Recommendation (clause 3.3.3,
051 *      "Attribute-Value Normalization"). For an enumerated attribute
052 *      that is not a notation
053 *      ({@link Type#NOTATION NOTATION}),
054 *      the parser will report the type as
055 *      {@link Type#NMTOKEN NMTOKEN}.
056 *  @param  value   The value of the attribute.
057 *  @param  index   The index of the attribute in the attributes list for the
058 *      element.
059 *
060 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
061 *  @version $Id: Attribute.java 1030 2022-04-06 13:42:02Z tquadrat $
062 *  @since 0.1.0
063 *
064 *  @UMLGraph.link
065 */
066@ClassVersion( sourceVersion = "$Id: Attribute.java 1030 2022-04-06 13:42:02Z tquadrat $" )
067@API( status = STABLE, since = "0.1.0" )
068public record Attribute( String qName, Optional<String> localName, Optional<URI> uri, Type type, String value, int index )
069{
070        /*---------------*\
071    ====** Inner Classes **====================================================
072        \*---------------*/
073    /**
074     *  The attribute types.
075     *
076     *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
077     *  @version $Id: Attribute.java 1030 2022-04-06 13:42:02Z tquadrat $
078     *  @since 0.1.0
079     *
080     *  @UMLGraph.link
081     */
082    @SuppressWarnings( "NewClassNamingConvention" )
083    @ClassVersion( sourceVersion = "$Id: Attribute.java 1030 2022-04-06 13:42:02Z tquadrat $" )
084    @API( status = STABLE, since = "0.1.0" )
085    public enum Type
086    {
087            /*------------------*\
088        ====** Enum Declaration **=============================================
089            \*------------------*/
090        /**
091         *  Character data.
092         */
093        CDATA,
094
095        /**
096         *  A unique element identifier.
097         */
098        ID,
099
100        /**
101         *  The value of a unique ID type attribute, as a reference to the
102         *  respective element.
103         */
104        IDREF,
105
106        /**
107         *  A list of
108         *  {@link #IDREF}s.
109         */
110        IDREFS,
111
112        /**
113         *  An XML name token.
114         */
115        NMTOKEN,
116
117        /**
118         *  Multiple
119         *  {@link #NMTOKEN}s.
120         */
121        NMTOKENS,
122
123        /**
124         *  An entity as declared in the DTD.
125         */
126        ENTITY,
127
128        /**
129         *  Multiple
130         *  {@linkplain #ENTITY entities}.
131         */
132        ENTITIES,
133
134        /**
135         *  A notation as declared in the DTD.
136         */
137        NOTATION
138    }
139    //  enum Type
140
141        /*---------*\
142    ====** Methods **==========================================================
143        \*---------*/
144    /**
145     *  If the attribute is of type
146     *  {@link Type#ENTITY}
147     *  or
148     *  {@link Type#ENTITIES},
149     *  this method will return a list of the entity values.
150     *
151     *  @return The entity values; the return value is empty, if the attribute
152     *      is not of type
153     *      {@link Type#ENTITY}
154     *      or
155     *      {@link Type#ENTITIES}.
156     */
157    public Collection<String> getEntities()
158    {
159        final Collection<String> retValue = switch( type )
160            {
161                case ENTITY -> List.of( value );
162                case ENTITIES -> List.of( value.split( "\\s" ) );
163                //required by Eclipse
164                case CDATA, ID, IDREF, IDREFS, NMTOKEN, NMTOKENS, NOTATION -> emptyList();
165                default -> emptyList();
166            };
167
168        //---* Done *----------------------------------------------------------
169        return retValue;
170    }   //  getEntities()
171
172    /**
173     *  If the attribute is of type
174     *  {@link Type#IDREF}
175     *  or
176     *  {@link Type#IDREFS},
177     *  this method will return a list of the ID references.
178     *
179     *  @return The ID references; the return value is empty, if the attribute
180     *      is not of type
181     *      {@link Type#IDREF}
182     *      or
183     *      {@link Type#IDREFS}.
184     */
185    public Collection<String> getIDReferences()
186    {
187        final Collection<String> retValue = switch( type )
188            {
189                case IDREF -> Set.of( value );
190                case IDREFS -> Set.of( value.split( "\\s" ) );
191                //required by Eclipse
192                case CDATA, ENTITIES, ENTITY, ID, NMTOKEN, NMTOKENS, NOTATION -> emptyList();
193                default -> emptySet();
194            };
195
196        //---* Done *----------------------------------------------------------
197        return retValue;
198    }   //  getIDReferences()
199
200    /**
201     *  If the attribute is of type
202     *  {@link Type#NMTOKEN}
203     *  or
204     *  {@link Type#NMTOKENS},
205     *  this method will return a list of the name tokens.
206     *
207     *  @return The name tokens; the return value is empty, if the attribute
208     *      is not of type
209     *      {@link Type#NMTOKEN}
210     *      or
211     *      {@link Type#NMTOKENS},
212     */
213    public Collection<String> getNameTokens()
214    {
215        final Collection<String> retValue = switch( type )
216            {
217                case NMTOKEN -> List.of( value );
218                case NMTOKENS -> List.of( value.split( "\\s" ) );
219                //required by Eclipse
220                case CDATA, ENTITIES, ENTITY, ID, IDREF, IDREFS, NOTATION -> emptyList();
221                default -> emptyList();
222            };
223
224        //---* Done *----------------------------------------------------------
225        return retValue;
226    }   //  getNameTokens()
227}
228//  record Attribute
229
230/*
231 *  End of File
232 */