1 19 20 package org.netbeans.modules.tasklist.usertasks.model; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.beans.PropertyChangeSupport ; 25 import java.io.BufferedReader ; 26 import java.io.IOException ; 27 import java.io.Reader ; 28 import java.io.Serializable ; 29 import java.io.Writer ; 30 import java.net.InetAddress ; 31 import java.net.URL ; 32 import java.net.UnknownHostException ; 33 import java.util.ArrayList ; 34 import java.util.Calendar ; 35 import java.util.Date ; 36 import java.util.Iterator ; 37 import java.util.List ; 38 import java.util.ResourceBundle ; 39 import javax.swing.tree.TreePath ; 40 import org.netbeans.modules.tasklist.usertasks.util.UTListTreeAbstraction; 41 import org.netbeans.modules.tasklist.usertasks.util.UTUtils; 42 import org.openide.filesystems.FileObject; 43 import org.openide.filesystems.URLMapper; 44 import org.openide.nodes.Node.Cookie; 45 import org.openide.text.Line; 46 import org.openide.util.NbBundle; 47 import org.netbeans.modules.tasklist.core.util.ObjectList; 48 import org.netbeans.modules.tasklist.core.util.ObjectListEvent; 49 import org.netbeans.modules.tasklist.core.util.ObjectListListener; 50 import org.netbeans.modules.tasklist.usertasks.annotations.UTAnnotation; 51 import org.netbeans.modules.tasklist.usertasks.util.UnaryFunction; 52 53 54 62 public final class UserTask implements Cloneable , Cookie, 63 PropertyChangeListener { 64 67 public static class WorkPeriod implements Comparable { 68 private long start; 69 private int duration; 70 71 77 public WorkPeriod(long start, int duration) { 78 this.start = start; 79 this.duration = duration; 80 } 81 82 public Object clone() throws CloneNotSupportedException { 83 return new WorkPeriod(start, duration); 84 } 85 86 92 public boolean intersects(WorkPeriod wp) { 93 long wpend = wp.start + wp.duration * 60 * 1000; 94 long end = start + duration * 60 * 1000; 95 return (duration + wp.duration) * 60 * 1000 > 96 Math.max(end, wpend) - Math.min(start, wp.start); 97 } 98 99 104 public long getStart() { 105 return start; 106 } 107 108 113 public int getDuration() { 114 return duration; 115 } 116 117 122 public void setDuration(int dur) { 123 this.duration = dur; 124 } 125 126 131 public boolean isToday() { 132 Calendar today = Calendar.getInstance(); 133 today.set(Calendar.HOUR_OF_DAY, 0); 134 today.set(Calendar.MINUTE, 0); 135 today.set(Calendar.SECOND, 0); 136 today.set(Calendar.MILLISECOND, 0); 137 return today.getTimeInMillis() <= start; 138 } 139 140 public int compareTo(Object obj) { 141 if (!(obj instanceof WorkPeriod)) 142 return -1; 143 WorkPeriod wp = (WorkPeriod) obj; 144 if (this.start < wp.start) 145 return -1; 146 else if (this.start > wp.start) 147 return 1; 148 else 149 return 0; 150 } 151 } 152 153 154 public static final int HIGH = 1; 155 156 157 public static final int MEDIUM_HIGH = 2; 158 159 160 public static final int MEDIUM = 3; 161 162 163 public static final int MEDIUM_LOW = 4; 164 165 166 public static final int LOW = 5; 167 168 172 public static final int[] PRIORITY_VALUES = { 173 HIGH, 174 MEDIUM_HIGH, 175 MEDIUM, 176 MEDIUM_LOW, 177 LOW 178 }; 179 180 181 private static final String [] PRIORITIES_KEYS = { 182 "PriorityHigh", "PriorityMediumHigh", "PriorityMedium", "PriorityMediumLow", "PriorityLow" }; 188 189 190 private static String [] PRIORITIES; 191 192 static { 193 PRIORITIES = new String [PRIORITIES_KEYS.length]; 194 ResourceBundle rb = NbBundle.getBundle(UserTask.class); 195 for (int i = 0; i < PRIORITIES_KEYS.length; i++) { 196 PRIORITIES[i] = rb.getString(PRIORITIES_KEYS[i]); 197 } 198 } 199 200 205 public static String getPriorityName(int p) { 206 return PRIORITIES[p - 1]; 207 } 208 209 217 public static UserTask[] reduce(UserTask[] tasks) { 218 List <UserTask> res = new ArrayList <UserTask>(); 219 for (int i = 0; i < tasks.length; i++) { 220 boolean ok = true; 221 for (int j = 0; j < tasks.length; j++) { 222 if (j != i) { 223 if (tasks[j].isAncestorOf(tasks[i])) { 224 ok = false; 225 break; 226 } 227 } 228 } 229 if (ok) 230 res.add(tasks[i]); 231 } 232 return res.toArray(new UserTask[res.size()]); 233 } 234 235 241 public static int getPriority(String name) { 242 for (int i = 0; i < PRIORITIES.length; i++) { 243 if (PRIORITIES[i].equals(name)) 244 return PRIORITY_VALUES[i]; 245 } 246 return -1; 247 } 248 249 254 public static String [] getPriorityNames() { 255 return PRIORITIES; 256 } 257 258 private final PropertyChangeSupport supp = new PropertyChangeSupport (this); 259 260 261 public static final String PROP_SUMMARY = "summary"; 263 264 public static final String PROP_ICON = "icon"; 266 267 public static final String PROP_DETAILS = "details"; 269 270 public static final String PROP_PRIORITY = "priority"; 272 273 public static final String PROP_VALID = "valid"; 275 276 public static final String PROP_URL = "url"; 278 279 public static final String PROP_LINE_NUMBER = "lineNumber"; 281 282 public static final String PROP_LINE = "line"; 284 public static final String PROP_DUE_DATE = "dueDate"; public static final String PROP_CATEGORY = "category"; public static final String PROP_PROGRESS = "progress"; public static final String PROP_EFFORT = "effort"; public static final String PROP_REMAINING_EFFORT = "remainingEffort"; public static final String PROP_SPENT_TIME = "spentTime"; public static final String PROP_OWNER = "owner"; public static final String PROP_COMPLETED_DATE = "completedDate"; public static final String PROP_WORK_PERIODS = "workPeriods"; public static final String PROP_START = "start"; public static final String PROP_SPENT_TIME_TODAY = "spentTimeToday"; 296 297 public static final String PROP_LAST_EDITED_DATE = 298 "lastEditedDate"; 300 301 public static final String PROP_VALUES_COMPUTED = 302 "valuesComputed"; 304 306 310 private boolean updateLastModified = true; 311 312 private UserTask parent; 313 314 315 private UserTaskObjectList subtasks; 316 317 321 private static String domain = null; 322 323 324 private static int unique = 0; 325 326 327 private String summary = null; 328 329 330 private String details = null; 331 332 333 private int priority = UserTask.MEDIUM; 334 335 339 public Object userObject; 340 341 342 private UserTaskList list; 343 344 private String uid; 345 346 349 private float progress = 0.0f; 350 351 357 private boolean valuesComputed = false; 358 359 private Date dueDate; 360 private boolean dueAlarmSent; 361 362 private String category; 363 private long created; 364 private long lastEditedDate; 365 366 367 private int effort = 60; 368 369 370 private int spentTime = 0; 371 372 private PropertyChangeListener lineListener; 373 374 376 private UTAnnotation annotation = null; 377 378 379 private URL url = null; 380 381 382 private Line line = null; 383 384 388 private int linenumber = -1; 389 391 private ObjectList<Dependency> dependencies = new ObjectList<Dependency>(); 392 private String owner = ""; private long completedDate = 0; 394 395 399 private long start = -1; 400 401 private ObjectList<WorkPeriod> workPeriods = new ObjectList<WorkPeriod>(); 403 405 411 public UserTask(String summary, UserTaskList list) { 412 this(summary, false, 3, "", "", null, list); } 414 415 427 public UserTask(String summary, boolean done, int priority, String details, 428 String category, UserTask parent, UserTaskList list) { 429 this.summary = summary; 430 this.parent = parent; 431 432 assert priority >= 1 && priority <= 5 : "priority ?"; assert summary != null : "desc == null"; assert details != null : "details == null"; assert category != null : "category == null"; 437 workPeriods.addListener(new ObjectListListener() { 438 public void listChanged(ObjectListEvent event) { 439 firePropertyChange(PROP_WORK_PERIODS, null, null); 440 } 441 }); 442 443 lineListener = new PropertyChangeListener () { 444 public void propertyChange(PropertyChangeEvent e) { 445 if (e.getPropertyName() == Line.PROP_LINE_NUMBER) { 446 firePropertyChange("lineNumber", e.getOldValue(), e.getNewValue()); 448 } 449 } 450 }; 451 452 subtasks = new UserTaskObjectList(this); 453 subtasks.addListener(new ObjectListListener() { 454 public void listChanged(ObjectListEvent ev) { 455 switch (ev.getType()) { 456 case ObjectListEvent.EVENT_ADDED: 457 structureChanged(); 458 break; 459 case ObjectListEvent.EVENT_REMOVED: { 460 structureChanged(); 461 break; 462 } 463 case ObjectListEvent.EVENT_REORDERED: 464 structureChanged(); 465 break; 466 case ObjectListEvent.EVENT_STRUCTURE_CHANGED: 467 structureChanged(); 468 break; 469 default: 470 throw new InternalError ("unexpected event type"); } 472 } 473 public void structureChanged() { 474 if (isValuesComputed()) { 475 setProgress_(computeProgress()); 476 setEffort_(computeEffort()); 477 setSpentTime_(computeSpentTime()); 478 } 479 if (UserTask.this.list != null) { 480 UserTask.this.list.fireChange(); 481 } 482 } 483 }); 484 485 this.list = list; 486 487 if (done) 488 setDone(true); 489 490 setPriority(priority); 491 492 this.category = category; 493 494 setDetails(details); 495 496 created = System.currentTimeMillis(); 497 lastEditedDate = created; 498 499 if (domain == null) { 500 try { 501 InetAddress address = InetAddress.getLocalHost(); 502 domain = address.toString(); 503 } catch (UnknownHostException e) { 504 domain = "unknown"; } 506 } 507 508 String timestamp = Long.toString(System.currentTimeMillis()); 510 511 uid = new StringBuffer (50).append("nb").append(timestamp). append('.').append(unique++).append('@').append(domain).toString(); 514 515 addPropertyChangeListener(this); 516 } 517 518 523 private void merge(ObjectList<WorkPeriod> wps) { 524 for (int i = 0; i < wps.size() - 1; i++) { 525 WorkPeriod a = wps.get(i); 526 WorkPeriod b = wps.get(i + 1); 527 if (a.intersects(b)) { 528 529 } 530 } 531 } 532 533 538 public ObjectList<WorkPeriod> getWorkPeriods() { 539 549 return workPeriods; 550 551 } 552 553 558 public UserTaskObjectList getParentObjectList() { 559 if (getParent() != null) 560 return getParent().getSubtasks(); 561 else if (getList() != null) 562 return getList().getSubtasks(); 563 else 564 return null; 565 } 566 567 572 public TreePath getPathTo() { 573 List <Object > l = new ArrayList <Object >(10); 574 UserTask t = this; 575 while (t != null) { 576 l.add(0, t); 577 t = t.getParent(); 578 } 579 l.add(0, getList()); 580 return new TreePath (l.toArray()); 581 } 582 583 586 public void moveUp() { 587 UserTaskObjectList list; 588 if (getParent() == null) 589 list = this.list.getSubtasks(); 590 else 591 list = this.parent.getSubtasks(); 592 int index = list.indexOf(this); 593 list.move(index, index - 1); 594 } 595 596 599 public void moveDown() { 600 UserTaskObjectList list; 601 if (getParent() == null) 602 list = this.list.getSubtasks(); 603 else 604 list = this.parent.getSubtasks(); 605 int index = list.indexOf(this); 606 list.move(index, index + 1); 607 } 608 609 614 public UserTaskObjectList getSubtasks() { 615 return subtasks; 616 } 617 618 623 public UserTaskList getList() { 624 return list; 625 } 626 627 632 void setList(UserTaskList list) { 633 this.list = list; 634 } 635 636 644 public boolean isAncestorOf(UserTask another) { 645 while (another != null) { 646 if (another == this) 647 return true; 648 another = another.getParent(); 649 } 650 return false; 651 } 652 653 658 public int getSpentTime() { 659 return spentTime; 660 } 661 662 667 public void setSpentTime(int spentTime) { 668 assert spentTime >= 0; 669 if (valuesComputed) 670 setValuesComputed(false); 671 672 setSpentTime_(spentTime); 673 674 if (isValuesComputed() && getSubtasks().size() == 0) 675 setProgress_(computeProgress()); 676 } 677 678 684 private void setSpentTime_(int spentTime) { 685 int old = this.spentTime; 686 687 if (this.spentTime != spentTime) { 688 this.spentTime = spentTime; 689 firePropertyChange("spentTime", new Integer (old), new Integer (spentTime)); 691 if (getParent() != null) { 692 UserTask p = (UserTask) getParent(); 693 if (p.isValuesComputed()) 694 p.setSpentTime_(p.computeSpentTime()); 695 } 696 } 697 } 698 699 705 public void setValuesComputed(boolean v) { 706 if (this.valuesComputed != v) { 707 if (isStarted()) 708 stop(); 709 this.valuesComputed = v; 710 firePropertyChange(PROP_VALUES_COMPUTED, 711 Boolean.valueOf(!v), Boolean.valueOf(v)); 712 if (v) { 713 setSpentTime_(computeSpentTime()); 714 setProgress_(computeProgress()); 715 setEffort_(computeEffort()); 716 717 } 718 } 719 } 720 721 727 public boolean isValuesComputed() { 728 return valuesComputed; 729 } 730 731 739 int computeSpentTime() { 740 assert valuesComputed; 741 742 int sum = 0; 743 Iterator it = getSubtasks().iterator(); 744 while (it.hasNext()) { 745 UserTask child = (UserTask) it.next(); 746 sum += child.getSpentTime(); 747 } 748 return sum; 749 } 750 751 754 public void start() { 755 StartedUserTask.getInstance().start(this); 756 } 757 758 761 public void stop() { 762 assert isStarted(); 763 StartedUserTask.getInstance().start(null); 764 } 765 766 771 public boolean isStarted() { 772 return StartedUserTask.getInstance().getStarted() == this; 773 } 774 775 780 public boolean areDependenciesDone() { 781 List deps = this.getDependencies(); 782 for (int i = 0; i < deps.size(); i++) { 783 Dependency d = (Dependency) deps.get(i); 784 if (d.getType() == Dependency.END_BEGIN) { 785 if (!d.getDependsOn().isDone()) 786 return false; 787 } 788 } 789 return true; 790 } 791 792 798 public boolean isStartable() { 799 return !isValuesComputed() && !isDone() && areDependenciesDone(); 800 } 801 802 807 public boolean isDueAlarmSent() { 808 return dueAlarmSent; 809 } 810 811 816 public void setDueAlarmSent(boolean flag) { 817 boolean old = this.dueAlarmSent; 818 dueAlarmSent = flag; 819 firePropertyChange("dueAlarmSent", Boolean.valueOf(old), Boolean.valueOf(dueAlarmSent)); 821 } 822 823 828 public Date getDueDate() { 829 return dueDate; 830 } 831 832 837 public void setDueDate(Date d) { 838 Date old = this.dueDate; 839 if (d != null) { 840 if (!d.equals(dueDate)) { 841 dueAlarmSent = false; 842 } 843 } else { 844 if (dueDate != null) { 845 dueAlarmSent = false; 846 } 847 } 848 dueDate = d; 849 firePropertyChange("dueDate", old, dueDate); } 851 852 857 public long getDueTime() { 858 long ret = Long.MAX_VALUE; 859 if (dueDate != null) { 860 ret = dueDate.getTime(); } 862 return ret; 863 } 864 865 875 boolean isDue(Date when) { 876 if (dueDate == null) { 877 return false; 878 } 879 long due = dueDate.getTime(); 880 long now = when.getTime(); 881 return (due < (now + (36 * 60 * 60 * 1000))); 882 } 885 886 891 public String getUID() { 892 return uid; 893 } 894 895 public void setUID(String nuid) { 896 String old = this.uid; 897 uid = nuid; 898 899 firePropertyChange("UID", old, this.uid); } 901 902 907 public boolean isDone() { 908 return Math.abs(100.0f - getProgress()) < 1e-6; 909 } 910 911 916 public void setDone(boolean done) { 917 if (done) 918 setPercentComplete(100); 919 else 920 setPercentComplete(0); 921 } 922 923 928 public int getPercentComplete() { 929 int p = Math.round(progress); 930 if (p == 100 && Math.abs(100.0f - progress) > 1e-6) 931 return 99; 932 else 933 return p; 934 } 935 936 941 public float getProgress() { 942 return progress; 943 } 944 945 950 public float getExpectedProgress() { 951 return ((float) getSpentTime()) / getEffort() * 100.0f; 952 } 953 954 960 private float computeProgress() { 961 assert valuesComputed; 962 963 if (getSubtasks().size() == 0) { 964 if (isValuesComputed()) 965 return 100.0f; 966 967 float p = (((float) getSpentTime()) / getEffort()) * 100.0f; 968 if (p > 99.0) 969 p = 99; 970 return p; 971 } 972 973 Iterator it = getSubtasks().iterator(); 974 int sum = 0; 975 int full = 0; 976 while (it.hasNext()) { 977 UserTask child = (UserTask) it.next(); 978 sum += child.getProgress() * child.getEffort(); 979 full += 100 * child.getEffort(); 980 } 981 982 if (full == sum) 983 return 100; 984 985 float p = ((float) sum) / full * 100.0f; 986 return p; 987 } 988 989 995 public void setPercentComplete(int percent) { 996 setProgress(percent); 997 } 998 999 1005 public void setProgress(float progress) { 1006 assert progress >= 0 && progress <= 100; 1007 if (valuesComputed) 1008 setValuesComputed(false); 1009 1010 setProgress_(progress); 1011 1012 if (isDone() && isStarted()) 1013 stop(); 1014 1015 if (isDone()) 1016 setCompletedDate(System.currentTimeMillis()); 1017 else 1018 setCompletedDate(0); 1019 1020 if (!isDone()) { 1021 UserTask[] t = findTasksThatDependOnThisOne(); 1022 for (int i = 0; i < t.length; i++) { 1023 Dependency d = t[i].findDependencyOn(this); 1024 if (d.getType() == Dependency.END_BEGIN) { 1025 t[i].setDone(false); 1026 t[i].setSpentTime(0); 1027 t[i].getWorkPeriods().clear(); 1028 } 1029 } 1030 } 1031 1032 if (annotation != null) { 1033 annotation.setDone(isDone()); 1034 } 1035 } 1036 1037 1044 private void setProgress_(float progress) { 1045 float old = this.progress; 1046 1047 if (this.progress != progress) { 1048 this.progress = progress; 1049 firePropertyChange("progress", new Float (old), new Float (progress)); 1051 if (getParent() != null) { 1052 UserTask p = (UserTask) getParent(); 1053 if (p.isValuesComputed()) 1054 p.setProgress_(p.computeProgress()); 1055 } 1056 } 1057 } 1058 1059 1065 public URL getUrl() { 1066 if (line == null) 1067 return url; 1068 1069 return UTUtils.getExternalURLForLine(line); 1070 } 1071 1072 1078 public void setUrl(URL url) { 1079 URL old = this.url; 1080 int oldn = this.linenumber; 1081 1082 this.url = url; 1083 this.linenumber = 0; 1084 1085 firePropertyChange(PROP_URL, old, url); 1086 firePropertyChange(PROP_LINE_NUMBER, new Integer (oldn), new Integer (linenumber)); 1087 1088 updateLine(); 1089 updateAnnotation(); 1090 } 1091 1092 1098 public int getLineNumber() { 1099 Line line = getLine(); 1100 if(line != null) 1101 return line.getLineNumber(); 1102 return linenumber; 1103 } 1104 1105 1110 public void setLineNumber(int n) { 1111 int old = this.linenumber; 1112 this.linenumber = n; 1113 1114 firePropertyChange(PROP_LINE_NUMBER, new Integer (old), 1115 new Integer (this.linenumber)); 1116 1117 updateLine(); 1118 updateAnnotation(); 1119 } 1120 1121 1126 public Line getLine() { 1127 return line; 1128 } 1129 1130 1135 public void setLine(final Line line) { 1136 Line old = this.line; 1137 1138 if (this.line != null) { 1139 this.line.removePropertyChangeListener(lineListener); 1140 } 1141 this.line = line; 1142 if (this.line != null) { 1143 this.line.addPropertyChangeListener(lineListener); 1144 } 1145 firePropertyChange(PROP_LINE, old, this.line); 1146 1147 if (line != null) { 1148 URL oldUrl = this.url; 1149 this.url = UTUtils.getExternalURLForLine(line); 1150 firePropertyChange(PROP_URL, oldUrl, this.url); 1151 1152 int oldLineNumber = this.linenumber; 1153 this.linenumber = line.getLineNumber(); 1154 firePropertyChange(PROP_LINE_NUMBER, new Integer (oldLineNumber), 1155 new Integer (this.linenumber)); 1156 } else { 1157 URL oldUrl = this.url; 1158 this.url = null; 1159 firePropertyChange(PROP_URL, oldUrl, this.url); 1160 1161 int oldLineNumber = this.linenumber; 1162 this.linenumber = -1; 1163 firePropertyChange(PROP_LINE_NUMBER, new Integer (oldLineNumber), 1164 new Integer (this.linenumber)); 1165 } 1166 1167 updateAnnotation(); 1168 } 1169 1170 1173 private void updateLine() { 1174 if (this.line != null) 1175 this.line.removePropertyChangeListener(lineListener); 1176 1177 Line oldLine = this.line; 1178 this.line = null; 1179 1180 if (url != null) { 1181 FileObject fo = URLMapper.findFileObject(url); 1182 if (fo != null) 1183 this.line = UTUtils.getLineByFile(fo, linenumber); 1184 } 1185 1186 if (this.line != null) 1187 this.line.addPropertyChangeListener(lineListener); 1188 1189 if (this.line != oldLine) 1190 firePropertyChange(PROP_LINE, oldLine, this.line); 1191 } 1192 1193 1199 public java.lang.String getCategory() { 1200 if (category == null) { 1201 return ""; } 1203 return category; 1204 } 1205 1206 1211 public void setCategory(java.lang.String category) { 1212 String old = this.category; 1213 this.category = category; 1214 firePropertyChange("category", old, this.category); } 1216 1217 1222 public long getCreatedDate() { 1223 return created; 1224 } 1225 1226 1231 public UTAnnotation getAnnotation() { 1232 return annotation; 1233 } 1234 1235 1238 private void updateAnnotation() { 1239 if (this.annotation != null) { 1240 this.annotation.detach(); 1241 this.annotation = null; 1242 } 1243 1244 if (this.line != null) { 1245 this.annotation = createAnnotation(); 1246 this.annotation.attach(this.line); 1247 } 1248 } 1249 1250 1253 public void setCreatedDate(long cr) { 1254 long old = this.created; 1255 created = cr; 1256 firePropertyChange("createdDate", new Long (old), new Long (this.created)); } 1258 1259 1268 public long getLastEditedDate() { 1269 return lastEditedDate; 1270 } 1271 1272 1277 public void setLastEditedDate(long ed) { 1278 lastEditedDate = ed; 1279 } 1280 1281 public int hashCode() { 1282 return summary.hashCode() + details.hashCode() + priority; 1283 } 1284 1285 1289 public Object clone() { 1290 UserTask t = new UserTask("", null); t.copyFrom(this); 1292 return t; 1293 } 1294 1295 1301 public ObjectList<Dependency> getDependencies() { 1302 return dependencies; 1303 } 1304 1305 1311 public Dependency findDependencyOn(UserTask ut) { 1312 for (int i = 0; i < dependencies.size(); i++) { 1313 Dependency d = (Dependency) dependencies.get(i); 1314 if (d.getDependsOn() == ut) 1315 return d; 1316 } 1317 return null; 1318 } 1319 1320 1325 public UserTask[] findTasksThatDependOnThisOne() { 1326 List <Object > t = UTUtils.filter( 1327 new UTListTreeAbstraction(getList()), new UnaryFunction() { 1328 public Object compute(Object obj) { 1329 if (obj instanceof UserTask) { 1330 UserTask ut = (UserTask) obj; 1331 Boolean b = Boolean.valueOf( 1332 ut.findDependencyOn(UserTask.this) != null); 1333 return b; 1334 } else { 1335 return Boolean.FALSE; 1336 } 1337 } 1338 }); 1339 return (UserTask[]) t.toArray(new UserTask[t.size()]); 1340 } 1341 1342 1357 protected void copyFrom(UserTask from) { 1358 if (this.line != null) 1360 this.line.removePropertyChangeListener(lineListener); 1361 this.line = from.line; 1362 if (this.line != null) 1363 this.line.addPropertyChangeListener(lineListener); 1364 1365 this.url = from.url; 1366 this.linenumber = from.linenumber; 1367 if (this.line == null) 1368 this.annotation = null; 1369 else 1370 this.annotation = createAnnotation(); 1371 1372 setSummary(from.getSummary()); 1373 setPriority(from.getPriority()); 1374 1375 setDetails(from.getDetails()); 1376 setDueDate(from.getDueDate()); 1377 setDueAlarmSent(from.isDueAlarmSent()); 1378 1379 parent = from.parent; 1384 1385 1387 Iterator it = from.subtasks.iterator(); 1390 subtasks = new UserTaskObjectList(this); 1391 while (it.hasNext()) { 1392 UserTask task = (UserTask)it.next(); 1393 UserTask mycopy = (UserTask)task.clone(); 1394 mycopy.list = list; 1395 mycopy.parent = this; 1396 subtasks.add(mycopy); 1397 } 1398 1399 progress = from.progress; 1400 valuesComputed = from.valuesComputed; 1401 category = from.category; 1402 created = from.created; 1403 effort = from.effort; 1404 spentTime = from.spentTime; 1405 dependencies.clear(); 1406 dependencies.addAll(from.dependencies); 1407 owner = from.owner; 1408 completedDate = from.completedDate; 1409 start = from.start; 1410 lastEditedDate = from.lastEditedDate; 1411 1412 workPeriods.clear(); 1413 for (int i = 0; i < from.workPeriods.size(); i++) { 1414 WorkPeriod wp = (WorkPeriod) from.workPeriods.get(i); 1415 try { 1416 workPeriods.add((WorkPeriod) wp.clone()); 1417 } catch (CloneNotSupportedException e) { 1418 throw new InternalError ("unexpected"); } 1420 } 1421 } 1422 1423 1428 public int getRemainingEffort() { 1429 return Math.round(getEffort() * (1 - getProgress() / 100)); 1430 } 1431 1432 1437 public int getEffort() { 1438 return effort; 1439 } 1440 1441 1449 int computeEffort() { 1450 assert valuesComputed; 1451 1452 Iterator it = getSubtasks().iterator(); 1453 int sum = 0; 1454 while (it.hasNext()) { 1455 UserTask child = (UserTask) it.next(); 1456 sum += child.getEffort(); 1457 } 1458 return sum; 1459 } 1460 1461 1466 public void setEffort(int effort) { 1467 assert effort >= 0; 1468 if (valuesComputed) 1469 setValuesComputed(false); 1470 1471 setEffort_(effort); 1472 1473 if (isValuesComputed() && getSubtasks().size() == 0) 1474 setProgress_(computeProgress()); 1475 } 1476 1477 1483 private void setEffort_(int effort) { 1484 int old = this.effort; 1485 1486 if (this.effort != effort) { 1487 int oldre = getRemainingEffort(); 1488 this.effort = effort; 1489 firePropertyChange("effort", new Integer (old), new Integer (effort)); 1491 firePropertyChange("remainingEffort", 1492 oldre, getRemainingEffort()); 1493 if (getParent() != null) { 1494 UserTask p = (UserTask) getParent(); 1495 if (p.isValuesComputed()) 1496 p.setEffort_(p.computeEffort()); 1497 if (p.isValuesComputed()) 1498 p.setProgress_(p.computeProgress()); 1499 } 1500 } 1501 } 1502 1503 1510 public String toString() { 1511 return "UserTask[" + getSummary() + ", " + 1512 getDetails() + "]"; } 1514 1515 public void propertyChange(PropertyChangeEvent evt) { 1516 if (updateLastModified) 1517 setLastEditedDate(System.currentTimeMillis()); 1518 } 1519 1520 1523 public void purgeCompleted() { 1524 getSubtasks().purgeCompletedItems(); 1525 } 1526 1527 1534 protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { 1535 supp.firePropertyChange(propertyName, oldValue, newValue); 1536 if (list != null) 1537 list.fireChange(); 1538 } 1539 1540 1546 public int indexOf(UserTask t) { 1547 return subtasks.indexOf(t); 1548 } 1549 1550 1555 public int getLevel() { 1556 UserTask t = getParent(); 1557 int level = 0; 1558 while (t != null) { 1559 level++; 1560 t = t.getParent(); 1561 } 1562 return level; 1563 } 1564 1565 1571 public void setSummary(final String summary) { 1572 if (summary == null) { 1573 throw new NullPointerException (); 1574 } 1575 String old = getSummary(); 1576 if (old.equals(summary)) return; 1577 this.summary = summary; 1578 firePropertyChange(PROP_SUMMARY, old, summary); 1579 } 1580 1581 1587 public void setDetails(final String details) { 1588 String old = getDetails(); 1589 if (old.equals(details)) return; 1590 this.details = details; 1591 firePropertyChange(PROP_DETAILS, old, details); 1592 } 1593 1594 1600 public void setPriority(int priority) { 1601 assert priority == HIGH || priority == MEDIUM_HIGH || 1602 priority == MEDIUM || priority == MEDIUM_LOW || priority == LOW; 1603 int old = getPriority(); 1604 if (old == priority) return; 1605 this.priority = priority; 1606 firePropertyChange(PROP_PRIORITY, new Integer (old), new Integer (priority)); 1607 } 1608 1609 1614 public final UserTask getParent() { 1615 return parent; 1616 } 1617 1618 1623 void setParent(UserTask parent) { 1624 this.parent = parent; 1625 } 1626 1627 1638 public static void generate(UserTask item, Writer w) throws IOException { 1639 w.write(item.getSummary()); 1640 } 1641 1642 1652 public static UserTask[] parse(Reader r) throws IOException { 1653 UserTaskList utl = new UserTaskList(); 1654 BufferedReader reader = new BufferedReader (r); 1655 String line; 1656 List <UserTask> res = new ArrayList <UserTask>(); 1657 while ((line = reader.readLine()) != null) { 1658 res.add(new UserTask(line, utl)); 1659 } 1660 return res.toArray(new UserTask[res.size()]); 1661 } 1662 1663 1668 public int getSubtaskCountRecursively() { 1669 int n = 0; 1670 Iterator it = subtasks.iterator(); 1671 while(it.hasNext()) { 1672 UserTask t = (UserTask) it.next(); 1673 n += t.getSubtaskCountRecursively() + 1; 1674 } 1675 return n; 1676 } 1677 1678 1682 public UserTask cloneTask() { 1683 UserTask clone = (UserTask) clone(); 1684 clone.parent = null; 1685 return clone; 1686 } 1687 1688 1693 public String getSummary() { 1694 if (summary == null) { 1695 summary = ""; } 1697 return summary; 1698 } 1699 1700 1701 1708 public String getDetails() { 1709 if (details == null) { 1710 details = ""; } 1712 return details; 1713 } 1714 1715 1721 public int getPriority() { 1722 return priority; 1723 } 1724 1725 1729 public final void addPropertyChangeListener(PropertyChangeListener l) { 1730 supp.removePropertyChangeListener(l); 1731 supp.addPropertyChangeListener(l); 1732 } 1733 1734 1739 public final void removePropertyChangeListener(PropertyChangeListener l) { 1740 supp.removePropertyChangeListener(l); 1741 } 1742 1743 1746 public void destroy() { 1747 if (this.annotation != null) { 1748 this.annotation.detach(); 1749 this.annotation = null; 1750 } 1751 1752 Iterator it = getSubtasks().iterator(); 1753 while (it.hasNext()) { 1754 UserTask ut = (UserTask) it.next(); 1755 ut.destroy(); 1756 } 1757 } 1758 1759 1764 private UTAnnotation createAnnotation() { 1765 UTAnnotation ann = new UTAnnotation(this, false); 1766 return ann; 1767 } 1768 1769 1774 public String getOwner() { 1775 return owner; 1776 } 1777 1778 1783 public void setOwner(String owner) { 1784 String old = this.owner; 1785 this.owner = owner; 1786 firePropertyChange("owner", old, this.owner); } 1788 1789 1794 public long getCompletedDate() { 1795 return completedDate; 1796 } 1797 1798 1803 public void setCompletedDate(long completed) { 1804 long old = this.completedDate; 1805 this.completedDate = completed; 1806 firePropertyChange("completedDate", new Long (old), new Long (completed)); } 1808 1809 1814 public int getSpentTimeToday() { 1815 int sum = 0; 1816 if (isValuesComputed()) { 1817 for (int i = 0; i < getSubtasks().size(); i++) { 1818 UserTask ut = (UserTask) getSubtasks().get(i); 1819 sum += ut.getSpentTimeToday(); 1820 } 1821 } else { 1822 for (int i = workPeriods.size() - 1; i >= 0; i--) { 1823 WorkPeriod wp = (WorkPeriod) workPeriods.get(i); 1824 if (wp.isToday()) 1825 sum += wp.getDuration(); 1826 else 1827 break; 1828 } 1829 } 1830 return sum; 1831 } 1832 1833 1839 public long getStart() { 1840 return start; 1841 } 1842 1843 1848 public Date getStartDate() { 1849 if (start == -1) 1850 return null; 1851 else 1852 return new Date (start); 1853 } 1854 1855 1861 public void setStart(long start) { 1862 long old = this.start; 1863 this.start = start; 1864 firePropertyChange("start", new Long (old), new Long (start)); } 1866 1867 1872 public void setStartDate(Date start) { 1873 if (start == null) 1874 setStart(-1); 1875 else 1876 setStart(start.getTime()); 1877 } 1878 1879 1882 public void clearEmptyWorkPeriods() { 1883 Iterator it = workPeriods.iterator(); 1884 while (it.hasNext()) { 1885 WorkPeriod wp = (WorkPeriod) it.next(); 1886 if (wp.getDuration() == 0) 1887 it.remove(); 1888 } 1889 } 1890 1891 1896 public void setUpdateLastModified(boolean b) { 1897 this.updateLastModified = b; 1898 } 1899} 1900 | Popular Tags |