Skip to content

Commit 4ee5dfa

Browse files
committed
review IntegerUnit and converters
1 parent 81f6fd2 commit 4ee5dfa

File tree

6 files changed

+133
-209
lines changed

6 files changed

+133
-209
lines changed

net.lecousin.core/src/main/java/net/lecousin/framework/math/IntegerUnit.java

Lines changed: 38 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
import java.lang.annotation.Retention;
55
import java.lang.annotation.RetentionPolicy;
66
import java.lang.annotation.Target;
7+
import java.util.ArrayList;
8+
9+
import net.lecousin.framework.plugins.ExtensionPoint;
10+
import net.lecousin.framework.plugins.Plugin;
711

812
/** Represent an integer unit. */
9-
// TODO review this, and create individual unit converters by using an extension point.
1013
public interface IntegerUnit {
1114

1215
/** Annotation to specify in which unit a field is expressed. */
@@ -29,100 +32,45 @@ public UnitConversionException(Class<? extends IntegerUnit> from, Class<? extend
2932

3033
}
3134

32-
/** Convert a value into this unit. */
33-
public long convertFrom(long value, Class<? extends IntegerUnit> unit) throws UnitConversionException;
34-
35-
/** Unit of time. */
36-
public interface Time extends IntegerUnit {
37-
38-
/** Milliseconds time unit. */
39-
public static class Millisecond implements Time {
40-
@Override
41-
public long convertFrom(long value, Class<? extends IntegerUnit> unit) throws UnitConversionException {
42-
if (Millisecond.class.equals(unit))
43-
return value;
44-
if (Second.class.equals(unit))
45-
return value * 1000;
46-
if (Minute.class.equals(unit))
47-
return value * 60 * 1000;
48-
if (Hour.class.equals(unit))
49-
return value * 60 * 60 * 1000;
50-
if (Day.class.equals(unit))
51-
return value * 24 * 60 * 60 * 1000;
52-
throw new UnitConversionException(getClass(), unit, value);
53-
}
54-
}
35+
/** Convert a value. */
36+
public static interface Converter extends Plugin {
37+
/** Return true if the conversion is supported. */
38+
boolean supportConversion(Class<? extends IntegerUnit> from, Class<? extends IntegerUnit> to);
5539

56-
/** Seconds time unit. */
57-
public static class Second implements Time {
58-
@Override
59-
public long convertFrom(long value, Class<? extends IntegerUnit> unit) throws UnitConversionException {
60-
if (Millisecond.class.equals(unit))
61-
return value / 1000;
62-
if (Second.class.equals(unit))
63-
return value;
64-
if (Minute.class.equals(unit))
65-
return value * 60;
66-
if (Hour.class.equals(unit))
67-
return value * 60 * 60;
68-
if (Day.class.equals(unit))
69-
return value * 24 * 60 * 60;
70-
throw new UnitConversionException(getClass(), unit, value);
71-
}
72-
}
73-
74-
/** Minutes time unit. */
75-
public static class Minute implements Time {
76-
@Override
77-
public long convertFrom(long value, Class<? extends IntegerUnit> unit) throws UnitConversionException {
78-
if (Millisecond.class.equals(unit))
79-
return value / (60 * 1000);
80-
if (Second.class.equals(unit))
81-
return value / 60;
82-
if (Minute.class.equals(unit))
83-
return value;
84-
if (Hour.class.equals(unit))
85-
return value * 60;
86-
if (Day.class.equals(unit))
87-
return value * 24 * 60;
88-
throw new UnitConversionException(getClass(), unit, value);
89-
}
40+
/** Convert a value. */
41+
long convert(long value, Class<? extends IntegerUnit> from, Class<? extends IntegerUnit> to) throws UnitConversionException;
42+
}
43+
44+
/** Extension point from converters. */
45+
public static class ConverterRegistry implements ExtensionPoint<Converter> {
46+
47+
/** Constructor. */
48+
public ConverterRegistry() {
49+
instance = this;
50+
converters.add(new TimeUnit.Converter());
9051
}
52+
53+
private static ConverterRegistry instance;
54+
private ArrayList<Converter> converters = new ArrayList<>();
9155

92-
/** Hour time unit. */
93-
public static class Hour implements Time {
94-
@Override
95-
public long convertFrom(long value, Class<? extends IntegerUnit> unit) throws UnitConversionException {
96-
if (Millisecond.class.equals(unit))
97-
return value / (60 * 60 * 1000);
98-
if (Second.class.equals(unit))
99-
return value / (60 * 60);
100-
if (Minute.class.equals(unit))
101-
return value / 60;
102-
if (Hour.class.equals(unit))
103-
return value;
104-
if (Day.class.equals(unit))
105-
return value * 24;
106-
throw new UnitConversionException(getClass(), unit, value);
107-
}
56+
@Override
57+
public Class<Converter> getPluginClass() { return Converter.class; }
58+
59+
@Override
60+
public void addPlugin(Converter plugin) { converters.add(plugin); }
61+
62+
@Override
63+
public void allPluginsLoaded() {
64+
// nothing to do
10865
}
10966

110-
/** Day time unit. */
111-
public static class Day implements Time {
112-
@Override
113-
public long convertFrom(long value, Class<? extends IntegerUnit> unit) throws UnitConversionException {
114-
if (Millisecond.class.equals(unit))
115-
return value / (24 * 60 * 60 * 1000);
116-
if (Second.class.equals(unit))
117-
return value / (24 * 60 * 60);
118-
if (Minute.class.equals(unit))
119-
return value / (24 * 60);
120-
if (Hour.class.equals(unit))
121-
return value / 24;
122-
if (Day.class.equals(unit))
123-
return value;
124-
throw new UnitConversionException(getClass(), unit, value);
125-
}
67+
/** Conversion. */
68+
public static long convert(long value, Class<? extends IntegerUnit> from, Class<? extends IntegerUnit> to)
69+
throws UnitConversionException {
70+
for (Converter c : instance.converters)
71+
if (c.supportConversion(from, to))
72+
return c.convert(value, from, to);
73+
throw new UnitConversionException(from, to, value);
12674
}
12775

12876
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package net.lecousin.framework.math;
2+
3+
/** Unit of time. */
4+
public interface TimeUnit extends IntegerUnit {
5+
6+
/** Milliseconds time unit. */
7+
public static class Millisecond implements TimeUnit {
8+
}
9+
10+
/** Seconds time unit. */
11+
public static class Second implements TimeUnit {
12+
}
13+
14+
/** Minutes time unit. */
15+
public static class Minute implements TimeUnit {
16+
}
17+
18+
/** Hour time unit. */
19+
public static class Hour implements TimeUnit {
20+
}
21+
22+
/** Day time unit. */
23+
public static class Day implements TimeUnit {
24+
}
25+
26+
/** Converter between time units. */
27+
public static class Converter implements IntegerUnit.Converter {
28+
29+
@Override
30+
public boolean supportConversion(Class<? extends IntegerUnit> from, Class<? extends IntegerUnit> to) {
31+
if (!from.equals(Millisecond.class) &&
32+
!from.equals(Second.class) &&
33+
!from.equals(Minute.class) &&
34+
!from.equals(Hour.class) &&
35+
!from.equals(Day.class)
36+
)
37+
return false;
38+
if (!to.equals(Millisecond.class) &&
39+
!to.equals(Second.class) &&
40+
!to.equals(Minute.class) &&
41+
!to.equals(Hour.class) &&
42+
!to.equals(Day.class)
43+
)
44+
return false;
45+
return true;
46+
}
47+
48+
@Override
49+
public long convert(long value, Class<? extends IntegerUnit> from, Class<? extends IntegerUnit> to)
50+
throws UnitConversionException {
51+
return convertFromMilliseconds(convertToMilliseconds(value, from), to);
52+
}
53+
54+
/** Convert a value into milliseconds. */
55+
public long convertToMilliseconds(long value, Class<? extends IntegerUnit> unit) throws UnitConversionException {
56+
if (unit.equals(Millisecond.class))
57+
return value;
58+
if (unit.equals(Second.class))
59+
return value * 1000;
60+
if (unit.equals(Minute.class))
61+
return value * 60 * 1000;
62+
if (unit.equals(Hour.class))
63+
return value * 60 * 60 * 1000;
64+
if (unit.equals(Day.class))
65+
return value * 24 * 60 * 60 * 1000;
66+
throw new UnitConversionException(unit, Millisecond.class, value);
67+
}
68+
69+
/** Convert a value from milliseconds. */
70+
public long convertFromMilliseconds(long value, Class<? extends IntegerUnit> unit) throws UnitConversionException {
71+
if (unit.equals(Millisecond.class))
72+
return value;
73+
if (unit.equals(Second.class))
74+
return value / 1000;
75+
if (unit.equals(Minute.class))
76+
return value / (60 * 1000);
77+
if (unit.equals(Hour.class))
78+
return value / (60 * 60 * 1000);
79+
if (unit.equals(Day.class))
80+
return value / (24 * 60 * 60 * 1000);
81+
throw new UnitConversionException(Millisecond.class, unit, value);
82+
}
83+
84+
}
85+
86+
}

net.lecousin.core/src/main/java/net/lecousin/framework/plugins/ExtensionPoints.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import net.lecousin.framework.adapter.AdapterRegistry;
88
import net.lecousin.framework.io.serialization.annotations.AnnotationToRule;
99
import net.lecousin.framework.locale.LocaleExtensionPoint;
10+
import net.lecousin.framework.math.IntegerUnit;
1011

1112
/** Extension points registry. */
1213
public final class ExtensionPoints {
@@ -21,6 +22,7 @@ private ExtensionPoints() {
2122
static {
2223
points.add(new AdapterRegistry());
2324
points.add(new AnnotationToRule());
25+
points.add(new IntegerUnit.ConverterRegistry());
2426
customs.add(new LocaleExtensionPoint());
2527
}
2628

net.lecousin.core/src/main/java/net/lecousin/framework/xml/XMLStreamCursor.java

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import java.util.Iterator;
1010
import java.util.Map;
1111

12+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
13+
1214
import net.lecousin.framework.event.Listener;
1315
import net.lecousin.framework.io.IO;
1416
import net.lecousin.framework.io.buffering.PreBufferedReadable;
@@ -21,8 +23,6 @@
2123
import net.lecousin.framework.util.UnprotectedString;
2224
import net.lecousin.framework.util.UnprotectedStringBuffer;
2325

24-
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
25-
2626
/**
2727
* Read an XML in a similar way as {@link javax.xml.stream.XMLStreamReader}: read-only, forward, event based.
2828
* The method next() allows to move forward to the next event (such as start element, end element, comment, text...).
@@ -192,9 +192,6 @@ protected char getNextChar() throws IOException {
192192
return stream.read();
193193
}
194194

195-
// private Charset getCharset() {
196-
// return stream.getCharset();
197-
// }
198195
}
199196

200197
private void initCharacterProvider() throws XMLException, IOException {
@@ -320,7 +317,6 @@ public void start() throws XMLException, IOException {
320317
String encoding = getAttribute("encoding");
321318
if (encoding != null)
322319
cp = new CharacterStreamProvider(Charset.forName(encoding));
323-
// TODO
324320
next();
325321
}
326322
}
@@ -749,7 +745,6 @@ private void readProcessingInstruction() throws XMLException, IOException {
749745
}
750746
if (!isNameStartChar(c))
751747
continue;
752-
//throw new XMLException(cp.getPosition(), "Unexpected character", Character.valueOf(c));
753748
// attribute name
754749
UnprotectedStringBuffer attrName = new UnprotectedStringBuffer();
755750
attrName.append(c);
@@ -924,6 +919,7 @@ private void readEndTag() throws XMLException, IOException {
924919
} while (true);
925920
}
926921

922+
// skip checkstyle: VariableDeclarationUsageDistance
927923
private void readIntSubset() throws XMLException, IOException {
928924
UnprotectedStringBuffer saveText = text;
929925
Type saveType = type;
@@ -1053,15 +1049,13 @@ private void readElementDeclaration() throws XMLException, IOException {
10531049
cp.back(c);
10541050
UnprotectedStringBuffer name = new UnprotectedStringBuffer();
10551051
readName(name);
1056-
// TODO
10571052
c = cp.nextChar();
10581053
while (c != '>') c = cp.nextChar();
10591054
}
10601055

10611056
private void readEntityDeclaration() throws IOException {
10621057
char c = cp.nextChar();
10631058
while (isSpaceChar(c)) c = cp.nextChar();
1064-
// TODO
10651059
boolean inString = false;
10661060
do {
10671061
c = cp.nextChar();
@@ -1080,7 +1074,6 @@ private void readAttListDeclaration() throws XMLException, IOException {
10801074
cp.back(c);
10811075
UnprotectedStringBuffer name = new UnprotectedStringBuffer();
10821076
readName(name);
1083-
// TODO
10841077
c = cp.nextChar();
10851078
while (c != '>') c = cp.nextChar();
10861079
}
@@ -1091,7 +1084,6 @@ private void readNotationDeclaration() throws XMLException, IOException {
10911084
cp.back(c);
10921085
UnprotectedStringBuffer name = new UnprotectedStringBuffer();
10931086
readName(name);
1094-
// TODO
10951087
c = cp.nextChar();
10961088
while (c != '>') c = cp.nextChar();
10971089
}

net.lecousin.core/src/test/java/net/lecousin/framework/core/tests/xml/TestXMLStreamCursorWithDOM.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,9 @@ public class TestXMLStreamCursorWithDOM extends LCCoreAbstractTest {
144144
"xml-test-suite/xmltest/valid/sa/105.xml",
145145
"xml-test-suite/xmltest/valid/sa/106.xml",
146146
"xml-test-suite/xmltest/valid/sa/107.xml",
147-
// TODO entity ref "xml-test-suite/xmltest/valid/sa/108.xml",
147+
// entity ref "xml-test-suite/xmltest/valid/sa/108.xml",
148148
"xml-test-suite/xmltest/valid/sa/109.xml",
149-
// TODO entity ref "xml-test-suite/xmltest/valid/sa/110.xml",
149+
// entity ref "xml-test-suite/xmltest/valid/sa/110.xml",
150150
//"xml-test-suite/xmltest/valid/sa/111.xml",
151151
"xml-test-suite/xmltest/valid/sa/112.xml",
152152
"xml-test-suite/xmltest/valid/sa/113.xml",
@@ -231,7 +231,6 @@ private static void checkNode(Node node, XMLStreamCursor xml, LinkedList<String>
231231
}
232232
if (node.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
233233
node = node.getOwnerDocument().createTextNode("&" + ((EntityReference)node).getNodeName() + ";");
234-
// TODO we should have entity reference in XMLStreamCursor as well
235234
}
236235
Assert.assertEquals("Expected text <" + xml.text.asString() + ">, but node " + node.getNodeType() + " found", Node.TEXT_NODE, node.getNodeType());
237236
checkText((Text)node, xml);
@@ -258,7 +257,6 @@ private static void checkDocType(DocumentType node, XMLStreamCursor xml) throws
258257
assertEquals("DOCTYPE name", node.getName(), xml.text);
259258
assertEquals("system id", node.getSystemId(), xml.system);
260259
assertEquals("public id", node.getPublicId(), xml.publicId);
261-
// TODO
262260
xml.next();
263261
}
264262

0 commit comments

Comments
 (0)