]> git.basschouten.com Git - openhab-addons.git/blob
ed5743406ace0f4e47cf96b6224d929396181ca5
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.deutschebahn.internal.timetable;
14
15 import java.io.File;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.nio.file.Files;
19 import java.util.ArrayList;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Properties;
23 import java.util.Set;
24 import java.util.function.Function;
25 import java.util.regex.Matcher;
26 import java.util.regex.Pattern;
27
28 import org.eclipse.jdt.annotation.NonNullByDefault;
29 import org.eclipse.jdt.annotation.Nullable;
30 import org.openhab.binding.deutschebahn.internal.timetable.TimetablesV1Impl.HttpCallable;
31
32 /**
33  * Stub Implementation for {@link HttpCallable}, that provides Data for the selected station, date and hour from file
34  * system.
35  * 
36  * @author Sönke Küper - initial contribution.
37  */
38 @NonNullByDefault
39 public class TimetableStubHttpCallable implements HttpCallable {
40
41     private static final Pattern PLAN_URL_PATTERN = Pattern
42             .compile("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/(\\d+)/(\\d+)/(\\d+)");
43     private static final Pattern FULL_CHANGES_URL_PATTERN = Pattern
44             .compile("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/fchg/(\\d+)");
45     private static final Pattern RECENT_CHANGES_URL_PATTERN = Pattern
46             .compile("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/rchg/(\\d+)");
47
48     private final File testdataDir;
49     private final List<String> requestedPlanUrls;
50     private final List<String> requestedFullChangesUrls;
51     private final List<String> requestedRecentChangesUrls;
52
53     // Allows simulation of available data.
54     // if not set all available files will be served.
55     private @Nullable Set<String> availableUrls = null;
56
57     public TimetableStubHttpCallable(File testdataDir) {
58         this.testdataDir = testdataDir;
59         this.requestedPlanUrls = new ArrayList<>();
60         this.requestedFullChangesUrls = new ArrayList<String>();
61         this.requestedRecentChangesUrls = new ArrayList<String>();
62     }
63
64     public void addAvailableUrl(String url) {
65         if (this.availableUrls == null) {
66             availableUrls = new HashSet<>();
67         }
68         this.availableUrls.add(url);
69     }
70
71     @Override
72     public String executeUrl( //
73             String httpMethod, //
74             String url, //
75             Properties httpHeaders, //
76             @Nullable InputStream content, //
77             @Nullable String contentType, //
78             int timeout) throws IOException {
79         final Matcher planMatcher = PLAN_URL_PATTERN.matcher(url);
80         if (planMatcher.matches()) {
81             requestedPlanUrls.add(url);
82             return processRequest(url, planMatcher, this::getPlanData);
83         }
84
85         final Matcher fullChangesMatcher = FULL_CHANGES_URL_PATTERN.matcher(url);
86         if (fullChangesMatcher.matches()) {
87             requestedFullChangesUrls.add(url);
88             return processRequest(url, fullChangesMatcher, this::getFullChanges);
89         }
90
91         final Matcher recentChangesMatcher = RECENT_CHANGES_URL_PATTERN.matcher(url);
92         if (recentChangesMatcher.matches()) {
93             requestedRecentChangesUrls.add(url);
94             return processRequest(url, recentChangesMatcher, this::getRecentChanges);
95         }
96         return "";
97     }
98
99     private String processRequest(String url, Matcher matcher, Function<Matcher, String> responseSupplier) {
100         if (availableUrls != null && !availableUrls.contains(url)) {
101             return "";
102         } else {
103             return responseSupplier.apply(matcher);
104         }
105     }
106
107     private String getPlanData(final Matcher planMatcher) {
108         final String evaNo = planMatcher.group(1);
109         final String day = planMatcher.group(2);
110         final String hour = planMatcher.group(3);
111
112         final File responseFile = new File(this.testdataDir, "plan/" + evaNo + "/" + day + "/" + hour + ".xml");
113         return serveFileContentIfExists(responseFile);
114     }
115
116     private String serveFileContentIfExists(File responseFile) {
117         if (!responseFile.exists()) {
118             return "";
119         }
120
121         try {
122             return Files.readString(responseFile.toPath());
123         } catch (IOException e) {
124             throw new AssertionError(e);
125         }
126     }
127
128     private String getRecentChanges(Matcher recentChangesMatcher) {
129         final String evaNo = recentChangesMatcher.group(1);
130         File responseFile = new File(this.testdataDir, "rchg/" + evaNo + ".xml");
131         return serveFileContentIfExists(responseFile);
132     }
133
134     private String getFullChanges(Matcher fullChangesMatcher) {
135         final String evaNo = fullChangesMatcher.group(1);
136         File responseFile = new File(this.testdataDir, "fchg/" + evaNo + ".xml");
137         return serveFileContentIfExists(responseFile);
138     }
139
140     public List<String> getRequestedPlanUrls() {
141         return requestedPlanUrls;
142     }
143
144     public List<String> getRequestedFullChangesUrls() {
145         return requestedFullChangesUrls;
146     }
147
148     public List<String> getRequestedRecentChangesUrls() {
149         return requestedRecentChangesUrls;
150     }
151 }