/*
Copyright 1996-2008 Ariba, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
$Id: //ariba/platform/ui/widgets/ariba/ui/wizard/meta/WizardStepMeta.java#3 $
*/
package ariba.ui.wizard.meta;
import ariba.util.core.Assert;
import ariba.util.core.ListUtil;
import ariba.ui.widgets.XMLUtil;
import org.w3c.dom.Element;
import java.util.List;
/**
A WizardStepMeta is the runtime counterpart to an XML definition of a
wizard step. It represents the static information about a step in a
wizard flow, i.e. name, label, list of frames, etc.
@aribaapi private
*/
public final class WizardStepMeta extends GenericMeta
{
/*-----------------------------------------------------------------------
Constants
-----------------------------------------------------------------------*/
// generic wizard step XML attributes
private static final String NumberedAttr = "numbered";
// extension wizard step XML elements
private static final String StepsElement = WizardMeta.StepsElement;
private static final String StepElement = WizardMeta.StepElement;
private static final String InFrameElement = WizardMeta.InFrameElement;
private static final String FrameElement = WizardMeta.FrameElement;
// extension attribute error messages
protected static final String UnknownFrameMsg = WizardMeta.UnknownFrameMsg;
// validation error messages
private static final String InvalidStepMsg =
"step '%s' in wizard '%s' must have either a frame or sub-steps (or both)";
/*-----------------------------------------------------------------------
Fields
-----------------------------------------------------------------------*/
// our main wizard meta info
private WizardMeta _wizard;
// should this step be numbered?
private Boolean _numbered = Boolean.TRUE;
// list of sub-step definitions
private List _substeps;
// frame to show for a leaf step
private WizardFrameMeta _frame;
/*-----------------------------------------------------------------------
Constructors
-----------------------------------------------------------------------*/
/**
Creates a new WizardStepMeta from static information, as opposed
to reading in this information from XML.
*/
public WizardStepMeta (WizardMeta wizard, String name, String label)
{
// initialize our core state
super(name, label);
_wizard = wizard;
}
/**
Creates a new WizardStepMeta by reading in data from a wizard XML
document. This is the normal case, as opposed to instances which are
created via application code (indirectly via the WizardStep
constructor).
*/
protected WizardStepMeta (WizardMeta wizard, Element stepElement)
{
// cache our top-level meta info
_wizard = wizard;
// read the wizard step attributes
readWizardStepAttrs(stepElement);
// read the frame for this step if given
_frame = wizard.readWizardFrames(stepElement, this, null);
// read any sub-steps that are given
_substeps = wizard.readWizardSteps(stepElement, this, false);
}
/*-----------------------------------------------------------------------
Initialization
-----------------------------------------------------------------------*/
protected void readInStepSubElements (Element inStepElement)
{
// read step attributes
readWizardStepAttrs(inStepElement);
// get the first (and only) child element
Element child = XMLUtil.getFirstChildElement(inStepElement);
String childName = elementName(child);
// recursively handle 'steps' sub-element
if (childName.equals(StepsElement)) {
_wizard.applyWizardStepsExtensions(inStepElement, this, _substeps);
}
// handle 'inFrame' sub-element to change source
else if (childName.equals(InFrameElement)) {
String fn = stringAttrFromElement(child, NameAttr);
_wizard.assertion(_frame.name().equals(fn), UnknownFrameMsg, fn, StepElement);
_frame = _wizard.readWizardFrames(inStepElement, this, null);
}
// handle 'frame' sub-element to allow full replacement
else if (childName.equals(FrameElement)) {
// todo: does this method call have side effects, or can we eliminate?
stringAttrFromElement(child, NameAttr);
_frame = _wizard.readWizardFrames(inStepElement, this, null);
}
}
private void readWizardStepAttrs (Element stepElement)
{
// required in both base & extensions
_name = stringAttrFromElement(stepElement, NameAttr, _name);
// required in base, optional in extensions
_label = stringAttrFromElement(stepElement, LabelAttr, _label);
// optional in both base & extensions
_numbered = booleanAttrFromElement(stepElement, NumberedAttr, _numbered);
}
/**
Checks that the final form of our step meta-data is valid. Asserts
this step and each of its sub-steps has either a frame or a non-empty
list of sub-steps (or both). Returns true if this step or any of its
sub-steps has a frame.
*/
private boolean validate ()
{
// check that we have either a frame or sub-steps
boolean valid = ((_frame != null) || !ListUtil.nullOrEmptyList(_substeps));
Assert.that(valid, InvalidStepMsg, _name, _wizard.name());
// validate our frame (if we have one)
if (_frame != null) {
_frame.validate();
}
// recurse and return true if at least one step frame found
return validate(_substeps, (_frame != null));
}
/**
@aribaapi private
*/
protected static boolean validate (List steps, boolean hasStepFrame)
{
for (int index = steps.size() - 1; index >= 0; index--) {
WizardStepMeta stepMeta = (WizardStepMeta)steps.get(index);
hasStepFrame = (stepMeta.validate() || hasStepFrame);
}
return hasStepFrame;
}
/*-----------------------------------------------------------------------
Field Accessors
-----------------------------------------------------------------------*/
public WizardMeta wizard ()
{
return _wizard;
}
public boolean numbered ()
{
return _numbered.booleanValue();
}
public List substeps ()
{
return _substeps;
}
public WizardFrameMeta frame ()
{
return _frame;
}
public void setFrame (WizardFrameMeta frame)
{
_frame = frame;
}
/*-----------------------------------------------------------------------
Protected Methods
-----------------------------------------------------------------------*/
protected boolean resourcesHaveChanged ()
{
if (_frame != null) {
return _frame.resourcesHaveChanged();
}
for (int i = 0, count = _substeps.size(); i < count; i++) {
if (((WizardStepMeta)_substeps.get(i)).resourcesHaveChanged()) {
return true;
}
}
return false;
}
}