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.Timestamp;
25 import java.sql.Types;
26 import java.text.SimpleDateFormat;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.Date;
30 import java.util.HashMap;
31 import java.util.LinkedList;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Set;
35 import java.util.SortedMap;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class Node {
56
57 private static double delta = 0.000001;
58
59 private static boolean eager = true;
60
61 private List<Link> srcLinks = new ArrayList<Link>();
62
63 private List<Link> dstLinks = new ArrayList<Link>();
64
65 private String typeName;
66
67 private Object value;
68
69 private long id;
70
71 private boolean saved = false;
72
73 private static Mapper mapper = Mapper.getInstance();
74
75 private static Map<Long, Node> nodeCache = Collections.synchronizedMap(new HashMap<Long, Node>());
76
77
78
79
80
81
82
83 public Node(Map args) {
84 JRubyIntegration.stringifyKeys(args);
85 initialize((String)args.get("type_name"), null);
86 }
87
88
89
90
91
92
93
94 public Node(String typeName) {
95 initialize(typeName, null);
96 }
97
98
99
100
101
102
103
104
105
106 public Node(String typeName, Object value) {
107 initialize(typeName, value);
108 }
109
110 private void initialize(String newTypeName, Object newValue) {
111 typeName = newTypeName;
112 if (newValue != null) {
113 setValue(newValue);
114 }
115 }
116
117
118
119
120
121
122
123
124 public String getTypeName() {
125 return typeName;
126 }
127
128
129
130
131
132
133
134
135
136 public Object getValue() {
137 return value;
138 }
139
140
141
142
143
144
145
146 public void setValue(Object newValue) {
147 if (newValue == null) {
148 return;
149 }
150 if (!(newValue instanceof Long || newValue instanceof Double || newValue instanceof Integer
151 || newValue instanceof Boolean || newValue instanceof String || newValue instanceof Date)) {
152 throw new IllegalArgumentException(newValue.getClass().toString());
153 }
154 this.value = newValue;
155 }
156
157 public void setValue(long newValue) {
158 this.value = new Long(newValue);
159 }
160
161 public void setValue(int newValue) {
162 this.value = new Long(newValue);
163 }
164
165
166
167
168
169
170 public Long getLongValue() {
171 if (value instanceof Long) {
172 return (Long)value;
173 }
174 if (value instanceof Integer) {
175 return new Long((Integer)value);
176 }
177 return null;
178 }
179
180
181
182
183
184
185
186 public void setValue(double newValue) {
187 this.value = new Double(newValue);
188 }
189
190
191
192
193
194
195 public Double getDoubleValue() {
196 if (value instanceof Double) {
197 return (Double)value;
198 }
199 return null;
200 }
201
202
203
204
205
206
207
208 public void setValue(boolean value) {
209 this.value = new Boolean(value);
210 }
211
212
213
214
215
216
217 public Boolean getBooleanValue() {
218 if (value instanceof Boolean) {
219 return (Boolean)value;
220 }
221 return null;
222 }
223
224
225
226
227
228
229
230 public void setValue(String value) {
231 this.value = value;
232 }
233
234
235
236
237
238
239 public String getStringValue() {
240 if (value instanceof String) {
241 return (String)value;
242 }
243 return null;
244 }
245
246
247
248
249
250
251
252 public void setValue(Date value) {
253 this.value = value;
254 }
255
256
257
258
259
260
261 public Date getDateValue() {
262 if (value instanceof Date) {
263 return (Date)value;
264 }
265 return null;
266 }
267
268
269
270
271
272 public List<Link> getSrcLinks() {
273 return srcLinks;
274 }
275
276
277
278
279
280
281
282 public void setSrcLinks(Set<Link> links) {
283 srcLinks.clear();
284 srcLinks.addAll(links);
285 }
286
287
288
289
290
291
292 public List<Link> getDstLinks() {
293 return dstLinks;
294 }
295
296
297
298
299
300
301
302 public void setDstLinks(Set<Link> links) {
303 dstLinks.clear();
304 dstLinks.addAll(links);
305 }
306
307
308
309
310
311
312
313
314
315
316
317 public void link(Node node, Object direction, String name) {
318 link(node, translateDirection(direction), name, Priority.NONE);
319 }
320
321
322
323
324
325
326
327
328
329
330
331
332
333 public void link(Node node, Direction direction, String name, Priority priority) {
334 Link link = new Link(null, null, name, priority);
335 if (direction == Direction.SRC) {
336 link.setSrc(this);
337 link.setDst(node);
338 srcLinks.add(link);
339 } else if (direction == Direction.DST) {
340 link.setDst(this);
341 link.setSrc(node);
342 dstLinks.add(link);
343 } else {
344 throw new IllegalArgumentException("Direction must be specified");
345 }
346 if (saved) {
347 link.save();
348 }
349 }
350
351
352
353
354
355
356
357
358
359
360 public List<Link> links(String name, Object directionObj) {
361 return links(name, translateDirection(directionObj));
362 }
363
364
365
366
367
368
369
370
371 private Direction translateDirection(Object directionObj) {
372 if (directionObj.toString().equals("dst")) {
373 return Direction.DST;
374 }
375 return Direction.SRC;
376 }
377
378
379
380
381
382
383
384
385 public List<Link> links(String name) {
386 return links(name, null);
387 }
388
389
390
391
392
393
394
395
396
397
398
399 public List<Link> links(String name, Direction direction) {
400 List<Link> sources = new LinkedList<Link>();
401 for (Link link : srcLinks) {
402 if (link.getName().equals(name)) {
403 sources.add(link);
404 }
405 }
406 List<Link> destinations = new LinkedList<Link>();
407 for (Link link : dstLinks) {
408 if (link.getName().equals(name)) {
409 destinations.add(link);
410 }
411 }
412 if (direction == Direction.SRC) {
413 return sources;
414 } else if (direction == Direction.DST) {
415 return destinations;
416 }
417 sources.addAll(destinations);
418 return sources;
419 }
420
421
422
423
424
425
426
427
428
429
430 public Link addDependent(Node node, String linkName) {
431 Link link = new Link(node, this, linkName, Priority.DST_OVER_SRC);
432 return link;
433 }
434
435
436
437
438
439
440 private String typeNameWithValue() {
441 StringBuilder str = new StringBuilder();
442 str.append(typeName);
443 str.append("[");
444 str.append(id);
445 if (value != null) {
446 str.append(",");
447 str.append(value);
448 }
449 str.append("]\n");
450 return str.toString();
451 }
452
453
454
455
456
457
458
459 @Override
460 public String toString() {
461 StringBuilder str = new StringBuilder();
462 str.append(typeNameWithValue());
463 str.append(" > \n");
464 for (Link link : srcLinks) {
465 if (link.getDst() != null) {
466 str.append(link.getDst().typeNameWithValue());
467 }
468 }
469 str.append(" < \n");
470 for (Link link : dstLinks) {
471 if (link.getSrc() != null) {
472 str.append(link.getSrc().typeNameWithValue());
473 }
474 }
475 return str.toString();
476 }
477
478 private static PreparedStatement findByIdStmt;
479
480 private static PreparedStatement findByIdStmtWithLinks;
481
482 private static PreparedStatement findByNameWithZeroLinks;
483
484 private static PreparedStatement findByIdStmtWithZeroLinks;
485
486 private static PreparedStatement findByIdStmtWithAttrs;
487
488 private static PreparedStatement findAttributeByIdStmt;
489
490 private static PreparedStatement findByName;
491
492 private static PreparedStatement findByNameWithLinks;
493
494 private static PreparedStatement insertNodeStmt;
495
496 private static PreparedStatement updateNodeStmt;
497
498 static {
499 String stmtStr;
500 try {
501 stmtStr = "SELECT id, type_name, int_value, float_value, "
502 + "string_value, date_value, boolean_value FROM nodes WHERE id = ?";
503 findByIdStmt = mapper.getConnection().prepareStatement(stmtStr);
504
505 stmtStr = "SELECT n1.id, n1.type_name, null, null, "
506 + "null, null, null, "
507 + "l1.id, l1.src_id, l1.dst_id, l1.priority, l1.name, "
508 + "l1.src_accessor, l1.dst_accessor, l1.src_position, l1.dst_position "
509 + "FROM nodes n1 INNER JOIN links l1 ON (n1.id = l1.src_id OR n1.id = l1.dst_id) "
510 + "WHERE n1.id = ? AND l1.src_accessor IS NOT NULL ";
511
512 findByIdStmtWithLinks = mapper.getConnection().prepareStatement(stmtStr);
513
514 stmtStr = "SELECT n1.id, n1.type_name, n1.int_value, n1.float_value, "
515 + "n1.string_value, n1.date_value, n1.boolean_value, "
516 + "l1.id, l1.src_id, l1.dst_id, l1.priority, l1.name, "
517 + "l1.src_accessor, l1.dst_accessor, l1.src_position, l1.dst_position "
518 + "FROM nodes n1 INNER JOIN links l1 ON (n1.id = l1.src_id OR n1.id = l1.dst_id) "
519 + "WHERE n1.id = ? AND l1.src_accessor IS NULL ";
520
521 findAttributeByIdStmt = mapper.getConnection().prepareStatement(stmtStr);
522
523 stmtStr = "SELECT l1.id, l1.src_id, l1.dst_id, l1.priority, l1.name, "
524 + "null, null, 0, 0, "
525 + "n2.id, n2.type_name, n2.int_value, n2.float_value, "
526 + "n2.string_value, n2.date_value, n2.boolean_value "
527 + "FROM links l1, nodes n2 "
528 + "WHERE ((l1.src_id = ? AND n2.id = l1.dst_id) OR "
529 + "(l1.dst_id = ? AND n2.id = l1.src_id)) "
530 + "AND l1.src_accessor IS NULL ";
531
532 findByIdStmtWithAttrs = mapper.getConnection().prepareStatement(stmtStr);
533
534 stmtStr = "SELECT id, type_name, int_value, float_value, "
535 + "string_value, date_value, boolean_value FROM nodes "
536 + "WHERE type_name = ?";
537 findByName = mapper.getConnection().prepareStatement(stmtStr);
538
539 stmtStr = "SELECT n1.id, n1.type_name, n1.int_value, n1.float_value, "
540 + "n1.string_value, n1.date_value, n1.boolean_value, "
541 + "l1.id, l1.src_id, l1.dst_id, l1.priority, l1.name, "
542 + "l1.src_accessor, l1.dst_accessor, l1.src_position, l1.dst_position, "
543 + "n2.id, n2.type_name, n2.int_value, n2.float_value, "
544 + "n2.string_value, n2.date_value, n2.boolean_value "
545 + "FROM nodes n1, links l1, nodes n2 "
546 + "WHERE ((n1.id = l1.src_id AND n2.id = l1.dst_id) OR "
547 + "(n1.id = l1.dst_id AND n2.id = l1.src_id)) "
548 + "AND n1.type_name = ? ORDER BY n1.id";
549
550 stmtStr = "SELECT n1.id, n1.type_name, null, null, "
551 + "null, null, null, "
552 + "l1.id, l1.src_id, l1.dst_id, l1.priority, l1.name, "
553 + "l1.src_accessor, l1.dst_accessor, l1.src_position, l1.dst_position "
554 + "FROM nodes n1 INNER JOIN links l1 ON (n1.id = l1.src_id OR n1.id = l1.dst_id)"
555 + "WHERE n1.type_name = ? AND l1.src_accessor IS NOT NULL "
556 + "ORDER BY n1.id";
557
558 findByNameWithLinks = mapper.getConnection().prepareStatement(stmtStr);
559
560 stmtStr = "SELECT n1.id, n1.type_name, int_value, float_value, "
561 + "string_value, date_value, boolean_value "
562 + "FROM nodes n1 "
563 + "WHERE n1.type_name = ? "
564 + "ORDER BY n1.id";
565
566 findByNameWithZeroLinks = mapper.getConnection().prepareStatement(stmtStr);
567
568 stmtStr = "SELECT n1.id, n1.type_name, int_value, float_value, "
569 + "string_value, date_value, boolean_value "
570 + "FROM nodes n1 "
571 + "WHERE n1.id = ? ";
572
573 findByIdStmtWithZeroLinks = mapper.getConnection().prepareStatement(stmtStr);
574
575 stmtStr = "INSERT INTO nodes SET type_name = ?, "
576 + "int_value = ?, float_value = ?, string_value = ?, date_value = ?, "
577 + "boolean_value = ? ";
578
579 insertNodeStmt = mapper.getConnection().prepareStatement(stmtStr, Statement.RETURN_GENERATED_KEYS);
580
581 stmtStr = "UPDATE nodes SET type_name = ?, "
582 + "int_value = ?, float_value = ?, string_value = ?, date_value = ?, "
583 + "boolean_value = ? WHERE id = ? LIMIT 1";
584
585 updateNodeStmt = mapper.getConnection().prepareStatement(stmtStr, Statement.RETURN_GENERATED_KEYS);
586
587 } catch (SQLException e) {
588 e.printStackTrace();
589 }
590 }
591
592
593
594
595
596
597
598
599
600
601 public boolean save() {
602 if (saved) {
603 return true;
604
605 }
606
607
608 if (typeName == null || typeName.equals("")) {
609 throw new IllegalArgumentException("Node's type name must not be blank: " + this);
610 }
611
612 try {
613 if (id == 0) {
614
615
616 setValues(insertNodeStmt);
617
618 insertNodeStmt.executeUpdate();
619 ResultSet rs = insertNodeStmt.getGeneratedKeys();
620 if (rs.next()) {
621 setId(rs.getLong(1));
622 setSaved(true);
623 } else {
624 throw new SQLException("Cannot obtain the last node id");
625 }
626
627
628
629 for (Link link : getSrcLinks()) {
630 link.save();
631 }
632 for (Link link : getDstLinks()) {
633 link.save();
634 }
635
636 return true;
637 } else {
638
639 setValues(updateNodeStmt);
640 updateNodeStmt.setLong(7, id);
641 updateNodeStmt.executeUpdate();
642 setSaved(true);
643
644 }
645 } catch (SQLException e) {
646 e.printStackTrace();
647 setSaved(false);
648
649
650
651
652
653 return false;
654 }
655
656 return false;
657
658 }
659
660
661
662
663
664
665
666
667 public static Node find(long nodeId) {
668
669 Node node;
670
671
672
673 node = nodeCache.get(nodeId);
674 if (node != null) {
675
676 return node;
677 }
678
679
680
681
682 try {
683 PreparedStatement stmt;
684 if (eager) {
685 stmt = findByIdStmtWithLinks;
686 } else {
687 stmt = findByIdStmt;
688 }
689
690 stmt.setLong(1, nodeId);
691 ResultSet resultSet = stmt.executeQuery();
692
693 if (!resultSet.next()) {
694 if (eager) {
695 findByIdStmtWithZeroLinks.setLong(1, nodeId);
696 resultSet = findByIdStmtWithZeroLinks.executeQuery();
697 if (!resultSet.next()) {
698 throw new RuntimeException("Node with id = " + nodeId
699 + " not found");
700 }
701 } else {
702 throw new RuntimeException("Node with id = " + nodeId
703 + " not found");
704 }
705 }
706
707 node = loadNode(resultSet, eager);
708 return node;
709 } catch (SQLException e) {
710 e.printStackTrace();
711 }
712 return null;
713 }
714
715
716
717
718
719
720
721
722 public static List<Node> find(String typeName) {
723 List<Node> nodes = new LinkedList<Node>();
724
725 try {
726 PreparedStatement stmt;
727 if (eager) {
728 stmt = findByNameWithLinks;
729 } else {
730 stmt = findByName;
731 }
732 stmt.setString(1, typeName);
733 ResultSet rs = stmt.executeQuery();
734 if (eager && !rs.next()) {
735
736 findByNameWithZeroLinks.setString(1, typeName);
737 rs = findByNameWithZeroLinks.executeQuery();
738 } else {
739 rs.previous();
740 }
741 while (rs.next()) {
742 nodes.add(loadNode(rs, eager));
743 }
744 return nodes;
745 } catch (SQLException e) {
746 e.printStackTrace();
747 }
748 return null;
749 }
750
751
752
753
754
755
756
757
758
759
760
761
762 public static List<Node> find(String typeName, SortedMap<String, Object> conditions) {
763 List<Node> nodes = new LinkedList<Node>();
764 Statement findWithConditions = null;
765
766 try {
767
768 StringBuilder stmtBuilder = new StringBuilder();
769
770 stmtBuilder.append("SELECT n1.id, n1.type_name, n1.int_value, n1.float_value, "
771 + "n1.string_value, n1.date_value, n1.boolean_value ");
772 if (eager) {
773 stmtBuilder.append(", l1.id, l1.src_id, l1.dst_id, l1.priority, l1.name, "
774 + "l1.src_accessor, l1.dst_accessor, l1.src_position, l1.dst_position ");
775 }
776 stmtBuilder.append("FROM nodes n1 ");
777 if (eager) {
778 stmtBuilder.append("INNER JOIN links l1 ON (n1.id = l1.src_id OR n1.id = l1.dst_id) ");
779 }
780 stmtBuilder.append("WHERE n1.id IN(");
781 subquery(conditions, stmtBuilder);
782 stmtBuilder.append(") AND type_name='");
783 stmtBuilder.append(typeName);
784 stmtBuilder.append("' ");
785 if (eager) {
786 stmtBuilder.append("AND l1.src_accessor IS NOT NULL");
787 }
788
789
790
791 findWithConditions = mapper.getConnection().createStatement();
792
793 ResultSet rs = findWithConditions.executeQuery(stmtBuilder.toString());
794
795 stmtBuilder.delete(0, stmtBuilder.length() - 1);
796 stmtBuilder = null;
797
798 while (rs.next()) {
799 nodes.add(loadNode(rs, eager));
800 }
801 return nodes;
802 } catch (SQLException e) {
803 e.printStackTrace();
804 } finally {
805 try {
806 if (findWithConditions != null) {
807 findWithConditions.close();
808 }
809 } catch (SQLException e) {
810 e.printStackTrace();
811 }
812 }
813 return null;
814
815 }
816
817 private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm");
818
819
820
821
822
823
824
825
826
827
828 private static void subquery(SortedMap<String, Object> conditions, StringBuilder stmtBuilder) {
829 String firstKey = conditions.firstKey();
830 Object firstValue = conditions.remove(firstKey);
831
832 stmtBuilder.append("SELECT dst_id FROM links INNER JOIN nodes ON src_id = nodes.id ");
833 stmtBuilder.append("WHERE name = '");
834
835 if (!firstKey.startsWith("get")) {
836 stmtBuilder.append("get");
837 stmtBuilder.append(firstKey.substring(0, 1).toUpperCase());
838 stmtBuilder.append(firstKey.substring(1));
839 } else {
840 stmtBuilder.append(firstKey);
841 }
842
843 stmtBuilder.append("' AND ");
844
845 if ((firstValue instanceof Long) || (firstValue instanceof Integer)) {
846 stmtBuilder.append("int_value = ");
847 stmtBuilder.append(firstValue);
848 } else if (firstValue instanceof String) {
849 stmtBuilder.append("string_value = '");
850 stmtBuilder.append(firstValue);
851 stmtBuilder.append("'");
852 } else if (firstValue instanceof Double) {
853 stmtBuilder.append("float_value = ");
854 stmtBuilder.append(firstValue);
855 } else if (firstValue instanceof java.util.Date) {
856 stmtBuilder.append("date_value = '");
857 stmtBuilder.append(SIMPLE_DATE_FORMAT.format((java.util.Date)firstValue));
858 stmtBuilder.append("'");
859 } else if (firstValue instanceof Boolean) {
860 if ((Boolean)firstValue) {
861 stmtBuilder.append("boolean_value = 1");
862 } else {
863 stmtBuilder.append("boolean_Value = 0");
864 }
865 } else {
866 throw new RuntimeException("Wrong type of condition value: "
867 + firstValue + " " + firstValue.getClass());
868 }
869
870 if (conditions.size() != 0) {
871 stmtBuilder.append(" AND dst_id IN (");
872 subquery(conditions, stmtBuilder);
873 stmtBuilder.append(")");
874 }
875
876 }
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901 private static Node loadNode(ResultSet resultSet, boolean eager) throws SQLException {
902 Node node;
903
904 long nodeId = resultSet.getLong(1);
905
906 node = nodeCache.get(nodeId);
907 if (node != null) {
908 if (eager) {
909
910
911 while (resultSet.next()) {
912 if (resultSet.getLong(1) != nodeId) {
913 resultSet.previous();
914 break;
915 }
916 }
917 }
918 return node;
919 }
920
921 node = createNode(resultSet, 0);
922
923 if (eager) {
924 node.loadLinks(resultSet);
925 } else {
926 node.loadSrcLinks();
927 node.loadDstLinks();
928 }
929
930 return node;
931 }
932
933
934
935
936
937
938
939
940
941
942
943
944 private static Node createNode(ResultSet resultSet, int offset) throws SQLException {
945 Node node = new Node(resultSet.getString(offset + 2));
946 node.setId(resultSet.getLong(offset + 1));
947 node.setSaved(true);
948
949 node.loadValues((Integer)resultSet.getObject(offset + 3), (Float)resultSet.getObject(offset + 4),
950 (String)resultSet.getObject(offset + 5), (Timestamp)resultSet.getObject(offset + 6), (Boolean)resultSet
951 .getObject(offset + 7));
952
953 nodeCache.put(node.getId(), node);
954 return node;
955 }
956
957
958
959
960
961
962
963
964
965
966 private void loadValues(Integer iValue, Float fValue, String sValue, Timestamp ttValue, Boolean bValue) {
967
968 Long lValue = null;
969 if (iValue != null) {
970 lValue = new Long(iValue);
971 }
972
973
974 Double ddValue = null;
975 if (fValue != null) {
976 ddValue = new Double(fValue);
977 }
978
979
980 java.util.Date dValue = null;
981 if (ttValue != null) {
982 dValue = new java.util.Date(ttValue.getTime());
983 }
984
985
986 if (lValue != null) {
987 setValue(lValue);
988 } else if (fValue != null) {
989 setValue(ddValue);
990 } else if (sValue != null) {
991 setValue(sValue);
992 } else if (dValue != null) {
993 setValue(dValue);
994 } else if (bValue != null) {
995 setValue(bValue);
996 }
997 }
998
999
1000
1001
1002
1003
1004 private void loadSrcLinks() throws SQLException {
1005 List<Link> links = Link.findWithSrc(id);
1006 for (Link link : links) {
1007 addSrcLink(link);
1008 }
1009 }
1010
1011
1012
1013
1014
1015
1016 private void loadDstLinks() throws SQLException {
1017 List<Link> links = Link.findWithDst(id);
1018 for (Link link : links) {
1019 addDstLink(link);
1020 }
1021 }
1022
1023
1024
1025
1026
1027
1028
1029 private void loadLinks(ResultSet resultSet) throws SQLException {
1030
1031
1032 resultSet.previous();
1033 while (resultSet.next()) {
1034 long nodeId = resultSet.getLong(1);
1035 if (nodeId != this.id) {
1036 resultSet.previous();
1037 break;
1038 }
1039 if (resultSet.getMetaData().getColumnCount() > 7) {
1040 Link link = Link.createLink(resultSet, 7);
1041 if (link.getSrcId() == this.id) {
1042 link.setSrc(this);
1043 } else {
1044 link.setDst(this);
1045 }
1046 addLink(link);
1047 }
1048 }
1049
1050
1051 findByIdStmtWithAttrs.setLong(1, this.id);
1052 findByIdStmtWithAttrs.setLong(2, this.id);
1053 resultSet = findByIdStmtWithAttrs.executeQuery();
1054 while (resultSet.next()) {
1055 Link link = Link.createLink(resultSet, 0);
1056 Node node = createNode(resultSet, 9);
1057 if (link.getSrcId() == this.id) {
1058 link.setSrc(this);
1059 addSrcLink(link);
1060 link.setDst(node);
1061 node.addDstLink(link);
1062 } else {
1063 link.setDst(this);
1064 addDstLink(link);
1065 link.setSrc(node);
1066 node.addSrcLink(link);
1067 }
1068 }
1069 }
1070
1071
1072
1073
1074
1075
1076 public void reloadLinks() throws SQLException {
1077 srcLinks.clear();
1078 dstLinks.clear();
1079 loadSrcLinks();
1080 loadDstLinks();
1081 }
1082
1083
1084
1085
1086
1087
1088
1089
1090 public static Node find(Mappable object) {
1091 return Node.find(object.getMid());
1092 }
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111 private void setValues(PreparedStatement stmt) throws SQLException {
1112 stmt.setString(1, getTypeName());
1113
1114 Long lValue = getLongValue();
1115 if (lValue != null) {
1116 stmt.setLong(2, lValue);
1117 } else {
1118 stmt.setNull(2, Types.BIGINT);
1119 }
1120
1121
1122 Double dValue = getDoubleValue();
1123 if (dValue != null) {
1124 stmt.setDouble(3, dValue);
1125 } else {
1126 stmt.setNull(3, Types.DOUBLE);
1127 }
1128
1129
1130 String sValue = getStringValue();
1131 if (sValue != null) {
1132 stmt.setString(4, sValue);
1133 } else {
1134 stmt.setNull(4, Types.VARCHAR);
1135 }
1136
1137
1138 java.util.Date date = getDateValue();
1139 if (date != null) {
1140 stmt.setTimestamp(5, new Timestamp(date.getTime()));
1141 } else {
1142 stmt.setNull(5, Types.DOUBLE);
1143 }
1144
1145
1146 Boolean bValue = getBooleanValue();
1147 if (bValue != null) {
1148 stmt.setBoolean(6, bValue);
1149 } else {
1150 stmt.setNull(6, Types.BOOLEAN);
1151 }
1152 }
1153
1154
1155
1156
1157
1158
1159
1160 public void setSaved(boolean saved) {
1161 this.saved = saved;
1162 }
1163
1164
1165
1166
1167
1168
1169
1170
1171 public static Node find(Node node) {
1172 return find(node.getId());
1173 }
1174
1175
1176
1177
1178
1179
1180
1181
1182 public static List<Node> findAllByTypeName(String typeName) {
1183 return Node.find(typeName);
1184 }
1185
1186
1187
1188
1189
1190
1191 public long getId() {
1192 return id;
1193 }
1194
1195
1196
1197
1198
1199
1200 void setId(long nodeId) {
1201 id = nodeId;
1202 }
1203
1204
1205
1206
1207
1208
1209
1210 @Override
1211 public boolean equals(Object other) {
1212 if (this == other) {
1213 return true;
1214 }
1215
1216 if (!(other instanceof Node)) {
1217 return false;
1218 }
1219 Node that = (Node)other;
1220
1221
1222 if (this.value == null) {
1223 if (that.value != null) {
1224 return false;
1225 }
1226 } else {
1227 if (this.value instanceof Double && that.value instanceof Double) {
1228 Double d1 = (Double)this.value;
1229 Double d2 = (Double)that.value;
1230 if (Math.abs(d1 - d2) > delta) {
1231 return false;
1232 }
1233 } else {
1234 if (!this.value.equals(that.value)) {
1235 return false;
1236 }
1237 }
1238 }
1239
1240 return this.typeName.equals(that.typeName) && this.srcLinks.equals(that.srcLinks)
1241 && this.dstLinks.equals(that.dstLinks) && this.id == that.id;
1242
1243
1244
1245 }
1246
1247
1248
1249
1250
1251
1252
1253 @Override
1254 public int hashCode() {
1255 int result = (int)(typeName.hashCode() ^ (srcLinks.hashCode() * 3) ^ (dstLinks.hashCode() * 5) ^ (id * 11));
1256 if (value != null) {
1257 result ^= value.hashCode() * 13;
1258 }
1259 return result;
1260 }
1261
1262
1263
1264
1265
1266
1267
1268 public void addSrcLink(Link link) {
1269 srcLinks.add(link);
1270 }
1271
1272
1273
1274
1275
1276
1277
1278 public void addDstLink(Link link) {
1279 dstLinks.add(link);
1280 }
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295 public void addLink(Link link) {
1296 if (link.getSrcId() == this.id) {
1297
1298 for (Link cLink : srcLinks) {
1299 if (cLink.getDstPosition() >= link.getDstPosition()) {
1300 srcLinks.add(srcLinks.indexOf(cLink), link);
1301 return;
1302 }
1303 }
1304 srcLinks.add(link);
1305 } else if (link.getDstId() == this.id) {
1306
1307 for (Link cLink : dstLinks) {
1308 if (cLink.getSrcPosition() >= link.getSrcPosition()) {
1309 dstLinks.add(dstLinks.indexOf(cLink), link);
1310 return;
1311 }
1312 }
1313 dstLinks.add(link);
1314 } else {
1315 throw new IllegalArgumentException("The source or destination of the link " +
1316 "must equal to this node id [" + this.id + "]");
1317 }
1318 }
1319
1320
1321
1322
1323 public static void stats() {
1324
1325
1326 }
1327
1328 static void clearCache() {
1329 nodeCache.clear();
1330 }
1331 }