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