1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package pl.edu.agh.cast.model.mapper;
19
20 import java.sql.PreparedStatement;
21 import java.sql.ResultSet;
22 import java.sql.SQLException;
23 import java.sql.Statement;
24 import java.sql.Types;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.LinkedList;
28 import java.util.List;
29 import java.util.Map;
30
31
32
33
34
35
36 public class Link {
37
38
39
40
41 private static final String SELECT_FIELDS = "SELECT id, src_id, dst_id, priority, name, " +
42 "src_accessor, dst_accessor, src_position, dst_position ";
43
44
45
46
47 private static final String DST_POSITION_FIELD = "dst_position";
48
49
50
51
52 private static final String SRC_POSITION_FIELD = "src_position";
53
54 private Node source;
55
56 private long sourceId;
57
58 private Node destination;
59
60 private long destinationId;
61
62 private String name;
63
64 private String sourceAccessor;
65
66 private String destinationAccessor;
67
68 private int priority;
69
70 private long id;
71
72 private int srcPosition = 0;
73
74 private int dstPosition = 0;
75
76 private boolean saved;
77
78 private static Mapper mapper = Mapper.getInstance();
79
80 private static Map<Long, Link> linkCache = Collections.synchronizedMap(new HashMap<Long, Link>());
81
82
83
84
85
86
87
88
89
90
91
92 public Link(Map args) {
93 JRubyIntegration.stringifyKeys(args);
94 int srcPos = 0;
95 if (args.containsKey(SRC_POSITION_FIELD)) {
96 srcPos = ((Long)args.get(SRC_POSITION_FIELD)).intValue();
97 }
98 int dstPos = 0;
99 if (args.containsKey(DST_POSITION_FIELD)) {
100 dstPos = ((Long)args.get(DST_POSITION_FIELD)).intValue();
101 }
102
103 initialize((Node)args.get("src"), (Node)args.get("dst"),
104 (String)args.get("name"), translatePriority(args
105 .get("priority")), (String)args.get("src_accessor"),
106 (String)args.get("dst_accessor"), srcPos, dstPos);
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120
121 public Link(Node src, Node dst, String name, int priority) {
122 initialize(src, dst, name, priority, null, null, 0, 0);
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136
137 public Link(long srcId, long dstId, String name, int priority) {
138 sourceId = srcId;
139 destinationId = dstId;
140 initialize(null, null, name, priority, null, null, 0, 0);
141 }
142
143 public Link(Node src, Node dst, String name, Priority priority, String srcAccessor, String dstAccessor) {
144 initialize(src, dst, name, priority.ordinal(), srcAccessor, dstAccessor, 0, 0);
145 }
146
147 public Link(Node src, Node dst, String name, Priority priority) {
148 initialize(src, dst, name, priority.ordinal(), null, null, 0, 0);
149 }
150
151 public Link(Node src, Node dst, String name, Priority priority, String srcAcc, String dstAcc, int srcPosition,
152 int dstPosition) {
153 initialize(src, dst, name, priority.ordinal(), srcAcc, dstAcc, srcPosition, dstPosition);
154 }
155
156 private void initialize(Node src, Node dst, String newName, int newPriority, String newSrcAccessor,
157 String newDstAccessor, int newSrcPosition, int newDstPosition) {
158 setSrc(src);
159 if (src != null) {
160 src.addSrcLink(this);
161 }
162 setDst(dst);
163 if (dst != null) {
164 dst.addDstLink(this);
165 }
166 name = newName;
167 priority = newPriority;
168 sourceAccessor = newSrcAccessor;
169 destinationAccessor = newDstAccessor;
170 srcPosition = newSrcPosition;
171 dstPosition = newDstPosition;
172 }
173
174 private static PreparedStatement findWithDstStmt;
175
176 private static PreparedStatement findWithSrcStmt;
177
178 private static PreparedStatement findStmt;
179
180 private static PreparedStatement saveStmt;
181
182 static {
183 String stmtStr;
184 try {
185 stmtStr = SELECT_FIELDS + "FROM links WHERE dst_id = ? ORDER BY src_position";
186 findWithDstStmt = mapper.getConnection().prepareStatement(stmtStr);
187
188 stmtStr = SELECT_FIELDS + " FROM links WHERE src_id = ? ORDER BY dst_position";
189 findWithSrcStmt = mapper.getConnection().prepareStatement(stmtStr);
190
191 stmtStr = SELECT_FIELDS + " FROM links WHERE id = ?";
192 findStmt = mapper.getConnection().prepareStatement(stmtStr);
193
194 stmtStr = "INSERT INTO links SET name = ?, src_id = ?, "
195 + "dst_id = ?, priority = ?, src_accessor = ?, "
196 + "dst_accessor = ?, src_position = ?, dst_position = ? ";
197 saveStmt = mapper.getConnection().prepareStatement(stmtStr, Statement.RETURN_GENERATED_KEYS);
198 } catch (SQLException e) {
199 e.printStackTrace();
200 }
201 }
202
203
204
205
206
207
208
209
210
211
212 public boolean save() {
213 if (saved) {
214 return true;
215 }
216
217
218
219
220 if (name == null || name.equals("")) {
221 throw new RuntimeException("Link's name must not be blank: " + this);
222 }
223
224 if (getSrc() == null) {
225 throw new RuntimeException("Link's src must not be null: " + this);
226 }
227
228 if (getDst() == null) {
229 throw new RuntimeException("Link's dst must not be null: " + this);
230 }
231
232 try {
233 if (id == 0) {
234
235
236 saveStmt.setString(1, name);
237
238 setSaved(true);
239 long srcId = getSrc().getId();
240 if (srcId == 0) {
241 if (!getSrc().save()) {
242 setSaved(false);
243 return false;
244 }
245 srcId = getSrc().getId();
246 if (srcId == 0) {
247 throw new RuntimeException("Node id is 0: " + getSrc());
248 }
249
250 }
251 saveStmt.setLong(2, srcId);
252
253 long dstId = getDst().getId();
254 if (dstId == 0) {
255 if (!getDst().save()) {
256 setSaved(false);
257 return false;
258 }
259 dstId = getDst().getId();
260 if (dstId == 0) {
261 throw new RuntimeException("Node id is 0: " + getDst());
262 }
263
264 }
265 saveStmt.setLong(3, dstId);
266
267 saveStmt.setInt(4, getPriority());
268
269 String srcAccessor = getSrcAccessor();
270 if (srcAccessor != null) {
271 saveStmt.setString(5, srcAccessor);
272 } else {
273 saveStmt.setNull(5, Types.VARCHAR);
274 }
275
276 String dstAccessor = getDstAccessor();
277 if (dstAccessor != null) {
278 saveStmt.setString(6, dstAccessor);
279 } else {
280 saveStmt.setNull(6, Types.VARCHAR);
281 }
282
283 saveStmt.setInt(7, getSrcPosition());
284 saveStmt.setInt(8, getDstPosition());
285
286 saveStmt.executeUpdate();
287 ResultSet rs = saveStmt.getGeneratedKeys();
288 if (rs.next()) {
289 setId(rs.getLong(1));
290 setSaved(true);
291 } else {
292 throw new SQLException("Cannot obtain the last link id");
293 }
294 return true;
295 }
296 } catch (SQLException e) {
297 System.err.println(e.getMessage());
298 setSaved(false);
299 return false;
300 }
301
302 return false;
303 }
304
305
306
307
308
309
310
311
312
313 public int getPriority() {
314 return priority;
315 }
316
317
318
319
320
321
322
323 public void setPriority(int newPriority) {
324 priority = newPriority;
325 }
326
327
328
329
330
331
332
333 public void setPriority(Object priority) {
334 setPriority(translatePriority(priority));
335 }
336
337 private int translatePriority(Object priorityObj) {
338 int priorityValue = 0;
339 if (priorityObj != null) {
340 if (priorityObj.toString().equals("src_over_dst")) {
341 priorityValue = 1;
342 } else if (priorityObj.toString().equals("dst_over_src")) {
343 priorityValue = 2;
344 }
345 }
346 return priorityValue;
347 }
348
349
350
351
352
353
354
355
356
357 public Node getDst() {
358 if (destination == null && destinationId != 0) {
359 destination = Node.find(destinationId);
360 }
361 return destination;
362 }
363
364
365
366
367
368
369 public long getDstId() {
370 if (destinationId == 0 && destination != null) {
371 destinationId = destination.getId();
372 }
373 return destinationId;
374 }
375
376
377
378
379
380
381 public Node getSrc() {
382 if (source == null && sourceId != 0) {
383 source = Node.find(sourceId);
384 }
385 return source;
386 }
387
388
389
390
391
392
393 public long getSrcId() {
394 if (sourceId == 0 && source != null) {
395 sourceId = source.getId();
396 }
397 return sourceId;
398 }
399
400
401
402
403
404
405 public long getId() {
406 return id;
407 }
408
409
410
411
412
413
414
415 @Override
416 public String toString() {
417 StringBuilder builder = new StringBuilder();
418 builder.append("Link: ");
419 builder.append(name);
420 builder.append(" [");
421 builder.append(id);
422 builder.append(", ");
423 builder.append(priority);
424 builder.append("] src ");
425 builder.append(getSrcId());
426 builder.append(" [");
427 builder.append(getSrcPosition());
428 builder.append("] dst ");
429 builder.append(getDstId());
430 builder.append(" [");
431 builder.append(getDstPosition());
432 builder.append("]");
433 return builder.toString();
434 }
435
436
437
438
439
440
441 public String getName() {
442 return name;
443 }
444
445
446
447
448
449
450
451 public void setSrc(Node srcNode) {
452 source = srcNode;
453 if (source != null) {
454 sourceId = source.getId();
455 }
456 }
457
458
459
460
461
462
463
464 public void setDst(Node dst) {
465 destination = dst;
466 if (destination != null) {
467 destinationId = destination.getId();
468 }
469 }
470
471
472
473
474
475
476
477 @Override
478 public boolean equals(Object other) {
479 if (this == other) {
480 return true;
481 }
482
483 if (!(other instanceof Link)) {
484 return false;
485 }
486
487 Link that = (Link)other;
488
489
490 if (this.sourceAccessor == null) {
491 if (that.sourceAccessor != null) {
492 return false;
493 }
494 } else {
495 if (!this.sourceAccessor.equals(that.sourceAccessor)) {
496 return false;
497 }
498 }
499
500
501 if (this.destinationAccessor == null) {
502 if (that.destinationAccessor != null) {
503 return false;
504 }
505 } else {
506 if (!this.destinationAccessor.equals(that.destinationAccessor)) {
507 return false;
508 }
509 }
510
511 return this.id == that.id && this.getDstId() == that.getDstId() && this.getSrcId() == that.getSrcId()
512 && this.name.equals(that.name) && this.priority == that.priority
513 && this.srcPosition == that.srcPosition && this.dstPosition == that.dstPosition;
514 }
515
516
517
518
519
520
521
522
523 public static Link find(long linkId) {
524
525 Link link;
526
527
528 link = linkCache.get(linkId);
529 if (link != null) {
530 return link;
531 }
532
533 try {
534 findStmt.setLong(1, linkId);
535 ResultSet rs = findStmt.executeQuery();
536
537 if (rs.next()) {
538 link = createLink(rs, 0);
539 } else {
540 return null;
541 }
542 return link;
543
544 } catch (SQLException e) {
545 e.printStackTrace();
546 } finally {
547 try {
548 findStmt.close();
549 } catch (SQLException e) {
550 e.printStackTrace();
551 }
552 }
553
554 return null;
555 }
556
557
558
559
560
561
562
563
564
565
566 static Link createLink(ResultSet resultSet, int fieldOffset) throws SQLException {
567 long linkId = resultSet.getLong(fieldOffset + 1);
568 Link link;
569
570
571 link = linkCache.get(linkId);
572 if (link != null) {
573 return link;
574 }
575
576 link = new Link(resultSet.getLong(fieldOffset + 2), resultSet.getLong(fieldOffset + 3), resultSet
577 .getString(fieldOffset + 5), resultSet.getInt(fieldOffset + 4));
578 link.setId(linkId);
579 link.setSaved(true);
580 link.setSrcAccessor(resultSet.getString(fieldOffset + 6));
581 link.setDstAccessor(resultSet.getString(fieldOffset + 7));
582 link.setSrcPosition(resultSet.getInt(fieldOffset + 8));
583 link.setDstPosition(resultSet.getInt(fieldOffset + 9));
584 linkCache.put(linkId, link);
585 return link;
586 }
587
588 public void setSrcPosition(int position) {
589 srcPosition = position;
590 }
591
592
593
594
595
596
597 public int getSrcPosition() {
598 return srcPosition;
599 }
600
601
602
603
604
605
606
607 public void setDstPosition(int position) {
608 dstPosition = position;
609 }
610
611
612
613
614
615
616 public int getDstPosition() {
617 return dstPosition;
618 }
619
620
621
622
623
624
625 @Override
626 public int hashCode() {
627 int value = (int)(name.hashCode() ^ priority + (id * 7) ^ (getSrcId() * 17) ^ (getDstId() * 19)
628 ^ (srcPosition * 11) ^ (dstPosition * 23));
629 if (sourceAccessor != null) {
630 value ^= sourceAccessor.hashCode();
631 } else {
632 value += 100000;
633 }
634 if (destinationAccessor != null) {
635 value ^= destinationAccessor.hashCode();
636 } else {
637 value += 200;
638 }
639
640 return value;
641 }
642
643
644
645
646
647
648 public String getSrcAccessor() {
649 return sourceAccessor;
650 }
651
652
653
654
655
656
657 public String getDstAccessor() {
658 return destinationAccessor;
659 }
660
661
662
663
664
665
666
667 public void setSaved(boolean newSaved) {
668 saved = newSaved;
669 }
670
671
672
673
674
675
676
677 public void setId(long newId) {
678 id = newId;
679 }
680
681
682
683
684
685
686
687 public void setSrcAccessor(String accessor) {
688 sourceAccessor = accessor;
689 }
690
691
692
693
694
695
696
697 public void setDstAccessor(String accessor) {
698 destinationAccessor = accessor;
699 }
700
701
702
703
704
705
706
707
708 public static Link find(Link link) {
709 return find(link.getId());
710 }
711
712
713
714
715
716
717
718
719
720 public static List<Link> findWithSrc(long nodeId) throws SQLException {
721
722 findWithSrcStmt.setLong(1, nodeId);
723 ResultSet rs = findWithSrcStmt.executeQuery();
724 List<Link> result = new LinkedList<Link>();
725 while (rs.next()) {
726 result.add(createLink(rs, 0));
727 }
728 return result;
729 }
730
731
732
733
734
735
736
737
738
739 public static List<Link> findWithDst(long nodeId) throws SQLException {
740 findWithDstStmt.setLong(1, nodeId);
741 ResultSet rs = findWithDstStmt.executeQuery();
742 List<Link> result = new LinkedList<Link>();
743 while (rs.next()) {
744 result.add(createLink(rs, 0));
745 }
746 return result;
747 }
748
749
750
751
752 public static void stats() {
753
754
755 }
756
757 static void clearCache() {
758 linkCache.clear();
759 }
760
761 }