modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java | 96 +-- modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/trigger/JobTriggerEditor.java | 316 ++++++++-- modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/ResourceOperationScheduleDetailsView.java | 23 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/operation/schedule/ResourceOperationScheduleDataSource.java | 4 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/CanvasUtility.java | 4 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java | 45 + 6 files changed, 378 insertions(+), 110 deletions(-)
New commits: commit 51864e3db11b09ee8fb6bed6d16dd1322e3f6c25 Author: Ian Springer ian.springer@redhat.com Date: Wed Dec 22 16:27:01 2010 -0500
finish up calendar mode of schedule editor widget functionality-wise; start on new SLSB method for scheduling an operation that takes a ResourceOperationSchedule as a param
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java index c2e2626..45bf782 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java @@ -24,7 +24,6 @@ import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.EnumSet; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; @@ -87,7 +86,6 @@ import com.smartgwt.client.widgets.grid.events.CellSavedHandler; import com.smartgwt.client.widgets.grid.events.RecordClickEvent; import com.smartgwt.client.widgets.grid.events.RecordClickHandler; import com.smartgwt.client.widgets.layout.HLayout; -import com.smartgwt.client.widgets.layout.LayoutSpacer; import com.smartgwt.client.widgets.layout.SectionStack; import com.smartgwt.client.widgets.layout.SectionStackSection; import com.smartgwt.client.widgets.layout.VLayout; @@ -123,7 +121,6 @@ import org.rhq.enterprise.gui.coregui.client.ImageManager; import org.rhq.enterprise.gui.coregui.client.gwt.ConfigurationGWTServiceAsync; import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository; -import org.rhq.enterprise.gui.coregui.client.util.CanvasUtility; import org.rhq.enterprise.gui.coregui.client.util.message.Message; import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm; import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableIButton; @@ -166,7 +163,6 @@ public class ConfigurationEditor extends LocatableVLayout { private int resourceId; private int resourceTypeId; private ConfigType configType; - private IButton saveButton;
private boolean readOnly = false; private Set<String> invalidPropertyNames = new HashSet<String>(); @@ -361,61 +357,50 @@ public class ConfigurationEditor extends LocatableVLayout { sectionStack.addSection(buildGroupSection(layout.extendLocatorId(definition.getName()), definition)); }
- toolStrip = new LocatableToolStrip(layout.extendLocatorId("Tools")); - toolStrip.setBackgroundImage(null); - toolStrip.setWidth100(); + this.toolStrip = buildToolStrip(layout, sectionStack); + layout.addMember(toolStrip); + layout.addMember(sectionStack); + }
- toolStrip.addMember(new LayoutSpacer()); - saveButton = new LocatableIButton(toolStrip.extendLocatorId("Save"), MSG.common_button_save()); - saveButton.setAlign(Alignment.CENTER); - saveButton.setDisabled(true); - //toolStrip.addMember(saveButton); + return layout; + }
- IButton resetButton = new LocatableIButton(toolStrip.extendLocatorId("Reset"), MSG.common_button_reset()); - resetButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() { - public void onClick(ClickEvent clickEvent) { - reload(); - } - }); - //toolStrip.addMember(resetButton); - - toolStrip.addMember(new LayoutSpacer()); - - Menu menu = new LocatableMenu(toolStrip.extendLocatorId("JumpMenu")); - for (SectionStackSection section : sectionStack.getSections()) { - MenuItem item = new MenuItem(section.getTitle()); - item.addClickHandler(new ClickHandler() { - public void onClick(MenuItemClickEvent event) { - int x = event.getMenu().getItemNum(event.getItem()); - sectionStack.expandSection(x); - sectionStack.showSection(x); - } - }); - menu.addItem(item); - } - menu.addItem(new MenuItemSeparator()); + private LocatableToolStrip buildToolStrip(LocatableVLayout layout, final SectionStack sectionStack) { + LocatableToolStrip toolStrip = new LocatableToolStrip(layout.extendLocatorId("Tools")); + toolStrip.setBackgroundImage(null); + toolStrip.setWidth100();
- MenuItem hideAllItem = new MenuItem(MSG.view_configEdit_hideAll()); - hideAllItem.addClickHandler(new ClickHandler() { + Menu menu = new LocatableMenu(toolStrip.extendLocatorId("JumpMenu")); + for (SectionStackSection section : sectionStack.getSections()) { + MenuItem item = new MenuItem(section.getTitle()); + item.addClickHandler(new ClickHandler() { public void onClick(MenuItemClickEvent event) { - for (int i = 0; i < sectionStack.getSections().length; i++) { - sectionStack.collapseSection(i); - } + int x = event.getMenu().getItemNum(event.getItem()); + sectionStack.expandSection(x); + sectionStack.showSection(x); } }); - menu.addItem(hideAllItem); + menu.addItem(item); + } + menu.addItem(new MenuItemSeparator());
- // TODO GH: Save button as saveListener() or remove the buttons from this form and have - // the container provide them? + MenuItem hideAllItem = new MenuItem(MSG.view_configEdit_hideAll()); + hideAllItem.addClickHandler(new ClickHandler() { + public void onClick(MenuItemClickEvent event) { + for (int i = 0; i < sectionStack.getSections().length; i++) { + sectionStack.collapseSection(i); + } + } + }); + menu.addItem(hideAllItem);
- toolStrip.addMember(new LocatableIMenuButton(toolStrip.extendLocatorId("Jump"), MSG - .view_configEdit_jumpToSection(), menu)); + // TODO GH: Save button as saveListener() or remove the buttons from this form and have + // the container provide them?
- layout.addMember(toolStrip); - layout.addMember(sectionStack); - } + toolStrip.addMember(new LocatableIMenuButton(toolStrip.extendLocatorId("Jump"), MSG + .view_configEdit_jumpToSection(), menu));
- return layout; + return toolStrip; }
public SectionStackSection buildGroupSection(String locatorId, PropertyGroupDefinition group) { @@ -451,17 +436,6 @@ public class ConfigurationEditor extends LocatableVLayout { form.setValuesManager(valuesManager); form.setValidateOnExit(true); form.setHiliteRequiredFields(true); - - form.addItemChangedHandler(new ItemChangedHandler() { - public void onItemChanged(ItemChangedEvent itemChangedEvent) { - if (!changed) { - changed = true; - CanvasUtility.blink(saveButton); - saveButton.setDisabled(false); - } - } - }); - form.setNumCols(4); form.setCellPadding(5); form.setColWidths(190, 28, 210); @@ -1123,7 +1097,6 @@ public class ConfigurationEditor extends LocatableVLayout {
final IButton okButton = new LocatableIButton(extendLocatorId("OK"), MSG.common_button_ok()); okButton.disable(); - // saveButton.setID("config_structured_button_save"); okButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() { public void onClick(ClickEvent clickEvent) { propertyList.add(newMemberPropertySimple); @@ -1469,7 +1442,6 @@ public class ConfigurationEditor extends LocatableVLayout {
final IButton okButton = new LocatableIButton(extendLocatorId("OK"), MSG.common_button_ok()); okButton.disable(); - // saveButton.setID("config_structured_button_save"); okButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() { public void onClick(ClickEvent clickEvent) { if (newRow) { diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/trigger/JobTriggerEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/trigger/JobTriggerEditor.java index 5684067..fc9aef4 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/trigger/JobTriggerEditor.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/trigger/JobTriggerEditor.java @@ -20,8 +20,11 @@ package org.rhq.enterprise.gui.coregui.client.components.trigger;
import java.util.Date; +import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.Map;
+import com.smartgwt.client.types.Visibility; import com.smartgwt.client.widgets.form.DynamicForm; import com.smartgwt.client.widgets.form.fields.DateTimeItem; import com.smartgwt.client.widgets.form.fields.FormItem; @@ -47,8 +50,47 @@ import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout; */ public class JobTriggerEditor extends LocatableVLayout {
+ private static final String FIELD_REPEAT_INTERVAL = "repeatInterval"; + private static final String FIELD_REPEAT_DURATION = "repeatDuration"; + private static final String FIELD_END_TIME = "endTime"; + + private static final Map<String, Long> UNITS_TO_MILLIS_MULTIPLIER_MAP = new HashMap(); + static { + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("seconds", 1000L); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("s", 1000L); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("minutes", 1000L * 60); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("m", 1000L * 60); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("hours", 1000L * 60 * 60); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("h", 1000L * 60 * 60); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("days", 1000L * 60 * 60 * 24); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("d", 1000L * 60 * 60 * 24); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("weeks", 1000L * 60 * 60 * 24 * 7); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("w", 1000L * 60 * 60 * 24 * 7); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("months", 1000L * 60 * 60 * 24 * 7 * 30); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("M", 1000L * 60 * 60 * 24 * 7 * 30); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("quarters", 1000L * 60 * 60 * 24 * 7 * 90); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("q", 1000L * 60 * 60 * 24 * 7 * 90); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("years", 1000L * 60 * 60 * 24 * 7 * 30 * 365); + UNITS_TO_MILLIS_MULTIPLIER_MAP.put("y", 1000L * 60 * 60 * 24 * 7 * 30 * 365); + } + private boolean isReadOnly; - private boolean isValid; + + private DynamicForm laterForm; + private DynamicForm repeatForm; + + // These flags allow us to determine the trigger type. + private boolean isCronMode; + private boolean isStartLater; + private boolean isRecurring; + private boolean isRepeatDuration; + private boolean isEndTime; + private boolean isStartDelay; + private boolean isStartTime; + private static final String FIELD_START_TYPE = "startType"; + private static final String FIELD_START_TIME = "startTime"; + private static final String FIELD_START_DELAY = "startDelay"; + private static final String FIELD_RECURRENCE_TYPE = "recurrenceType";
/** * Create a new job trigger. @@ -111,70 +153,81 @@ public class JobTriggerEditor extends LocatableVLayout { modeItem.addChangedHandler(new ChangedHandler() { public void onChanged(ChangedEvent event) { if (event.getValue().equals("calendar")) { - calendarTypeForm.show(); + JobTriggerEditor.this.isCronMode = false; + calendarTypeForm.show(); } } });
- final DynamicForm laterForm = createLaterForm(); - addMember(laterForm); + this.laterForm = createLaterForm(); + addMember(this.laterForm);
- final DynamicForm repeatForm = createRepeatForm(); - addMember(repeatForm); + this.repeatForm = createRepeatForm(); + addMember(this.repeatForm);
calendarTypeItem.addChangedHandler(new ChangedHandler() { public void onChanged(ChangedEvent event) { String value = (String)event.getValue(); if (value.equals("now")) { - isValid = true; + JobTriggerEditor.this.isStartLater = false; + JobTriggerEditor.this.isRecurring = false; } else if (value.equals("nowAndRepeat")) { - laterForm.hide(); - FormItem repeatIntervalItem = repeatForm.getItem("repeatInterval"); + JobTriggerEditor.this.isStartLater = false; + JobTriggerEditor.this.isRecurring = true; + + FormItem repeatIntervalItem = repeatForm.getItem(FIELD_REPEAT_INTERVAL); repeatIntervalItem.setTitle("Run now and every"); repeatIntervalItem.redraw(); - repeatForm.show(); } else if (value.equals("later")) { - repeatForm.hide(); - laterForm.show(); + JobTriggerEditor.this.isStartLater = true; + JobTriggerEditor.this.isRecurring = false; } else { - // later and repeat - laterForm.show(); - FormItem repeatIntervalItem = repeatForm.getItem("repeatInterval"); + // value.equals("laterAndRepeat") + JobTriggerEditor.this.isStartLater = true; + JobTriggerEditor.this.isRecurring = true; + + FormItem repeatIntervalItem = repeatForm.getItem(FIELD_REPEAT_INTERVAL); repeatIntervalItem.setTitle("Repeat every"); repeatIntervalItem.redraw(); - repeatForm.show(); } + laterForm.setVisibility(JobTriggerEditor.this.isStartLater ? Visibility.VISIBLE : Visibility.HIDDEN); + repeatForm.setVisibility(JobTriggerEditor.this.isRecurring ? Visibility.VISIBLE : Visibility.HIDDEN); } }); }
private DynamicForm createRepeatForm() { - final DynamicForm nowAndRepeatForm = new DynamicForm(); - nowAndRepeatForm.setNumCols(6); - nowAndRepeatForm.setColWidths(130, 130, 130, 130, 130); + final DynamicForm repeatForm = new DynamicForm(); + repeatForm.setNumCols(6); + repeatForm.setColWidths(130, 130, 130, 130, 130);
- TextItem repeatIntervalItem = new TextItem("repeatInterval", "Run now and every"); + TextItem repeatIntervalItem = new TextItem(FIELD_REPEAT_INTERVAL, "Run now and every"); + repeatIntervalItem.setRequired(true);
// Configure hint. - repeatIntervalItem.setHint("[1-9][0-9]* (seconds|minutes|hours|days|weeks|months|quarters|years)"); + repeatIntervalItem.setHint("N UNITS (where N is a positive integer and UNITS is "seconds", "minutes", "hours", "days", "weeks", "months", "quarters", or "years", e.g. "30 seconds" or "6 weeks")"); repeatIntervalItem.setShowHint(false); repeatIntervalItem.addFocusHandler(new FocusHandler() { public void onFocus(FocusEvent event) { + repeatForm.setColWidths(130, 400, 130, 130, 130); event.getItem().setShowHint(true); + repeatForm.markForRedraw(); } }); repeatIntervalItem.addBlurHandler(new BlurHandler() { public void onBlur(BlurEvent event) { - event.getItem().setShowHint(false); + repeatForm.setColWidths(130, 130, 130, 130, 130); + event.getItem().setShowHint(false); + repeatForm.markForRedraw(); } });
// Configure validation. - RegExpValidator repeatIntervalValidator = new RegExpValidator("[1-9][0-9]*[ ]+(seconds|minutes|hours|days|weeks|months|quarters|years)"); + RegExpValidator repeatIntervalValidator = new RegExpValidator("[1-9][0-9]*[ ]*(seconds|s|minutes|m|hours|h|days|d|weeks|w|months|M|quarters|q|years|y)"); repeatIntervalItem.setValidators(repeatIntervalValidator); repeatIntervalItem.setValidateOnExit(true);
- RadioGroupItem recurrenceTypeItem = new RadioGroupItem("recurrenceType"); + RadioGroupItem recurrenceTypeItem = new RadioGroupItem(FIELD_RECURRENCE_TYPE); recurrenceTypeItem.setShowTitle(false); LinkedHashMap<String, String> recurrenceTypeValueMap = new LinkedHashMap<String, String>(); recurrenceTypeValueMap.put("for", "For"); @@ -182,31 +235,34 @@ public class JobTriggerEditor extends LocatableVLayout { recurrenceTypeValueMap.put("indefinitely", "Indefinitely"); recurrenceTypeItem.setValueMap(recurrenceTypeValueMap);
- final TextItem repeatDurationItem = new TextItem("repeatDuration"); + final TextItem repeatDurationItem = new TextItem(FIELD_REPEAT_DURATION); repeatDurationItem.setShowTitle(false); repeatDurationItem.setVisible(false);
// Configure hint. - repeatDurationItem.setHint("[1-9][0-9]* (repetitions|seconds|minutes|hours|days|weeks|months|quarters|years)"); + repeatDurationItem.setHint("N UNITS (where N is a positive integer and UNITS is "times", "seconds", "minutes", "hours", "days", "weeks", "months", "quarters", or "years", e.g. "30 seconds" or "5 repetitions")"); repeatDurationItem.setShowHint(false); repeatDurationItem.addFocusHandler(new FocusHandler() { public void onFocus(FocusEvent event) { + repeatForm.setColWidths(130, 130, 400, 130, 130); event.getItem().setShowHint(true); + repeatForm.markForRedraw(); } }); repeatDurationItem.addBlurHandler(new BlurHandler() { public void onBlur(BlurEvent event) { + repeatForm.setColWidths(130, 130, 130, 130, 130); event.getItem().setShowHint(false); + repeatForm.markForRedraw(); } });
// Configure validation. - RegExpValidator repeatDurationValidator = new RegExpValidator("[1-9][0-9]*[ ]+(repetitions|seconds|minutes|hours|days|weeks|months|quarters|years)"); + RegExpValidator repeatDurationValidator = new RegExpValidator("[1-9][0-9]*[ ]*(times|repetitions|seconds|s|minutes|m|hours|h|days|d|weeks|w|months|M|quarters|q|years|y)"); repeatDurationItem.setValidators(repeatDurationValidator); repeatDurationItem.setValidateOnExit(true);
- - final DateTimeItem endTimeItem = createDateTimeItem("endTime"); + final DateTimeItem endTimeItem = createDateTimeItem(FIELD_END_TIME); endTimeItem.setShowTitle(false); endTimeItem.setVisible(false);
@@ -216,22 +272,36 @@ public class JobTriggerEditor extends LocatableVLayout { public void onChanged(ChangedEvent event) { String value = (String)event.getValue(); if (value.equals("for")) { - endTimeItem.hide(); - repeatDurationItem.show(); + JobTriggerEditor.this.isEndTime = false; + JobTriggerEditor.this.isRepeatDuration = true; } else if (value.equals("until")) { - repeatDurationItem.hide(); + JobTriggerEditor.this.isEndTime = true; + JobTriggerEditor.this.isRepeatDuration = false; + } else { + // indefinite + JobTriggerEditor.this.isEndTime = false; + JobTriggerEditor.this.isRepeatDuration = false; + } + + endTimeItem.setRequired(JobTriggerEditor.this.isEndTime); + if (JobTriggerEditor.this.isEndTime) { endTimeItem.show(); } else { - repeatDurationItem.hide(); endTimeItem.hide(); } + repeatDurationItem.setRequired(JobTriggerEditor.this.isRepeatDuration); + if (JobTriggerEditor.this.isRepeatDuration) { + repeatDurationItem.show(); + } else { + repeatDurationItem.hide(); + } } });
- nowAndRepeatForm.setFields(repeatIntervalItem, recurrenceTypeItem, repeatDurationItem, endTimeItem, spacerItem); - nowAndRepeatForm.setVisible(false); + repeatForm.setFields(repeatIntervalItem, recurrenceTypeItem, repeatDurationItem, endTimeItem, spacerItem); + repeatForm.setVisible(false);
- return nowAndRepeatForm; + return repeatForm; }
private DynamicForm createLaterForm() { @@ -239,34 +309,38 @@ public class JobTriggerEditor extends LocatableVLayout { laterForm.setNumCols(4); laterForm.setColWidths(130, 130, 130);
- RadioGroupItem startTypeItem = new RadioGroupItem("startType", "Run"); + RadioGroupItem startTypeItem = new RadioGroupItem(FIELD_START_TYPE, "Run"); LinkedHashMap<String, String> startTypeValueMap = new LinkedHashMap<String, String>(); startTypeValueMap.put("on", "on"); startTypeValueMap.put("in", "in"); startTypeItem.setValueMap(startTypeValueMap);
- final DateTimeItem startTimeItem = createDateTimeItem("startTime"); + final DateTimeItem startTimeItem = createDateTimeItem(FIELD_START_TIME);
- final TextItem startDelayItem = new TextItem("startDelay"); + final TextItem startDelayItem = new TextItem(FIELD_START_DELAY); startDelayItem.setShowTitle(false); startDelayItem.setVisible(false);
// Configure hint. - startDelayItem.setHint("[1-9][0-9]* (seconds|minutes|hours|days|weeks|months|quarters|years)"); + startDelayItem.setHint("N UNITS (where N is a positive integer and UNITS is "seconds", "minutes", "hours", "days", "weeks", "months", "quarters", or "years", e.g. "30 seconds" or "6 weeks")"); startDelayItem.setShowHint(false); startDelayItem.addFocusHandler(new FocusHandler() { public void onFocus(FocusEvent event) { + laterForm.setColWidths(130, 130, 400); event.getItem().setShowHint(true); + laterForm.markForRedraw(); } }); startDelayItem.addBlurHandler(new BlurHandler() { public void onBlur(BlurEvent event) { + laterForm.setColWidths(130, 130, 130); event.getItem().setShowHint(false); + laterForm.markForRedraw(); } });
// Configure validation. - RegExpValidator startDelayValidator = new RegExpValidator("[1-9][0-9]*[ ]+(seconds|minutes|hours|days|weeks|months|quarters|years)"); + RegExpValidator startDelayValidator = new RegExpValidator("[1-9][0-9]*([ ]+(seconds|minutes|hours|days|weeks|months|quarters|years)|(s|m|h|d|w|M|q|y))"); startDelayItem.setValidators(startDelayValidator); startDelayItem.setValidateOnExit(true);
@@ -276,11 +350,24 @@ public class JobTriggerEditor extends LocatableVLayout { public void onChanged(ChangedEvent event) { String value = (String)event.getValue(); if (value.equals("on")) { + JobTriggerEditor.this.isStartDelay = false; + JobTriggerEditor.this.isStartTime = true; + } else { + // value.equals("in") + JobTriggerEditor.this.isStartDelay = true; + JobTriggerEditor.this.isStartTime = false; + } + startDelayItem.setRequired(JobTriggerEditor.this.isStartDelay); + if (JobTriggerEditor.this.isStartDelay) { + startDelayItem.show(); + } else { startDelayItem.hide(); + } + startTimeItem.setRequired(JobTriggerEditor.this.isStartTime); + if (JobTriggerEditor.this.isStartTime) { startTimeItem.show(); } else { startTimeItem.hide(); - startDelayItem.show(); } } }); @@ -291,6 +378,139 @@ public class JobTriggerEditor extends LocatableVLayout { return laterForm; }
+ public JobTrigger getJobTrigger() throws Exception { + JobTrigger jobTrigger = null; + + if (this.isCronMode) { + // TODO + } else { + // calendar mode + + // Validate first. + boolean isValid = true; + if (this.isStartLater) { + isValid = isValid && this.laterForm.validate(); + } + if (this.isRecurring) { + isValid = isValid && this.repeatForm.validate(); + } + if (!isValid) { + throw new Exception("The specified schedule is not valid."); + } + + if (this.isStartLater) { + Date startDate; + if (this.isStartDelay) { + // start delay - computer start time + String startDelay = this.laterForm.getValueAsString(FIELD_START_DELAY); + Duration startDelayDuration = parseDurationString(startDelay); + long delay = startDelayDuration.count * startDelayDuration.multiplier; + long startTime = System.currentTimeMillis() + delay; + startDate = new Date(startTime); + } else { + // start time + DateTimeItem startTimeItem = (DateTimeItem)this.laterForm.getField(FIELD_START_TIME); + startDate = startTimeItem.getValueAsDate(); + } + + if (this.isRecurring) { + // LATER AND REPEAT + + String repeatInterval = this.repeatForm.getValueAsString(FIELD_REPEAT_INTERVAL); + Duration intervalDuration = parseDurationString(repeatInterval); + long intervalMillis = intervalDuration.count * intervalDuration.multiplier; + + if (this.isRepeatDuration) { + String repeatDurationString = this.repeatForm.getValueAsString(FIELD_REPEAT_DURATION); + Duration repeatDuration = parseDurationString(repeatDurationString); + if (repeatDuration.multiplier == null) { + // n repetitions + int repetitions = repeatDuration.count; + jobTrigger = JobTrigger.createLaterAndRepeatTrigger(startDate, intervalMillis, repetitions); + } else { + // n units of time - compute end time + long delay = repeatDuration.count * repeatDuration.multiplier; + long endTime = System.currentTimeMillis() + delay; + Date endDate = new Date(endTime); + jobTrigger = JobTrigger.createLaterAndRepeatTrigger(startDate, intervalMillis, endDate); + } + } else if (this.isEndTime) { + DateTimeItem endTimeItem = (DateTimeItem)this.repeatForm.getField(FIELD_END_TIME); + Date endDate = endTimeItem.getValueAsDate(); + jobTrigger = JobTrigger.createLaterAndRepeatTrigger(startDate, intervalMillis, endDate); + } + } else { + // LATER + + jobTrigger = JobTrigger.createLaterTrigger(startDate); + } + } else { + if (this.isRecurring) { + // NOW AND REPEAT + + String repeatInterval = this.repeatForm.getValueAsString(FIELD_REPEAT_INTERVAL); + Duration intervalDuration = parseDurationString(repeatInterval); + long intervalMillis = intervalDuration.count * intervalDuration.multiplier; + + if (this.isRepeatDuration) { + String repeatDurationString = this.repeatForm.getValueAsString(FIELD_REPEAT_DURATION); + Duration repeatDuration = parseDurationString(repeatDurationString); + if (repeatDuration.multiplier == null) { + // n repetitions + int repetitions = repeatDuration.count; + jobTrigger = JobTrigger.createNowAndRepeatTrigger(intervalMillis, repetitions); + } else { + // n units of time - compute end time + long delay = repeatDuration.count * repeatDuration.multiplier; + long endTime = System.currentTimeMillis() + delay; + Date endDate = new Date(endTime); + jobTrigger = JobTrigger.createNowAndRepeatTrigger(intervalMillis, endDate); + } + } else if (this.isEndTime) { + DateTimeItem endTimeItem = (DateTimeItem)this.repeatForm.getField(FIELD_END_TIME); + Date endDate = endTimeItem.getValueAsDate(); + jobTrigger = JobTrigger.createNowAndRepeatTrigger(intervalMillis, endDate); + } + } else { + // NOW + + jobTrigger = JobTrigger.createNowTrigger(); + } + } + } + + return jobTrigger; + } + + private static Duration parseDurationString(String durationString) { + String countString = ""; + int index; + for (index = 0; index < durationString.length(); index++) { + char c = durationString.charAt(index); + if (Character.isDigit(c)) { + countString += c; + } else { + break; + } + } + int count = Integer.valueOf(countString); + + // Skip optional whitespace. + while (index < durationString.length()) { + char c = durationString.charAt(index); + if (c != ' ') { + break; + } + index++; + } + + String units = durationString.substring(index); + Long multiplier = UNITS_TO_MILLIS_MULTIPLIER_MAP.get(units.toLowerCase()); + + return new Duration(count, multiplier); + } + + private static DateTimeItem createDateTimeItem(String name) { final DateTimeItem dateTimeItem = new DateTimeItem(name); dateTimeItem.setEnforceDate(true); @@ -307,8 +527,14 @@ public class JobTriggerEditor extends LocatableVLayout { return isReadOnly; }
- public boolean isValid() { - return isValid; + private static class Duration { + public int count; + // a null multiplier means the count refers repetitions, rather than units of time + public Long multiplier; + + private Duration(int count, Long multiplier) { + this.count = count; + this.multiplier = multiplier; + } } - } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/ResourceOperationScheduleDetailsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/ResourceOperationScheduleDetailsView.java index 6da2ec5..1a87bd3 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/ResourceOperationScheduleDetailsView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/ResourceOperationScheduleDetailsView.java @@ -33,17 +33,20 @@ import com.smartgwt.client.widgets.form.fields.TextAreaItem; import com.smartgwt.client.widgets.form.fields.events.ChangedEvent; import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
+import org.rhq.core.domain.common.JobTrigger; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; import org.rhq.core.domain.operation.OperationDefinition; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.resource.composite.ResourceComposite; +import org.rhq.enterprise.gui.coregui.client.CoreGUI; import org.rhq.enterprise.gui.coregui.client.ViewPath; import org.rhq.enterprise.gui.coregui.client.components.configuration.ConfigurationEditor; import org.rhq.enterprise.gui.coregui.client.components.form.AbstractRecordEditor; import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedDynamicForm; import org.rhq.enterprise.gui.coregui.client.components.trigger.JobTriggerEditor; import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.operation.schedule.ResourceOperationScheduleDataSource; +import org.rhq.enterprise.gui.coregui.client.util.message.Message; import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableHLayout; import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
@@ -63,6 +66,7 @@ public class ResourceOperationScheduleDetailsView extends AbstractRecordEditor { private StaticTextItem operationDescriptionItem; private StaticTextItem operationParametersItem; private LocatableHLayout operationParametersConfigurationHolder; + private JobTriggerEditor triggerEditor;
public ResourceOperationScheduleDetailsView(String locatorId, ResourceComposite resourceComposite, int scheduleId) { super(locatorId, new ResourceOperationScheduleDataSource(resourceComposite), scheduleId, "Scheduled Operation", null); @@ -117,8 +121,8 @@ public class ResourceOperationScheduleDetailsView extends AbstractRecordEditor { contentPane.addMember(this.operationParametersConfigurationHolder);
if (isNewRecord()) { - JobTriggerEditor triggerEditor = new JobTriggerEditor(extendLocatorId("TriggerEditor")); - contentPane.addMember(triggerEditor); + this.triggerEditor = new JobTriggerEditor(extendLocatorId("TriggerEditor")); + contentPane.addMember(this.triggerEditor); }
EnhancedDynamicForm notesForm = new EnhancedDynamicForm(extendLocatorId("NotesForm"), isReadOnly(), @@ -144,6 +148,21 @@ public class ResourceOperationScheduleDetailsView extends AbstractRecordEditor { return ResourceOperationScheduleDataSource.Field.OPERATION_DISPLAY_NAME; }
+ @Override + protected void save() { + try { + JobTrigger trigger = this.triggerEditor.getJobTrigger(); + System.out.println(trigger); + } + catch (Exception e) { + e.printStackTrace(); + CoreGUI.getMessageCenter().notify(new Message(e.getMessage(), Message.Severity.Warning)); + return; + } + + super.save(); + } + private void refreshOperationDescriptionItem() { String operationName = this.operationNameItem.getValueAsString(); String value; diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/operation/schedule/ResourceOperationScheduleDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/operation/schedule/ResourceOperationScheduleDataSource.java index 6e9c744..8080f30 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/operation/schedule/ResourceOperationScheduleDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/operation/schedule/ResourceOperationScheduleDataSource.java @@ -67,4 +67,8 @@ public class ResourceOperationScheduleDataSource extends OperationScheduleDataSo }); }
+ @Override + protected void executeAdd(Record recordToAdd, DSRequest request, DSResponse response) { + operationService.scheduleResourceOperation(); + } } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/CanvasUtility.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/CanvasUtility.java index ef37367..5e1e6c0 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/CanvasUtility.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/CanvasUtility.java @@ -27,7 +27,9 @@ import com.smartgwt.client.widgets.Canvas; public class CanvasUtility {
public static void blink(Canvas canvas) { - canvas.animateFade(10, new FadeAnimationCallback(3,canvas,false)); + if (canvas != null) { + canvas.animateFade(10, new FadeAnimationCallback(3, canvas, false)); + } }
private static class FadeAnimationCallback implements AnimationCallback { diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java index b54dc27..3c71dd4 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationManagerBean.java @@ -18,6 +18,7 @@ */ package org.rhq.enterprise.server.operation;
+import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; @@ -165,6 +166,18 @@ public class OperationManagerBean implements OperationManagerLocal, OperationMan } }
+ public ResourceOperationSchedule scheduleResourceOperation(Subject subject, ResourceOperationSchedule schedule) + throws ScheduleException { + JobTrigger jobTrigger = schedule.getJobTrigger(); + Trigger trigger = convertToTrigger(jobTrigger); + try { + return scheduleResourceOperation(subject, schedule.getResource().getId(), schedule.getOperationName(), schedule.getParameters(), trigger, schedule.getDescription()); + } + catch (SchedulerException e) { + throw new ScheduleException(e); + } + } + public ResourceOperationSchedule scheduleResourceOperation(Subject subject, int resourceId, String operationName, Configuration parameters, Trigger trigger, String notes) throws SchedulerException { Resource resource = getResourceIfAuthorized(subject, resourceId); @@ -1943,4 +1956,36 @@ public class OperationManagerBean implements OperationManagerLocal, OperationMan return schedule; }
+ private static Trigger convertToTrigger(JobTrigger jobTrigger) { + Trigger trigger; + if (jobTrigger.getRecurrenceType() == JobTrigger.RecurrenceType.CRON_EXPRESSION) { + CronTrigger cronTrigger = new CronTrigger(); + try { + cronTrigger.setCronExpression(jobTrigger.getCronExpression()); + } + catch (ParseException e) { + throw new RuntimeException(e); + } + trigger = cronTrigger; + } else { + SimpleTrigger simpleTrigger = new SimpleTrigger(); + Date startTime = null; + switch (jobTrigger.getStartType()) { + case NOW: + startTime = new Date(); + break; + case DATETIME: + startTime = jobTrigger.getStartDate(); + break; + } + simpleTrigger.setStartTime(startTime); + + // TODO (ips): Finish implementing this. + + trigger= simpleTrigger; + } + + return trigger; + } + } \ No newline at end of file
rhq-commits@lists.fedorahosted.org