[feat] Result table for stops list WIP
This commit is contained in:
parent
5bd350643a
commit
9514d5d254
7 changed files with 430 additions and 5 deletions
19
pom.xml
19
pom.xml
|
@ -37,6 +37,22 @@
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-dependencies</id>
|
||||||
|
<phase>prepare-package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-dependencies</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/${project.build.finalName}.lib</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
@ -45,7 +61,8 @@
|
||||||
<archive>
|
<archive>
|
||||||
<manifest>
|
<manifest>
|
||||||
<addClasspath>true</addClasspath>
|
<addClasspath>true</addClasspath>
|
||||||
<mainClass>fr.u_paris.gla.project.App</mainClass>
|
<classpathPrefix>${project.build.finalName}.lib/</classpathPrefix>
|
||||||
|
<mainClass>fr.u_paris.gla.project.itinerary.ItineraryCalculator</mainClass>
|
||||||
</manifest>
|
</manifest>
|
||||||
</archive>
|
</archive>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<children>
|
<children>
|
||||||
<component id="3cb9b" class="javax.swing.JTextField" binding="textField1" default-binding="true">
|
<component id="3cb9b" class="javax.swing.JTextField" binding="textField1" default-binding="true">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="1" use-parent-layout="false">
|
||||||
<preferred-size width="150" height="-1"/>
|
<preferred-size width="150" height="-1"/>
|
||||||
</grid>
|
</grid>
|
||||||
</constraints>
|
</constraints>
|
||||||
|
@ -83,7 +83,7 @@
|
||||||
</hspacer>
|
</hspacer>
|
||||||
</children>
|
</children>
|
||||||
</grid>
|
</grid>
|
||||||
<grid id="184ef" binding="NetworkPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="184ef" binding="NetworkPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<card name="Card2"/>
|
<card name="Card2"/>
|
||||||
|
@ -103,6 +103,14 @@
|
||||||
<text value="Network"/>
|
<text value="Network"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
|
<scrollpane id="44153" binding="mypane" custom-create="true">
|
||||||
|
<constraints>
|
||||||
|
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties/>
|
||||||
|
<border type="none"/>
|
||||||
|
<children/>
|
||||||
|
</scrollpane>
|
||||||
</children>
|
</children>
|
||||||
</grid>
|
</grid>
|
||||||
<grid id="dfb19" binding="FavoritesPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="dfb19" binding="FavoritesPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
package fr.u_paris.gla.project.gui;
|
package fr.u_paris.gla.project.gui;
|
||||||
|
|
||||||
|
import fr.u_paris.gla.project.itinerary.Stop;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.table.DefaultTableModel;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.KeyAdapter;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class View extends JFrame{
|
public class View extends JFrame{
|
||||||
private JPanel Cardpanel;
|
private JPanel Cardpanel;
|
||||||
|
@ -16,8 +22,23 @@ public class View extends JFrame{
|
||||||
private JButton searchButton;
|
private JButton searchButton;
|
||||||
private JPanel HomePanel;
|
private JPanel HomePanel;
|
||||||
private JPanel MainPanel;
|
private JPanel MainPanel;
|
||||||
|
private DefaultTableModel dtm;
|
||||||
|
|
||||||
|
private JTable table;
|
||||||
|
|
||||||
|
private JScrollPane mypane;
|
||||||
|
|
||||||
|
private ArrayList<Stop> StopList;
|
||||||
|
|
||||||
|
private Stop StopCur;
|
||||||
|
|
||||||
|
private ArrayList<Stop> searchRes;
|
||||||
|
|
||||||
|
public View(ArrayList<Stop> s) throws HeadlessException {
|
||||||
|
this.createUIComponents();
|
||||||
|
this.StopList = s;
|
||||||
|
this.StopCur = StopList.get(0);
|
||||||
|
|
||||||
public View() throws HeadlessException {
|
|
||||||
setContentPane(MainPanel);
|
setContentPane(MainPanel);
|
||||||
setTitle("app");
|
setTitle("app");
|
||||||
setExtendedState(JFrame.MAXIMIZED_BOTH);
|
setExtendedState(JFrame.MAXIMIZED_BOTH);
|
||||||
|
@ -56,11 +77,81 @@ public class View extends JFrame{
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
textField1.addKeyListener(new KeyAdapter() {
|
||||||
|
@Override
|
||||||
|
public void keyReleased(KeyEvent e) {
|
||||||
|
super.keyReleased(e);
|
||||||
|
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||||
|
System.out.println("Enter key released");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
View v = new View();
|
ArrayList<Stop> s = new ArrayList<>();
|
||||||
|
s.add(new Stop("M8", "Balard", 1.0315897, 3.0265513));
|
||||||
|
s.add(new Stop("M14", "Gare de Lyon", 2.4658452681, 3.0265513));
|
||||||
|
System.out.println(s.toString());
|
||||||
|
View v = new View(s);
|
||||||
|
v.showSearch(s);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void createUIComponents() {
|
||||||
|
// TODO: place custom component creation code here
|
||||||
|
|
||||||
|
table = new JTable();
|
||||||
|
dtm = new DefaultTableModel(0, 0);
|
||||||
|
|
||||||
|
String[] header = new String[] { "Line", "Stop" };
|
||||||
|
dtm.setColumnIdentifiers(header);
|
||||||
|
table.setModel(dtm);
|
||||||
|
mypane = new JScrollPane(table);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showSearch(ArrayList<Stop> stops) {
|
||||||
|
// Clear existing rows from the table
|
||||||
|
dtm.setRowCount(0);
|
||||||
|
|
||||||
|
// Add new rows based on the search results
|
||||||
|
for (Stop stop : stops) {
|
||||||
|
// Add a row to the table with Stop's line in the first column and Stop's name in the second column
|
||||||
|
|
||||||
|
dtm.addRow(new Object[]{stop.getLines(), stop.getName()});
|
||||||
|
}
|
||||||
|
this.displayTableValues();
|
||||||
|
dtm.fireTableDataChanged();
|
||||||
|
table.repaint();
|
||||||
|
table.revalidate();
|
||||||
|
Cardpanel.repaint();
|
||||||
|
Cardpanel.revalidate();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displayTableValues() {
|
||||||
|
int rowCount = dtm.getRowCount();
|
||||||
|
int columnCount = dtm.getColumnCount();
|
||||||
|
|
||||||
|
// Iterate over each row
|
||||||
|
for (int row = 0; row < rowCount; row++) {
|
||||||
|
// Iterate over each column
|
||||||
|
for (int col = 0; col < columnCount; col++) {
|
||||||
|
// Get the value at the current cell
|
||||||
|
Object value = dtm.getValueAt(row, col);
|
||||||
|
// Display the value
|
||||||
|
System.out.println("Value at row " + row + ", column " + col + ": " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package fr.u_paris.gla.project.itinerary;
|
||||||
|
|
||||||
|
public class Connection{
|
||||||
|
// Destination of the connection between the two stops
|
||||||
|
private final Stop stop;
|
||||||
|
|
||||||
|
// The line used for this connection
|
||||||
|
private final String lineName;
|
||||||
|
|
||||||
|
private final double distance;
|
||||||
|
|
||||||
|
private final int time;
|
||||||
|
|
||||||
|
public Connection(Stop stop, String lineName, double distance, int time){
|
||||||
|
this.stop = stop;
|
||||||
|
this.lineName=lineName;
|
||||||
|
this.distance = distance;
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getLineName() {
|
||||||
|
return lineName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDistance() {
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stop getStop() {
|
||||||
|
return stop;
|
||||||
|
}
|
||||||
|
}
|
28
src/main/java/fr/u_paris/gla/project/itinerary/Graph.java
Normal file
28
src/main/java/fr/u_paris/gla/project/itinerary/Graph.java
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package fr.u_paris.gla.project.itinerary;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class Graph{
|
||||||
|
private final Set<Stop> nodes;
|
||||||
|
|
||||||
|
private final Map<Stop, Set<Connection>> connections;
|
||||||
|
|
||||||
|
public Graph(Set<Stop> nodes, Map<Stop, Set<Connection>> connections) {
|
||||||
|
this.nodes = nodes;
|
||||||
|
this.connections = connections;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Connection> getConnections(Stop node) {
|
||||||
|
return connections.get(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Stop> getNodes() {
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Stop, Set<Connection>> getConnections() {
|
||||||
|
return connections;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
package fr.u_paris.gla.project.itinerary;
|
||||||
|
|
||||||
|
import fr.u_paris.gla.project.idfm.*;
|
||||||
|
import fr.u_paris.gla.project.utils.CSVTools;
|
||||||
|
import fr.u_paris.gla.project.utils.GPS;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class ItineraryCalculator {
|
||||||
|
private static final Logger LOGGER = Logger
|
||||||
|
.getLogger(IDFMNetworkExtractor.class.getName());
|
||||||
|
|
||||||
|
// IDF mobilite generated file
|
||||||
|
private static final String TRACE_FILE_NAME = "./trace.csv";
|
||||||
|
|
||||||
|
private static final String HOURS_FILE_NAME = "./hours.csv";
|
||||||
|
|
||||||
|
// IDF mobilite file format
|
||||||
|
|
||||||
|
private static final int IDFM_TRACE_ID_INDEX = 0;
|
||||||
|
|
||||||
|
private static final int IDFM_TRACE_DERIV_INDEX = 1;
|
||||||
|
|
||||||
|
private static final int IDFM_TRACE_FROM_INDEX = 2;
|
||||||
|
|
||||||
|
private static final int IDFM_TRACE_FROM_GPS_INDEX = 3;
|
||||||
|
|
||||||
|
private static final int IDFM_TRACE_TO_INDEX= 4;
|
||||||
|
|
||||||
|
private static final int IDFM_TRACE_TO_GPS_INDEX = 5;
|
||||||
|
|
||||||
|
private static final int IDFM_TRACE_TIME_INDEX = 6;
|
||||||
|
|
||||||
|
private static final int IDFM_TRACE_DISTANCE_INDEX = 7;
|
||||||
|
|
||||||
|
private static final double ERROR_MARGIN = 1.;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the coordinates from a String to a double array:
|
||||||
|
* "49.08, 3.07" -> {49.08, 3.07}
|
||||||
|
* @param gps the string representation
|
||||||
|
* @return the double array
|
||||||
|
*/
|
||||||
|
private static double[] getCoords(String gps) {
|
||||||
|
String []stringCoords = gps.split(", ");
|
||||||
|
return new double[] {Double.parseDouble(stringCoords[0]), Double.parseDouble(stringCoords[1])};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searchs for a stop with the same name and GPS coordinates in the graph, and creates it if non existant
|
||||||
|
* @param nodes a graph of the stops
|
||||||
|
* @param tmp list of the created stops
|
||||||
|
* @param name the name of the stop
|
||||||
|
* @param gps the coordinate of the stop
|
||||||
|
* @param lineId the line the stop is on
|
||||||
|
* @return the Stop object
|
||||||
|
*/
|
||||||
|
private static Stop getOrCreateStop(HashSet<Stop> nodes, HashMap<String, ArrayList<Stop>> tmp, String name, String gps, String lineId) {
|
||||||
|
ArrayList<Stop> stopList = tmp.get(name);
|
||||||
|
// First we search by name, and then compare the coordinates since multiple stations can have the same name. A margin of error is necessary since stops can have multiple GPS coordinates
|
||||||
|
if (stopList != null) {
|
||||||
|
for(Stop stop : stopList) {
|
||||||
|
double[] coords = getCoords(gps);
|
||||||
|
double dist = GPS.distance(coords[0], coords[1], stop.getLatitude(), stop.getLongitude());
|
||||||
|
if(dist < ERROR_MARGIN) {
|
||||||
|
stop.addLine(lineId);
|
||||||
|
return stop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double[] coords = getCoords(gps);
|
||||||
|
Stop newStop = new Stop(lineId, name, coords[0], coords[1]);
|
||||||
|
nodes.add(newStop);
|
||||||
|
stopList = stopList == null ? new ArrayList<>() : stopList;
|
||||||
|
stopList.add(newStop);
|
||||||
|
tmp.put(name, stopList);
|
||||||
|
return newStop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds into the graph the connection between two stops, parsed from a CSV line
|
||||||
|
* @param line the current line we want to parse
|
||||||
|
* @param nodes the graph of stops
|
||||||
|
* @param tmp list of the created stops
|
||||||
|
* @param connections
|
||||||
|
*/
|
||||||
|
private static void addLine(String[] line, HashSet<Stop> nodes, HashMap<String, ArrayList<Stop>> tmp, HashMap<Stop, Set<Connection>> connections) {
|
||||||
|
Stop fromStop = getOrCreateStop(nodes, tmp, line[IDFM_TRACE_FROM_INDEX], line[IDFM_TRACE_FROM_GPS_INDEX], line[IDFM_TRACE_ID_INDEX]);
|
||||||
|
Stop toStop = getOrCreateStop(nodes, tmp, line[IDFM_TRACE_TO_INDEX], line[IDFM_TRACE_TO_GPS_INDEX], line[IDFM_TRACE_ID_INDEX]);
|
||||||
|
|
||||||
|
String[] timeString = line[IDFM_TRACE_TIME_INDEX].split(":");
|
||||||
|
int time = Integer.parseInt(timeString[0]) * 60 + Integer.parseInt(timeString[1]);
|
||||||
|
|
||||||
|
Connection connection = new Connection(toStop, line[IDFM_TRACE_ID_INDEX], Double.parseDouble(line[IDFM_TRACE_DISTANCE_INDEX]), time);
|
||||||
|
|
||||||
|
connections.computeIfAbsent(fromStop, k -> new HashSet<>()).add(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args){
|
||||||
|
if (args.length != 0) {
|
||||||
|
LOGGER.severe("Invalid command line. Target file names are in the main file for now.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
HashSet<Stop> nodes = new HashSet<>();
|
||||||
|
HashMap<Stop, Set<Connection>> connections = new HashMap<>();
|
||||||
|
HashMap<String, ArrayList<Stop>> tmp = new HashMap<>();
|
||||||
|
CSVTools.readCSVFromFile(TRACE_FILE_NAME,
|
||||||
|
(String[] line) -> addLine(line, nodes, tmp, connections));
|
||||||
|
|
||||||
|
|
||||||
|
Stop porteivry = tmp.get("Porte d'Ivry").get(0);
|
||||||
|
Stop repu = tmp.get("République").get(0);
|
||||||
|
|
||||||
|
Graph graph = new Graph(nodes, connections);
|
||||||
|
int cpt = 0;
|
||||||
|
for (Map.Entry<Stop, Set<Connection>> entry : graph.getConnections().entrySet()) {
|
||||||
|
if (entry.getValue() == null) cpt +=1;
|
||||||
|
}
|
||||||
|
Stop garenord = tmp.get("Gare du Nord").get(0);
|
||||||
|
|
||||||
|
Stop chatelet = tmp.get("Châtelet").get(0);
|
||||||
|
//System.out.println(graph.getConnections(garenord));
|
||||||
|
//System.out.println(cpt);
|
||||||
|
//System.out.println(graph.getConnections(porteivry));
|
||||||
|
Finder finder = new Finder(graph);
|
||||||
|
|
||||||
|
List<Stop> res = finder.findPath(porteivry, chatelet);
|
||||||
|
|
||||||
|
for (Stop element : res) {
|
||||||
|
System.out.println(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.log(Level.SEVERE, "Error while reading the line paths", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
98
src/main/java/fr/u_paris/gla/project/itinerary/Stop.java
Normal file
98
src/main/java/fr/u_paris/gla/project/itinerary/Stop.java
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
package fr.u_paris.gla.project.itinerary;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class Stop implements GraphNode {
|
||||||
|
// The total number of stops
|
||||||
|
private static int counter = 0;
|
||||||
|
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// The set of all the lines the stop is on
|
||||||
|
private final Set<String> lines;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private final double latitude;
|
||||||
|
|
||||||
|
private final double longitude;
|
||||||
|
|
||||||
|
private double f;
|
||||||
|
|
||||||
|
public Stop(String line, String name, double latitude, double longitude) {
|
||||||
|
lines = new HashSet<>();
|
||||||
|
lines.add(line);
|
||||||
|
this.id = counter++;
|
||||||
|
this.name = name;
|
||||||
|
this.latitude = latitude;
|
||||||
|
this.longitude = longitude;
|
||||||
|
this.f = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Stop{" +
|
||||||
|
"id=" + id +
|
||||||
|
", lines=" + lines +
|
||||||
|
", name='" + name + '\'' +
|
||||||
|
", latitude=" + latitude +
|
||||||
|
", longitude=" + longitude +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId(){
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getHeuristicCost(Stop goalNode) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Stop> getNeighbors() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getCost(Stop neighbor) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getF() {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setF(double value) {
|
||||||
|
this.f = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName(){
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLatitude(){
|
||||||
|
return latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLongitude(){
|
||||||
|
return longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLine(String s){
|
||||||
|
lines.add(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getLines() {
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Reference in a new issue