in tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyRendererBase.java [519:629]
public boolean hasNext() {
if (nextItem != null) {
return true;
}
if (nestedItems != null) {
if (nestedItems.hasNext()) {
return true;
}
nestedItems = null;
currentComponent = null;
}
if (children.hasNext()) {
UIComponent child = children.next();
// When there is other components nested that does
// not extends from UISelectItem or UISelectItems
// the behavior for this iterator is just skip this
// element(s) until an element that extends from these
// classes are found. If there is no more elements
// that conform this condition, just return false.
while (!(child instanceof UISelectItem) && !(child instanceof UISelectItems)) {
// Try to skip it
if (children.hasNext()) {
// Skip and do the same check
child = children.next();
} else {
// End loop, so the final result is return false,
// since there are no more components to iterate.
return false;
}
}
if (child instanceof UISelectItem) {
final UISelectItem uiSelectItem = (UISelectItem) child;
Object item = uiSelectItem.getValue();
if (item == null) {
// no value attribute --> create the SelectItem out of the other attributes
final Object itemValue = uiSelectItem.getItemValue();
String label = uiSelectItem.getItemLabel();
final String description = uiSelectItem.getItemDescription();
final boolean disabled = uiSelectItem.isItemDisabled();
final boolean escape = uiSelectItem.isItemEscaped();
final boolean noSelectionOption = uiSelectItem.isNoSelectionOption();
if (label == null) {
label = itemValue.toString();
}
item = new SelectItem(itemValue, label, description, disabled, escape, noSelectionOption);
} else if (!(item instanceof SelectItem)) {
final ValueExpression expression = uiSelectItem.getValueExpression("value");
throw new IllegalArgumentException("ValueExpression '"
+ (expression == null ? null : expression.getExpressionString()) + "' of UISelectItem : "
+ getPathToComponent(child) + " does not reference an Object of type SelectItem");
}
nextItem = (SelectItem) item;
currentComponent = child;
return true;
} else if (child instanceof UISelectItems) {
currentUISelectItems = (UISelectItems) child;
final Object value = currentUISelectItems.getValue();
currentComponent = child;
if (value instanceof SelectItem) {
nextItem = (SelectItem) value;
return true;
} else if (value != null && value.getClass().isArray()) {
// value is any kind of array (primitive or non-primitive)
// --> we have to use class Array to get the values
final int length = Array.getLength(value);
final Collection<Object> items = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
items.add(Array.get(value, i));
}
nestedItems = items.iterator();
return hasNext();
} else if (value instanceof Iterable) {
// value is Iterable --> Collection, DataModel,...
nestedItems = ((Iterable<?>) value).iterator();
return hasNext();
} else if (value instanceof Map) {
final Map<Object, Object> map = (Map<Object, Object>) value;
final Collection<SelectItem> items = new ArrayList<>(map.size());
for (final Map.Entry<Object, Object> entry : map.entrySet()) {
items.add(new SelectItem(entry.getValue(), entry.getKey().toString()));
}
nestedItems = items.iterator();
return hasNext();
} else {
if (facesContext.isProjectStage(ProjectStage.Production) && LOG.isDebugEnabled()
|| LOG.isWarnEnabled()) {
final ValueExpression expression = currentUISelectItems.getValueExpression("value");
final Object[] objects = {
expression == null ? null : expression.getExpressionString(),
getPathToComponent(child),
value == null ? null : value.getClass().getName()
};
final String message = "ValueExpression {0} of UISelectItems with component-path {1}"
+ " does not reference an Object of type SelectItem,"
+ " array, Iterable or Map, but of type: {2}";
if (facesContext.isProjectStage(ProjectStage.Production)) {
LOG.debug(message, objects);
} else {
LOG.warn(message, objects);
}
}
}
} else {
currentComponent = null;
}
}
return false;
}