tags = way.getTags();
245 | if (tags != null) {
246 | if (RuleSet.checkRule(rule, tags)) {
247 | // TODO: verify if there is a path and render text along the path? or see how osmarender does it?
248 | graphics.setFont(font);
249 | graphics.setPaint(d.getColor());
250 | Node nd = way.getWayNode().get(0);
251 | Coordinate xy = Mercator.coord2xy(nd.getLat(), nd.getLon(), surface.zoomLevel, resolution);
252 |
253 | graphics.drawString(
254 | way.getName(),
255 | (int) (xy.x - surface.offset.x),
256 | (int) (xy.y - surface.offset.y));
257 | }
258 | }
259 | }
260 | }
261 | break;
262 | }
263 | d = d.next();
264 | }
265 | }
266 | }
267 |
--------------------------------------------------------------------------------
/map-render-service/src/main/java/io/vertx/workshop/map/rules/Draw.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 the original author or authors.
3 | */
4 | package io.vertx.workshop.map.rules;
5 |
6 | import java.awt.Color;
7 |
8 | /**
9 | * LinkedList Struct for Draws
10 | *
11 | * @author Paulo Lopes
12 | */
13 | public class Draw {
14 |
15 | public static final int UNKNOWN = 0;
16 | public static final int LINE = 1;
17 | public static final int POLYGONE = 2;
18 | public static final int TEXT = 3;
19 |
20 | public final int type;
21 |
22 | private int minzoom;
23 | private int maxzoom;
24 | private Color color;
25 | private String pattern;
26 | private float width;
27 |
28 | Draw next;
29 |
30 | public Draw(int type) {
31 | this.type = type;
32 | maxzoom = 99;
33 | }
34 |
35 | public void setColor(Color c) {
36 | this.color = c;
37 | }
38 |
39 | public Color getColor() {
40 | return color;
41 | }
42 |
43 | public void setWidth(float w) {
44 | this.width = w;
45 | }
46 |
47 | public float getWidth() {
48 | return width;
49 | }
50 |
51 | public void setPattern(String pattern) {
52 | this.pattern = pattern;
53 | }
54 |
55 | public void setZoom(int min, int max) {
56 | this.minzoom = min;
57 | this.maxzoom = max;
58 | }
59 |
60 | public int getMinZoom() {
61 | return minzoom;
62 | }
63 |
64 | public int getMaxZoom() {
65 | return maxzoom;
66 | }
67 |
68 | public Draw next() {
69 | return next;
70 | }
71 |
72 | public String getPattern() {
73 | return pattern;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/map-render-service/src/main/java/io/vertx/workshop/map/rules/Rule.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 the original author or authors.
3 | */
4 | package io.vertx.workshop.map.rules;
5 |
6 | /**
7 | * Defines a drawing rule for the #RuleSet.
8 | *
9 | * @author Paulo Lopes
10 | * @since 1.0
11 | */
12 | public class Rule {
13 |
14 | public static final int UNKNOWN = 0;
15 | public static final int WAY = 1;
16 | public static final int NODE = 2;
17 | public static final int RELATION = 4;
18 |
19 | /* an array of key strings */
20 | public final String[] keys;
21 | /* an array of value strings */
22 | public final String[] values;
23 | /* the type of the rule */
24 | public final int type;
25 | /* the mode of the rule */
26 | public final boolean negate;
27 |
28 | /* Next terminal rule */
29 | private Rule next;
30 |
31 | private Rule parent;
32 |
33 | private Draw draw;
34 |
35 | /**
36 | * Creates a new Rule
37 | *
38 | * @param type type of the rule
39 | * @param key the key of the rule
40 | * @param value the value of the rule
41 | */
42 | public Rule(int type, String[] key, String[] value) {
43 | this(type, key, value, false);
44 | }
45 |
46 | /**
47 | * Create a new Rule
48 | *
49 | * @param type type of the rule
50 | * @param key the key of the rule
51 | * @param value the value of the rule
52 | * @param negate true for else rules, false for normal rules
53 | */
54 | public Rule(int type, String[] key, String[] value, boolean negate) {
55 | this.type = type;
56 | this.keys = new String[key.length];
57 | for (int i = 0; i < keys.length; i++) {
58 | keys[i] = key[i].intern();
59 | }
60 | this.values = new String[value.length];
61 | for (int i = 0; i < values.length; i++) {
62 | values[i] = value[i].intern();
63 | }
64 | this.negate = negate;
65 | }
66 |
67 | public void addRule(Rule rule) {
68 | this.next = rule;
69 | }
70 |
71 | public void setParent(Rule parent) {
72 | this.parent = parent;
73 | }
74 |
75 | public Rule getParent() {
76 | return parent;
77 | }
78 |
79 | public void appendDraw(Draw draw) {
80 | Draw curr = this.draw;
81 | Draw prev = null;
82 |
83 | while (curr != null) {
84 | prev = curr;
85 | curr = curr.next;
86 | }
87 | if (prev != null)
88 | prev.next = draw;
89 | else
90 | this.draw = draw;
91 |
92 | draw.next = null;
93 | }
94 |
95 | public Draw getDraw() {
96 | return draw;
97 | }
98 |
99 | public Rule next() {
100 | return next;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/map-render-service/src/main/java/io/vertx/workshop/map/rules/RuleSet.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 the original author or authors.
3 | */
4 | package io.vertx.workshop.map.rules;
5 |
6 | import java.awt.Color;
7 | import java.io.FileInputStream;
8 | import java.io.FileNotFoundException;
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 | import java.util.Map;
12 |
13 | import javax.xml.parsers.ParserConfigurationException;
14 |
15 | import io.vertx.workshop.map.MapException;
16 | import org.xml.sax.SAXException;
17 |
18 | import io.vertx.workshop.map.rules.osm.OSMRules;
19 |
20 | /**
21 | * Defines drawing rules for the renderer. This Object defines drawing rules for a Renderer.
22 | *
23 | * @author Paulo Lopes
24 | */
25 | public class RuleSet extends OSMRules {
26 |
27 | private static final int TAG_CMP_NOT_EQUAL = 0;
28 | private static final int TAG_CMP_EQUAL = 1;
29 | private static final int TAG_CMP_ANY = 2;
30 | private static final int TAG_CMP_MISSING = 3;
31 |
32 | private final Rule root;
33 | private Color bgColor = Color.WHITE;
34 |
35 | public RuleSet(String filename) throws MapException, FileNotFoundException {
36 | this(new FileInputStream(filename));
37 | }
38 |
39 | public RuleSet(InputStream stream) throws MapException {
40 | try {
41 | Rule o_root = null;
42 | Rule curr = null;
43 | Rule next;
44 |
45 | for (Rule r = read(stream); r != null; ) {
46 | next = r.next();
47 |
48 | if (r.getDraw() != null) {
49 | if (o_root == null) {
50 | o_root = r;
51 | curr = o_root;
52 | } else {
53 | curr.addRule(r);
54 | curr = r;
55 | }
56 | }
57 | r = next;
58 | }
59 | root = o_root;
60 | } catch (SAXException | ParserConfigurationException | IOException e) {
61 | throw new MapException(e);
62 | }
63 | }
64 |
65 | @Override
66 | protected void setBgColor(Color bgColor) {
67 | this.bgColor = bgColor;
68 | }
69 |
70 | public Color getBgColor() {
71 | return bgColor;
72 | }
73 |
74 | public Rule root() {
75 | return root;
76 | }
77 |
78 | private static int stringInStrings(String string, String[] strings) {
79 | for (int i = 0; i < strings.length; i++) {
80 | if (string.equals(strings[i]))
81 | return TAG_CMP_EQUAL;
82 | if ("*".equals(strings[i]))
83 | return TAG_CMP_ANY;
84 | if ("~".equals(strings[i]))
85 | return TAG_CMP_MISSING;
86 | }
87 | return TAG_CMP_NOT_EQUAL;
88 | }
89 |
90 | /**
91 | * function: matchRule
92 | *
93 | * Check if an element matches a rule.
94 | */
95 | public static boolean matchRule(Rule rule, Map tags) {
96 | int k, v;
97 |
98 | for (Map.Entry t : tags.entrySet()) {
99 | k = stringInStrings(t.getKey(), rule.keys);
100 | v = stringInStrings(t.getValue(), rule.values);
101 |
102 | if (k == TAG_CMP_EQUAL && v == TAG_CMP_EQUAL)
103 | return true;
104 | if (k == TAG_CMP_EQUAL && v == TAG_CMP_ANY)
105 | return true;
106 | if (k == TAG_CMP_NOT_EQUAL && v == TAG_CMP_MISSING)
107 | return true;
108 | }
109 | return false;
110 | }
111 |
112 | /**
113 | * function: checkRule
114 | *
115 | * Check if an element matches to a rule and to all it's parents.
116 | */
117 | public static boolean checkRule(Rule rule, Map tags) {
118 |
119 | for (Rule r = rule.getParent(); r != null; r = r.getParent()) {
120 | if (matchRule(r, tags) == r.negate) {
121 | return false;
122 | }
123 | }
124 |
125 | return matchRule(rule, tags);
126 |
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/map-render-service/src/main/java/io/vertx/workshop/map/rules/osm/OSMRules.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 the original author or authors.
3 | */
4 | package io.vertx.workshop.map.rules.osm;
5 |
6 | import java.awt.Color;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.util.logging.Logger;
10 |
11 | import javax.xml.parsers.ParserConfigurationException;
12 | import javax.xml.parsers.SAXParserFactory;
13 |
14 | import io.vertx.workshop.map.rules.Rule;
15 | import io.vertx.workshop.map.rules.Draw;
16 | import org.xml.sax.Attributes;
17 | import org.xml.sax.SAXException;
18 | import org.xml.sax.helpers.DefaultHandler;
19 |
20 | /**
21 | * LinkedList Struct for Rules
22 | *
23 | * @author Paulo Lopes
24 | */
25 | public abstract class OSMRules extends DefaultHandler {
26 |
27 | private int depth;
28 | private Rule rule;
29 |
30 | // parsing helpers
31 | private static final Logger LOG = Logger.getLogger(OSMRules.class.getName());
32 | private static final int MAXSTACK = 20;
33 | // Pointers to work with
34 | private Rule currentRule;
35 | private Rule[] ruleStack;
36 |
37 | public Rule read(InputStream stream) throws SAXException, IOException, ParserConfigurationException {
38 |
39 | depth = -1;
40 | rule = null;
41 |
42 | long tRead = System.currentTimeMillis();
43 |
44 | // NULL rule stack
45 | ruleStack = new Rule[MAXSTACK];
46 |
47 | // Create a builder factory
48 | SAXParserFactory factory = SAXParserFactory.newInstance();
49 | factory.setValidating(false);
50 | // Create the builder and parse the file
51 | factory.newSAXParser().parse(stream, this);
52 | // free resources
53 | stream.close();
54 |
55 | LOG.info("OSM Rules parsing done (" + ((System.currentTimeMillis() - tRead) / 1000f) + ") secs");
56 | ruleStack = null;
57 | return rule;
58 | }
59 |
60 | @Override
61 | public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
62 | // Parsing Rules
63 | if ("rules".equals(qName)) {
64 | // Init Ruleset
65 | rule = null;
66 | String bg = attributes.getValue("background");
67 | if (bg.length() > 7) {
68 | setBgColor(new Color(
69 | Integer.parseInt(bg.substring(1, 3), 16),
70 | Integer.parseInt(bg.substring(3, 5), 16),
71 | Integer.parseInt(bg.substring(5, 7), 16),
72 | Integer.parseInt(bg.substring(7, 9), 16)));
73 | } else {
74 | setBgColor(new Color(
75 | Integer.parseInt(bg.substring(1, 3), 16),
76 | Integer.parseInt(bg.substring(3, 5), 16),
77 | Integer.parseInt(bg.substring(5, 7), 16), 255));
78 | }
79 | }
80 | // Parsing Rule
81 | else if ("rule".equals(qName)) {
82 | depth++;
83 |
84 | // Create Rule
85 | int type = Rule.UNKNOWN;
86 |
87 | // Populate Rule
88 | String e = attributes.getValue("e");
89 | if (e != null && e.contains("way")) {
90 | type |= Rule.WAY;
91 | }
92 | if (e != null && e.contains("node")) {
93 | type |= Rule.NODE;
94 | }
95 |
96 | String[] key = null, value = null;
97 |
98 | String k = attributes.getValue("k");
99 | if (k != null) {
100 | key = k.split("\\|");
101 | }
102 | String v = attributes.getValue("v");
103 | if (v != null) {
104 | value = v.split("\\|");
105 | }
106 | if (key != null && value != null) {
107 | Rule new_rule = new Rule(type, key, value);
108 |
109 | // Insert Rule to chain
110 | if (rule == null)
111 | rule = new_rule;
112 | else
113 | currentRule.addRule(new_rule);
114 | currentRule = new_rule;
115 |
116 | // Adding to stack
117 | ruleStack[depth] = currentRule;
118 | }
119 | }
120 | // Parsing Else
121 | else if ("else".equals(qName)) {
122 | // the else rule is *always* after a rule, this means that the
123 | // current stack position
124 | // should contain the previous rule
125 | // Create Rule
126 | Rule new_rule = new Rule(
127 | ruleStack[depth].type,
128 | ruleStack[depth].keys,
129 | ruleStack[depth].values,
130 | true);
131 |
132 | depth++;
133 |
134 | // Insert Rule to chain (rule cannot be null)
135 | currentRule.addRule(new_rule);
136 | currentRule = new_rule;
137 |
138 | // Adding to stack
139 | ruleStack[depth] = currentRule;
140 | }
141 | // Parsing Polygone, etc.
142 | else if ("polygone".equals(qName) || "line".equals(qName) || "text".equals(qName)) {
143 | // Create Draw
144 | int type = Draw.UNKNOWN;
145 |
146 | // Populate Draw
147 | if ("polygone".equals(qName))
148 | type = Draw.POLYGONE;
149 | else if ("line".equals(qName))
150 | type = Draw.LINE;
151 | else if ("text".equals(qName))
152 | type = Draw.TEXT;
153 |
154 | Draw draw = new Draw(type);
155 |
156 | String color = attributes.getValue("color");
157 | if (color != null) {
158 | draw.setColor(new Color(
159 | Integer.parseInt(color.substring(1, 3), 16),
160 | Integer.parseInt(color.substring(3, 5), 16),
161 | Integer.parseInt(color.substring(5, 7), 16)));
162 | }
163 | String width = attributes.getValue("width");
164 | if (width != null) {
165 | draw.setWidth(Float.parseFloat(width));
166 | }
167 | draw.setPattern(attributes.getValue("pattern"));
168 | String zoom = attributes.getValue("zoom");
169 | if (zoom != null) {
170 | String[] zooms = zoom.split(":");
171 | draw.setZoom(Integer.parseInt(zooms[0]), Integer.parseInt(zooms[1]));
172 | }
173 |
174 | // Insert Draw
175 | ruleStack[depth].appendDraw(draw);
176 | }
177 | }
178 |
179 | @Override
180 | public void endElement(String uri, String localName, String qName) throws SAXException {
181 | if ("rule".equals(qName)) {
182 | // Fetching Parent from stack
183 | if (depth > 0) {
184 | ruleStack[depth].setParent(ruleStack[depth - 1]);
185 | }
186 |
187 | depth--;
188 | } else if ("else".equals(qName)) {
189 | // Fetching Parent from stack
190 | if (depth > 0) {
191 | ruleStack[depth].setParent(ruleStack[depth - 1]);
192 | }
193 |
194 | depth--;
195 | }
196 | }
197 |
198 | protected abstract void setBgColor(Color c);
199 | }
200 |
--------------------------------------------------------------------------------
/map-render-service/src/main/java/io/vertx/workshop/map/source/MapSource.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 the original author or authors.
3 | */
4 | package io.vertx.workshop.map.source;
5 |
6 | import java.io.File;
7 | import java.io.FileInputStream;
8 | import java.io.FileOutputStream;
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 | import java.io.ObjectInputStream;
12 | import java.io.ObjectOutputStream;
13 | import java.util.List;
14 | import java.util.logging.Logger;
15 | import java.util.zip.GZIPInputStream;
16 | import java.util.zip.GZIPOutputStream;
17 |
18 | import io.vertx.workshop.map.BoundingBox;
19 | import io.vertx.workshop.map.MapException;
20 | import io.vertx.workshop.map.index.QTree;
21 | import io.vertx.workshop.map.source.osm.OSMReader;
22 |
23 | /**
24 | * Map Source is a class capable of loading some source map data into a structure we can use to render.
25 | *
26 | * @author Paulo Lopes
27 | */
28 | public class MapSource extends OSMReader {
29 |
30 | private static final Logger LOG = Logger.getLogger(MapSource.class.getName());
31 |
32 | private QTree wayIndex;
33 |
34 | @SuppressWarnings("unchecked")
35 | public MapSource(String filename) throws MapException, ClassNotFoundException, IOException {
36 | long tRead = System.currentTimeMillis();
37 | File fIndex = new File(filename + ".idx.gz");
38 | if (fIndex.exists()) {
39 | ObjectInputStream in = new ObjectInputStream(new FileInputStream(fIndex));
40 | wayIndex = (QTree) in.readObject();
41 | in.close();
42 | } else {
43 | FileInputStream in = new FileInputStream(filename);
44 | load(in);
45 | in.close();
46 | ObjectOutputStream out = new ObjectOutputStream(new GZIPOutputStream(new FileOutputStream(fIndex)));
47 | out.writeObject(wayIndex);
48 | out.close();
49 | }
50 | LOG.info("OSM loading done (" + ((System.currentTimeMillis() - tRead) / 1000f) + ") secs");
51 | }
52 |
53 | @SuppressWarnings("unchecked")
54 | public MapSource(InputStream in) throws ClassNotFoundException, IOException {
55 | long tRead = System.currentTimeMillis();
56 | ObjectInputStream oin = new ObjectInputStream(new GZIPInputStream(in));
57 | wayIndex = (QTree) oin.readObject();
58 | oin.close();
59 | LOG.info("OSM loading done (" + ((System.currentTimeMillis() - tRead) / 1000f) + ") secs");
60 | }
61 |
62 | public BoundingBox getBoundingBox() {
63 | return wayIndex.getBoundingBox();
64 | }
65 |
66 | public List getWaysInBoundingBox(BoundingBox bbox) {
67 | return wayIndex.get(bbox);
68 | }
69 |
70 | public List getNodesInBoundingBox(BoundingBox bbox) {
71 | throw new RuntimeException("Not implemented!");
72 | }
73 |
74 | @Override
75 | public void initIndex(BoundingBox bbox) {
76 | wayIndex = new QTree<>(bbox);
77 | }
78 |
79 | @Override
80 | public void indexWay(Way w) {
81 | wayIndex.add(w);
82 | }
83 |
84 | @Override
85 | public void indexNode(Node n) {
86 |
87 | }
88 |
89 | // public static void main(String[] args) throws Exception {
90 | // new MapSource("map-render/map-data/Antwerpen.osm");
91 | // }
92 | }
93 |
--------------------------------------------------------------------------------
/map-render-service/src/main/java/io/vertx/workshop/map/source/Member.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 the original author or authors.
3 | */
4 | package io.vertx.workshop.map.source;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * OSM Member
10 | *
11 | * @author Paulo Lopes
12 | */
13 | class Member implements Serializable {
14 |
15 | private static final long serialVersionUID = 1L;
16 |
17 | Node node;
18 | Way way;
19 | String role;
20 | Member next;
21 | }
22 |
--------------------------------------------------------------------------------
/map-render-service/src/main/java/io/vertx/workshop/map/source/Node.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 the original author or authors.
3 | */
4 | package io.vertx.workshop.map.source;
5 |
6 | import java.io.Serializable;
7 | import java.util.HashMap;
8 | import java.util.Map;
9 |
10 | /**
11 | * OSM Node
12 | *
13 | * @author Paulo Lopes
14 | */
15 | public class Node implements Serializable {
16 |
17 | private static final long serialVersionUID = 1L;
18 |
19 | private final double lat;
20 | private final double lon;
21 | private int layer;
22 |
23 | private Map tags;
24 |
25 | public Node(double lat, double lon) {
26 | this.lat = lat;
27 | this.lon = lon;
28 | }
29 |
30 | public double getLat() {
31 | return lat;
32 | }
33 |
34 | public double getLon() {
35 | return lon;
36 | }
37 |
38 | public int getLayer() {
39 | return layer;
40 | }
41 |
42 | public void setLayer(int layer) {
43 | this.layer = layer;
44 | }
45 |
46 | public void insertTag(String key, String value) {
47 |
48 | if(tags == null) tags = new HashMap<>();
49 | tags.put(key, value);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/map-render-service/src/main/java/io/vertx/workshop/map/source/Relation.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 the original author or authors.
3 | */
4 | package io.vertx.workshop.map.source;
5 |
6 | import java.io.Serializable;
7 | import java.util.Map;
8 |
9 | /**
10 | * OSM Relation
11 | *
12 | * @author Paulo Lopes
13 | */
14 | class Relation implements Serializable {
15 |
16 | private static final long serialVersionUID = 1L;
17 |
18 | int id;
19 | Map tags;
20 | Member member;
21 | }
22 |
--------------------------------------------------------------------------------
/map-render-service/src/main/java/io/vertx/workshop/map/source/Way.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 the original author or authors.
3 | */
4 | package io.vertx.workshop.map.source;
5 |
6 | import java.io.Serializable;
7 | import java.util.ArrayList;
8 | import java.util.HashMap;
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | import io.vertx.workshop.map.BoundingBox;
13 |
14 | /**
15 | * OSM Way
16 | *
17 | * @author Paulo Lopes
18 | */
19 | public class Way extends BoundingBox implements Serializable {
20 |
21 | private static final long serialVersionUID = 1L;
22 |
23 | private final List nd;
24 |
25 | private int layer;
26 | private String name;
27 | private Map tags;
28 |
29 | public Way() {
30 | super(360.0, 360.0, -360.0, -360.0);
31 | nd = new ArrayList<>();
32 | }
33 |
34 | public void setName(String name) {
35 | this.name = name;
36 | }
37 |
38 | public String getName() {
39 | return name;
40 | }
41 |
42 | public int getLayer() {
43 | return layer;
44 | }
45 |
46 | public void setLayer(int layer) {
47 | this.layer = layer;
48 | }
49 |
50 | public void insertTag(String key, String value) {
51 | if (tags == null) tags = new HashMap<>();
52 | tags.put(key, value);
53 | }
54 |
55 | public void addWayNode(Node node) {
56 | nd.add(node);
57 | double lat = node.getLat();
58 | double lon = node.getLon();
59 |
60 | if (lat < getMinLat()) setMinLat(lat);
61 | if (lat > getMaxLat()) setMaxLat(lat);
62 | if (lon < getMinLon()) setMinLon(lon);
63 | if (lon > getMaxLon()) setMaxLon(lon);
64 | }
65 |
66 | public Map getTags() {
67 | return tags;
68 | }
69 |
70 | public List getWayNode() {
71 | return nd;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/map-render-service/src/main/java/io/vertx/workshop/map/source/osm/OSMReader.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 the original author or authors.
3 | */
4 | package io.vertx.workshop.map.source.osm;
5 |
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.util.HashMap;
9 | import java.util.Map;
10 | import java.util.logging.Logger;
11 |
12 | import javax.xml.parsers.ParserConfigurationException;
13 | import javax.xml.parsers.SAXParserFactory;
14 |
15 | import io.vertx.workshop.map.source.Node;
16 | import io.vertx.workshop.map.source.Way;
17 | import io.vertx.workshop.map.MapException;
18 | import org.xml.sax.Attributes;
19 | import org.xml.sax.SAXException;
20 | import org.xml.sax.helpers.DefaultHandler;
21 |
22 | import io.vertx.workshop.map.BoundingBox;
23 |
24 | /**
25 | * OSM XML Parser for the OSM format
26 | *
27 | * @author Paulo Lopes
28 | */
29 | public abstract class OSMReader extends DefaultHandler {
30 |
31 | Map nodeidx = new HashMap<>();
32 |
33 | private Node cNode = null;
34 | private Way cWay = null;
35 |
36 | private static final Logger LOG = Logger.getLogger(OSMReader.class.getName());
37 |
38 | public void load(InputStream stream) throws MapException {
39 | try {
40 | // Create a builder factory
41 | SAXParserFactory factory = SAXParserFactory.newInstance();
42 | factory.setValidating(false);
43 | // Create the builder and parse the file
44 | factory.newSAXParser().parse(stream, this);
45 |
46 | nodeidx.clear();
47 | nodeidx = null;
48 | } catch(SAXException | IOException | ParserConfigurationException e) {
49 | throw new MapException(e);
50 | }
51 | }
52 |
53 | @Override
54 | @SuppressWarnings("boxing")
55 | public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
56 | // Parsing Bounds
57 | if ("bounds".equals(qName)) {
58 | // LOG.fine("Parsing bounds");
59 | initIndex(new BoundingBox(
60 | Double.parseDouble(attributes.getValue("minlat")),
61 | Double.parseDouble(attributes.getValue("minlon")),
62 | Double.parseDouble(attributes.getValue("maxlat")),
63 | Double.parseDouble(attributes.getValue("maxlon"))));
64 | }
65 | // Parsing bound (OSM 0.6) using osmosis
66 | if ("bound".equals(qName)) {
67 | String[] box = attributes.getValue("box").split(",");
68 | initIndex(new BoundingBox(
69 | Double.parseDouble(box[0]),
70 | Double.parseDouble(box[1]),
71 | Double.parseDouble(box[2]),
72 | Double.parseDouble(box[3])));
73 | }
74 | // Parsing Node
75 | else if ("node".equals(qName)) {
76 | long id = Long.parseLong(attributes.getValue("id"));
77 | cNode = new Node(
78 | Double.parseDouble(attributes.getValue("lat")),
79 | Double.parseDouble(attributes.getValue("lon")));
80 |
81 | // Insert Node local hash
82 | nodeidx.put(id, cNode);
83 | }
84 | // Parsing Tags
85 | else if ("tag".equals(qName)) {
86 |
87 | if (cNode == null && cWay == null) // End if there is nothing to add the tag to
88 | return;
89 |
90 | String k, v;
91 |
92 | k = attributes.getValue("k").intern();
93 | v = attributes.getValue("v").intern();
94 | // attributes.getValue("created_by");
95 | // attributes.getValue("source");
96 | if ("layer".equals(k)) {
97 | int layer;
98 | try {
99 | if(v.charAt(0) == '+') v = v.substring(1);
100 | layer = Integer.parseInt(v);
101 | } catch(NumberFormatException nfe) {
102 | LOG.severe("Not a number: " + v);
103 | layer = 1;
104 | }
105 | if (cNode != null) {
106 | cNode.setLayer(layer);
107 | } else {
108 | cWay.setLayer(layer);
109 | }
110 | } else if ("name".equals(k)) {
111 | if (cWay != null) {
112 | cWay.setName(v);
113 | }
114 | }
115 |
116 | if (cNode != null)
117 | cNode.insertTag(k, v);
118 | else if (cWay != null)
119 | cWay.insertTag(k, v);
120 | }
121 | // Parsing Way
122 | else if ("way".equals(qName)) {
123 | cWay = new Way();
124 | }
125 | // Parsing WayNode
126 | else if ("nd".equals(qName)) {
127 | long ref = Long.parseLong(attributes.getValue("ref"));
128 |
129 | if (ref != 0) {
130 | Node n;
131 |
132 | n = nodeidx.get(ref);
133 | if (n == null) {
134 | LOG.severe("No node with reference " + ref + " found!");
135 | return;
136 | }
137 |
138 | // Insert WayNode
139 | cWay.addWayNode(n);
140 | cNode = null;
141 | }
142 | }
143 | }
144 |
145 | @Override
146 | public void endElement(String uri, String localName, String qName) throws SAXException {
147 | if ("node".equals(qName)) {
148 | if(cNode != null) {
149 | indexNode(cNode);
150 | }
151 | cNode = null;
152 | } else if ("way".equals(qName)) {
153 | if(cWay != null) {
154 | indexWay(cWay);
155 | }
156 | cWay = null;
157 | }
158 | }
159 |
160 | public abstract void initIndex(BoundingBox bbox);
161 |
162 | public abstract void indexWay(Way w);
163 |
164 | public abstract void indexNode(Node n);
165 | }
166 |
--------------------------------------------------------------------------------
/map-render-service/src/main/resources/antwerpen.osm.idx.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescoffier/vertx-workshop/e1d8d12970bbca89c74927843035d836f204be9f/map-render-service/src/main/resources/antwerpen.osm.idx.gz
--------------------------------------------------------------------------------
/map-render-service/src/main/resources/pattern/landuse-cemetery-christian.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescoffier/vertx-workshop/e1d8d12970bbca89c74927843035d836f204be9f/map-render-service/src/main/resources/pattern/landuse-cemetery-christian.png
--------------------------------------------------------------------------------
/map-render-service/src/main/resources/pattern/landuse-cemetery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescoffier/vertx-workshop/e1d8d12970bbca89c74927843035d836f204be9f/map-render-service/src/main/resources/pattern/landuse-cemetery.png
--------------------------------------------------------------------------------
/map-render-service/src/main/resources/pattern/landuse-vineyard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescoffier/vertx-workshop/e1d8d12970bbca89c74927843035d836f204be9f/map-render-service/src/main/resources/pattern/landuse-vineyard.png
--------------------------------------------------------------------------------
/map-render-service/src/main/resources/pattern/military.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescoffier/vertx-workshop/e1d8d12970bbca89c74927843035d836f204be9f/map-render-service/src/main/resources/pattern/military.png
--------------------------------------------------------------------------------
/map-render-service/src/main/resources/pattern/wood-deciduous.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescoffier/vertx-workshop/e1d8d12970bbca89c74927843035d836f204be9f/map-render-service/src/main/resources/pattern/wood-deciduous.png
--------------------------------------------------------------------------------
/map-render-service/src/main/resources/pattern/wood-mixed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cescoffier/vertx-workshop/e1d8d12970bbca89c74927843035d836f204be9f/map-render-service/src/main/resources/pattern/wood-mixed.png
--------------------------------------------------------------------------------
/map-render-service/src/main/resources/rule.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
--------------------------------------------------------------------------------
/map-server-proxy/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | 4.0.0
7 |
8 |
9 | io.vertx.workshop
10 | vertx-microservice-workshop
11 | 1.0-SNAPSHOT
12 |
13 |
14 | map-server-proxy
15 | Map Render Service - Proxy
16 |
17 |
18 | io.vertx.workshop.map.server.MapServerVerticle
19 |
20 |
21 |
22 |
23 |
24 | org.apache.maven.plugins
25 | maven-shade-plugin
26 |
27 |
28 | org.jolokia
29 | docker-maven-plugin
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/map-server-proxy/src/main/docker/assembly.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | target/${project.artifactId}-${project.version}-fat.jar
7 | .
8 | vertx-service-fat.jar
9 |
10 |
11 |
12 |
13 |
14 | ${project.basedir}/src/conf
15 |
16 | *.json
17 |
18 | .
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/map-server-proxy/src/main/java/io/vertx/workshop/map/server/MapServerVerticle.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 the original author or authors.
3 | */
4 | package io.vertx.workshop.map.server;
5 |
6 | import io.vertx.core.AbstractVerticle;
7 | import io.vertx.core.buffer.Buffer;
8 | import io.vertx.core.eventbus.DeliveryOptions;
9 | import io.vertx.core.eventbus.EventBus;
10 | import io.vertx.core.http.HttpMethod;
11 | import io.vertx.core.http.HttpServerRequest;
12 |
13 | import java.text.ParseException;
14 | import java.text.SimpleDateFormat;
15 | import java.util.Date;
16 | import java.util.TimeZone;
17 | import java.util.regex.Matcher;
18 | import java.util.regex.Pattern;
19 |
20 | /**
21 | * Map Tile Server Micro-Service
22 | *
23 | * @author Paulo Lopes
24 | */
25 | public class MapServerVerticle extends AbstractVerticle {
26 |
27 | // Regular Expression to match requests
28 | private static final Pattern TILE = Pattern.compile("^/(\\d+)/(\\d+)/(\\d+)\\.png$");
29 |
30 | private final SimpleDateFormat ISODATE;
31 |
32 | public MapServerVerticle() {
33 | ISODATE = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
34 | ISODATE.setTimeZone(TimeZone.getTimeZone("UTC"));
35 | }
36 |
37 | @Override
38 | public void start() {
39 |
40 | final int port = config().getInteger("port", 8000);
41 | final int cache = config().getInteger("cache", 86400);
42 |
43 | vertx.createHttpServer().requestHandler(req -> {
44 | if (req.method() == HttpMethod.GET) {
45 | final Matcher matcher = TILE.matcher(req.path());
46 |
47 | if (matcher.matches()) {
48 | String z = matcher.group(1);
49 | String x = matcher.group(2);
50 | String y = matcher.group(3);
51 |
52 | final String etag = "\"" + z + "-" + x + "-" + y + "\"";
53 |
54 | req.response()
55 | .putHeader("etag", etag)
56 | .putHeader("cache-control", "public, max-age=" + cache);
57 |
58 | if (isFresh(etag, req)) {
59 |
60 | // some caching code here
61 | req.response()
62 | .setStatusCode(304)
63 | .end();
64 |
65 | } else {
66 | //Replace next line by "vertx.createHttpClient().getNow(8001, "localhost"," to use the local version:
67 | vertx.createHttpClient().getNow(80, "map0render0service-vertxdemos.rhcloud.com",
68 | "/render/" + x + "/" + y + "/" + z, response -> {
69 | if (response.statusCode() == 200) {
70 | response.bodyHandler(buffer -> {
71 | req.response()
72 | .putHeader("last-modified", ISODATE.format(new Date()))
73 | .putHeader("content-type", "image/png")
74 | .end(buffer);
75 | }
76 | );
77 | } else {
78 | req.response().setStatusCode(500).end("Cannot retrieve map tile");
79 | }
80 | });
81 | }
82 | return;
83 | }
84 | }
85 | // if it reached this step it is a bad request
86 | req.response().setStatusCode(400).end();
87 |
88 | }).listen(port);
89 | }
90 |
91 | private boolean isFresh(final String etag, final HttpServerRequest request) {
92 | // defaults
93 | boolean etagMatches = true;
94 | boolean notModified = true;
95 |
96 | // fields
97 | String modifiedSince = request.getHeader("if-modified-since");
98 | String noneMatch = request.getHeader("if-none-match");
99 | String[] noneMatchTokens = null;
100 |
101 | // unconditional request
102 | if (modifiedSince == null && noneMatch == null) {
103 | return false;
104 | }
105 |
106 | // parse if-none-match
107 | if (noneMatch != null) {
108 | noneMatchTokens = noneMatch.split(" *, *");
109 | }
110 |
111 | // if-none-match
112 | if (noneMatchTokens != null) {
113 | etagMatches = false;
114 | for (String s : noneMatchTokens) {
115 | if (etag.equals(s) || "*".equals(noneMatchTokens[0])) {
116 | etagMatches = true;
117 | break;
118 | }
119 | }
120 | }
121 |
122 | // if-modified-since
123 | if (modifiedSince != null) {
124 | try {
125 | Date modifiedSinceDate = ISODATE.parse(modifiedSince);
126 | notModified = System.currentTimeMillis() <= modifiedSinceDate.getTime();
127 | } catch (ParseException e) {
128 | notModified = false;
129 | }
130 | }
131 |
132 | return etagMatches && notModified;
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | io.vertx.workshop
8 | vertx-microservice-workshop
9 | 1.0-SNAPSHOT
10 |
11 | pom
12 |
13 |
14 | 3.1.0
15 |
16 |
17 |
18 |
19 |
20 | data-provisioning
21 | data-storage-service
22 | data-storage-client
23 | recommendation-service
24 | map-render-service
25 | map-server-proxy
26 | frontend
27 | eventbus-to-hawkular-bridge
28 |
29 |
30 |
31 |
32 |
33 | io.vertx
34 | vertx-dependencies
35 | ${vertx.version}
36 | pom
37 | import
38 |
39 |
40 |
41 | biz.paluch.logging
42 | logstash-gelf
43 | 1.7.0
44 |
45 |
46 | junit
47 | junit
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | io.vertx
58 | vertx-core
59 |
60 |
61 | io.vertx
62 | vertx-hazelcast
63 |
64 |
65 | io.vertx
66 | vertx-codegen
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | org.apache.maven.plugins
75 | maven-shade-plugin
76 | 2.3
77 |
78 |
79 | package
80 |
81 | shade
82 |
83 |
84 |
85 |
86 |
87 | io.vertx.core.Launcher
88 | ${main.verticle}
89 |
90 |
91 |
92 | META-INF/services/io.vertx.core.spi.VerticleFactory
93 |
94 |
95 |
96 |
97 | ${project.build.directory}/${project.artifactId}-${project.version}-fat.jar
98 |
99 |
100 |
101 |
102 |
103 |
104 | org.jolokia
105 | docker-maven-plugin
106 | 0.13.6
107 |
108 |
109 |
110 | vertx-devoxx/${project.artifactId}:${project.version}
111 |
112 | java:openjdk-8u66-jre
113 |
114 | latest
115 |
116 |
117 |
118 | java
119 | -jar
120 | /opt/vertx/vertx-service-fat.jar
121 | --conf=/opt/vertx/config.json
122 | --cluster
123 |
124 |
125 |
126 | dir
127 | /opt/vertx
128 |
129 | assembly.xml
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 | maven-resources-plugin
139 | 2.7
140 |
141 |
142 | add-groovy-sources
143 | prepare-package
144 |
145 | copy-resources
146 |
147 |
148 | ${project.build.outputDirectory}
149 |
150 |
151 | ${project.basedir}/src/main/groovy
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 | maven-compiler-plugin
163 | 3.1
164 |
165 | 1.8
166 | 1.8
167 |
168 | io.vertx.codegen.CodeGenProcessor
169 |
170 |
171 | -AoutputDirectory=${project.basedir}/src/main
172 |
173 | ${project.basedir}/src/main/generated
174 |
175 |
176 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/recommendation-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | io.vertx.workshop
9 | vertx-microservice-workshop
10 | 1.0-SNAPSHOT
11 |
12 |
13 | recommendation-service
14 | Recommendation Service
15 |
16 |
17 | io.vertx.workshop.recommendation.impl.RecommendationVerticle
18 |
19 |
20 |
21 |
22 | io.vertx
23 | vertx-redis-client
24 |
25 |
26 | io.vertx
27 | vertx-service-proxy
28 |
29 |
30 | io.vertx
31 | vertx-lang-groovy
32 |
33 |
34 | io.vertx
35 | vertx-lang-js
36 |
37 |
38 |
39 |
40 |
41 |
42 | org.apache.maven.plugins
43 | maven-shade-plugin
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/recommendation-service/src/conf/config-docker-machine.json:
--------------------------------------------------------------------------------
1 | {
2 | "host": "192.168.99.100",
3 | "port": 6379
4 | }
--------------------------------------------------------------------------------
/recommendation-service/src/conf/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "host": "localhost",
3 | "port": 6379
4 | }
--------------------------------------------------------------------------------
/recommendation-service/src/main/generated/io/vertx/workshop/recommendation/RecommendationServiceVertxEBProxy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Red Hat, Inc.
3 | *
4 | * Red Hat licenses this file to you under the Apache License, version 2.0
5 | * (the "License"); you may not use this file except in compliance with the
6 | * License. You may obtain a copy of the License at:
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations
14 | * under the License.
15 | */
16 |
17 | package io.vertx.workshop.recommendation;
18 |
19 | import io.vertx.workshop.recommendation.RecommendationService;
20 | import io.vertx.core.eventbus.DeliveryOptions;
21 | import io.vertx.core.Vertx;
22 | import io.vertx.core.Future;
23 | import io.vertx.core.json.JsonObject;
24 | import io.vertx.core.json.JsonArray;
25 | import java.util.ArrayList;
26 | import java.util.HashSet;
27 | import java.util.List;
28 | import java.util.Map;
29 | import java.util.Set;
30 | import java.util.stream.Collectors;
31 | import io.vertx.serviceproxy.ProxyHelper;
32 | import io.vertx.core.Vertx;
33 | import io.vertx.core.json.JsonObject;
34 | import io.vertx.core.AsyncResult;
35 | import io.vertx.core.Handler;
36 | import io.vertx.workshop.recommendation.RecommendationService;
37 |
38 | /*
39 | Generated Proxy code - DO NOT EDIT
40 | @author Roger the Robot
41 | */
42 | public class RecommendationServiceVertxEBProxy implements RecommendationService {
43 |
44 | private Vertx _vertx;
45 | private String _address;
46 | private DeliveryOptions _options;
47 | private boolean closed;
48 |
49 | public RecommendationServiceVertxEBProxy(Vertx vertx, String address) {
50 | this(vertx, address, null);
51 | }
52 |
53 | public RecommendationServiceVertxEBProxy(Vertx vertx, String address, DeliveryOptions options) {
54 | this._vertx = vertx;
55 | this._address = address;
56 | this._options = options;
57 | }
58 |
59 | public void vote(String name, boolean plus, Handler> resultHandler) {
60 | if (closed) {
61 | resultHandler.handle(Future.failedFuture(new IllegalStateException("Proxy is closed")));
62 | return;
63 | }
64 | JsonObject _json = new JsonObject();
65 | _json.put("name", name);
66 | _json.put("plus", plus);
67 | DeliveryOptions _deliveryOptions = (_options != null) ? new DeliveryOptions(_options) : new DeliveryOptions();
68 | _deliveryOptions.addHeader("action", "vote");
69 | _vertx.eventBus().send(_address, _json, _deliveryOptions, res -> {
70 | if (res.failed()) {
71 | resultHandler.handle(Future.failedFuture(res.cause()));
72 | } else {
73 | resultHandler.handle(Future.succeededFuture(res.result().body()));
74 | }
75 | });
76 | }
77 |
78 | public void get(String name, Handler> resultHandler) {
79 | if (closed) {
80 | resultHandler.handle(Future.failedFuture(new IllegalStateException("Proxy is closed")));
81 | return;
82 | }
83 | JsonObject _json = new JsonObject();
84 | _json.put("name", name);
85 | DeliveryOptions _deliveryOptions = (_options != null) ? new DeliveryOptions(_options) : new DeliveryOptions();
86 | _deliveryOptions.addHeader("action", "get");
87 | _vertx.eventBus().send(_address, _json, _deliveryOptions, res -> {
88 | if (res.failed()) {
89 | resultHandler.handle(Future.failedFuture(res.cause()));
90 | } else {
91 | resultHandler.handle(Future.succeededFuture(res.result().body()));
92 | }
93 | });
94 | }
95 |
96 |
97 | private List convertToListChar(JsonArray arr) {
98 | List list = new ArrayList<>();
99 | for (Object obj: arr) {
100 | Integer jobj = (Integer)obj;
101 | list.add((char)(int)jobj);
102 | }
103 | return list;
104 | }
105 |
106 | private Set convertToSetChar(JsonArray arr) {
107 | Set set = new HashSet<>();
108 | for (Object obj: arr) {
109 | Integer jobj = (Integer)obj;
110 | set.add((char)(int)jobj);
111 | }
112 | return set;
113 | }
114 |
115 | private Map convertMap(Map map) {
116 | return (Map)map;
117 | }
118 | private List convertList(List list) {
119 | return (List)list;
120 | }
121 | private Set convertSet(List list) {
122 | return new HashSet((List)list);
123 | }
124 | }
--------------------------------------------------------------------------------
/recommendation-service/src/main/generated/io/vertx/workshop/recommendation/RecommendationServiceVertxProxyHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Red Hat, Inc.
3 | *
4 | * Red Hat licenses this file to you under the Apache License, version 2.0
5 | * (the "License"); you may not use this file except in compliance with the
6 | * License. You may obtain a copy of the License at:
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations
14 | * under the License.
15 | */
16 |
17 | package io.vertx.workshop.recommendation;
18 |
19 | import io.vertx.workshop.recommendation.RecommendationService;
20 | import io.vertx.core.Vertx;
21 | import io.vertx.core.Handler;
22 | import io.vertx.core.AsyncResult;
23 | import io.vertx.core.eventbus.EventBus;
24 | import io.vertx.core.eventbus.Message;
25 | import io.vertx.core.eventbus.MessageConsumer;
26 | import io.vertx.core.eventbus.DeliveryOptions;
27 | import io.vertx.core.eventbus.ReplyException;
28 | import io.vertx.core.json.JsonObject;
29 | import io.vertx.core.json.JsonArray;
30 | import java.util.Collection;
31 | import java.util.ArrayList;
32 | import java.util.HashSet;
33 | import java.util.List;
34 | import java.util.Map;
35 | import java.util.Set;
36 | import java.util.UUID;
37 | import java.util.stream.Collectors;
38 | import io.vertx.serviceproxy.ProxyHelper;
39 | import io.vertx.serviceproxy.ProxyHandler;
40 | import io.vertx.core.Vertx;
41 | import io.vertx.core.json.JsonObject;
42 | import io.vertx.core.AsyncResult;
43 | import io.vertx.core.Handler;
44 | import io.vertx.workshop.recommendation.RecommendationService;
45 |
46 | /*
47 | Generated Proxy code - DO NOT EDIT
48 | @author Roger the Robot
49 | */
50 | public class RecommendationServiceVertxProxyHandler extends ProxyHandler {
51 |
52 | public static final long DEFAULT_CONNECTION_TIMEOUT = 5 * 60; // 5 minutes
53 |
54 | private final Vertx vertx;
55 | private final RecommendationService service;
56 | private final long timerID;
57 | private long lastAccessed;
58 | private final long timeoutSeconds;
59 |
60 | public RecommendationServiceVertxProxyHandler(Vertx vertx, RecommendationService service) {
61 | this(vertx, service, DEFAULT_CONNECTION_TIMEOUT);
62 | }
63 |
64 | public RecommendationServiceVertxProxyHandler(Vertx vertx, RecommendationService service, long timeoutInSecond) {
65 | this(vertx, service, true, timeoutInSecond);
66 | }
67 |
68 | public RecommendationServiceVertxProxyHandler(Vertx vertx, RecommendationService service, boolean topLevel, long timeoutSeconds) {
69 | this.vertx = vertx;
70 | this.service = service;
71 | this.timeoutSeconds = timeoutSeconds;
72 | if (timeoutSeconds != -1 && !topLevel) {
73 | long period = timeoutSeconds * 1000 / 2;
74 | if (period > 10000) {
75 | period = 10000;
76 | }
77 | this.timerID = vertx.setPeriodic(period, this::checkTimedOut);
78 | } else {
79 | this.timerID = -1;
80 | }
81 | accessed();
82 | }
83 |
84 | public MessageConsumer registerHandler(String address) {
85 | MessageConsumer consumer = vertx.eventBus().consumer(address).handler(this);
86 | this.setConsumer(consumer);
87 | return consumer;
88 | }
89 |
90 | private void checkTimedOut(long id) {
91 | long now = System.nanoTime();
92 | if (now - lastAccessed > timeoutSeconds * 1000000000) {
93 | close();
94 | }
95 | }
96 |
97 | @Override
98 | public void close() {
99 | if (timerID != -1) {
100 | vertx.cancelTimer(timerID);
101 | }
102 | super.close();
103 | }
104 |
105 | private void accessed() {
106 | this.lastAccessed = System.nanoTime();
107 | }
108 |
109 | public void handle(Message msg) {
110 | try {
111 | JsonObject json = msg.body();
112 | String action = msg.headers().get("action");
113 | if (action == null) {
114 | throw new IllegalStateException("action not specified");
115 | }
116 | accessed();
117 | switch (action) {
118 |
119 | case "vote": {
120 | service.vote((java.lang.String)json.getValue("name"), (boolean)json.getValue("plus"), createHandler(msg));
121 | break;
122 | }
123 | case "get": {
124 | service.get((java.lang.String)json.getValue("name"), createHandler(msg));
125 | break;
126 | }
127 | default: {
128 | throw new IllegalStateException("Invalid action: " + action);
129 | }
130 | }
131 | } catch (Throwable t) {
132 | msg.fail(-1, t.getMessage());
133 | throw t;
134 | }
135 | }
136 |
137 | private Handler> createHandler(Message msg) {
138 | return res -> {
139 | if (res.failed()) {
140 | msg.fail(-1, res.cause().getMessage());
141 | } else {
142 | msg.reply(res.result());
143 | }
144 | };
145 | }
146 |
147 | private Handler>> createListHandler(Message msg) {
148 | return res -> {
149 | if (res.failed()) {
150 | msg.fail(-1, res.cause().getMessage());
151 | } else {
152 | msg.reply(new JsonArray(res.result()));
153 | }
154 | };
155 | }
156 |
157 | private Handler>> createSetHandler(Message msg) {
158 | return res -> {
159 | if (res.failed()) {
160 | msg.fail(-1, res.cause().getMessage());
161 | } else {
162 | msg.reply(new JsonArray(new ArrayList<>(res.result())));
163 | }
164 | };
165 | }
166 |
167 | private Handler>> createListCharHandler(Message msg) {
168 | return res -> {
169 | if (res.failed()) {
170 | msg.fail(-1, res.cause().getMessage());
171 | } else {
172 | JsonArray arr = new JsonArray();
173 | for (Character chr: res.result()) {
174 | arr.add((int) chr);
175 | }
176 | msg.reply(arr);
177 | }
178 | };
179 | }
180 |
181 | private Handler>> createSetCharHandler(Message msg) {
182 | return res -> {
183 | if (res.failed()) {
184 | msg.fail(-1, res.cause().getMessage());
185 | } else {
186 | JsonArray arr = new JsonArray();
187 | for (Character chr: res.result()) {
188 | arr.add((int) chr);
189 | }
190 | msg.reply(arr);
191 | }
192 | };
193 | }
194 |
195 | private Map convertMap(Map map) {
196 | return (Map)map;
197 | }
198 |
199 | private List convertList(List list) {
200 | return (List)list;
201 | }
202 |
203 | private Set convertSet(List list) {
204 | return new HashSet((List)list);
205 | }
206 | }
--------------------------------------------------------------------------------
/recommendation-service/src/main/groovy/io/vertx/workshop/groovy/recommendation/RecommendationService.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Red Hat, Inc.
3 | *
4 | * Red Hat licenses this file to you under the Apache License, version 2.0
5 | * (the "License"); you may not use this file except in compliance with the
6 | * License. You may obtain a copy of the License at:
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations
14 | * under the License.
15 | */
16 |
17 | package io.vertx.workshop.groovy.recommendation;
18 | import groovy.transform.CompileStatic
19 | import io.vertx.lang.groovy.InternalHelper
20 | import io.vertx.core.json.JsonObject
21 | import io.vertx.groovy.core.Vertx
22 | import io.vertx.core.json.JsonObject
23 | import io.vertx.core.AsyncResult
24 | import io.vertx.core.Handler
25 | /**
26 | * A service to recommend places.
27 | */
28 | @CompileStatic
29 | public class RecommendationService {
30 | private final def io.vertx.workshop.recommendation.RecommendationService delegate;
31 | public RecommendationService(Object delegate) {
32 | this.delegate = (io.vertx.workshop.recommendation.RecommendationService) delegate;
33 | }
34 | public Object getDelegate() {
35 | return delegate;
36 | }
37 | /**
38 | * The method used to create proxy to consume the service.
39 | * @param vertx vert.x
40 | * @param address the address where the service is served
41 | * @return the proxy
42 | */
43 | public static RecommendationService createProxy(Vertx vertx, String address) {
44 | def ret= InternalHelper.safeCreate(io.vertx.workshop.recommendation.RecommendationService.createProxy((io.vertx.core.Vertx)vertx.getDelegate(), address), io.vertx.workshop.groovy.recommendation.RecommendationService.class);
45 | return ret;
46 | }
47 | /**
48 | * Votes for a place.
49 | * When a vote is placed, the new rating of the place are brodcasted to the event bus.
50 | * @param name the name of the place
51 | * @param plus whether or not you liked the place.
52 | * @param resultHandler invoked when the action is completed
53 | */
54 | public void vote(String name, boolean plus, Handler> resultHandler) {
55 | this.delegate.vote(name, plus, resultHandler);
56 | }
57 | /**
58 | * Gets the number or votes.
59 | * @param name the name of the place
60 | * @param resultHandler the result handler. The votes are given in a JSON object using the "up" and "down" fields.
61 | */
62 | public void get(String name, Handler>> resultHandler) {
63 | this.delegate.get(name, new Handler>() {
64 | public void handle(AsyncResult event) {
65 | AsyncResult