1 /* Copyright 2002-2016 CS Systèmes d'Information
2 * Licensed to CS Systèmes d'Information (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.orekit.files.ccsds;
18
19 import java.util.Locale;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22
23 import org.orekit.errors.OrekitException;
24 import org.orekit.errors.OrekitMessages;
25
26 /** Holder for key-value pair.
27 * <p>
28 * The syntax for key-value lines in CCSDS files is:
29 * </p>
30 * <pre>
31 * KEY = value [unit]
32 * </pre>
33 * <p>
34 * The "[unit]" part (with the square brackets included) is optional.
35 * The COMMENT keyword is an exception and does not have an '=' but directly
36 * the value as free form text. The META_START, META_STOP, COVARIANCE_START
37 * and COVARIANCE_STOP keywords are other exception and do not have anything
38 * else following them on the line.
39 * </p>
40 * @author Luc Maisonobe
41 * @since 6.1
42 */
43 class KeyValue {
44
45 /** Regular expression for splitting lines. */
46 private final Pattern PATTERN =
47 Pattern.compile("\\p{Space}*([A-Z][A-Z_0-9]*)\\p{Space}*=?\\p{Space}*(.*?)\\p{Space}*(?:\\[.*\\])?\\p{Space}*");
48
49 /** Regular expression for user defined keywords. */
50 private final Pattern USER_DEFINED_KEYWORDS =
51 Pattern.compile("USER_DEFINED_[A-Z][A-Z_]*");
52
53 /** Line from which pair is extracted. */
54 private final String line;
55
56 /** Number of the line from which pair is extracted. */
57 private final int lineNumber;
58
59 /** Name of the file. */
60 private final String fileName;
61
62 /** Keyword enum corresponding to parsed key. */
63 private final Keyword keyword;
64
65 /** Key part of the pair. */
66 private final String key;
67
68 /** Value part of the line. */
69 private final String value;
70
71 /** Build a pair by splitting a key-value line.
72 * <p>
73 * The splitting is very basic and only extracts words using a regular
74 * expression ignoring the '=' sign and the optional unit. No attempt
75 * is made to recognize the special keywords. The key and value parts
76 * may be empty if not matched, and the keyword may be null.
77 * </p>
78 * <p> The value part may be upper case or lower case. This constructor
79 * converts all lower case values to upper case.
80 * @param line to split
81 * @param lineNumber number of the line in the CCSDS data message
82 * @param fileName name of the file
83 */
84 KeyValue(final String line, final int lineNumber, final String fileName) {
85
86 this.line = line;
87 this.lineNumber = lineNumber;
88 this.fileName = fileName;
89
90 final Matcher matcher = PATTERN.matcher(line);
91 if (matcher.matches()) {
92 key = matcher.group(1);
93 final String rawValue = matcher.group(2);
94 Keyword recognized;
95 try {
96 recognized = Keyword.valueOf(key);
97 } catch (IllegalArgumentException iae) {
98 if (USER_DEFINED_KEYWORDS.matcher(key).matches()) {
99 recognized = Keyword.USER_DEFINED_X;
100 } else {
101 recognized = null;
102 }
103 }
104 keyword = recognized;
105 if (recognized == Keyword.COMMENT) {
106 value = rawValue;
107 } else {
108 value = rawValue.
109 toUpperCase(Locale.US).
110 replace('_', ' ').
111 replaceAll("\\p{Space}+", " ");
112 }
113 } else {
114 key = "";
115 value = key;
116 keyword = null;
117 }
118 }
119
120 /** Keyword corresponding to the parsed key.
121 * @return keyword corresponding to the parsed key
122 * (null if not recognized)
123 */
124 public Keyword getKeyword() {
125 return keyword;
126 }
127
128 /** Get the key.
129 * @return key
130 */
131 public String getKey() {
132 return key;
133 }
134
135 /** Get the value.
136 * @return value
137 */
138 public String getValue() {
139 return value;
140 }
141
142 /** Get the value as a double number.
143 * @return value
144 * @exception OrekitException if value is not a number
145 */
146 public double getDoubleValue() throws OrekitException {
147 try {
148 return Double.parseDouble(value);
149 } catch (NumberFormatException nfe) {
150 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
151 lineNumber, fileName, line);
152 }
153 }
154
155 }