/* * RHQ Management Platform * Copyright (C) 2005-2014 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as * published by the Free Software Foundation, and/or the GNU Lesser * General Public License, version 2.1, also as published by the Free * Software Foundation. * * This program 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 General Public License and the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU General Public License * and the GNU Lesser General Public License along with this program; * if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.rhq.core.domain.configuration.definition; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.FetchType; import javax.persistence.OneToMany; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import org.hibernate.annotations.IndexColumn; import org.jetbrains.annotations.NotNull; import org.rhq.core.domain.configuration.definition.constraint.Constraint; import org.rhq.core.domain.measurement.MeasurementUnits; /** * Defines a simple property. * * @author Jason Dobies * @author Greg Hinkle * @author Ian Springer */ @DiscriminatorValue("property") @Entity(name = "PropertyDefinitionSimple") @XmlRootElement(name = "PropertyDefinitionSimple") @XmlAccessorType(XmlAccessType.FIELD) public class PropertyDefinitionSimple extends PropertyDefinition { private static final long serialVersionUID = 1L; @Column(name = "SIMPLE_TYPE") @Enumerated(EnumType.STRING) private PropertySimpleType type; @Column(name = "ALLOW_CUSTOM_ENUM_VALUE") private boolean allowCustomEnumeratedValue = false; @OneToMany(mappedBy = "propertyDefinitionSimple", cascade = { CascadeType.ALL }, fetch = FetchType.EAGER, orphanRemoval = true) private Set<Constraint> constraints = null; /** * The <options> within <property-options> for a <simple-property> */ @IndexColumn(name = "order_index") @OneToMany(mappedBy = "propertyDefinitionSimple", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true) private List<PropertyDefinitionEnumeration> enumeratedValues = null; /** * This property's default value. This field should have a non-null value for properties whose * {@link PropertyDefinition#required} field is <code>false</code> (i.e. for optional properties). Conversely, this * field should be null for properties whose {@link PropertyDefinition#required} field is <code>true</code> (i.e. for * required properties). * * This field is mainly used to help build default templates. You usually do not want to use this * default value member variable directly - consider using the configuration definition's default template. */ @Column(name = "DEFAULT_VALUE", length = 2000) private String defaultValue; /** * Measurement unit in which this simple property is taken */ @Enumerated(EnumType.ORDINAL) private MeasurementUnits units; @OneToMany(mappedBy = "propertyDefinition", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true) List<PropertyOptionsSource> optionsSource = null; public PropertyDefinitionSimple(@NotNull String name, String description, boolean required, @NotNull PropertySimpleType type) { super(name, description, required); this.type = type; } protected PropertyDefinitionSimple() { // JPA use } public PropertySimpleType getType() { return type; } public void setType(PropertySimpleType type) { this.type = type; } /** * Return all the constraints on this simple-property no matter how they are grouped together in the XML. * * @return the constraints, not null */ @NotNull public Set<Constraint> getConstraints() { if (this.constraints == null) { return Collections.EMPTY_SET; } return this.constraints; } public void setConstraints(Set<Constraint> constraints) { // Don't replace the possible Hibernate proxy when orphanRemoval=true. It can cause // "collection with cascade=all-delete-orphan was no longer referenced" exceptions. if (constraints == null || constraints.isEmpty()) { if (null != this.constraints) { this.constraints.clear(); } return; } if (this.constraints == null) { this.constraints = new HashSet<Constraint>(constraints.size()); } for (Constraint constraint : constraints) { getConstraints().add(constraint); constraint.setPropertyDefinitionSimple(this); } } public void addConstraints(Constraint... constraintsToAdd) { if (this.constraints == null) { this.constraints = new HashSet<Constraint>(constraintsToAdd.length); } for (Constraint constraint : constraintsToAdd) { getConstraints().add(constraint); constraint.setPropertyDefinitionSimple(this); } } /** * Get the <options> within <property-options> for a <simple-property> * @return not null */ @NotNull public List<PropertyDefinitionEnumeration> getEnumeratedValues() { if (this.enumeratedValues == null) { return new ArrayList<PropertyDefinitionEnumeration>(1); } return this.enumeratedValues; } public void setEnumeratedValues(List<PropertyDefinitionEnumeration> enumeratedValues, boolean allowCustomEnumValue) { addEnumeratedValues(enumeratedValues.toArray(new PropertyDefinitionEnumeration[enumeratedValues.size()])); this.allowCustomEnumeratedValue = allowCustomEnumValue; ensureOrdering(); } public void addEnumeratedValues(PropertyDefinitionEnumeration... enumerations) { if (this.enumeratedValues == null) { this.enumeratedValues = new ArrayList<PropertyDefinitionEnumeration>(1); } for (PropertyDefinitionEnumeration enumeration : enumerations) { enumeration.setPropertyDefinitionSimple(this); getEnumeratedValues().add(enumeration); } ensureOrdering(); } public void removeEnumeratedValues(PropertyDefinitionEnumeration... enumerations) { // Don't replace the possible Hibernate proxy when orphanRemoval=true. It can cause // "collection with cascade=all-delete-orphan was no longer referenced" exceptions. for (PropertyDefinitionEnumeration enumeration : enumerations) { getEnumeratedValues().remove(enumeration); } ensureOrdering(); } private void ensureOrdering() { if (null == this.enumeratedValues) { return; } for (int i = 0, size = getEnumeratedValues().size(); (i < size); ++i) { getEnumeratedValues().get(i).setOrderIndex(i); } } /** * If <code>false</code> and this simple property has {@link #getEnumeratedValues() enumerated values} defined, then * the value of the simple property <b>must</b> be one of the enumerated values. If <code>true</code>, then the * value of this simple property is not required to be one of the enumerated values - a user can opt to set the * value to some other custom value. This is useful, for example, when a property has an enumerated list of common * JDBC drivers but allows a user to enter their own custom JDBC driver if not one of the common drivers given in * the enumerated list. * * <p>Note that this flag has no effect if there are no enumerated values defined for this simple property.</p> * * @return flag to indicate if the property value is not restricted to one of the enumerated values */ public boolean getAllowCustomEnumeratedValue() { return this.allowCustomEnumeratedValue; } /** * See {@link #getAllowCustomEnumeratedValue()} for a description of this flag. * * @param allowCustomEnumValue */ public void setAllowCustomEnumeratedValue(boolean allowCustomEnumValue) { this.allowCustomEnumeratedValue = allowCustomEnumValue; } /** * Returns the default value that this property definition defines for its * value. Note, however, you rarely want to use this directly. Under most * circumstances, you should be using the configuration definition's * {@link ConfigurationDefinition#getDefaultTemplate() default template}. * * For an example of where this method is useful, see * org.rhq.core.clientapi.agent.configuration.ConfigurationUtility.initializeDefaultTemplate(ConfigurationDefinition) * * @return property default value */ public String getDefaultValue() { return defaultValue; } /** * Sets the default value for this property. Note that you normally call this * only at times when you plan on building default templates with this * property definition later. See {@link #getDefaultValue()} for more details * on this default value. * * @param defaultValue */ public void setDefaultValue(String defaultValue) { this.defaultValue = defaultValue; } public MeasurementUnits getUnits() { return units; } public void setUnits(MeasurementUnits units) { this.units = units; } public PropertyOptionsSource getOptionsSource() { if (optionsSource == null || optionsSource.isEmpty()) return null; return optionsSource.get(0); } public void setOptionsSource(PropertyOptionsSource source) { if (this.optionsSource == null) { optionsSource = new ArrayList<PropertyOptionsSource>(1); } this.optionsSource.clear(); if (source == null) return; source.propertyDefinition = this; this.optionsSource.add(source); } public boolean shouldBeObfuscated() { return getType() == PropertySimpleType.PASSWORD; } @Override public String toString() { return "SimpleProperty[" + getName() + "] (Type: " + getType() + ")" + ((getPropertyGroupDefinition() != null) ? ("(Group: " + getPropertyGroupDefinition().getName() + ")") : ""); } }