1 /* Ametros Dive Computer
2 * Copyright (C) 2010 Geoff Johnstone
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 package net
.ametros
.dive
.parser
;
20 import net
.ametros
.dive
.data
.Dive
;
21 import net
.ametros
.dive
.data
.Gas
;
22 import net
.ametros
.dive
.data
.Stop
;
25 import java
.io
.FileReader
;
26 import java
.io
.IOException
;
27 import java
.util
.ArrayList
;
28 import java
.util
.List
;
29 import java
.util
.regex
.Matcher
;
30 import java
.util
.regex
.Pattern
;
31 import javax
.swing
.text
.MutableAttributeSet
;
32 import javax
.swing
.text
.html
.HTML
;
33 import javax
.swing
.text
.html
.HTMLEditorKit
;
34 import javax
.swing
.text
.html
.parser
.ParserDelegator
;
37 /** Parser for DDPlan 2.x HTML dive plans. */
38 public class DDPlanParser
extends AbstractParser
40 private static final Pattern depthPattern
= Pattern
.compile ("^(\\d+)m$");
42 private static final Pattern stopPattern
=
43 Pattern
.compile ("^(\\d+)\\s*/\\s*\\d+$");
47 protected void doParse (File file
) throws IOException
53 fr
= new FileReader (file
);
54 new ParserDelegator().parse (fr
, new ParserCallback(), true);
66 INITIAL
, // Look for <table>.
67 FIND_DEPTH
, // First text gives dive depth, then START_DIVE.
68 START_DIVE
, // Look for <table>.
69 TITLES
, // Texts are column names, then look for </tr>. Special
70 // column names are Gas, ppO2, D\RT; others are durations.
71 STOPS
, // Texts are column values, then look for Text CNS%.
72 GRADIENTS
; // Text starting "Gradient Factors", then INITIAL.
76 class ParserCallback
extends HTMLEditorKit
.ParserCallback
78 private ParserState state
;
79 private int diveDepth
;
80 private final List
<String
> columns
= new ArrayList
<String
>();
84 private int stopDepth
;
87 public ParserCallback()
95 state
= ParserState
.INITIAL
;
106 public void handleEndTag (HTML
.Tag tag
, int pos
)
108 // System.err.println ("End " + tag);
113 if (HTML
.Tag
.TR
.equals (tag
))
115 dives
= new Dive
[columns
.size()];
118 for (String str
: columns
)
120 if (!"Gas".equals (str
) &&
121 !"ppO2".equals (str
) &&
122 !"D\\RT".equals (str
))
124 final int duration
= Integer
.parseInt (str
);
125 dives
[i
] = createDive (diveDepth
, duration
, getDefaultGas());
131 state
= ParserState
.STOPS
;
143 public void handleStartTag (HTML
.Tag tag
, MutableAttributeSet a
, int pos
)
145 // System.err.println ("Start " + tag);
150 if (HTML
.Tag
.TABLE
.equals (tag
))
151 state
= ParserState
.FIND_DEPTH
;
155 if (HTML
.Tag
.TABLE
.equals (tag
))
156 state
= ParserState
.TITLES
;
166 public void handleText (char[] data
, int pos
)
168 final String text
= normaliseWhitespace (data
);
169 // System.err.println ("Text: " + text);
174 final Matcher m0
= depthPattern
.matcher (text
);
176 throw new RuntimeException ("Expected dive depth; got " + text
);
178 diveDepth
= Integer
.parseInt (m0
.group (1));
179 state
= ParserState
.START_DIVE
;
187 if (text
.startsWith ("CNS%"))
188 state
= ParserState
.GRADIENTS
;
191 if (nextCol
== columns
.size())
198 final String key
= columns
.get (nextCol
);
199 if ("Gas".equals (key
))
201 stopGas
= parseGas (text
);
204 else if ("D\\RT".equals (key
))
206 stopDepth
= Integer
.parseInt (text
);
209 else if (!"ppO2".equals (key
) && !text
.isEmpty())
211 final Matcher m1
= stopPattern
.matcher (text
);
213 throw new RuntimeException ("Expected stop; got " + text
);
215 final Stop stop
= of
.createStop();
216 stop
.setDepth (stopDepth
);
217 stop
.setDuration (Integer
.parseInt (m1
.group (1)));
218 stop
.setGas (stopGas
);
219 dives
[nextCol
].getAscent().getStops().add (stop
);
228 if (text
.startsWith ("Gradient Factors"))
230 // TODO: WTF are gradient factors?
232 for (Dive dive
: dives
)