protected <T> FormItem<T> formItem(List<FormItem> formItems, String name) { for (FormItem formItem : formItems) { if (name.equals(formItem.getName())) { return formItem; } } return null; }
public ModelNode getAttributeMetaData(String name) { ModelNode metaData = null; for (Map<String, FormItem> groupItems : formItems.values()) { for (FormItem item : groupItems.values()) { if (name.equals(item.getName())) { metaData = (ModelNode) item.getMetadata(); break; } } } return metaData; }
@Override public Map<String, Object> getChangedValues() { final Map<String, Object> changedValues = new HashMap<String, Object>(); final ModelNode src = editedEntity == null ? new ModelNode() : editedEntity; final ModelNode dest = getUpdatedEntity(); ModelNodeInspector inspector = new ModelNodeInspector(this.getUpdatedEntity()); inspector.accept( new ModelNodeVisitor() { @Override public boolean visitValueProperty( String propertyName, ModelNode value, PropertyContext ctx) { // protected mode (see edit() ) requires us to prevent mutation ModelNode modelNode = src.hasDefined(propertyName) ? src.get(propertyName) : UNDEFINED; if (!modelNode.equals(dest.get(propertyName))) { Object castedValue = downCast(dest.get(propertyName), getAttributeMetaData(propertyName)); changedValues.put(propertyName, castedValue); } return true; } }); Map<String, Object> finalDiff = new HashMap<String, Object>(); // map changes, but skip unmodified fields for (Map<String, FormItem> groupItems : formItems.values()) { for (FormItem item : groupItems.values()) { Object val = changedValues.get(item.getName()); // expression have precedence over real values if (item.isExpressionValue()) { finalDiff.put(item.getName(), item.asExpressionValue()); } // regular values else if (val != null && item.isModified()) { if (item.isUndefined()) finalDiff.put(item.getName(), FormItem.VALUE_SEMANTICS.UNDEFINED); else finalDiff.put(item.getName(), val); } } } return finalDiff; }
private ToolStrip mainTableTools() { ToolStrip tools = new ToolStrip(); ToolButton addButton = new ToolButton( Console.CONSTANTS.common_label_add(), event -> { ModelNodeFormBuilder.FormAssets addFormAssets = new ModelNodeFormBuilder() .setResourceDescription(resourceDescription) .setCreateMode(true) .unsorted() .setCreateNameAttribute(false) .setSecurityContext(securityContext) .build(); addFormAssets.getForm().setEnabled(true); addFormAssets .getForm() .addFormValidator( (formItems, formValidation) -> { // at least one field is necessary to fill boolean allEmpty = true; for (FormItem formItem : formItems) { if (!formItem.isUndefined()) { allEmpty = false; break; } } if (allEmpty) { formValidation.addError("match-abstract-type"); FormItem mechanismNameFormItem = formItem(formItems, "match-abstract-type"); mechanismNameFormItem.setErrMessage( "At least one field must contain valid values."); mechanismNameFormItem.setErroneous(true); } }); DefaultWindow dialog = new DefaultWindow(Console.MESSAGES.newTitle("Match Rule")); AddResourceDialog.Callback callback = new AddResourceDialog.Callback() { @Override public void onAdd(ModelNode payload) { for (Property node : payload.asPropertyList()) { // remove undefined attributes if (!node.getValue().isDefined()) { payload.remove(node.getName()); } } circuit.dispatch( new AddListAttribute( ElytronStore.AUTHENTICATION_CONTEXT_ADDRESS, MATCH_RULES, authContextName, payload)); dialog.hide(); } @Override public void onCancel() { dialog.hide(); } }; AddResourceDialog addDialog = new AddResourceDialog(addFormAssets, resourceDescription, callback); dialog.setWidth(480); dialog.setHeight(510); dialog.setWidget(addDialog); dialog.setGlassEnabled(true); dialog.center(); }); ToolButton removeButton = new ToolButton( Console.CONSTANTS.common_label_delete(), event -> { final ModelNode selection = selectionModel.getSelectedObject(); if (selection != null) { Feedback.confirm( "Match Rule", Console.MESSAGES.deleteConfirm("Match Rule " + selection.asString()), isConfirmed -> { if (isConfirmed) { circuit.dispatch( new RemoveListAttribute( ElytronStore.AUTHENTICATION_CONTEXT_ADDRESS, authContextName, MATCH_RULES, selection)); } }); } }); tools.addToolButtonRight(addButton); tools.addToolButtonRight(removeButton); return tools; }
public FormAssets build() { // pre-requisite if (createMode && !modelDescription.hasDefined("operations")) { throw new IllegalStateException("Operation descriptions not defined"); } this.form = new ModelNodeForm(this.address, this.securityContext); this.form.setNumColumns(2); this.form.setEnabled(false); assert modelDescription.hasDefined("attributes") : "Invalid model description. Expected child 'attributes'"; List<Property> attributeDescriptions = new ArrayList<Property>(); if (createMode && modelDescription.get("operations").get("add").hasDefined("request-properties")) { attributeDescriptions = modelDescription.get("operations").get("add").get("request-properties").asPropertyList(); } else if (!createMode) { attributeDescriptions = modelDescription.get("attributes").asPropertyList(); } // sort fields if (!unsorted) { Collections.sort( attributeDescriptions, new Comparator<Property>() { @Override public int compare(Property property, Property property1) { return property.getName().compareTo(property1.getName()); } }); } // catch-all directive, if no explicit attributes given if (includes.isEmpty()) { for (Property attr : attributeDescriptions) { includes.add(attr.getName()); } } // in any case remove attributes marked for exclusion includes.removeAll(excludes); LinkedList<FormItem> requiredItems = new LinkedList<FormItem>(); LinkedList<FormItem> optionalItems = new LinkedList<FormItem>(); SafeHtmlBuilder helpTexts = new SafeHtmlBuilder(); helpTexts.appendHtmlConstant("<table class='help-attribute-descriptions'>"); Map<String, ModelNode> defaultValues = new HashMap<String, ModelNode>(); int numWritable = 0; boolean hasRequired = false; // for some decision below we need to know wether or not required attributes exist at all if (requiredOnly) { for (Property attr : attributeDescriptions) { ModelNode value = attr.getValue(); boolean required = isRequired(value); boolean readOnly = value.get("access-type").asString().equals("read-only"); if (required & !readOnly) { hasRequired = true; break; } } } Set<String[]> unsupportedTypes = new HashSet<>(); for (String attribute : includes) { for (Property attr : attributeDescriptions) { boolean isRuntime = attr.getValue().get("storage").asString().equals("runtime"); boolean isConfig = !attr.getValue().get("storage").asString().equals("runtime"); // TODO: verify statement if (runtimeAttributes == false && isRuntime) { continue; } if (configAttributes == false && isConfig) { continue; } if (!attr.getName().equals(attribute)) continue; // ------- // Attribute meta data // name char[] attrName = attr.getName().toCharArray(); attrName[0] = Character.toUpperCase(attrName[0]); // field label String label = new String(attrName).replace("-", " "); ModelNode attrDesc = attr.getValue(); // skip deprecated attributes if (attrDesc.hasDefined("deprecated")) { // Log.error("Skip deprecated attribute '" + attr.getName() + "'"); continue; } // type ModelType type = ModelType.valueOf(attrDesc.get("type").asString().toUpperCase()); // default value if (attrDesc.hasDefined("default")) { ModelNode defaultValue = attrDesc.get("default"); ModelNode value = new ModelNode(); // value.set(type, ModelNodeForm.downCast(defaultValue)); setValue( value, type, ModelNodeForm.downCast(defaultValue, attrDesc)); // workaround for numeric types defaultValues.put(attr.getName(), value); } // read-only final boolean readOnly = attrDesc.hasDefined("access-type") ? attrDesc.get("access-type").asString().equals("read-only") : false; // nillable boolean isRequired = isRequired(attrDesc); // createMode flag if ((createMode && readOnly)) continue; // requiredOnly flag if (requiredOnly && hasRequired && !isRequired) continue; // count writable attributes if (!readOnly && !isRuntime) numWritable++; // ------- // help helpTexts.appendHtmlConstant("<tr class='help-field-row'>"); helpTexts.appendHtmlConstant("<td class='help-field-name'>"); helpTexts.appendEscaped(label).appendEscaped(": "); helpTexts.appendHtmlConstant("</td>"); helpTexts.appendHtmlConstant("<td class='help-field-desc'>"); try { String descWorkaround = attrDesc.get("description").asString(); helpTexts.appendHtmlConstant(descWorkaround.equals("null") ? "n/a" : descWorkaround); } catch (Throwable e) { // ignore parse errors helpTexts.appendHtmlConstant("<i>Failed to parse description</i>"); } helpTexts.appendHtmlConstant("</td>"); helpTexts.appendHtmlConstant("</tr>"); FormItem formItem = null; // explicitly created form items (monkey patching) if (itemFactories.containsKey(attr.getName())) { formItem = itemFactories.get(attr.getName()).create(attr); } // not created by explicit factory if (null == formItem) { switch (type) { case BOOLEAN: formItem = new CheckBoxItem(attr.getName(), label); formItem.setRequired(isRequired); formItem.setEnabled(!readOnly && !isRuntime); break; case DOUBLE: formItem = new DoubleFormItem(attr.getName(), label); formItem.setRequired(isRequired); formItem.setEnabled(!readOnly && !isRuntime); break; case LONG: boolean allowNegativeValues = false; if (attrDesc.hasDefined("default")) allowNegativeValues = attrDesc.get("default").asLong() < 0; formItem = new NumberBoxItem(attr.getName(), label, allowNegativeValues); formItem.setRequired(isRequired); formItem.setEnabled(!readOnly && !isRuntime); break; case BIG_DECIMAL: formItem = new NumberBoxItem(attr.getName(), label); formItem.setRequired(isRequired); formItem.setEnabled(!readOnly && !isRuntime); break; case INT: if (attrDesc.hasDefined("min") && attrDesc.hasDefined("max")) { formItem = new NumberBoxItem( attr.getName(), label, attrDesc.get("min").asLong(), attrDesc.get("max").asLong()); } else { formItem = new NumberBoxItem(attr.getName(), label); } formItem.setRequired(isRequired); formItem.setEnabled(!readOnly && !isRuntime); break; case LIST: formItem = new ListItem(attr.getName(), label); formItem.setRequired(isRequired); formItem.setEnabled(!readOnly && !isRuntime); break; case STRING: if (attrDesc.get("allowed").isDefined()) { List<ModelNode> allowed = attrDesc.get("allowed").asList(); Set<String> allowedValues = new HashSet<String>(allowed.size()); for (ModelNode value : allowed) allowedValues.add(value.asString()); final boolean isNillable = attrDesc.hasDefined(NILLABLE) && attrDesc.get(NILLABLE).asBoolean(); ComboBoxItem combo = new ComboBoxItem(attr.getName(), label, isNillable); combo.setValueMap(allowedValues); combo.setEnabled(!readOnly && !isRuntime); combo.setRequired(isRequired); formItem = combo; } else { formItem = createSuggestBoxForCapabilityReference(attr, label, isRequired); if (formItem == null) { // there is no capability-reference TextBoxItem textBoxItem = new TextBoxItem(attr.getName(), label); textBoxItem.setAllowWhiteSpace(true); textBoxItem.setRequired(isRequired); textBoxItem.setEnabled(!readOnly && !isRuntime); formItem = textBoxItem; } } // TODO: Support for TextAreaItem break; case OBJECT: if (attrDesc.has("value-type") && attrDesc.get("value-type").asString().equals("STRING")) { PropertyListItem propList = new PropertyListItem(attr.getName(), label); propList.setRequired(isRequired); propList.setEnabled(!readOnly && !isRuntime); formItem = propList; break; } default: { unsupportedTypes.add(new String[] {attr.getName(), type.toString()}); Log.error("Unsupported ModelType " + type + ", attribute '" + attr.getName() + "'"); } } } if (formItem != null) { if (createMode) { if (isRequired && includeOptionals) requiredItems.add(formItem); else optionalItems.add(formItem); } else { requiredItems.add(formItem); } // attribute meta data attached to form item formItem.setMetadata(attrDesc); } } } // some resources already contain a name attribute FormItem nameItem = null; if (createMode) { for (FormItem item : requiredItems) { if ("name".equals(item.getName())) { nameItem = item; break; } } for (FormItem item : optionalItems) { if ("name".equals(item.getName())) { nameItem = item; break; } } } // remove so it can be prepended if (nameItem != null) { requiredItems.remove(nameItem); optionalItems.remove(nameItem); } // distinguish required and optional fields (createMode) if (requiredItems.isEmpty()) { // no required fields explicitly given, treat all fields as required if (createMode) { optionalItems.addFirst(new TextBoxItem("name", "Name", true)); numWritable++; } form.setFields(optionalItems.toArray(new FormItem[] {})); } else { if (createMode) { requiredItems.addFirst(new TextBoxItem("name", "Name", true)); numWritable++; } form.setFields(requiredItems.toArray(new FormItem[] {})); if (optionalItems.size() > 0) form.setFieldsInGroup( "Optional Fields", new DisclosureGroupRenderer(), optionalItems.toArray(new FormItem[] {})); } // form meta data form.setDefaults(defaultValues); form.setHasWritableAttributes(numWritable > 0); FormAssets formAssets = new FormAssets(form, helpTexts.toSafeHtml()); formAssets.setUnsupportedTypes(unsupportedTypes); return formAssets; }
@Override public void setErroneous(boolean b) { super.setErroneous(b); wrapper.setErroneous(b); }
@Override public void resetMetaData() { super.resetMetaData(); textBox.setValue(null); }
@Override public void setFiltered(boolean filtered) { super.setFiltered(filtered); super.toggleAccessConstraint(textBox, filtered); textBox.setEnabled(!filtered); }