1 /* Copyright 2022-2025 Luc Maisonobe
2 * Licensed to CS GROUP (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.sinex;
18
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.function.Predicate;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
24
25 /** Parser for SINEX block.
26 * @param <T> type of the sinex files parse info
27 * @author Luc Maisonobe
28 * @since 13.0
29 */
30 class BlockParser<T extends ParseInfo<?>> implements LineParser<T> {
31
32 /** Start block pattern. */
33 private final Pattern startPattern;
34
35 /** End block pattern. */
36 private Pattern endPattern;
37
38 /** Allowed parsers when dealing within this block (content + end marker). */
39 private final List<LineParser<T>> inBlockParsers;
40
41 /** Allowed parsers when leaving this block. */
42 private List<LineParser<T>> siblingParsers;
43
44 /** Simple constructor.
45 * @param blockId regular expression for block name
46 * @param predicates predicates for parsing block content lines
47 */
48 protected BlockParser(final String blockId, final List<Predicate<T>> predicates) {
49 this.startPattern = Pattern.compile("^\\+(" + blockId + ") *$");
50 this.endPattern = null;
51 this.inBlockParsers = new ArrayList<>(1 + predicates.size());
52 for (final Predicate<T> predicate : predicates) {
53 inBlockParsers.add(new LineParser<T>() {
54
55 /** {@inheritDoc} */
56 @Override
57 public boolean parseIfRecognized(final T parseInfo) {
58 return predicate.test(parseInfo);
59 }
60
61 /** {@inheritDoc} */
62 @Override
63 public Iterable<LineParser<T>> allowedNextParsers(final T parseInfo) {
64 return inBlockParsers;
65 }
66
67 });
68 }
69 this.inBlockParsers.add(this);
70 }
71
72 /** Set allowed parsers when leaving this block.
73 * @param siblingParsers allowed parsers when leaving this block
74 */
75 public void setSiblingParsers(final List<LineParser<T>> siblingParsers) {
76 this.siblingParsers = siblingParsers;
77 }
78
79 /** {@inheritDoc} */
80 @Override
81 public boolean parseIfRecognized(final T parseInfo) {
82 return outsideBlock() ? checkEntering(parseInfo) : checkLeaving(parseInfo);
83 }
84
85 /** {@inheritDoc} */
86 @Override
87 public Iterable<LineParser<T>> allowedNextParsers(final T parseInfo) {
88 return outsideBlock() ? siblingParsers : inBlockParsers;
89 }
90
91 /** Check if we are outside block.
92 * @return true if we are at block end
93 */
94 protected boolean outsideBlock() {
95 return endPattern == null;
96 }
97
98 /** Check if we are at the start marker.
99 * @param parseInfo holder for transient data
100 * @return true if we are at block start
101 */
102 protected boolean checkEntering(final T parseInfo) {
103 final Matcher matcher = startPattern.matcher(parseInfo.getLine());
104 if (matcher.matches()) {
105 // we are entering the block
106 endPattern = Pattern.compile("^-" + matcher.group(1) + " *$");
107 return true;
108 } else {
109 return false;
110 }
111 }
112
113 /** Check if we are at the end marker.
114 * @param parseInfo holder for transient data
115 * @return true if we are at block end
116 */
117 protected boolean checkLeaving(final T parseInfo) {
118 if (endPattern != null && endPattern.matcher(parseInfo.getLine()).matches()) {
119 endPattern = null;
120 return true;
121 } else {
122 return false;
123 }
124 }
125
126 }
127