-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* CSV TimeLine parser * XML TimeLine parser * Add unit tests * Add TimelineEntry pojo class for the output of the parsers Signed-off-by: Marcos de Miguel <demiguelm@aia.es> Signed-off-by: lisrte <laurent.issertial@rte-france.com> Signed-off-by: Florian Dupuy <florian.dupuy@rte-france.com>
- Loading branch information
Showing
12 changed files
with
407 additions
and
0 deletions.
There are no files selected for viewing
81 changes: 81 additions & 0 deletions
81
commons/src/main/java/com/powsybl/dynawo/commons/timeline/CsvTimeLineParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/** | ||
* Copyright (c) 2023, RTE (http://www.rte-france.com/) | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
* SPDX-License-Identifier: MPL-2.0 | ||
*/ | ||
package com.powsybl.dynawo.commons.timeline; | ||
|
||
import com.powsybl.commons.PowsyblException; | ||
import com.univocity.parsers.common.ParsingContext; | ||
import com.univocity.parsers.common.ResultIterator; | ||
import com.univocity.parsers.csv.CsvParser; | ||
import com.univocity.parsers.csv.CsvParserSettings; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.io.UncheckedIOException; | ||
import java.nio.charset.StandardCharsets; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
/** | ||
* @author Laurent Issertial <laurent.issertial at rte-france.com> | ||
*/ | ||
public final class CsvTimeLineParser implements TimeLineParser { | ||
|
||
private static final int NB_COLUMNS = 3; | ||
private final char separator; | ||
|
||
public CsvTimeLineParser() { | ||
this('|'); | ||
} | ||
|
||
public CsvTimeLineParser(char separator) { | ||
this.separator = separator; | ||
} | ||
|
||
public List<TimelineEntry> parse(Path file) { | ||
return parse(file, separator); | ||
} | ||
|
||
public static List<TimelineEntry> parse(Path file, char separator) { | ||
try (BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) { | ||
return parse(reader, separator); | ||
} catch (IOException e) { | ||
throw new UncheckedIOException(e); | ||
} | ||
} | ||
|
||
static List<TimelineEntry> parse(BufferedReader reader, char separator) { | ||
Objects.requireNonNull(reader); | ||
CsvParserSettings settings = new CsvParserSettings(); | ||
settings.getFormat().setDelimiter(separator); | ||
settings.getFormat().setQuoteEscape('"'); | ||
settings.getFormat().setLineSeparator(System.lineSeparator()); | ||
settings.setMaxColumns(NB_COLUMNS); | ||
CsvParser csvParser = new CsvParser(settings); | ||
ResultIterator<String[], ParsingContext> iterator = csvParser.iterate(reader).iterator(); | ||
return read(iterator); | ||
} | ||
|
||
static List<TimelineEntry> read(ResultIterator<String[], ParsingContext> iterator) { | ||
List<TimelineEntry> timeline = new ArrayList<>(); | ||
int iLine = 0; | ||
while (iterator.hasNext()) { | ||
iLine++; | ||
String[] tokens = iterator.next(); | ||
if (tokens.length != NB_COLUMNS) { | ||
throw new PowsyblException("Columns of line " + iLine + " are inconsistent"); | ||
} | ||
TimeLineUtil.createEvent(tokens[0], tokens[1], tokens[2]) | ||
.ifPresent(timeline::add); | ||
} | ||
return timeline; | ||
} | ||
|
||
} |
18 changes: 18 additions & 0 deletions
18
commons/src/main/java/com/powsybl/dynawo/commons/timeline/TimeLineParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* Copyright (c) 2023, RTE (http://www.rte-france.com/) | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
* SPDX-License-Identifier: MPL-2.0 | ||
*/ | ||
package com.powsybl.dynawo.commons.timeline; | ||
|
||
import java.nio.file.Path; | ||
import java.util.List; | ||
|
||
/** | ||
* @author Florian Dupuy <florian.dupuy at rte-france.com> | ||
*/ | ||
public interface TimeLineParser { | ||
List<TimelineEntry> parse(Path timeLineFile); | ||
} |
38 changes: 38 additions & 0 deletions
38
commons/src/main/java/com/powsybl/dynawo/commons/timeline/TimeLineUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/** | ||
* Copyright (c) 2023, RTE (http://www.rte-france.com/) | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
* SPDX-License-Identifier: MPL-2.0 | ||
*/ | ||
package com.powsybl.dynawo.commons.timeline; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.util.Optional; | ||
|
||
/** | ||
* @author Florian Dupuy <florian.dupuy at rte-france.com> | ||
*/ | ||
public final class TimeLineUtil { | ||
|
||
private TimeLineUtil() { | ||
} | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(TimeLineUtil.class); | ||
|
||
static Optional<TimelineEntry> createEvent(String time, String modelName, String message) { | ||
if (time == null || modelName == null || message == null) { | ||
LOGGER.warn("Inconsistent event entry (time: '{}', modelName: '{}', message: '{}')", time, modelName, message); | ||
} else { | ||
try { | ||
double timeD = Double.parseDouble(time); | ||
return Optional.of(new TimelineEntry(timeD, modelName, message)); | ||
} catch (NumberFormatException e) { | ||
LOGGER.warn("Inconsistent time entry '{}'", time); | ||
} | ||
} | ||
return Optional.empty(); | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
commons/src/main/java/com/powsybl/dynawo/commons/timeline/TimelineEntry.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/** | ||
* Copyright (c) 2023, RTE (http://www.rte-france.com) | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
* SPDX-License-Identifier: MPL-2.0 | ||
*/ | ||
package com.powsybl.dynawo.commons.timeline; | ||
|
||
/** | ||
* @author Florian Dupuy <florian.dupuy at rte-france.com> | ||
*/ | ||
public class TimelineEntry { | ||
|
||
private final double time; | ||
private final String modelName; | ||
private final String message; | ||
|
||
public TimelineEntry(double time, String modelName, String message) { | ||
this.time = time; | ||
this.modelName = modelName; | ||
this.message = message; | ||
} | ||
|
||
public double getTime() { | ||
return time; | ||
} | ||
|
||
public String getModelName() { | ||
return modelName; | ||
} | ||
|
||
public String getMessage() { | ||
return message; | ||
} | ||
} |
85 changes: 85 additions & 0 deletions
85
commons/src/main/java/com/powsybl/dynawo/commons/timeline/XmlTimeLineParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/** | ||
* Copyright (c) 2023, RTE (http://www.rte-france.com/) | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
* SPDX-License-Identifier: MPL-2.0 | ||
*/ | ||
package com.powsybl.dynawo.commons.timeline; | ||
|
||
import com.powsybl.commons.exceptions.UncheckedXmlStreamException; | ||
import com.powsybl.commons.xml.XmlUtil; | ||
|
||
import javax.xml.XMLConstants; | ||
import javax.xml.stream.XMLInputFactory; | ||
import javax.xml.stream.XMLStreamConstants; | ||
import javax.xml.stream.XMLStreamException; | ||
import javax.xml.stream.XMLStreamReader; | ||
import java.io.IOException; | ||
import java.io.Reader; | ||
import java.io.UncheckedIOException; | ||
import java.nio.charset.StandardCharsets; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
/** | ||
* @author Laurent Issertial <laurent.issertial at rte-france.com> | ||
* @author Marcos de Miguel <demiguelm at aia.es> | ||
*/ | ||
public final class XmlTimeLineParser implements TimeLineParser { | ||
|
||
private static final String TIME = "time"; | ||
private static final String MODEL_NAME = "modelName"; | ||
private static final String MESSAGE = "message"; | ||
|
||
public List<TimelineEntry> parse(Path timeLineFile) { | ||
Objects.requireNonNull(timeLineFile); | ||
|
||
try (Reader reader = Files.newBufferedReader(timeLineFile, StandardCharsets.UTF_8)) { | ||
return parse(reader); | ||
} catch (IOException e) { | ||
throw new UncheckedIOException(e); | ||
} catch (XMLStreamException e) { | ||
throw new UncheckedXmlStreamException(e); | ||
} | ||
} | ||
|
||
public static List<TimelineEntry> parse(Reader reader) throws XMLStreamException { | ||
|
||
List<TimelineEntry> timeLineSeries; | ||
XMLInputFactory factory = XMLInputFactory.newInstance(); | ||
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); | ||
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); | ||
XMLStreamReader xmlReader = null; | ||
try { | ||
xmlReader = factory.createXMLStreamReader(reader); | ||
timeLineSeries = read(xmlReader); | ||
} finally { | ||
if (xmlReader != null) { | ||
xmlReader.close(); | ||
} | ||
} | ||
return timeLineSeries; | ||
} | ||
|
||
private static List<TimelineEntry> read(XMLStreamReader xmlReader) throws XMLStreamException { | ||
List<TimelineEntry> timeline = new ArrayList<>(); | ||
int state = xmlReader.next(); | ||
while (state == XMLStreamConstants.COMMENT) { | ||
state = xmlReader.next(); | ||
} | ||
XmlUtil.readUntilEndElement("timeline", xmlReader, () -> { | ||
if (xmlReader.getLocalName().equals("event")) { | ||
String time = xmlReader.getAttributeValue(null, TIME); | ||
String modelName = xmlReader.getAttributeValue(null, MODEL_NAME); | ||
String message = xmlReader.getAttributeValue(null, MESSAGE); | ||
TimeLineUtil.createEvent(time, modelName, message) | ||
.ifPresent(timeline::add); | ||
} | ||
}); | ||
return timeline; | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
commons/src/test/java/com/powsybl/dynawo/commons/timeline/CsvTimeLineParserTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/** | ||
* Copyright (c) 2023, RTE (http://www.rte-france.com/) | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
* SPDX-License-Identifier: MPL-2.0 | ||
*/ | ||
package com.powsybl.dynawo.commons.timeline; | ||
|
||
import com.powsybl.commons.PowsyblException; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.ValueSource; | ||
|
||
import java.net.URISyntaxException; | ||
import java.nio.file.Path; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
||
/** | ||
* @author Laurent Issertial <laurent.issertial at rte-france.com> | ||
* @author Marcos de Miguel <demiguelm at aia.es> | ||
*/ | ||
class CsvTimeLineParserTest { | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = {"/timeline.log", "/timelineWithQuotes.log"}) | ||
void testTimeline(String fileName) throws URISyntaxException { | ||
|
||
Path path = Path.of(Objects.requireNonNull(getClass().getResource(fileName)).toURI()); | ||
List<TimelineEntry> timeline = new CsvTimeLineParser().parse(path); | ||
|
||
assertEquals(5, timeline.size()); | ||
assertEquals("PMIN : activation", timeline.get(0).getMessage()); | ||
assertEquals("GEN____8_SM", timeline.get(0).getModelName()); | ||
assertEquals(0., timeline.get(0).getTime(), 1e-9); | ||
assertEquals("PMIN : activation", timeline.get(1).getMessage()); | ||
assertEquals("GEN____3_SM", timeline.get(1).getModelName()); | ||
assertEquals(0.0306911, timeline.get(1).getTime(), 1e-9); | ||
assertEquals("PMIN : deactivation", timeline.get(2).getMessage()); | ||
assertEquals("GEN____8_SM", timeline.get(2).getModelName()); | ||
assertEquals("PMIN : deactivation", timeline.get(3).getMessage()); | ||
assertEquals("GEN____3_SM", timeline.get(3).getModelName()); | ||
assertEquals("PMIN : activation", timeline.get(4).getMessage()); | ||
assertEquals("GEN____8_SM", timeline.get(4).getModelName()); | ||
} | ||
|
||
@Test | ||
void testInconsistentFile() throws URISyntaxException { | ||
Path path = Path.of(Objects.requireNonNull(getClass().getResource("/wrongTimeline.log")).toURI()); | ||
Exception e = assertThrows(PowsyblException.class, () -> CsvTimeLineParser.parse(path, '|')); | ||
assertEquals("Columns of line 2 are inconsistent", e.getMessage()); | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
commons/src/test/java/com/powsybl/dynawo/commons/timeline/XmlTimeLineParserTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/** | ||
* Copyright (c) 2023, RTE (http://www.rte-france.com/) | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
* SPDX-License-Identifier: MPL-2.0 | ||
*/ | ||
package com.powsybl.dynawo.commons.timeline; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import javax.xml.stream.XMLStreamException; | ||
import java.io.InputStreamReader; | ||
import java.net.URISyntaxException; | ||
import java.nio.file.Path; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
||
/** | ||
* @author Marcos de Miguel <demiguelm at aia.es> | ||
*/ | ||
class XmlTimeLineParserTest { | ||
|
||
@Test | ||
void test() throws XMLStreamException { | ||
|
||
InputStreamReader xml = new InputStreamReader(Objects.requireNonNull(getClass().getResourceAsStream("/timeline.xml"))); | ||
List<TimelineEntry> timeline = XmlTimeLineParser.parse(xml); | ||
|
||
assertEquals(5, timeline.size()); | ||
assertEquals("PMIN : activation", timeline.get(0).getMessage()); | ||
assertEquals("GEN____8_SM", timeline.get(0).getModelName()); | ||
assertEquals(0., timeline.get(0).getTime(), 1e-9); | ||
assertEquals("PMIN : activation", timeline.get(1).getMessage()); | ||
assertEquals("GEN____3_SM", timeline.get(1).getModelName()); | ||
assertEquals(0.030691068513160655, timeline.get(1).getTime(), 1e-9); | ||
assertEquals("PMIN : deactivation", timeline.get(2).getMessage()); | ||
assertEquals("GEN____8_SM", timeline.get(2).getModelName()); | ||
assertEquals("PMIN : deactivation", timeline.get(3).getMessage()); | ||
assertEquals("GEN____3_SM", timeline.get(3).getModelName()); | ||
assertEquals("PMIN : activation", timeline.get(4).getMessage()); | ||
assertEquals("GEN____8_SM", timeline.get(4).getModelName()); | ||
} | ||
|
||
@Test | ||
void parseFromPath() throws URISyntaxException { | ||
Path path = Path.of(Objects.requireNonNull(getClass().getResource("/timeline.xml")).toURI()); | ||
List<TimelineEntry> timeline = new XmlTimeLineParser().parse(path); | ||
assertEquals(5, timeline.size()); | ||
} | ||
|
||
@Test | ||
void testInconsistentFile() throws XMLStreamException { | ||
InputStreamReader xml = new InputStreamReader(Objects.requireNonNull(getClass().getResourceAsStream("/wrongTimeline.xml"))); | ||
List<TimelineEntry> timeline = XmlTimeLineParser.parse(xml); | ||
assertEquals(4, timeline.size()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
0 | GEN____8_SM | PMIN : activation | ||
0.0306911 | GEN____3_SM | PMIN : activation | ||
0.348405 | GEN____8_SM | PMIN : deactivation | ||
0.828675 | GEN____3_SM | PMIN : deactivation | ||
0.834701 | GEN____8_SM | PMIN : activation |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?> | ||
<!-- Dynawo timeline --> | ||
<timeline xmlns="http://www.rte-france.com/dynawo"> | ||
<event time="0" modelName="GEN____8_SM" message="PMIN : activation"/> | ||
<event time="0.030691068513160655" modelName="GEN____3_SM" message="PMIN : activation"/> | ||
<event time="0.348405399018546" modelName="GEN____8_SM" message="PMIN : deactivation"/> | ||
<event time="0.82867509138207629" modelName="GEN____3_SM" message="PMIN : deactivation"/> | ||
<event time="0.83470144243143729" modelName="GEN____8_SM" message="PMIN : activation"/> | ||
</timeline> |
Oops, something went wrong.