    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     */
    017    package org.apache.logging.log4j.message;
    018
    019    import java.io.Serializable;
    020
    021    import org.apache.logging.log4j.util.Strings;
    022
    023    /**
    024     * The StructuredData identifier.
    025     */
    026    public class StructuredDataId implements Serializable {
    027
    028        private static final String AT = "@";
    029
    030        /**
    031         * RFC 5424 Time Quality.
    032         */
    033        public static final StructuredDataId TIME_QUALITY = new StructuredDataId("timeQuality", null,
    034            new String[]{"tzKnown", "isSynced", "syncAccuracy"});
    035
    036        /**
    037         * RFC 5424 Origin.
    038         */
    039        public static final StructuredDataId ORIGIN = new StructuredDataId("origin", null,
    040            new String[]{"ip", "enterpriseId", "software", "swVersion"});
    041
    042        /**
    043         * RFC 5424 Meta.
    044         */
    045        public static final StructuredDataId META = new StructuredDataId("meta", null,
    046            new String[]{"sequenceId", "sysUpTime", "language"});
    047
    048        /**
    049         * Reserved enterprise number.
    050         */
    051        public static final int RESERVED = -1;
    052
    053        private static final long serialVersionUID = 9031746276396249990L;
    054        private static final int MAX_LENGTH = 32;
    055
    056        private final String name;
    057        private final int enterpriseNumber;
    058        private final String[] required;
    059        private final String[] optional;
    060
    061
    062        protected StructuredDataId(final String name, final String[] required, final String[] optional) {
    063            int index = -1;
    064            if (name != null) {
    065                if (name.length() > MAX_LENGTH) {
    066                    throw new IllegalArgumentException(String.format("Length of id %s exceeds maximum of %d characters",
    067                            name, MAX_LENGTH));
    068                }
    069                index = name.indexOf(AT);
    070            }
    071
    072            if (index > 0) {
    073                this.name = name.substring(0, index);
    074                this.enterpriseNumber = Integer.parseInt(name.substring(index + 1));
    075            } else {
    076                this.name = name;
    077                this.enterpriseNumber = RESERVED;
    078            }
    079            this.required = required;
    080            this.optional = optional;
    081        }
    082
    083        /**
    084         * A Constructor that helps conformance to RFC 5424.
    085         *
    086         * @param name             The name portion of the id.
    087         * @param enterpriseNumber The enterprise number.
    088         * @param required         The list of keys that are required for this id.
    089         * @param optional         The list of keys that are optional for this id.
    090         */
    091        public StructuredDataId(final String name, final int enterpriseNumber, final String[] required,
    092                                final String[] optional) {
    093            if (name == null) {
    094                throw new IllegalArgumentException("No structured id name was supplied");
    095            }
    096            if (name.contains(AT)) {
    097                throw new IllegalArgumentException("Structured id name cannot contain an " + Strings.quote(AT));
    098            }
    099            if (enterpriseNumber <= 0) {
    100                throw new IllegalArgumentException("No enterprise number was supplied");
    101            }
    102            this.name = name;
    103            this.enterpriseNumber = enterpriseNumber;
    104            final String id = enterpriseNumber < 0 ? name : name + AT + enterpriseNumber;
    105            if (id.length() > MAX_LENGTH) {
    106                throw new IllegalArgumentException("Length of id exceeds maximum of 32 characters: " + id);
    107            }
    108            this.required = required;
    109            this.optional = optional;
    110        }
    111
    112        /**
    113         * Creates an id using another id to supply default values.
    114         * @param id The original StructuredDataId.
    115         * @return the new StructuredDataId.
    116         */
    117        public StructuredDataId makeId(final StructuredDataId id) {
    118            if (id == null) {
    119                return this;
    120            }
    121            return makeId(id.getName(), id.getEnterpriseNumber());
    122        }
    123
    124        /**
    125         * Creates an id based on the current id.
    126         * @param defaultId The default id to use if this StructuredDataId doesn't have a name.
    127         * @param enterpriseNumber The enterprise number.
    128         * @return a StructuredDataId.
    129         */
    130        public StructuredDataId makeId(final String defaultId, final int enterpriseNumber) {
    131            String id;
    132            String[] req;
    133            String[] opt;
    134            if (enterpriseNumber <= 0) {
    135                return this;
    136            }
    137            if (this.name != null) {
    138                id = this.name;
    139                req = this.required;
    140                opt = this.optional;
    141            } else {
    142                id = defaultId;
    143                req = null;
    144                opt = null;
    145            }
    146
    147            return new StructuredDataId(id, enterpriseNumber, req, opt);
    148        }
    149
    150        /**
    151         * Returns a list of required keys.
    152         * @return a List of required keys or null if none have been provided.
    153         */
    154        public String[] getRequired() {
    155            return required;
    156        }
    157
    158        /**
    159         * Returns a list of optional keys.
    160         * @return a List of optional keys or null if none have been provided.
    161         */
    162        public String[] getOptional() {
    163            return optional;
    164        }
    165
    166        /**
    167         * Returns the StructuredDataId name.
    168         * @return the StructuredDataId name.
    169         */
    170        public String getName() {
    171            return name;
    172        }
    173
    174        /**
    175         * Returns the enterprise number.
    176         * @return the enterprise number.
    177         */
    178        public int getEnterpriseNumber() {
    179            return enterpriseNumber;
    180        }
    181
    182        /**
    183         * Indicates if the id is reserved.
    184         * @return true if the id uses the reserved enterprise number, false otherwise.
    185         */
    186        public boolean isReserved() {
    187            return enterpriseNumber <= 0;
    188        }
    189
    190        @Override
    191        public String toString() {
    192            return isReserved() ? name : name + AT + enterpriseNumber;
    193        }
    194    }