001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2009-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2016 ForgeRock AS. 016 */ 017package org.opends.guitools.controlpanel.ui; 018 019import static org.opends.messages.AdminToolMessages.*; 020 021import java.awt.Component; 022import java.awt.Dimension; 023import java.awt.GridBagConstraints; 024import java.awt.GridBagLayout; 025import java.awt.event.ItemEvent; 026import java.awt.event.ItemListener; 027import java.util.ArrayList; 028import java.util.Calendar; 029import java.util.Collection; 030import java.util.Date; 031import java.util.GregorianCalendar; 032 033import javax.swing.Box; 034import javax.swing.DefaultComboBoxModel; 035import javax.swing.JCheckBox; 036import javax.swing.JComboBox; 037import javax.swing.JComponent; 038import javax.swing.JEditorPane; 039import javax.swing.JLabel; 040import javax.swing.JPanel; 041import javax.swing.JTextField; 042import javax.swing.text.PlainDocument; 043 044import org.forgerock.i18n.LocalizableMessage; 045import org.opends.guitools.controlpanel.datamodel.CategorizedComboBoxElement; 046import org.opends.guitools.controlpanel.datamodel.ScheduleType; 047import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; 048import org.opends.guitools.controlpanel.ui.components.NumericLimitedSizeDocumentFilter; 049import org.opends.guitools.controlpanel.ui.components.TimeDocumentFilter; 050import org.opends.guitools.controlpanel.ui.renderer.NoLeftInsetCategoryComboBoxRenderer; 051import org.opends.guitools.controlpanel.util.Utilities; 052import org.opends.server.backends.task.RecurringTask; 053 054/** The panel that allows the user to specify when a task will be launched. */ 055public class TaskToSchedulePanel extends StatusGenericPanel 056{ 057 private static final long serialVersionUID = 6855081932432566784L; 058 059 private final String taskName; 060 061 private JComboBox scheduleType; 062 063 private JTextField time; 064 private JTextField day; 065 private JComboBox<String> month; 066 private JComboBox<String> year; 067 068 private JLabel lTime; 069 private JLabel lDay; 070 private JLabel lMonth; 071 private JLabel lYear; 072 073 private JLabel lDailyTime; 074 private JTextField dailyTime; 075 076 private JLabel lWeeklyTime; 077 private JLabel lWeeklyDays; 078 private JTextField weeklyTime; 079 private final JCheckBox sunday, monday, tuesday, wednesday, thursday, friday, saturday; 080 { 081 sunday = 082 Utilities.createCheckBox(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_SUNDAY.get()); 083 monday = 084 Utilities.createCheckBox(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_MONDAY.get()); 085 tuesday = 086 Utilities.createCheckBox(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TUESDAY.get()); 087 wednesday = 088 Utilities.createCheckBox( 089 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_WEDNESDAY.get()); 090 thursday = 091 Utilities.createCheckBox(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_THURSDAY.get()); 092 friday = 093 Utilities.createCheckBox(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_FRIDAY.get()); 094 saturday = 095 Utilities.createCheckBox(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_SATURDAY.get()); 096 } 097 098 private final JCheckBox[] weekDays = 099 { 100 sunday, monday, tuesday, wednesday, thursday, friday, saturday 101 }; 102 103 private JLabel lMonthlyTime; 104 private JLabel lMonthlyDays; 105 private JTextField monthlyTime; 106 private final JCheckBox[] monthDays = new JCheckBox[31]; 107 108 private JLabel lCronMinute; 109 private JLabel lCronHour; 110 private JLabel lCronWeekDay; 111 private JLabel lCronMonthDay; 112 private JLabel lCronMonth; 113 114 private JTextField cronMinute; 115 private JTextField cronHour; 116 private JTextField cronWeekDay; 117 private JTextField cronMonthDay; 118 private JTextField cronMonth; 119 120 private Component launchLaterPanel; 121 private Component dailyPanel; 122 private Component weeklyPanel; 123 private Component monthlyPanel; 124 private Component cronPanel; 125 126 private final LocalizableMessage LAUNCH_NOW = INFO_CTRL_PANEL_LAUNCH_NOW.get(); 127 private final LocalizableMessage LAUNCH_LATER = INFO_CTRL_PANEL_LAUNCH_LATER.get(); 128 private final LocalizableMessage LAUNCH_DAILY = INFO_CTRL_PANEL_TASK_TO_SCHEDULE_DAILY.get(); 129 private final LocalizableMessage LAUNCH_WEEKLY = INFO_CTRL_PANEL_TASK_TO_SCHEDULE_WEEKLY.get(); 130 private final LocalizableMessage LAUNCH_MONTHLY = 131 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_MONTHLY.get(); 132 private final LocalizableMessage CRON = INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON.get(); 133 134 private ScheduleType schedule; 135 136 /** 137 * Default constructor. 138 * @param taskName the name of the task to be scheduled. 139 */ 140 public TaskToSchedulePanel(String taskName) 141 { 142 super(); 143 this.taskName = taskName; 144 createLayout(); 145 } 146 147 /** Creates the layout of the panel (but the contents are not populated here). */ 148 private void createLayout() 149 { 150 GridBagConstraints gbc = new GridBagConstraints(); 151 JEditorPane explanation = Utilities.makeHtmlPane( 152 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_SUMMARY.get(taskName).toString(), 153 ColorAndFontConstants.defaultFont); 154 gbc.gridx = 0; 155 gbc.gridy = 0; 156 gbc.gridwidth = 1; 157 gbc.fill = GridBagConstraints.HORIZONTAL; 158 add(explanation, gbc); 159 gbc.gridy ++; 160 gbc.insets.top = 10; 161 scheduleType = Utilities.createComboBox(); 162 scheduleType.setModel(new DefaultComboBoxModel()); 163 164 ArrayList<Object> newElements = new ArrayList<>(); 165 newElements.add(new CategorizedComboBoxElement(LAUNCH_NOW, 166 CategorizedComboBoxElement.Type.REGULAR)); 167 newElements.add(COMBO_SEPARATOR); 168 newElements.add(new CategorizedComboBoxElement(LAUNCH_LATER, 169 CategorizedComboBoxElement.Type.REGULAR)); 170 newElements.add(COMBO_SEPARATOR); 171 newElements.add(new CategorizedComboBoxElement(LAUNCH_DAILY, 172 CategorizedComboBoxElement.Type.REGULAR)); 173 newElements.add(new CategorizedComboBoxElement(LAUNCH_WEEKLY, 174 CategorizedComboBoxElement.Type.REGULAR)); 175 newElements.add(new CategorizedComboBoxElement(LAUNCH_MONTHLY, 176 CategorizedComboBoxElement.Type.REGULAR)); 177 newElements.add(new CategorizedComboBoxElement(CRON, 178 CategorizedComboBoxElement.Type.REGULAR)); 179 updateComboBoxModel(newElements, 180 (DefaultComboBoxModel)scheduleType.getModel()); 181 scheduleType.setRenderer( 182 new NoLeftInsetCategoryComboBoxRenderer(scheduleType)); 183 scheduleType.addItemListener(new IgnoreItemListener(scheduleType)); 184 185 gbc.weightx = 0.0; 186 gbc.anchor = GridBagConstraints.NORTHWEST; 187 gbc.fill = GridBagConstraints.NONE; 188 add(scheduleType, gbc); 189 190 launchLaterPanel = createLaunchLaterPanel(); 191 dailyPanel = createDailyPanel(); 192 weeklyPanel = createWeeklyPanel(); 193 monthlyPanel = createMonthlyPanel(); 194 cronPanel = createCronPanel(); 195 196 scheduleType.addItemListener(new ItemListener() 197 { 198 @Override 199 public void itemStateChanged(ItemEvent ev) 200 { 201 Object element = scheduleType.getSelectedItem(); 202 boolean launchLaterVisible = false; 203 boolean launchDailyVisible = false; 204 boolean launchWeeklyVisible = false; 205 boolean launchMonthlyVisible = false; 206 boolean cronVisible = false; 207 if (element != null) 208 { 209 if (element instanceof CategorizedComboBoxElement) 210 { 211 element = ((CategorizedComboBoxElement)element).getValue(); 212 } 213 launchLaterVisible = element == LAUNCH_LATER; 214 launchDailyVisible = element == LAUNCH_DAILY; 215 launchWeeklyVisible = element == LAUNCH_WEEKLY; 216 launchMonthlyVisible = element == LAUNCH_MONTHLY; 217 cronVisible = element == CRON; 218 } 219 launchLaterPanel.setVisible(launchLaterVisible); 220 dailyPanel.setVisible(launchDailyVisible); 221 weeklyPanel.setVisible(launchWeeklyVisible); 222 monthlyPanel.setVisible(launchMonthlyVisible); 223 cronPanel.setVisible(cronVisible); 224 } 225 }); 226 launchLaterPanel.setVisible(false); 227 dailyPanel.setVisible(false); 228 weeklyPanel.setVisible(false); 229 monthlyPanel.setVisible(false); 230 cronPanel.setVisible(false); 231 232 int width = 0; 233 int height = 0; 234 Component[] comps = 235 {launchLaterPanel, dailyPanel, weeklyPanel, monthlyPanel, cronPanel}; 236 for (Component comp : comps) 237 { 238 width = Math.max(width, comp.getPreferredSize().width); 239 height = Math.max(height, comp.getPreferredSize().height); 240 } 241 242 gbc.gridy ++; 243 gbc.gridwidth = 1; 244 gbc.gridx = 0; 245 gbc.weightx = 0.0; 246 gbc.insets.left = 30; 247 add(launchLaterPanel, gbc); 248 add(dailyPanel, gbc); 249 add(weeklyPanel, gbc); 250 add(monthlyPanel, gbc); 251 add(cronPanel, gbc); 252 add(Box.createRigidArea(new Dimension(width, height)), gbc); 253 gbc.gridy ++; 254 gbc.gridx = 0; 255 gbc.fill = GridBagConstraints.VERTICAL; 256 gbc.weighty = 1.0; 257 add(Box.createVerticalGlue(), gbc); 258 } 259 260 @Override 261 public void toBeDisplayed(boolean visible) 262 { 263 // Reset the schedule and the labels 264 if (visible) 265 { 266 schedule = null; 267 setPrimaryValid(lTime); 268 setPrimaryValid(lDay); 269 setPrimaryValid(lMonth); 270 setPrimaryValid(lYear); 271 setPrimaryValid(lWeeklyTime); 272 setPrimaryValid(lWeeklyDays); 273 setPrimaryValid(lMonthlyTime); 274 setPrimaryValid(lMonthlyDays); 275 setPrimaryValid(lCronMinute); 276 setPrimaryValid(lCronHour); 277 setPrimaryValid(lCronMonthDay); 278 setPrimaryValid(lCronMonth); 279 setPrimaryValid(lCronWeekDay); 280 } 281 } 282 283 @Override 284 public LocalizableMessage getTitle() 285 { 286 return INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TITLE.get(taskName); 287 } 288 289 @Override 290 public void okClicked() 291 { 292 schedule = null; 293 ArrayList<LocalizableMessage> errorMessages = new ArrayList<>(); 294 295 updateErrorMessages(errorMessages); 296 297 if (!errorMessages.isEmpty()) 298 { 299 displayErrorDialog(errorMessages); 300 } 301 else 302 { 303 schedule = createSchedule(); 304 Utilities.getParentDialog(this).setVisible(false); 305 } 306 } 307 308 /** 309 * Checks the validity of the provided information and updates the provided 310 * collection of messages with the errors that have been found. 311 * @param errorMessages the collection of messages to be updated. 312 */ 313 private void updateErrorMessages(Collection<LocalizableMessage> errorMessages) 314 { 315 Object type = 316 ((CategorizedComboBoxElement)scheduleType.getSelectedItem()).getValue(); 317 if (type == LAUNCH_LATER) 318 { 319 updateLaunchLaterErrorMessages(errorMessages); 320 } 321 else if (type == LAUNCH_DAILY) 322 { 323 updateLaunchDailyErrorMessages(errorMessages); 324 } 325 else if (type == LAUNCH_WEEKLY) 326 { 327 updateLaunchWeeklyErrorMessages(errorMessages); 328 } 329 else if (type == LAUNCH_MONTHLY) 330 { 331 updateLaunchMonthlyErrorMessages(errorMessages); 332 } 333 else if (type == CRON) 334 { 335 updateCronErrorMessages(errorMessages); 336 } 337 } 338 339 /** 340 * Checks the validity of the launch later information and updates 341 * the provided collection of messages with the errors that have been found. 342 * The associated labels are also updated. 343 * @param errorMessages the collection of messages to be updated. 344 */ 345 private void updateLaunchLaterErrorMessages(Collection<LocalizableMessage> errorMessages) 346 { 347 setPrimaryValid(lTime); 348 setPrimaryValid(lDay); 349 setPrimaryValid(lMonth); 350 setPrimaryValid(lYear); 351 352 int previousErrorNumber = errorMessages.size(); 353 354 int y = Integer.parseInt(year.getSelectedItem().toString()); 355 int d = -1; 356 int m = month.getSelectedIndex(); 357 int[] h = {-1}; 358 int[] min = {-1}; 359 checkTime(time, lTime, h, min, errorMessages); 360 try 361 { 362 d = Integer.parseInt(day.getText().trim()); 363 if (d < 0 || d > 31) 364 { 365 errorMessages.add(ERR_CTRL_PANEL_INVALID_DAY.get()); 366 setPrimaryInvalid(lDay); 367 } 368 } 369 catch (Exception ex) 370 { 371 errorMessages.add(ERR_CTRL_PANEL_INVALID_DAY.get()); 372 setPrimaryInvalid(lDay); 373 } 374 375 if (errorMessages.size() == previousErrorNumber) 376 { 377 GregorianCalendar calendar = new GregorianCalendar(y, m, d, h[0], min[0]); 378 Date date = calendar.getTime(); 379 // Check that the actual date's month date corresponds to a valid day 380 // (for instance if user specifies 30th of February, the resulting date 381 // is 2nd (or 1st depending of the year) of Mars. 382 if (calendar.get(Calendar.MONTH) != m) 383 { 384 errorMessages.add(ERR_CTRL_PANEL_INVALID_DAY_IN_MONTH.get(d, month.getSelectedItem())); 385 setPrimaryInvalid(lDay); 386 setPrimaryInvalid(lMonth); 387 } 388 else if (date.before(new Date())) 389 { 390 errorMessages.add(ERR_CTRL_PANEL_DATE_ALREADY_PASSED.get()); 391 setPrimaryInvalid(lTime); 392 setPrimaryInvalid(lDay); 393 setPrimaryInvalid(lMonth); 394 setPrimaryInvalid(lYear); 395 } 396 } 397 } 398 399 /** 400 * Checks the validity of the launch daily information and updates 401 * the provided collection of messages with the errors that have been found. 402 * The associated labels are also updated. 403 * @param errorMessages the collection of messages to be updated. 404 */ 405 private void updateLaunchDailyErrorMessages(Collection<LocalizableMessage> errorMessages) 406 { 407 setPrimaryValid(lDailyTime); 408 409 int[] h = {-1}; 410 int[] min = {-1}; 411 checkTime(dailyTime, lDailyTime, h, min, errorMessages); 412 } 413 414 /** 415 * Checks the validity of the launch weekly information and updates 416 * the provided collection of messages with the errors that have been found. 417 * The associated labels are also updated. 418 * @param errorMessages the collection of messages to be updated. 419 */ 420 private void updateLaunchWeeklyErrorMessages( 421 Collection<LocalizableMessage> errorMessages) 422 { 423 setPrimaryValid(lWeeklyTime); 424 setPrimaryValid(lWeeklyDays); 425 426 int[] h = {-1}; 427 int[] min = {-1}; 428 checkTime(weeklyTime, lWeeklyTime, h, min, errorMessages); 429 430 boolean oneSelected = false; 431 for (JCheckBox cb : weekDays) 432 { 433 if (cb.isSelected()) 434 { 435 oneSelected = true; 436 break; 437 } 438 } 439 if (!oneSelected) 440 { 441 errorMessages.add(ERR_CTRL_PANEL_NO_WEEK_DAY_SELECTED.get()); 442 setPrimaryInvalid(lWeeklyDays); 443 } 444 } 445 446 /** 447 * Checks the validity of the launch monthly information and updates 448 * the provided collection of messages with the errors that have been found. 449 * The associated labels are also updated. 450 * @param errorMessages the collection of messages to be updated. 451 */ 452 private void updateLaunchMonthlyErrorMessages( 453 Collection<LocalizableMessage> errorMessages) 454 { 455 setPrimaryValid(lMonthlyTime); 456 setPrimaryValid(lMonthlyDays); 457 458 int[] h = {-1}; 459 int[] min = {-1}; 460 checkTime(monthlyTime, lMonthlyTime, h, min, errorMessages); 461 462 boolean oneSelected = false; 463 for (JCheckBox cb : monthDays) 464 { 465 if (cb.isSelected()) 466 { 467 oneSelected = true; 468 break; 469 } 470 } 471 if (!oneSelected) 472 { 473 errorMessages.add(ERR_CTRL_PANEL_NO_MONTH_DAY_SELECTED.get()); 474 setPrimaryInvalid(lMonthlyDays); 475 } 476 } 477 478 /** 479 * Checks the validity of the cron schedule information and updates 480 * the provided collection of messages with the errors that have been found. 481 * The associated labels are also updated. 482 * @param errorMessages the collection of messages to be updated. 483 */ 484 private void updateCronErrorMessages(Collection<LocalizableMessage> errorMessages) 485 { 486 setPrimaryValid(lCronMinute); 487 setPrimaryValid(lCronHour); 488 setPrimaryValid(lCronMonthDay); 489 setPrimaryValid(lCronMonth); 490 setPrimaryValid(lCronWeekDay); 491 492 String minute = cronMinute.getText().trim(); 493 String hour = cronHour.getText().trim(); 494 String monthDay = cronMonthDay.getText().trim(); 495 String month = cronMonth.getText().trim(); 496 String weekDay = cronWeekDay.getText().trim(); 497 498 updateCronErrorMessages(minute, lCronMinute, 499 ERR_CTRL_PANEL_NO_CRON_MINUTE_PROVIDED.get(), 500 ERR_CTRL_PANEL_NOT_VALID_CRON_MINUTE_PROVIDED.get(), 501 0, 59, 502 errorMessages); 503 updateCronErrorMessages(hour, lCronHour, 504 ERR_CTRL_PANEL_NO_CRON_HOUR_PROVIDED.get(), 505 ERR_CTRL_PANEL_NOT_VALID_CRON_HOUR_PROVIDED.get(), 506 0, 23, 507 errorMessages); 508 updateCronErrorMessages(weekDay, lCronWeekDay, 509 ERR_CTRL_PANEL_NO_CRON_WEEK_DAY_PROVIDED.get(), 510 ERR_CTRL_PANEL_NOT_VALID_CRON_WEEK_DAY_PROVIDED.get(), 511 0, 6, 512 errorMessages); 513 updateCronErrorMessages(monthDay, lCronMonthDay, 514 ERR_CTRL_PANEL_NO_CRON_MONTH_DAY_PROVIDED.get(), 515 ERR_CTRL_PANEL_NOT_VALID_CRON_MONTH_DAY_PROVIDED.get(), 516 1, 31, 517 errorMessages); 518 updateCronErrorMessages(month, lCronMonth, 519 ERR_CTRL_PANEL_NO_CRON_MONTH_PROVIDED.get(), 520 ERR_CTRL_PANEL_NOT_VALID_CRON_MONTH_PROVIDED.get(), 521 1, 12, 522 errorMessages); 523 } 524 525 /** 526 * Checks the validity of the cron schedule information tab and updates 527 * the provided collection of messages with the errors that have been found. 528 * The associated labels are also updated. 529 * @param value the value of the cron schedule tab. 530 * @param label the label associated with the cron schedule tab. 531 * @param errorIfEmpty the message to be displayed if the value tab is empty. 532 * @param contentError the message to be displayed if the value tab is not 533 * valid. 534 * @param minValue the minimum value accepted. 535 * @param maxValue the maximum value accepted. 536 * @param errorMessages the collection of messages to be updated. 537 */ 538 private void updateCronErrorMessages(String value, JLabel label, 539 LocalizableMessage errorIfEmpty, LocalizableMessage contentError, int minValue, int maxValue, 540 Collection<LocalizableMessage> errorMessages) 541 { 542 if (value.length() == 0) 543 { 544 errorMessages.add(errorIfEmpty); 545 setPrimaryInvalid(label); 546 } 547 else 548 { 549 try 550 { 551 RecurringTask.parseTaskTabField(value, minValue, maxValue); 552 } 553 catch (Exception ex) 554 { 555 errorMessages.add(contentError); 556 setPrimaryInvalid(label); 557 } 558 } 559 } 560 561 /** 562 * Returns the schedule type corresponding to the input provided by user. 563 * This method assumes that all the date provided by the user has been 564 * validated. 565 * @return the schedule type corresponding to the input provided by user. 566 */ 567 private ScheduleType createSchedule() 568 { 569 ScheduleType schedule; 570 Object type = 571 ((CategorizedComboBoxElement)scheduleType.getSelectedItem()).getValue(); 572 if (type == LAUNCH_NOW) 573 { 574 schedule = ScheduleType.createLaunchNow(); 575 } 576 else if (type == LAUNCH_LATER) 577 { 578 int y = Integer.parseInt(year.getSelectedItem().toString()); 579 int d = Integer.parseInt(day.getText().trim()); 580 int m = month.getSelectedIndex(); 581 String sTime = time.getText().trim(); 582 int index = sTime.indexOf(':'); 583 int h = Integer.parseInt(sTime.substring(0, index).trim()); 584 int min = Integer.parseInt(sTime.substring(index+1).trim()); 585 GregorianCalendar calendar = new GregorianCalendar(y, m, d, h, min); 586 schedule = ScheduleType.createLaunchLater(calendar.getTime()); 587 } 588 else if (type == LAUNCH_DAILY) 589 { 590 String sTime = dailyTime.getText().trim(); 591 int index = sTime.indexOf(':'); 592 int h = Integer.parseInt(sTime.substring(0, index).trim()); 593 int m = Integer.parseInt(sTime.substring(index+1).trim()); 594 String cron = m+" "+h+" * * *"; 595 schedule = ScheduleType.createCron(cron); 596 } 597 else if (type == LAUNCH_WEEKLY) 598 { 599 String sTime = weeklyTime.getText().trim(); 600 int index = sTime.indexOf(':'); 601 int h = Integer.parseInt(sTime.substring(0, index).trim()); 602 int m = Integer.parseInt(sTime.substring(index+1).trim()); 603 StringBuilder sb = new StringBuilder(); 604 sb.append(m).append(" ").append(h).append(" * * "); 605 606 boolean oneDayAdded = false; 607 for (int i=0; i<weekDays.length; i++) 608 { 609 if (weekDays[i].isSelected()) 610 { 611 if (oneDayAdded) 612 { 613 sb.append(','); 614 } 615 sb.append(i); 616 oneDayAdded = true; 617 } 618 } 619 schedule = ScheduleType.createCron(sb.toString()); 620 } 621 else if (type == LAUNCH_MONTHLY) 622 { 623 String sTime = monthlyTime.getText().trim(); 624 int index = sTime.indexOf(':'); 625 int h = Integer.parseInt(sTime.substring(0, index).trim()); 626 int m = Integer.parseInt(sTime.substring(index+1).trim()); 627 StringBuilder sb = new StringBuilder(); 628 sb.append(m).append(" ").append(h).append(" "); 629 boolean oneDayAdded = false; 630 for (int i=0; i<monthDays.length; i++) 631 { 632 if (monthDays[i].isSelected()) 633 { 634 if (oneDayAdded) 635 { 636 sb.append(','); 637 } 638 sb.append(i+1); 639 oneDayAdded = true; 640 } 641 } 642 sb.append(" * *"); 643 schedule = ScheduleType.createCron(sb.toString()); 644 } 645 else if (type == CRON) 646 { 647 String cron = cronMinute.getText().trim() + " "+ 648 cronHour.getText().trim() + " "+ 649 cronMonthDay.getText().trim() + " "+ 650 cronMonth.getText().trim() + " "+ 651 cronWeekDay.getText().trim(); 652 schedule = ScheduleType.createCron(cron); 653 } 654 else 655 { 656 throw new RuntimeException("Unknown schedule type: "+type); 657 } 658 return schedule; 659 } 660 661 /** 662 * Convenience method to retrieve the time specified by the user. 663 * @param time the text field where the user specifies time. 664 * @param lTime the label associated with the text field. 665 * @param h an integer array of size 1 where the value of the hour specified 666 * by the user will be set. 667 * @param m an integer array of size 1 where the value of the minute specified 668 * by the user will be set. 669 * @param errorMessages the collection of error messages that will be updated 670 * with the encountered problems. 671 */ 672 private void checkTime(JTextField time, JLabel lTime, int[] h, int[] m, 673 Collection<LocalizableMessage> errorMessages) 674 { 675 String sTime = time.getText().trim(); 676 int index = sTime.indexOf(':'); 677 try 678 { 679 h[0] = Integer.parseInt(sTime.substring(0, index).trim()); 680 m[0] = Integer.parseInt(sTime.substring(index+1).trim()); 681 if (h[0] < 0 || h[0] > 23) 682 { 683 errorMessages.add(ERR_CTRL_PANEL_INVALID_HOUR.get()); 684 setPrimaryInvalid(lTime); 685 } 686 if (m[0] < 0 || m[0] > 59) 687 { 688 errorMessages.add(ERR_CTRL_PANEL_INVALID_MINUTE.get()); 689 setPrimaryInvalid(lTime); 690 } 691 } 692 catch (Exception ex) 693 { 694 errorMessages.add(ERR_CTRL_PANEL_INVALID_TIME.get()); 695 setPrimaryInvalid(lTime); 696 } 697 } 698 699 /** 700 * Tells whether the user chose to close the dialog discarding the provided 701 * input. 702 * @return <CODE>true</CODE> if the user chose to close the dialog discarding 703 * the provided input and <CODE>false</CODE> otherwise. 704 */ 705 public boolean isCanceled() 706 { 707 return schedule == null; 708 } 709 710 @Override 711 public void configurationChanged(ConfigurationChangeEvent ev) 712 { 713 // no-op 714 } 715 716 @Override 717 public Component getPreferredFocusComponent() 718 { 719 return scheduleType; 720 } 721 722 /** 723 * Returns the schedule provided by the user. 724 * @return the schedule provided by the user. 725 */ 726 public ScheduleType getSchedule() 727 { 728 return schedule; 729 } 730 731 private Component createLaunchLaterPanel() 732 { 733 JPanel panel = new JPanel(new GridBagLayout()); 734 panel.setOpaque(false); 735 GridBagConstraints gbc = new GridBagConstraints(); 736 Calendar calendar = Calendar.getInstance(); 737 738 int currentYear = calendar.get(Calendar.YEAR); 739 int currentHour = calendar.get(Calendar.HOUR_OF_DAY); 740 int currentMinute = calendar.get(Calendar.MINUTE); 741 int currentDay = calendar.get(Calendar.DAY_OF_MONTH); 742 int currentMonth = calendar.get(Calendar.MONTH); 743 744 time = Utilities.createShortTextField(); 745 PlainDocument plainTextDocument = new PlainDocument(); 746 time.setDocument(plainTextDocument); 747 String sHour = currentHour >= 10 ? 748 String.valueOf(currentHour) : "0"+currentHour; 749 String sMinute = currentMinute >= 10 ? 750 String.valueOf(currentMinute) : "0"+currentMinute; 751 time.setText(sHour+":"+sMinute); 752 plainTextDocument.setDocumentFilter(new TimeDocumentFilter(time)); 753 754 755 day = Utilities.createShortTextField(); 756 day.setColumns(4); 757 plainTextDocument = new PlainDocument(); 758 day.setDocument(plainTextDocument); 759 day.setText(String.valueOf(currentDay)); 760 plainTextDocument.setDocumentFilter( 761 new NumericLimitedSizeDocumentFilter(day, 2)); 762 month = Utilities.createComboBox(); 763 year = Utilities.createComboBox(); 764 765 int[][] maxMin = 766 { 767 {currentYear, currentYear + 5} 768 }; 769 770 JComboBox[] numericBoxes = { year }; 771 772 int[] currentValues = 773 { 774 currentYear 775 }; 776 777 for (int i=0; i<maxMin.length; i++) 778 { 779 int min = maxMin[i][0]; 780 int max = maxMin[i][1]; 781 782 DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>(); 783 784 int selectedIndex = 0; 785 786 int index = 0; 787 for (int j=min; j<=max; j++) 788 { 789 String s; 790 if (j < 10) 791 { 792 s = "0"+j; 793 } 794 else 795 { 796 s = String.valueOf(j); 797 } 798 model.addElement(s); 799 800 if (j == currentValues[i]) 801 { 802 selectedIndex= index; 803 } 804 index++; 805 } 806 807 numericBoxes[i].setModel(model); 808 809 if (selectedIndex != 0) 810 { 811 numericBoxes[i].setSelectedIndex(selectedIndex); 812 } 813 } 814 815 DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>(); 816 month.setModel(model); 817 818 LocalizableMessage[] monthMessages = 819 { 820 INFO_CTRL_PANEL_JANUARY.get(), 821 INFO_CTRL_PANEL_FEBRUARY.get(), 822 INFO_CTRL_PANEL_MARCH.get(), 823 INFO_CTRL_PANEL_APRIL.get(), 824 INFO_CTRL_PANEL_MAY.get(), 825 INFO_CTRL_PANEL_JUNE.get(), 826 INFO_CTRL_PANEL_JULY.get(), 827 INFO_CTRL_PANEL_AUGUST.get(), 828 INFO_CTRL_PANEL_SEPTEMBER.get(), 829 INFO_CTRL_PANEL_OCTOBER.get(), 830 INFO_CTRL_PANEL_NOVEMBER.get(), 831 INFO_CTRL_PANEL_DECEMBER.get(), 832 }; 833 for (LocalizableMessage msg : monthMessages) 834 { 835 model.addElement(msg.toString()); 836 } 837 838 month.setSelectedIndex(currentMonth); 839 840 lTime = Utilities.createPrimaryLabel( 841 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TIME.get()); 842 lDay = Utilities.createPrimaryLabel( 843 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_DAY.get()); 844 lMonth = Utilities.createPrimaryLabel( 845 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_MONTH.get()); 846 lYear = Utilities.createPrimaryLabel( 847 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_YEAR.get()); 848 849 gbc.gridy = 0; 850 851 JLabel[] labels = {lTime, lDay, lMonth, lYear}; 852 JComponent[] comps = {time, day, month, year}; 853 LocalizableMessage[] inlineHelp = 854 { 855 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TIME_TOOLTIP.get(), 856 null, 857 null, 858 null 859 }; 860 861 gbc.gridwidth = 1; 862 gbc.fill = GridBagConstraints.HORIZONTAL; 863 864 for (int i=0; i<labels.length; i++) 865 { 866 gbc.gridx = 0; 867 gbc.weightx = 0.0; 868 gbc.gridwidth = 1; 869 870 panel.add(labels[i], gbc); 871 gbc.gridx = 1; 872 gbc.insets.left = 10; 873 panel.add(comps[i], gbc); 874 gbc.gridx = 2; 875 gbc.weightx = 1.0; 876 gbc.insets.left = 0; 877 panel.add(Box.createHorizontalGlue(), gbc); 878 879 if (inlineHelp[i] != null) 880 { 881 gbc.gridwidth = 2; 882 gbc.insets.top = 3; 883 gbc.insets.left = 10; 884 gbc.gridx = 1; 885 gbc.gridy ++; 886 panel.add(Utilities.createInlineHelpLabel(inlineHelp[i]), gbc); 887 } 888 889 gbc.insets.top = 10; 890 gbc.gridy ++; 891 } 892 893 gbc.insets.top = 0; 894 gbc.weighty = 1.0; 895 gbc.fill = GridBagConstraints.VERTICAL; 896 panel.add(Box.createVerticalGlue(), gbc); 897 898 return panel; 899 } 900 901 private Component createDailyPanel() 902 { 903 JPanel panel = new JPanel(new GridBagLayout()); 904 panel.setOpaque(false); 905 GridBagConstraints gbc = new GridBagConstraints(); 906 gbc.gridx = 0; 907 gbc.gridy = 0; 908 gbc.weightx = 0.0; 909 910 lDailyTime = 911 Utilities.createPrimaryLabel(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TIME.get()); 912 913 dailyTime = Utilities.createShortTextField(); 914 PlainDocument plainTextDocument = new PlainDocument(); 915 dailyTime.setDocument(plainTextDocument); 916 dailyTime.setColumns(4); 917 dailyTime.setText("00:00"); 918 plainTextDocument.setDocumentFilter(new TimeDocumentFilter(dailyTime)); 919 920 panel.add(lDailyTime, gbc); 921 gbc.gridx = 1; 922 gbc.insets.left = 10; 923 gbc.fill = GridBagConstraints.NONE; 924 panel.add(dailyTime, gbc); 925 gbc.gridx = 2; 926 gbc.weightx = 1.0; 927 gbc.insets.left = 0; 928 gbc.fill = GridBagConstraints.HORIZONTAL; 929 panel.add(Box.createHorizontalGlue(), gbc); 930 931 gbc.gridy ++; 932 gbc.gridwidth = 2; 933 gbc.insets.top = 3; 934 gbc.insets.left = 10; 935 gbc.gridx = 1; 936 panel.add(Utilities.createInlineHelpLabel( 937 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TIME_TOOLTIP.get()), gbc); 938 939 return panel; 940 } 941 942 private Component createWeeklyPanel() 943 { 944 JPanel panel = new JPanel(new GridBagLayout()); 945 panel.setOpaque(false); 946 GridBagConstraints gbc = new GridBagConstraints(); 947 gbc.gridx = 0; 948 gbc.gridy = 0; 949 gbc.weightx = 0.0; 950 951 lWeeklyTime = 952 Utilities.createPrimaryLabel(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TIME.get()); 953 954 weeklyTime = Utilities.createShortTextField(); 955 PlainDocument plainTextDocument = new PlainDocument(); 956 weeklyTime.setDocument(plainTextDocument); 957 weeklyTime.setColumns(4); 958 weeklyTime.setText("00:00"); 959 plainTextDocument.setDocumentFilter(new TimeDocumentFilter(weeklyTime)); 960 961 lWeeklyDays = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_DAYS.get()); 962 for (JCheckBox cb : weekDays) 963 { 964 cb.setFont(ColorAndFontConstants.inlineHelpFont); 965 } 966 sunday.setSelected(true); 967 wednesday.setSelected(true); 968 969 gbc.anchor = GridBagConstraints.WEST; 970 panel.add(lWeeklyTime, gbc); 971 gbc.gridx = 1; 972 gbc.insets.left = 10; 973 gbc.gridwidth = weekDays.length; 974 gbc.fill = GridBagConstraints.NONE; 975 panel.add(weeklyTime, gbc); 976 gbc.gridx = 2; 977 gbc.weightx = 1.0; 978 gbc.insets.left = 0; 979 gbc.gridwidth = 1; 980 gbc.fill = GridBagConstraints.HORIZONTAL; 981 panel.add(Box.createHorizontalGlue(), gbc); 982 gbc.gridy ++; 983 gbc.gridwidth = weekDays.length + 1; 984 gbc.insets.top = 3; 985 gbc.insets.left = 10; 986 gbc.gridx = 1; 987 panel.add(Utilities.createInlineHelpLabel( 988 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TIME_TOOLTIP.get()), gbc); 989 990 gbc.gridx = 0; 991 gbc.gridy ++; 992 gbc.insets.top = 10; 993 gbc.weightx = 1.0; 994 panel.add(lWeeklyDays, gbc); 995 gbc.insets.left = 10; 996 gbc.gridwidth = 1; 997 for (JCheckBox cb : weekDays) 998 { 999 gbc.gridx ++; 1000 panel.add(cb, gbc); 1001 } 1002 gbc.weightx = 1.0; 1003 gbc.insets.left = 0; 1004 gbc.gridwidth = 1; 1005 gbc.gridx ++; 1006 panel.add(Box.createHorizontalGlue(), gbc); 1007 1008 return panel; 1009 } 1010 1011 private Component createMonthlyPanel() 1012 { 1013 JPanel panel = new JPanel(new GridBagLayout()); 1014 panel.setOpaque(false); 1015 GridBagConstraints gbc = new GridBagConstraints(); 1016 gbc.gridx = 0; 1017 gbc.gridy = 0; 1018 gbc.weightx = 0.0; 1019 1020 lMonthlyTime = 1021 Utilities.createPrimaryLabel(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TIME.get()); 1022 1023 monthlyTime = Utilities.createShortTextField(); 1024 PlainDocument plainTextDocument = new PlainDocument(); 1025 monthlyTime.setDocument(plainTextDocument); 1026 monthlyTime.setColumns(4); 1027 monthlyTime.setText("00:00"); 1028 plainTextDocument.setDocumentFilter(new TimeDocumentFilter(monthlyTime)); 1029 1030 lMonthlyDays = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_DAYS.get()); 1031 1032 gbc.anchor = GridBagConstraints.WEST; 1033 panel.add(lMonthlyTime, gbc); 1034 gbc.gridx = 1; 1035 gbc.insets.left = 10; 1036 gbc.fill = GridBagConstraints.NONE; 1037 gbc.gridwidth = 7; 1038 panel.add(monthlyTime, gbc); 1039 gbc.gridx = 2; 1040 gbc.weightx = 1.0; 1041 gbc.insets.left = 0; 1042 gbc.gridwidth = 1; 1043 gbc.fill = GridBagConstraints.HORIZONTAL; 1044 panel.add(Box.createHorizontalGlue(), gbc); 1045 gbc.gridy ++; 1046 gbc.gridwidth = 8; 1047 gbc.insets.top = 3; 1048 gbc.insets.left = 10; 1049 gbc.gridx = 1; 1050 panel.add(Utilities.createInlineHelpLabel( 1051 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TIME_TOOLTIP.get()), gbc); 1052 1053 gbc.gridx = 0; 1054 gbc.gridy ++; 1055 gbc.insets.top = 10; 1056 gbc.weightx = 1.0; 1057 gbc.gridwidth = 1; 1058 panel.add(lMonthlyDays, gbc); 1059 gbc.insets.left = 10; 1060 gbc.gridwidth = 1; 1061 for (int i=0 ; i<monthDays.length; i++) 1062 { 1063 monthDays[i] = Utilities.createCheckBox(LocalizableMessage.raw(String.valueOf(i+1))); 1064 monthDays[i].setFont(ColorAndFontConstants.inlineHelpFont); 1065 int x = i % 7; 1066 if (x == 0 && i != 0) 1067 { 1068 gbc.gridy ++; 1069 gbc.insets.top = 5; 1070 } 1071 if (x != 0) 1072 { 1073 gbc.insets.left = 5; 1074 } 1075 else 1076 { 1077 gbc.insets.left = 10; 1078 } 1079 gbc.gridx = x + 1; 1080 panel.add(monthDays[i], gbc); 1081 } 1082 monthDays[0].setSelected(true); 1083 gbc.weightx = 1.0; 1084 gbc.insets.left = 0; 1085 gbc.gridwidth = 1; 1086 gbc.gridx ++; 1087 panel.add(Box.createHorizontalGlue(), gbc); 1088 1089 return panel; 1090 } 1091 1092 private Component createCronPanel() 1093 { 1094 JPanel panel = new JPanel(new GridBagLayout()); 1095 panel.setOpaque(false); 1096 GridBagConstraints gbc = new GridBagConstraints(); 1097 1098 JEditorPane explanation = Utilities.makeHtmlPane( 1099 INFO_CTRL_PANEL_CRON_HELP.get(), 1100 ColorAndFontConstants.inlineHelpFont); 1101 gbc.gridx = 0; 1102 gbc.gridy = 0; 1103 gbc.gridwidth = 2; 1104 gbc.fill = GridBagConstraints.HORIZONTAL; 1105 panel.add(explanation, gbc); 1106 gbc.gridy ++; 1107 gbc.insets.top = 10; 1108 1109 gbc.gridwidth = 1; 1110 lCronMinute = Utilities.createPrimaryLabel( 1111 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_MINUTE.get()); 1112 lCronHour = Utilities.createPrimaryLabel( 1113 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_HOUR.get()); 1114 lCronWeekDay = Utilities.createPrimaryLabel( 1115 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_WEEK_DAY.get()); 1116 lCronMonthDay = Utilities.createPrimaryLabel( 1117 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_MONTH_DAY.get()); 1118 lCronMonth = Utilities.createPrimaryLabel( 1119 INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_MONTH.get()); 1120 1121 cronMinute = Utilities.createShortTextField(); 1122 cronMinute.setText("*"); 1123 1124 cronHour = Utilities.createShortTextField(); 1125 cronHour.setText("*"); 1126 1127 cronWeekDay = Utilities.createShortTextField(); 1128 cronWeekDay.setText("*"); 1129 1130 cronMonthDay = Utilities.createShortTextField(); 1131 cronMonthDay.setText("*"); 1132 1133 cronMonth = Utilities.createShortTextField(); 1134 cronMonth.setText("*"); 1135 1136 JLabel[] labels = {lCronMinute, lCronHour, lCronWeekDay, lCronMonthDay, 1137 lCronMonth}; 1138 Component[] comps = {cronMinute, cronHour, cronWeekDay, cronMonthDay, 1139 cronMonth}; 1140 LocalizableMessage[] help = 1141 { 1142 INFO_CTRL_PANEL_CRON_MINUTE_HELP.get(), 1143 INFO_CTRL_PANEL_CRON_HOUR_HELP.get(), 1144 INFO_CTRL_PANEL_CRON_WEEK_DAY_HELP.get(), 1145 INFO_CTRL_PANEL_CRON_MONTH_DAY_HELP.get(), 1146 INFO_CTRL_PANEL_CRON_MONTH_HELP.get(), 1147 }; 1148 1149 gbc.gridwidth = 1; 1150 gbc.fill = GridBagConstraints.HORIZONTAL; 1151 1152 for (int i=0; i<labels.length; i++) 1153 { 1154 gbc.gridx = 0; 1155 gbc.weightx = 0.0; 1156 1157 gbc.insets.left = 0; 1158 panel.add(labels[i], gbc); 1159 gbc.gridx = 1; 1160 gbc.insets.left = 10; 1161 panel.add(comps[i], gbc); 1162 gbc.gridx = 2; 1163 gbc.weightx = 1.0; 1164 gbc.insets.left = 0; 1165 panel.add(Box.createHorizontalGlue(), gbc); 1166 if (help[i] != null) 1167 { 1168 gbc.insets.top = 3; 1169 gbc.insets.left = 10; 1170 gbc.gridy ++; 1171 gbc.gridx = 1; 1172 panel.add(Utilities.createInlineHelpLabel(help[i]), gbc); 1173 } 1174 1175 gbc.insets.top = 10; 1176 gbc.gridy ++; 1177 } 1178 1179 gbc.insets.top = 0; 1180 gbc.weighty = 1.0; 1181 gbc.fill = GridBagConstraints.VERTICAL; 1182 panel.add(Box.createVerticalGlue(), gbc); 1183 1184 return panel; 1185 } 1186 1187 /** 1188 * The main method to test this panel. 1189 * @param args the arguments. 1190 */ 1191 public static void main(String[] args) 1192 { 1193 while (true) 1194 { 1195 TaskToSchedulePanel p = new TaskToSchedulePanel("TEST TASK"); 1196 GenericDialog dlg = new GenericDialog(Utilities.createFrame(), p); 1197 dlg.setModal(true); 1198 dlg.setVisible(true); 1199 } 1200 } 1201}