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 }