/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.controller;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jboss.as.controller.access.management.AccessConstraintDefinition;
import org.jboss.as.controller.capability.RuntimeCapability;
import org.jboss.as.controller.client.helpers.MeasurementUnit;
import org.jboss.as.controller.operations.validation.ParameterValidator;
import org.jboss.as.controller.registry.AttributeAccess;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
/**
* Provides a builder API for creating an {@link org.jboss.as.controller.AttributeDefinition}.
*
* @param <BUILDER> the specific subclass type returned by the various builder API methods
* @param <ATTRIBUTE> the type of {@link org.jboss.as.controller.AttributeDefinition} produced by the {@link #build()} method
*
* @author Tomaz Cerar
*/
@SuppressWarnings("unchecked")
public abstract class AbstractAttributeDefinitionBuilder<BUILDER extends AbstractAttributeDefinitionBuilder, ATTRIBUTE extends AttributeDefinition> {
protected String name;
protected ModelType type;
protected String xmlName;
protected boolean allowNull;
protected boolean allowExpression;
protected ModelNode defaultValue;
protected MeasurementUnit measurementUnit;
protected String[] alternatives;
protected String[] requires;
protected ModelNode[] allowedValues;
protected ParameterCorrector corrector;
protected ParameterValidator validator;
protected boolean validateNull = true;
protected int minSize = 0;
private boolean minSizeSet;
protected int maxSize = Integer.MAX_VALUE;
private boolean maxSizeSet;
protected AttributeAccess.Flag[] flags;
protected AttributeMarshaller attributeMarshaller = null;
protected boolean resourceOnly = false;
protected DeprecationData deprecated = null;
protected AccessConstraintDefinition[] accessConstraints;
protected Boolean nullSignificant;
protected AttributeParser parser;
protected String attributeGroup;
protected CapabilityReferenceRecorder referenceRecorder;
protected Map<String, ModelNode> arbitraryDescriptors = null;
private ModelNode undefinedMetricValue;
private static AccessConstraintDefinition[] ZERO_CONSTRAINTS = new AccessConstraintDefinition[0];
/**
* Creates a builder for an attribute with the give name and type. Equivalent to
* {@link #AbstractAttributeDefinitionBuilder(String, org.jboss.dmr.ModelType, boolean) AbstractAttributeDefinitionBuilder(attributeName, type, false}
* @param attributeName the {@link AttributeDefinition#getName() name} of the attribute. Cannot be {@code null}
* @param type the {@link AttributeDefinition#getType() type} of the attribute. Cannot be {@code null}
*/
public AbstractAttributeDefinitionBuilder(final String attributeName, final ModelType type) {
this(attributeName, type, false);
}
/**
* Creates a builder for an attribute with the give name and type and nullability setting.
* @param attributeName the {@link AttributeDefinition#getName() name} of the attribute. Cannot be {@code null}
* @param type the {@link AttributeDefinition#getType() type} of the attribute. Cannot be {@code null}
* @param optional {@code true} if the attribute {@link AttributeDefinition#isAllowNull() allows undefined values} in the absence of {@link #setAlternatives(String...) alternatives}
*/
public AbstractAttributeDefinitionBuilder(final String attributeName, final ModelType type, final boolean optional) {
this.name = attributeName;
this.type = type;
this.allowNull = optional;
this.xmlName = name;
}
/**
* Creates a builder populated with the values of an existing attribute definition.
*
* @param basis the existing attribute definition. Cannot be {@code null}
*/
public AbstractAttributeDefinitionBuilder(final AttributeDefinition basis) {
this(null, basis);
}
/**
* Creates a builder populated with the values of an existing attribute definition, with an optional
* change of the attribute's name.
*
* @param attributeName the {@link AttributeDefinition#getName() name} of the attribute,
* or {@code null} if the name from {@code basis} should be used
* @param basis the existing attribute definition. Cannot be {@code null}
*/
public AbstractAttributeDefinitionBuilder(final String attributeName, final AttributeDefinition basis) {
this.name = attributeName != null ? attributeName : basis.getName();
this.xmlName = basis.getXmlName();
this.defaultValue = basis.getDefaultValue();
this.type = basis.getType();
this.allowNull = basis.isAllowNull();
this.allowExpression = basis.isAllowExpression();
this.measurementUnit = basis.getMeasurementUnit();
this.corrector = basis.getCorrector();
this.validator = basis.getValidator();
this.alternatives = basis.getAlternatives();
this.requires = basis.getRequires();
this.attributeMarshaller = basis.getAttributeMarshaller();
this.resourceOnly = basis.isResourceOnly();
this.deprecated = basis.getDeprecationData();
this.nullSignificant = basis.getNilSignificant();
List<AccessConstraintDefinition> acl = basis.getAccessConstraints();
this.accessConstraints = acl.toArray(new AccessConstraintDefinition[acl.size()]);
this.parser = basis.getParser();
Set<AttributeAccess.Flag> basisFlags = basis.getFlags();
this.flags = basisFlags.toArray(new AttributeAccess.Flag[basisFlags.size()]);
if (basis.getAllowedValues().size() > 0) {
List<ModelNode> basisAllowedValues = basis.getAllowedValues();
this.allowedValues = basisAllowedValues.toArray(new ModelNode[basisAllowedValues.size()]);
}
this.attributeGroup = basis.getAttributeGroup();
if(!basis.getArbitraryDescriptors().isEmpty()) {
this.arbitraryDescriptors = new HashMap<>(basis.getArbitraryDescriptors().size());
this.arbitraryDescriptors.putAll(basis.getArbitraryDescriptors());
}
this.referenceRecorder = basis.getReferenceRecorder();
}
/**
* Create the {@link org.jboss.as.controller.AttributeDefinition}
* @return the attribute definition. Will not return {@code null}
*/
public abstract ATTRIBUTE build();
/**
* Sets the {@link AttributeDefinition#getName() name} for the attribute, which is only needed
* if the attribute was created from an existing {@link SimpleAttributeDefinition} using
* {@link SimpleAttributeDefinitionBuilder#create(org.jboss.as.controller.SimpleAttributeDefinition)}
* method.
*
* @param name the attribute's name. {@code null} is not allowed
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setName(String name) {
assert name != null;
this.name = name;
return (BUILDER) this;
}
/**
* Sets the {@link AttributeDefinition#getXmlName() xml name} for the attribute, which is only needed
* if the name used for the attribute is different from its ordinary
* {@link AttributeDefinition#getName() name in the model}. If not set the default value is the name
* passed to the builder constructor.
*
* @param xmlName the xml name. {@code null} is allowed
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setXmlName(String xmlName) {
this.xmlName = xmlName == null ? this.name : xmlName;
return (BUILDER) this;
}
/**
* Sets the {@link AttributeDefinition#getType() type} for the attribute.
* @param type the type. {@code null} is not allowed
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setType(ModelType type) {
this.type = type;
return (BUILDER) this;
}
/**
* Sets whether the attribute should {@link AttributeDefinition#isRequired() require a defined value}
* in the absence of {@link #setAlternatives(String...) alternatives}.
* If not set the default value is the value provided to the builder constructor, or {@code true}
* if no value is provided.
*
* @param required {@code true} if undefined values should not be allowed in the absence of alternatives
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setRequired(boolean required) {
this.allowNull = !required;
return (BUILDER) this;
}
/**
* Inverse of the preferred {@link #setRequired(boolean)}; sets whether the attribute should
* {@link AttributeDefinition#isAllowNull() allow undefined values}
* in the absence of {@link #setAlternatives(String...) alternatives}.
* If not set the default value is the value provided to the builder constructor, or {@code false}
* if no value is provided.
*
* @param allowNull {@code true} if undefined values should be allowed in the absence of alternatives
* @return a builder that can be used to continue building the attribute definition
*
* @deprecated use {@link #setRequired(boolean)}
*/
@Deprecated
public BUILDER setAllowNull(boolean allowNull) {
this.allowNull = allowNull;
return (BUILDER) this;
}
/**
* Sets whether the attribute should {@link AttributeDefinition#isAllowExpression() allow expressions}
* If not set the default value is {@code false}.
*
* @param allowExpression {@code true} if expression values should be allowed
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setAllowExpression(boolean allowExpression) {
this.allowExpression = allowExpression;
return (BUILDER) this;
}
/**
* Sets a {@link AttributeDefinition#getDefaultValue() default value} to use for the attribute if no
* user-provided value is available.
* @param defaultValue the default value, or {@code null} if no default should be used
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setDefaultValue(ModelNode defaultValue) {
this.defaultValue = (defaultValue == null || !defaultValue.isDefined()) ? null : defaultValue;
return (BUILDER) this;
}
/**
* Sets a {@link AttributeDefinition#getMeasurementUnit() measurement unit} to describe the unit in
* which a numeric attribute is expressed.
* @param unit the unit. {@code null} is allowed
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setMeasurementUnit(MeasurementUnit unit) {
this.measurementUnit = unit;
return (BUILDER) this;
}
/**
* Sets a {@link org.jboss.as.controller.ParameterCorrector} to use to adjust any user provided values
* before {@link org.jboss.as.controller.AttributeDefinition#validateOperation(org.jboss.dmr.ModelNode, boolean) validation}
* occurs.
* @param corrector the corrector. May be {@code null}
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setCorrector(ParameterCorrector corrector) {
this.corrector = corrector;
return (BUILDER) this;
}
/**
* Sets the validator that should be used to validate attribute values. The resulting attribute definition
* will wrap this validator in one that enforces the attribute's
* {@link AttributeDefinition#isAllowNull() allow null} and
* {@link AttributeDefinition#isAllowExpression() allow expression} settings, so the given {@code validator}
* need not be properly configured for those validations.
* @param validator the validator. {@code null} is allowed
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setValidator(ParameterValidator validator) {
this.validator = validator;
return (BUILDER) this;
}
/**
* Has no effect. The behavior of {@link AttributeDefinition} now is to allow undefined values
* for {@link #setRequired(boolean) required} attributes if alternatives have been declared via
* {@link #setAlternatives(String...)} or {@link #addAlternatives(String...)}. Handling such
* situations was the original purpose for this setting.
*
* @param validateNull ignored
* @return a builder that can be used to continue building the attribute definition
*
* @deprecated has no effect
*/
@Deprecated
public BUILDER setValidateNull(boolean validateNull) {
this.validateNull = validateNull;
return (BUILDER) this;
}
/**
* Sets {@link AttributeDefinition#getAlternatives() names of alternative attributes} that should not
* be defined if this attribute is defined.
* @param alternatives the attribute names
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setAlternatives(String... alternatives) {
this.alternatives = alternatives;
return (BUILDER) this;
}
/**
* Adds {@link AttributeDefinition#getAlternatives() names of alternative attributes} that should not
* be defined if this attribute is defined.
* @param alternatives the attribute names
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER addAlternatives(String... alternatives) {
if (this.alternatives == null) {
this.alternatives = alternatives;
} else {
String[] newAlternatives = Arrays.copyOf(this.alternatives, this.alternatives.length + alternatives.length);
System.arraycopy(alternatives, 0, newAlternatives, this.alternatives.length, alternatives.length);
this.alternatives = newAlternatives;
}
return (BUILDER) this;
}
/**
* Adds {@link AttributeDefinition#getArbitraryDescriptors() arbitrary descriptor}.
* @param arbitraryDescriptor the arbitrary descriptor name.
* @param value the value of the arbitrary descriptor.
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER addArbitraryDescriptor(String arbitraryDescriptor, ModelNode value) {
if (this.arbitraryDescriptors == null) {
this.arbitraryDescriptors = new HashMap<>();
}
arbitraryDescriptors.put(arbitraryDescriptor, value);
return (BUILDER) this;
}
public Map<String, ModelNode> getArbitraryDescriptors() {
return arbitraryDescriptors;
}
/**
* Sets {@link AttributeDefinition#getRequires() names of required attributes} that must
* be defined if this attribute is defined.
* @param requires the attribute names
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setRequires(String... requires) {
this.requires = requires;
return (BUILDER) this;
}
/**
* Sets the {@link AttributeAccess.Flag special purpose flags} that are relevant to the attribute
* @param flags the flags
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setFlags(AttributeAccess.Flag... flags) {
this.flags = flags;
return (BUILDER) this;
}
/**
* Adds a {@link AttributeAccess.Flag special purpose flag} that is relevant to the attribute
* @param flag the flag
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER addFlag(final AttributeAccess.Flag flag) {
if (flags == null) {
flags = new AttributeAccess.Flag[]{flag};
} else {
final int i = flags.length;
flags = Arrays.copyOf(flags, i + 1);
flags[i] = flag;
}
return (BUILDER) this;
}
/**
* Removes a {@link AttributeAccess.Flag special purpose flag} from the set of those relevant to the attribute
* @param flag the flag
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER removeFlag(final AttributeAccess.Flag flag) {
if (!isFlagPresent(flag)) {
return (BUILDER) this; //if not present no need to remove
}
if (flags != null && flags.length > 0) {
final int length = flags.length;
final AttributeAccess.Flag[] newFlags = new AttributeAccess.Flag[length - 1];
int k = 0;
for (AttributeAccess.Flag flag1 : flags) {
if (flag1 != flag) {
newFlags[k] = flag1;
k++;
}
}
if (k != length - 1) {
flags = newFlags;
}
}
return (BUILDER) this;
}
/**
* Checks if a {@link AttributeAccess.Flag special purpose flag} has been recorded as relevant to the attribute
* @param flag the flag
* @return a builder that can be used to continue building the attribute definition
*/
protected boolean isFlagPresent(final AttributeAccess.Flag flag) {
if (flags == null) { return false; }
for (AttributeAccess.Flag f : flags) {
if (f.equals(flag)) { return true; }
}
return false;
}
/**
* Adds the {@link AttributeAccess.Flag#STORAGE_RUNTIME} flag and removes any conflicting flag.
*
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setStorageRuntime() {
removeFlag(AttributeAccess.Flag.STORAGE_CONFIGURATION);
return addFlag(AttributeAccess.Flag.STORAGE_RUNTIME);
}
/**
* Adds the {@link AttributeAccess.Flag#RUNTIME_SERVICE_NOT_REQUIRED} flag.
*
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setRuntimeServiceNotRequired() {
return addFlag(AttributeAccess.Flag.RUNTIME_SERVICE_NOT_REQUIRED);
}
/**
* Adds the {@link AttributeAccess.Flag#RESTART_ALL_SERVICES} flag and removes any conflicting flag.
*
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setRestartAllServices() {
removeFlag(AttributeAccess.Flag.RESTART_NONE);
removeFlag(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES);
removeFlag(AttributeAccess.Flag.RESTART_JVM);
return addFlag(AttributeAccess.Flag.RESTART_ALL_SERVICES);
}
/**
* Adds the {@link AttributeAccess.Flag#RESTART_JVM} flag and removes any conflicting flag.
*
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setRestartJVM() {
removeFlag(AttributeAccess.Flag.RESTART_NONE);
removeFlag(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES);
removeFlag(AttributeAccess.Flag.RESTART_ALL_SERVICES);
return addFlag(AttributeAccess.Flag.RESTART_JVM);
}
/**
* Sets a maximum size for a collection-type attribute or one whose value is a string or byte[].
* The value represents the maximum number of elements in the collection, or the maximum length of
* the string or array. <strong>It does not represent a maximum value for a numeric attribute and should
* not be configured for numeric attributes.</strong>
* @param maxSize the maximum size
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setMaxSize(final int maxSize) {
this.maxSize = maxSize;
this.maxSizeSet = true;
return (BUILDER) this;
}
/**
* Gets the {@link #getMaxSize() max size} if {@link #setMaxSize(int)} has been called, otherwise {@code null}.
* This is a workaround needed because maxSize is protected, preventing changing its type to Integer to allow null
* values needed to discriminate unconfigured defaults from configured values that match the default.
* @return the minimum size or {@code null} if it was not explicitly set
*/
Integer getConfiguredMaxSize() {
return maxSizeSet ? maxSize : null;
}
/**
* Sets a minimum size description for a collection-type attribute or one whose value is a string or byte[].
* The value represents the minimum number of elements in the collection, or the minimum length of
* the string or array. <strong>It does not represent a minimum value for a numeric attribute and should
* not be configured for numeric attributes.</strong>
* @param minSize the minimum size
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setMinSize(final int minSize) {
this.minSize = minSize;
this.minSizeSet = true;
return (BUILDER) this;
}
/**
* Gets the {@link #getMinSize() min size} if {@link #setMinSize(int)} has been called, otherwise {@code null}.
* This is a workaround needed because minSize is protected, preventing changing its type to Integer to allow null
* values needed to discriminate unconfigured defaults from configured values that match the default.
* @return the minimum size or {@code null} if it was not explicitly set
*/
Integer getConfiguredMinSize() {
return minSizeSet ? minSize : null;
}
/**
* Sets a custom {@link org.jboss.as.controller.AttributeMarshaller} to use for marshalling the attribute to xml.
* If not set, a {@link org.jboss.as.controller.DefaultAttributeMarshaller} will be used.
* @param marshaller the marshaller. Can be {@code null}
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setAttributeMarshaller(AttributeMarshaller marshaller) {
this.attributeMarshaller = marshaller;
return (BUILDER) this;
}
/**
* Sets a custom {@link org.jboss.as.controller.AttributeParser} to use for parsing attribute from xml.
* If not set, a {@link org.jboss.as.controller.AttributeParser#SIMPLE} will be used.
* @param parser the parser. Can be {@code null}
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setAttributeParser(AttributeParser parser) {
this.parser = parser;
return (BUILDER) this;
}
/**
* Marks an attribute as only relevant to a resource, and not a valid parameter to an "add" operation that
* creates that resource. Typically used for legacy "name" attributes that display the final value in the
* resource's address as an attribute.
*
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setResourceOnly() {
this.resourceOnly = true;
return (BUILDER) this;
}
/**
* Marks the attribute as deprecated since the given API version. This is equivalent to calling
* {@link #setDeprecated(ModelVersion, boolean)} with the {@code notificationUseful} parameter
* set to {@code true}.
*
* @param since the API version, with the API being the one (core or a subsystem) in which the attribute is used
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setDeprecated(ModelVersion since) {
return setDeprecated(since, true);
}
/**
* Marks the attribute as deprecated since the given API version, with the ability to configure that
* notifications to the user (e.g. via a log message) about deprecation of the attribute should not be emitted.
* Notifying the user should only be done if the user can take some action in response. Advising that
* something will be removed in a later release is not useful if there is no alternative in the
* current release. If the {@code notificationUseful} param is {@code true} the text
* description of the attribute deprecation available from the {@code read-resource-description}
* management operation should provide useful information about how the user can avoid using
* the attribute.
*
* @param since the API version, with the API being the one (core or a subsystem) in which the attribute is used
* @param notificationUseful whether actively advising the user about the deprecation is useful
*
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setDeprecated(ModelVersion since, boolean notificationUseful) {
this.deprecated = new DeprecationData(since, notificationUseful);
return (BUILDER) this;
}
/**
* Sets access constraints to use with the attribute
* @param accessConstraints the constraints
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setAccessConstraints(AccessConstraintDefinition... accessConstraints) {
this.accessConstraints = accessConstraints;
return (BUILDER) this;
}
/**
* Adds an access constraint to the set used with the attribute
* @param accessConstraint the constraint
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER addAccessConstraint(final AccessConstraintDefinition accessConstraint) {
if (accessConstraints == null) {
accessConstraints = new AccessConstraintDefinition[] {accessConstraint};
} else {
accessConstraints = Arrays.copyOf(accessConstraints, accessConstraints.length + 1);
accessConstraints[accessConstraints.length - 1] = accessConstraint;
}
return (BUILDER) this;
}
/**
* Sets whether an access control check is required to implicitly set an attribute to {@code undefined}
* in a resource "add" operation. "Implicitly" setting an attribute refers to not providing a value for
* it in the add operation, leaving the attribute in an undefined state. If not set
* the default value is whether the attribute {@link AttributeDefinition#isRequired()} () is not required} and
* has a {@link AttributeDefinition#getDefaultValue() default value}.
*
* @param nullSignificant {@code true} if an undefined value is significant
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setNullSignificant(boolean nullSignificant) {
this.nullSignificant = nullSignificant;
return (BUILDER) this;
}
/**
* @deprecated Use {@link #setNullSignificant(boolean)}.
*/
@Deprecated
public BUILDER setNullSignficant(boolean nullSignficant) {
return setNullSignificant(nullSignficant);
}
/**
* Sets the name of the attribute group with which this attribute is associated.
*
* @param attributeGroup the attribute group name. Cannot be an empty string but can be {@code null}
* if the attribute is not associated with a group.
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setAttributeGroup(String attributeGroup) {
assert attributeGroup == null || attributeGroup.length() > 0;
this.attributeGroup = attributeGroup;
return (BUILDER) this;
}
/**
* Sets allowed values for attribute
*
* @param allowedValues values that are legal as part in this attribute
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setAllowedValues(ModelNode ... allowedValues) {
assert allowedValues!= null;
this.allowedValues = allowedValues;
return (BUILDER) this;
}
/**
* Sets allowed values for attribute
*
* @param allowedValues values that are legal as part in this attribute
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setAllowedValues(String ... allowedValues) {
assert allowedValues!= null;
this.allowedValues = new ModelNode[allowedValues.length];
for (int i = 0; i < allowedValues.length; i++) {
this.allowedValues[i] = new ModelNode(allowedValues[i]);
}
return (BUILDER) this;
}/**
* Sets allowed values for attribute
*
* @param allowedValues values that are legal as part in this attribute
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setAllowedValues(int ... allowedValues) {
assert allowedValues!= null;
this.allowedValues = new ModelNode[allowedValues.length];
for (int i = 0; i < allowedValues.length; i++) {
this.allowedValues[i] = new ModelNode(allowedValues[i]);
}
return (BUILDER) this;
}
/**
* Records that this attribute's value represents a reference to an instance of a
* {@link org.jboss.as.controller.capability.RuntimeCapability#isDynamicallyNamed() dynamic capability}.
* <p>
* This method is a convenience method equivalent to calling
* {@link #setCapabilityReference(CapabilityReferenceRecorder)}
* passing in a {@link org.jboss.as.controller.CapabilityReferenceRecorder.DefaultCapabilityReferenceRecorder}
* constructed using the parameters passed to this method.
*
* @param referencedCapability the name of the dynamic capability the dynamic portion of whose name is
* represented by the attribute's value
* @param dependentCapability the capability that depends on {@code referencedCapability}
* @return the builder
* @see SimpleAttributeDefinition#addCapabilityRequirements(OperationContext, ModelNode)
* @see SimpleAttributeDefinition#removeCapabilityRequirements(OperationContext, ModelNode)
*/
public BUILDER setCapabilityReference(String referencedCapability, RuntimeCapability<?> dependentCapability) {
return setCapabilityReference(referencedCapability, dependentCapability.getName(), dependentCapability.isDynamicallyNamed());
}
/**
* Records that this attribute's value represents a reference to an instance of a
* {@link org.jboss.as.controller.capability.RuntimeCapability#isDynamicallyNamed() dynamic capability}.
* <p>
* This method is a convenience method equivalent to calling
* {@link #setCapabilityReference(CapabilityReferenceRecorder)}
* passing in a {@link CapabilityReferenceRecorder.ContextDependencyRecorder}
* constructed using the parameters passed to this method.
* <p>
* <strong>NOTE:</strong> This method of recording capability references is only suitable for use in attributes
* only used in resources that themselves expose a single capability. When the capability requirement
* is registered, the dependent capability will be that capability.
*
* @param referencedCapability the name of the dynamic capability the dynamic portion of whose name is
* represented by the attribute's value
* @return the builder
* @see SimpleAttributeDefinition#addCapabilityRequirements(OperationContext, ModelNode)
* @see SimpleAttributeDefinition#removeCapabilityRequirements(OperationContext, ModelNode)
*/
public BUILDER setCapabilityReference(String referencedCapability) {
referenceRecorder = new CapabilityReferenceRecorder.ContextDependencyRecorder(referencedCapability);
return (BUILDER) this;
}
/**
* Records that this attribute's value represents a reference to an instance of a
* {@link org.jboss.as.controller.capability.RuntimeCapability#isDynamicallyNamed() dynamic capability}.
* <p>
* This method is a convenience method equivalent to calling
* {@link #setCapabilityReference(CapabilityReferenceRecorder)}
* passing in a {@link org.jboss.as.controller.CapabilityReferenceRecorder.DefaultCapabilityReferenceRecorder}
* constructed using the parameters passed to this method.
*
* @param referencedCapability the name of the dynamic capability the dynamic portion of whose name is
* represented by the attribute's value
* @param dependentCapability the name of the capability that depends on {@code referencedCapability}
* @param dynamicDependent {@code true} if {@code dependentCapability} is a dynamic capability, the dynamic
* portion of which comes from the name of the resource with which
* the attribute is associated
* @return the builder
* @see SimpleAttributeDefinition#addCapabilityRequirements(OperationContext, ModelNode)
* @see SimpleAttributeDefinition#removeCapabilityRequirements(OperationContext, ModelNode)
*/
public BUILDER setCapabilityReference(String referencedCapability, String dependentCapability, boolean dynamicDependent) {
referenceRecorder = new CapabilityReferenceRecorder.DefaultCapabilityReferenceRecorder(referencedCapability, dependentCapability, dynamicDependent);
return (BUILDER) this;
}
/**
* Records that this attribute's value represents a reference to an instance of a
* {@link org.jboss.as.controller.capability.RuntimeCapability#isDynamicallyNamed() dynamic capability} and assigns the
* object that should be used to handle adding and removing capability requirements.
*
* @param referenceRecorder recorder to handle adding and removing capability requirements. May be {@code null}
* @return the builder
*
* @see SimpleAttributeDefinition#addCapabilityRequirements(OperationContext, ModelNode)
* @see SimpleAttributeDefinition#removeCapabilityRequirements(OperationContext, ModelNode)
*/
public BUILDER setCapabilityReference(CapabilityReferenceRecorder referenceRecorder) {
this.referenceRecorder = referenceRecorder;
return (BUILDER)this;
}
/**
* Sets a {@link AttributeDefinition#getUndefinedMetricValue() default value} to use for the
* metric if no runtime value is available (e.g. we are a server running in admin-only mode).
*
* @param undefinedMetricValue the default value, or {@code null} if no default should be used
* @return a builder that can be used to continue building the attribute definition
*/
public BUILDER setUndefinedMetricValue(ModelNode undefinedMetricValue) {
this.undefinedMetricValue = (undefinedMetricValue == null || !undefinedMetricValue.isDefined()) ? null : undefinedMetricValue;
return (BUILDER) this;
}
public String getName() {
return name;
}
public ModelType getType() {
return type;
}
public String getXmlName() {
return xmlName;
}
public boolean isAllowNull() {
return allowNull;
}
public boolean isAllowExpression() {
return allowExpression;
}
public ModelNode getDefaultValue() {
return defaultValue;
}
public MeasurementUnit getMeasurementUnit() {
return measurementUnit;
}
public String[] getAlternatives() {
return copyStrings(alternatives);
}
public String[] getRequires() {
return copyStrings(requires);
}
public ParameterCorrector getCorrector() {
return corrector;
}
public ParameterValidator getValidator() {
return validator;
}
/** @deprecated meaningless and not used. */
@Deprecated
public boolean isValidateNull() {
return validateNull;
}
public int getMinSize() {
return minSize;
}
public int getMaxSize() {
return maxSize;
}
public AttributeAccess.Flag[] getFlags() {
return copyFlags(flags);
}
public AttributeMarshaller getAttributeMarshaller() {
return attributeMarshaller;
}
public boolean isResourceOnly() {
return resourceOnly;
}
public DeprecationData getDeprecated() {
return deprecated;
}
public AccessConstraintDefinition[] getAccessConstraints() {
return copyConstraints(accessConstraints);
}
public Boolean getNullSignificant() {
return nullSignificant;
}
public ModelNode getUndefinedMetricValue() {
return undefinedMetricValue;
}
/**
* @deprecated Use {@link #getNullSignificant()}.
*/
@Deprecated
public Boolean getNullSignficant() {
return getNullSignificant();
}
public AttributeParser getParser() {
return parser;
}
public String getAttributeGroup() {
return attributeGroup;
}
public ModelNode[] getAllowedValues() {
return allowedValues;
}
private String[] copyStrings(String[] toCopy) {
if (toCopy == null) {
return null;
}
String[] result = new String[toCopy.length];
System.arraycopy(toCopy, 0, result, 0, toCopy.length);
return result;
}
private AttributeAccess.Flag[] copyFlags(AttributeAccess.Flag[] toCopy) {
if (toCopy == null) {
return null;
}
AttributeAccess.Flag[] result = new AttributeAccess.Flag[toCopy.length];
System.arraycopy(toCopy, 0, result, 0, toCopy.length);
return result;
}
private AccessConstraintDefinition[] copyConstraints(AccessConstraintDefinition[] toCopy) {
if (toCopy == null) {
return null;
}
if (toCopy.length == 0){
return ZERO_CONSTRAINTS;
}
AccessConstraintDefinition[] result = new AccessConstraintDefinition[toCopy.length];
System.arraycopy(toCopy, 0, result, 0, toCopy.length);
return result;
}
}