/* * RHQ Management Platform * Copyright (C) 2005-2013 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.resource; import java.io.Serializable; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EntityResult; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.NamedNativeQueries; import javax.persistence.NamedNativeQuery; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.OrderBy; import javax.persistence.PrePersist; import javax.persistence.PreUpdate; import javax.persistence.SequenceGenerator; import javax.persistence.SqlResultSetMapping; import javax.persistence.Table; import javax.persistence.Transient; import javax.xml.bind.annotation.XmlTransient; import org.rhq.core.domain.bundle.BundleType; import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; import org.rhq.core.domain.content.PackageType; import org.rhq.core.domain.drift.DriftDefinitionTemplate; import org.rhq.core.domain.event.EventDefinition; import org.rhq.core.domain.measurement.MeasurementDefinition; import org.rhq.core.domain.operation.OperationDefinition; import org.rhq.core.domain.resource.group.ResourceGroup; import org.rhq.core.domain.util.Summary; /** * Defines a type of {@link Resource} (e.g. a Linux platform, a JBossAS server, or a Datasource service). * Unique business key (and therefore equals/hashCode basis) is the (String name, String plugin) combination. * This will keep plugin writers from stepping on each other's toes. * * @author Greg Hinkle * @author Ian Springer */ @Entity @Table(name = ResourceType.TABLE_NAME) @SequenceGenerator(allocationSize = org.rhq.core.domain.util.Constants.ALLOCATION_SIZE, name = "RHQ_RESOURCE_TYPE_ID_SEQ", sequenceName = "RHQ_RESOURCE_TYPE_ID_SEQ") @NamedQueries( { @NamedQuery(name = ResourceType.QUERY_GET_BUNDLE_CONFIG_BY_GROUP_ID, query = "SELECT rg.resourceType.bundleConfiguration FROM ResourceGroup rg WHERE rg.id = :groupId"), @NamedQuery(name = ResourceType.QUERY_FIND_BY_PLUGIN, query = "SELECT rt FROM ResourceType AS rt " + "WHERE rt.plugin = :plugin AND rt.deleted = false"), @NamedQuery(name = ResourceType.QUERY_FIND_BY_NAME_AND_PLUGIN, // TODO: QUERY: names are case-sensitive query = "SELECT rt FROM ResourceType AS rt WHERE LOWER(rt.name) = LOWER(:name) AND rt.plugin = :plugin " + "AND rt.deleted = false"), @NamedQuery(name = ResourceType.QUERY_FIND_ALL, query = "SELECT rt FROM ResourceType AS rt where rt.deleted = false"), @NamedQuery(name = ResourceType.QUERY_FIND_BY_PARENT_AND_NAME, // TODO: QUERY: Not looking up by the full key, get rid of this query query = "SELECT rt FROM ResourceType AS rt WHERE :parent MEMBER OF rt.parentResourceTypes AND rt.name = :name " + "AND rt.deleted = false"), /* authz'ed queries for ResourceTypeManagerBean */ @NamedQuery(name = ResourceType.QUERY_FIND_CHILDREN, query = "SELECT c " + "FROM ResourceType rt JOIN rt.childResourceTypes c WHERE rt.id = :resourceTypeId AND rt.deleted = false " + "AND c.deleted = false"), @NamedQuery(name = ResourceType.FIND_CHILDREN_BY_PARENT, query = "SELECT DISTINCT rt FROM ResourceType AS rt " + "JOIN FETCH rt.parentResourceTypes AS pa " + // also fetch parents, as we need them later "WHERE rt.deleted = false and pa IN (:resourceType)"), @NamedQuery(name = ResourceType.FIND_ALL_TEMPLATE_COUNT_COMPOSITES, query = "" // + "SELECT new org.rhq.core.domain.resource.composite.ResourceTypeTemplateCountComposite" // + "(" // + " rt," // + " (SELECT COUNT(md) FROM MeasurementDefinition AS md WHERE md.resourceType = rt AND md.defaultOn = TRUE), "// + " (SELECT COUNT(md) FROM MeasurementDefinition AS md WHERE md.resourceType = rt AND md.defaultOn = FALSE), "// + " (SELECT COUNT(ad) FROM AlertDefinition AS ad WHERE ad.resourceType = rt AND ad.deleted = FALSE AND ad.enabled = TRUE), "// + " (SELECT COUNT(ad) FROM AlertDefinition AS ad WHERE ad.resourceType = rt AND ad.deleted = FALSE AND ad.enabled = FALSE), "// + " (SELECT COUNT(ddt) FROM DriftDefinitionTemplate AS ddt WHERE ddt.resourceType = rt AND ddt.isUserDefined = FALSE), "// + " (SELECT COUNT(ddt) FROM DriftDefinitionTemplate AS ddt WHERE ddt.resourceType = rt AND ddt.isUserDefined = TRUE) "// + ")" // + "FROM ResourceType AS rt WHERE rt.deleted = false"), @NamedQuery(name = ResourceType.QUERY_FIND_BY_CATEGORY, query = "SELECT rt FROM ResourceType AS rt " + "WHERE rt.category = :category and rt.deleted = false"), @NamedQuery(name = ResourceType.QUERY_FIND_UTILIZED_BY_CATEGORY, query = "SELECT DISTINCT res.resourceType " + "FROM Resource res, IN (res.implicitGroups) g, IN (g.roles) r, IN (r.subjects) s " // + "WHERE s = :subject " // + "AND res.resourceType.category = :category " + "AND res.resourceType.deleted = false " + "AND (UPPER(res.name) LIKE :nameFilter ESCAPE :escapeChar OR :nameFilter is null) " + "AND (res.resourceType.plugin = :pluginName OR :pluginName is null) " + "AND (:inventoryStatus = res.inventoryStatus OR :inventoryStatus is null) " + "ORDER BY res.resourceType.name "), @NamedQuery(name = ResourceType.QUERY_FIND_UTILIZED_BY_CATEGORY_admin, query = "SELECT DISTINCT res.resourceType " + "FROM Resource res " // + "WHERE res.resourceType.category = :category " + "AND (UPPER(res.name) LIKE :nameFilter ESCAPE :escapeChar OR :nameFilter is null) " + "AND res.resourceType.deleted = false " + "AND (res.resourceType.plugin = :pluginName OR :pluginName is null) " + "AND (:inventoryStatus = res.inventoryStatus OR :inventoryStatus is null) " + "ORDER BY res.resourceType.name "), @NamedQuery(name = ResourceType.QUERY_FIND_UTILIZED_CHILDREN_BY_CATEGORY, query = "SELECT DISTINCT res.resourceType " + "FROM Resource res, IN (res.implicitGroups) g, IN (g.roles) r, IN (r.subjects) s " + "WHERE s = :subject " + "AND res.parentResource = :parentResource " + "AND res.resourceType.category = :category " + "AND res.resourceType.deleted = false " + "AND (:inventoryStatus = res.inventoryStatus OR :inventoryStatus is null) "), @NamedQuery(name = ResourceType.QUERY_FIND_UTILIZED_CHILDREN_BY_CATEGORY_admin, query = "SELECT DISTINCT res.resourceType " + "FROM Resource res " + "WHERE res.parentResource = :parentResource " + "AND res.resourceType.deleted = false " + "AND res.resourceType.category = :category " + "AND (:inventoryStatus = res.inventoryStatus OR :inventoryStatus is null) "), @NamedQuery(name = ResourceType.QUERY_FIND_BY_RESOURCE_GROUP, query = "" // + "SELECT DISTINCT rt " // + " FROM ResourceGroup rg " // + " JOIN rg.resourceType rt" // + " JOIN rg.roles r JOIN r.subjects s " // + " WHERE s = :subject " // + " AND rt.deleted = false " + " AND ( rt.plugin = :pluginName OR :pluginName is null ) "), @NamedQuery(name = ResourceType.QUERY_FIND_BY_RESOURCE_GROUP_admin, query = "" // + "SELECT DISTINCT rt " // + " FROM ResourceGroup rg " // + " JOIN rg.resourceType rt" // + " WHERE rt.deleted = false AND ( rt.plugin = :pluginName OR :pluginName is null ) "), @NamedQuery(name = ResourceType.QUERY_GET_EXPLICIT_RESOURCE_TYPE_COUNTS_BY_GROUP, query = "" // + "SELECT type.id, type.name, COUNT(type.id) " // + " FROM ResourceGroup rg JOIN rg.explicitResources res JOIN res.resourceType type " // + " WHERE rg.id = :groupId AND res.resourceType.deleted = false AND res.inventoryStatus = 'COMMITTED' " // + " GROUP BY type.id, type.name "), @NamedQuery(name = ResourceType.QUERY_GET_IMPLICIT_RESOURCE_TYPE_COUNTS_BY_GROUP, query = "" // + "SELECT type.id, type.name, COUNT(type.id) " // + " FROM ResourceGroup rg JOIN rg.implicitResources res JOIN res.resourceType type " // + " WHERE rg.id = :groupId AND res.resourceType.deleted = false AND res.inventoryStatus = 'COMMITTED' " // + " GROUP BY type.id, type.name "), @NamedQuery(name = ResourceType.QUERY_FIND_BY_ID_WITH_ALL_OPERATIONS, query = "SELECT DISTINCT rt " + "FROM ResourceType rt " + "LEFT JOIN FETCH rt.operationDefinitions def " + "LEFT JOIN FETCH def.parametersConfigurationDefinition psDef " + "LEFT JOIN FETCH def.resultsConfigurationDefinition rcDef " + "WHERE rt.id = :id AND rt.deleted = false"), @NamedQuery(name = ResourceType.QUERY_FIND_RESOURCE_FACETS, query = "" // + "SELECT new org.rhq.core.domain.resource.composite.ResourceFacets " // + " ( " // + " rt.id," // the resourceTypeId + " (SELECT COUNT(metricDef) FROM rt.metricDefinitions metricDef)," // measurement + " (SELECT COUNT(eventDef) FROM rt.eventDefinitions eventDef)," // event + " (SELECT COUNT(pluginConfig) FROM rt.pluginConfigurationDefinition pluginConfig)," // pluginConfiguration + " (SELECT COUNT(resConfig) FROM rt.resourceConfigurationDefinition resConfig)," // configuration + " (SELECT COUNT(operationDef) FROM rt.operationDefinitions operationDef)," // operation + " (SELECT COUNT(packageType) FROM rt.packageTypes packageType)," // content + " (SELECT COUNT(metricDef) FROM rt.metricDefinitions metricDef WHERE metricDef.dataType = 3)," // calltime + " (SELECT COUNT(propDef) FROM rt.pluginConfigurationDefinition pluginConfig JOIN pluginConfig.propertyDefinitions propDef WHERE propDef.name = 'snapshotLogEnabled')," // + " (SELECT COUNT(driftDef) FROM rt.driftDefinitionTemplates driftDef)," // drift + " (SELECT COUNT(bundleConfig) FROM rt.bundleConfiguration bundleConfig)" // bundle + " ) " // + " FROM ResourceType rt " // + " WHERE rt.deleted = false AND ( rt.id = :resourceTypeId OR :resourceTypeId IS NULL )"), @NamedQuery(name = ResourceType.QUERY_FIND_DUPLICATE_TYPE_NAMES, query = "" // + " SELECT rt.name " // + " FROM ResourceType rt " // + " WHERE rt.deleted = false " + " GROUP BY rt.name " // + " HAVING COUNT(rt.name) > 1"), // @NamedQuery(name = ResourceType.QUERY_DYNAMIC_CONFIG_WITH_PLUGIN, query = "" // + "SELECT rt.plugin || ' - ' || rt.name, rt.plugin || '-' || rt.name FROM ResourceType rt WHERE rt.deleted = false"), // @NamedQuery(name = ResourceType.QUERY_MARK_TYPES_DELETED, query = "UPDATE ResourceType t SET t.deleted = true WHERE t.id IN (:resourceTypeIds)"), @NamedQuery(name = ResourceType.QUERY_FIND_IDS_BY_PLUGIN, query = "SELECT t.id FROM ResourceType t WHERE t.plugin = :plugin AND t.deleted = false"), @NamedQuery(name = ResourceType.QUERY_FIND_COUNT_BY_PLUGIN, query = "SELECT COUNT(t) FROM ResourceType t WHERE t.plugin = :plugin AND t.deleted = false") }) @NamedNativeQueries( { // TODO: Add authz conditions to the below query. @NamedNativeQuery(name = ResourceType.QUERY_FIND_CHILDREN_BY_CATEGORY, query = "" // + "(SELECT crt.id, crt.name, crt.category, crt.creation_data_type, crt.create_delete_policy, crt.singleton, crt.supports_manual_add, crt.description, crt.plugin, crt.ctime, crt.mtime, crt.deleted, crt.subcategory, crt.plugin_config_def_id, crt.res_config_def_id " + "FROM RHQ_resource_type crt, RHQ_resource res, RHQ_resource_type rt, RHQ_resource_type_parents rtp " + "WHERE res.id = ? " + "AND crt.deleted = false " + "AND res.resource_type_id = rt.id " + "AND rt.id = rtp.parent_resource_type_id " + "AND rtp.resource_type_id = crt.id " + "AND crt.category = ? " + // "ORDER BY crt.name " + "UNION " + "SELECT DISTINCT crt2.id, crt2.name, crt2.category, crt2.creation_data_type, crt2.create_delete_policy, crt2.singleton, crt2.supports_manual_add, crt2.description, crt2.plugin, crt2.ctime, crt2.mtime, crt2.deleted, crt2.subcategory, crt2.plugin_config_def_id, crt2.res_config_def_id " + "FROM RHQ_resource_type crt2 " + "WHERE 1 = " + "(SELECT COUNT(res2.id) " + "FROM RHQ_resource res2, RHQ_resource_type rt2 " + "WHERE res2.id = ? " + "AND res2.resource_type_id = rt2.id " + "AND rt2.category = 'PLATFORM') " + "AND 0 = " + "(SELECT COUNT(rtp2.resource_type_id) " + "FROM RHQ_resource_type_parents rtp2 " + "WHERE rtp2.resource_type_id = crt2.id) " + "AND crt2.deleted = false " + "AND crt2.category = ? " + " ) ORDER BY name", resultSetMapping = ResourceType.MAPPING_FIND_CHILDREN_BY_CATEGORY), @NamedNativeQuery(name = ResourceType.QUERY_FIND_CHILDREN_BY_CATEGORY_admin, query = "" // + "(SELECT crt.id, crt.name, crt.category, crt.creation_data_type, crt.create_delete_policy, crt.singleton, crt.supports_manual_add, crt.description, crt.plugin, crt.ctime, crt.mtime, crt.deleted, crt.subcategory, crt.plugin_config_def_id, crt.res_config_def_id " + "FROM RHQ_resource_type crt, RHQ_resource res, RHQ_resource_type rt, RHQ_resource_type_parents rtp " + "WHERE res.id = ? " + "AND crt.deleted = false " + "AND res.resource_type_id = rt.id " + "AND rt.id = rtp.parent_resource_type_id " + "AND rtp.resource_type_id = crt.id " + "AND crt.category = ? " + // "ORDER BY crt.name " + "UNION " + "(SELECT DISTINCT crt2.id, crt2.name, crt2.category, crt2.creation_data_type, crt2.create_delete_policy, crt2.singleton, crt2.supports_manual_add, crt2.description, crt2.plugin, crt2.ctime, crt2.mtime, crt2.deleted, crt2.subcategory, crt2.plugin_config_def_id, crt2.res_config_def_id " + "FROM RHQ_resource_type crt2 " + "WHERE 1 = " + "(SELECT COUNT(res2.id) " + "FROM RHQ_resource res2, RHQ_resource_type rt2 " + "WHERE res2.id = ? " + "AND res2.resource_type_id = rt2.id " + "AND rt2.category = 'PLATFORM') " + "AND 0 = " + "(SELECT COUNT(rtp2.resource_type_id) " + "FROM RHQ_resource_type_parents rtp2 " + "WHERE rtp2.resource_type_id = crt2.id) " + "AND crt2.category = ?" + // "ORDER BY crt2.name" + ")) ORDER BY name", resultSetMapping = ResourceType.MAPPING_FIND_CHILDREN_BY_CATEGORY) // }) @SqlResultSetMapping(name = ResourceType.MAPPING_FIND_CHILDREN_BY_CATEGORY, entities = { @EntityResult(entityClass = ResourceType.class) }) // @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) public class ResourceType implements Serializable, Comparable<ResourceType> { private static final long serialVersionUID = 4L; public static final String TABLE_NAME = "RHQ_RESOURCE_TYPE"; public static final ResourceType ANY_PLATFORM_TYPE = null; public static final String QUERY_GET_BUNDLE_CONFIG_BY_GROUP_ID = "ResourceType.getBundleConfigByGroupResourceType"; public static final String QUERY_GET_EXPLICIT_RESOURCE_TYPE_COUNTS_BY_GROUP = "ResourceType.getExplicitResourceTypeCountsByGroup"; public static final String QUERY_GET_IMPLICIT_RESOURCE_TYPE_COUNTS_BY_GROUP = "ResourceType.getImplicitResourceTypeCountsByGroup"; public static final String QUERY_FIND_BY_NAME_AND_PLUGIN = "ResourceType.findByNameAndPlugin"; public static final String QUERY_FIND_BY_PLUGIN = "ResourceType.findByPlugin"; public static final String QUERY_FIND_BY_PARENT_AND_NAME = "ResourceType.findByParentAndName"; public static final String QUERY_FIND_ALL = "ResourceType.findAll"; public static final String QUERY_FIND_BY_ID_WITH_ALL_OPERATIONS = "ResourceType.findByIdWithAllOperations"; public static final String QUERY_FIND_BY_CATEGORY = "ResourceType.findByCategory"; public static final String QUERY_FIND_CHILDREN = "ResourceType.findChildren"; /** find child resource types for resource :parentResource and category :category */ public static final String QUERY_FIND_CHILDREN_BY_CATEGORY = "ResourceType.findChildrenByCategory"; public static final String QUERY_FIND_CHILDREN_BY_CATEGORY_admin = "ResourceType.findChildrenByCategory_admin"; /** find utilized (i.e. represented in inventory) child resource types for resource :parentResource and category :category */ public static final String QUERY_FIND_UTILIZED_CHILDREN_BY_CATEGORY = "ResourceType.findUtilizedChildrenByCategory"; public static final String QUERY_FIND_UTILIZED_CHILDREN_BY_CATEGORY_admin = "ResourceType.findUtilizedChildrenByCategory_admin"; /** find child resource types for the resource type passed in :resourceType */ public static final String FIND_CHILDREN_BY_PARENT = "ResourceType.findChildrenByParent"; public static final String FIND_ALL_TEMPLATE_COUNT_COMPOSITES = "ResourceType.findAllTemplateCountComposites"; public static final String QUERY_FIND_UTILIZED_BY_CATEGORY = "ResourceType.findUtilizedByCategory"; public static final String QUERY_FIND_UTILIZED_BY_CATEGORY_admin = "ResourceType.findUtilizedByCategory_admin"; public static final String QUERY_FIND_BY_RESOURCE_GROUP = "ResourceType.findByResourceGroup"; public static final String QUERY_FIND_BY_RESOURCE_GROUP_admin = "ResourceType.findByResourceGroup_admin"; public static final String MAPPING_FIND_CHILDREN_BY_CATEGORY = "ResourceType.findChildrenByCategoryMapping"; public static final String QUERY_FIND_RESOURCE_FACETS = "ResourceType.findResourceFacets"; public static final String QUERY_FIND_DUPLICATE_TYPE_NAMES = "ResourceType.findDuplicateTypeNames"; public static final String QUERY_DYNAMIC_CONFIG_WITH_PLUGIN = "ResourceType.dynamicConfigWithPlugin"; public static final String QUERY_MARK_TYPES_DELETED = "ResourceType.markTypesDeleted"; public static final String QUERY_FIND_IDS_BY_PLUGIN = "ResourceType.findIdsByPlugin"; public static final String QUERY_FIND_COUNT_BY_PLUGIN = "ResourceType.findCountByPlugin"; @Id @Column(name = "ID", nullable = false) @GeneratedValue(strategy = GenerationType.AUTO, generator = "RHQ_RESOURCE_TYPE_ID_SEQ") @Summary(index = 0) private int id; @Column(name = "NAME", nullable = false) @Summary(index = 1) private String name; @Column(name = "DESCRIPTION") private String description; @Column(name = "CATEGORY", nullable = false) @Enumerated(EnumType.STRING) @Summary(index = 2) private ResourceCategory category; @Column(name = "CREATION_DATA_TYPE", nullable = false) @Enumerated(EnumType.STRING) private ResourceCreationDataType creationDataType = ResourceCreationDataType.CONFIGURATION; @Column(name = "CREATE_DELETE_POLICY", nullable = false) @Enumerated(EnumType.STRING) private CreateDeletePolicy createDeletePolicy = CreateDeletePolicy.BOTH; @Column(name = "SUPPORTS_MANUAL_ADD", nullable = false) private boolean supportsManualAdd; @Column(name = "SINGLETON", nullable = false) private boolean singleton; @Column(name = "PLUGIN", nullable = false) @Summary(index = 3) private String plugin; @Column(name = "CTIME") private Long ctime; @Column(name = "MTIME") private Long mtime; @Column(name = "DELETED") private boolean deleted; @Column(name = "IGNORED") private boolean ignored; @Column(name = "SUPPORTS_MISSING") private boolean supportsMissingAvailabilityType; @Column(name = "MISSING_POLICY", nullable = false) @Enumerated(EnumType.STRING) private MissingPolicy missingPolicy = MissingPolicy.DOWN; @ManyToMany(mappedBy = "parentResourceTypes", cascade = { CascadeType.REFRESH }) @OrderBy //@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) private Set<ResourceType> childResourceTypes; @ManyToMany(cascade = CascadeType.PERSIST) // persist so self-injecting plugins work @JoinTable(name = "RHQ_RESOURCE_TYPE_PARENTS", joinColumns = { @JoinColumn(name = "RESOURCE_TYPE_ID") }, inverseJoinColumns = { @JoinColumn(name = "PARENT_RESOURCE_TYPE_ID") }) @OrderBy //@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) private Set<ResourceType> parentResourceTypes; @JoinColumn(name = "PLUGIN_CONFIG_DEF_ID", nullable = true) @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = true) //@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) private ConfigurationDefinition pluginConfigurationDefinition; @JoinColumn(name = "RES_CONFIG_DEF_ID", nullable = true) @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = true) //@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) private ConfigurationDefinition resourceConfigurationDefinition; @Column(name = "SUBCATEGORY") private String subCategory; @Column(name = "DISPLAY_NAME") private String displayName; @OneToMany(mappedBy = "resourceType", cascade = CascadeType.ALL) @OrderBy // primary key //@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) private Set<MeasurementDefinition> metricDefinitions = new LinkedHashSet<MeasurementDefinition>(); @OneToMany(mappedBy = "resourceType", cascade = CascadeType.ALL) @OrderBy // primary key //@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) private Set<EventDefinition> eventDefinitions; @OneToMany(mappedBy = "resourceType", cascade = CascadeType.ALL) @OrderBy // primary key private Set<OperationDefinition> operationDefinitions; @JoinColumn(name = "RESOURCE_TYPE_ID") @OneToMany(cascade = CascadeType.ALL) private Set<ProcessScan> processScans; @OneToMany(mappedBy = "resourceType", cascade = CascadeType.ALL) private Set<PackageType> packageTypes; @OneToMany(mappedBy = "resourceType", cascade = CascadeType.REMOVE) private List<Resource> resources; @OneToMany(mappedBy = "resourceType", cascade = CascadeType.REMOVE) private List<ResourceGroup> resourceGroups; @OneToMany(mappedBy = "resourceType", cascade = CascadeType.ALL) private Set<ProductVersion> productVersions; @OneToOne(mappedBy = "resourceType", fetch = FetchType.LAZY, cascade = CascadeType.ALL, optional = true) private BundleType bundleType; @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "resourceType") private Set<DriftDefinitionTemplate> driftDefinitionTemplates; // note that this is mapped to a Configuration entity, which is what it really is. However, our getter/setter // only provides access to this via ResourceTypeBundleConfiguration to encapsulate the innards of this implementation // detail, exposing only the more strongly typed methods to obtain bundle-related config properties @JoinColumn(name = "BUNDLE_CONFIG_ID", nullable = true) @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = true) private Configuration bundleConfiguration; @ManyToMany(mappedBy = "explicitlyTargetedResourceTypes") private Set<BundleType> explicitlyTargetingBundleTypes; @Transient private transient String helpText; @Transient private transient String helpTextContentType; @Transient private transient ClassLoaderType classLoaderType; /* no-arg constructor required by EJB spec and Externalizable (Externalizable also requires it to be public) */ public ResourceType() { // Intentionally left blank } public ResourceType(String name, String plugin, ResourceCategory category, ResourceType parentResourceType) { if (name == null) { throw new IllegalArgumentException("name==null"); } if (plugin == null) { throw new IllegalArgumentException("plugin==null"); } // Initialize empty ordered lists... this.childResourceTypes = null; this.parentResourceTypes = new HashSet<ResourceType>(1); this.metricDefinitions = new LinkedHashSet<MeasurementDefinition>(); this.name = name; this.category = category; this.plugin = plugin; this.mtime = this.ctime = System.currentTimeMillis(); if (parentResourceType != null) { parentResourceType.addChildResourceType(this); } } public int getId() { return this.id; } public void setId(int id) { this.id = id; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public String getDisplayName() { return displayName; } public void setDisplayName(String displayName) { this.displayName = displayName; } public ResourceCategory getCategory() { return this.category; } public void setCategory(ResourceCategory category) { this.category = category; } public ResourceCreationDataType getCreationDataType() { return creationDataType; } public void setCreationDataType(ResourceCreationDataType creationDataType) { if (creationDataType == null) throw new IllegalArgumentException("creationDataType cannot be null"); this.creationDataType = creationDataType; } public CreateDeletePolicy getCreateDeletePolicy() { return createDeletePolicy; } public void setCreateDeletePolicy(CreateDeletePolicy createDeletePolicy) { if (createDeletePolicy == null) throw new IllegalArgumentException("createDeletePolicy cannot be null"); this.createDeletePolicy = createDeletePolicy; } public boolean isCreatable() { return (createDeletePolicy == CreateDeletePolicy.BOTH || createDeletePolicy == CreateDeletePolicy.CREATE_ONLY); } public boolean isDeletable() { return (createDeletePolicy == CreateDeletePolicy.BOTH || createDeletePolicy == CreateDeletePolicy.DELETE_ONLY); } public MissingPolicy getMissingPolicy() { return missingPolicy; } public void setMissingPolicy(MissingPolicy missingPolicy) { if (missingPolicy == null) throw new IllegalArgumentException("missingPolicy cannot be null"); this.missingPolicy = missingPolicy; } /** * Returns the resource subcategory, if any, which this ResourceType * has been tagged with. If the ResourceType has not been tagged with * a subcategory, <code>null</code> is returned. */ public String getSubCategory() { return this.subCategory; } /** * Tags this ResourceType as being part of the specified subcategory */ public void setSubCategory(String subcategory) { this.subCategory = subcategory; } /** * If true, this resource may only ever have one discovered instance per parent resource. * @return true if this is a singleton resource */ public boolean isSingleton() { return singleton; } /** * @param singleton true if there is only ever one discovered instance per parent resource */ public void setSingleton(boolean singleton) { this.singleton = singleton; } public boolean isSupportsManualAdd() { return supportsManualAdd; } public void setSupportsManualAdd(boolean supportsManualAdd) { this.supportsManualAdd = supportsManualAdd; } public String getDescription() { return this.description; } public void setDescription(String description) { this.description = description; } public String getPlugin() { return this.plugin; } public void setPlugin(String plugin) { this.plugin = plugin; } public long getCtime() { return this.ctime; } @PrePersist void onPersist() { this.mtime = this.ctime = System.currentTimeMillis(); } public long getMtime() { return this.mtime; } public boolean isDeleted() { return deleted; } public void setDeleted(boolean deleted) { this.deleted = deleted; } public boolean isIgnored() { return ignored; } public void setIgnored(boolean ignored) { this.ignored = ignored; } public boolean isSupportsMissingAvailabilityType() { return supportsMissingAvailabilityType; } public void setSupportsMissingAvailabilityType(boolean uninventoryMissing) { this.supportsMissingAvailabilityType = uninventoryMissing; } @PreUpdate void onUpdate() { this.mtime = System.currentTimeMillis(); } public List<Resource> getResources() { return resources; } public void setResources(List<Resource> resources) { this.resources = resources; } public List<ResourceGroup> getResourceGroups() { return resourceGroups; } public void setResourceGroups(List<ResourceGroup> resourceGroups) { this.resourceGroups = resourceGroups; } public Set<ResourceType> getParentResourceTypes() { return this.parentResourceTypes; } public void setParentResourceTypes(Set<ResourceType> parentResourceTypes) { this.parentResourceTypes = parentResourceTypes; } /** * Makes this resource type a child of the given parent resource type. * @param parentResourceType */ public void addParentResourceType(ResourceType parentResourceType) { if (parentResourceType.childResourceTypes==null || parentResourceType.childResourceTypes.equals(Collections.emptySet())) { parentResourceType.childResourceTypes = new HashSet<ResourceType>(1); } parentResourceType.childResourceTypes.add(this); this.parentResourceTypes.add(parentResourceType); } /** * Removes the given resource type as a parent of this resource type. * @param oldParentResourceType */ public void removeParentResourceType(ResourceType oldParentResourceType) { oldParentResourceType.childResourceTypes.remove(this); this.parentResourceTypes.remove(oldParentResourceType); } public Set<ResourceType> getChildResourceTypes() { if (this.childResourceTypes==null) { return Collections.emptySet(); } return this.childResourceTypes; } /** * Makes this resource type a parent of the given child resource type. * @param childResourceType */ public void addChildResourceType(ResourceType childResourceType) { if (this.childResourceTypes==null) { childResourceTypes = new LinkedHashSet<ResourceType>(1); } childResourceType.parentResourceTypes.add(this); this.childResourceTypes.add(childResourceType); } /** * Removes the given resource type as a child of this resource type. * @param oldChildResourceType */ public void removeChildResourceType(ResourceType oldChildResourceType) { if (this.childResourceTypes==null) { return; } oldChildResourceType.parentResourceTypes.remove(this); this.childResourceTypes.remove(oldChildResourceType); if (this.childResourceTypes.isEmpty()) { this.childResourceTypes=null; } } public void setChildResourceTypes(Set<ResourceType> childResourceTypes) { this.childResourceTypes = childResourceTypes; } public ConfigurationDefinition getPluginConfigurationDefinition() { return pluginConfigurationDefinition; } public void setPluginConfigurationDefinition(ConfigurationDefinition pluginConfigurationDefinition) { this.pluginConfigurationDefinition = pluginConfigurationDefinition; } public ConfigurationDefinition getResourceConfigurationDefinition() { return resourceConfigurationDefinition; } public void setResourceConfigurationDefinition(ConfigurationDefinition resourceConfigurationDefinition) { this.resourceConfigurationDefinition = resourceConfigurationDefinition; } public ResourceTypeBundleConfiguration getResourceTypeBundleConfiguration() { if (this.bundleConfiguration == null) { return null; } else { return new ResourceTypeBundleConfiguration(bundleConfiguration); } } public void setResourceTypeBundleConfiguration(ResourceTypeBundleConfiguration rtbc) { if (rtbc == null) { this.bundleConfiguration = null; } else { this.bundleConfiguration = rtbc.getBundleConfiguration(); } } @XmlTransient public Set<MeasurementDefinition> getMetricDefinitions() { return metricDefinitions; } public void setMetricDefinitions(Set<MeasurementDefinition> metricDefinitions) { this.metricDefinitions = metricDefinitions; } public boolean addMetricDefinition(MeasurementDefinition metricDef) { metricDef.setResourceType(this); return this.metricDefinitions.add(metricDef); } @XmlTransient public Set<EventDefinition> getEventDefinitions() { if (eventDefinitions==null) { return Collections.emptySet(); } return eventDefinitions; } public void setEventDefinitions(Set<EventDefinition> eventDefinitions) { this.eventDefinitions = eventDefinitions; } public void addEventDefinition(EventDefinition eventDefinition) { if (this.eventDefinitions==null) { this.eventDefinitions = new HashSet<EventDefinition>(1); } this.eventDefinitions.add(eventDefinition); } public Set<OperationDefinition> getOperationDefinitions() { if (operationDefinitions==null) { return Collections.emptySet(); } return operationDefinitions; } public void setOperationDefinitions(Set<OperationDefinition> operationDefinitions) { this.operationDefinitions = operationDefinitions; } public boolean addOperationDefinition(OperationDefinition operationDefinition) { if (operationDefinitions==null) { operationDefinitions = new LinkedHashSet<OperationDefinition>(1); } operationDefinition.setResourceType(this); return this.operationDefinitions.add(operationDefinition); } public Set<ProcessScan> getProcessScans() { if (processScans==null) { return Collections.emptySet(); } return this.processScans; } public void setProcessScans(Set<ProcessScan> processScans) { this.processScans = processScans; } public boolean addProcessScan(ProcessScan processMatch) { // this is unidirection - no need to set this resource this on process match if (this.processScans == null) { this.processScans = new HashSet<ProcessScan>(1); } return this.processScans.add(processMatch); } public Set<PackageType> getPackageTypes() { if (packageTypes==null) { return Collections.emptySet(); } return packageTypes; } public void setPackageTypes(Set<PackageType> packageTypes) { this.packageTypes = packageTypes; } public void addPackageType(PackageType packageType) { if (packageTypes==null) { packageTypes= new HashSet<PackageType>(1); } packageType.setResourceType(this); packageTypes.add(packageType); } public void removePackageType(PackageType packageType) { packageTypes.remove(packageType); packageType.setResourceType(null); if (packageTypes.isEmpty()) { packageTypes=null; } } public Set<ProductVersion> getProductVersions() { if (productVersions==null) { return Collections.emptySet(); } return productVersions; } public void setProductVersions(Set<ProductVersion> productVersions) { this.productVersions = productVersions; } public String getHelpText() { return helpText; } public void setHelpText(String helpText) { this.helpText = helpText; } public String getHelpTextContentType() { return helpTextContentType; } public void setHelpTextContentType(String helpTextContentType) { this.helpTextContentType = helpTextContentType; } public ClassLoaderType getClassLoaderType() { return classLoaderType; } public void setClassLoaderType(ClassLoaderType classLoaderType) { this.classLoaderType = classLoaderType; } public BundleType getBundleType() { return this.bundleType; } public void setBundleType(BundleType bundleType) { this.bundleType = bundleType; } public Set<DriftDefinitionTemplate> getDriftDefinitionTemplates() { if (driftDefinitionTemplates==null) { return Collections.emptySet(); } return driftDefinitionTemplates; } public void addDriftDefinitionTemplate(DriftDefinitionTemplate template) { if (driftDefinitionTemplates == null) { driftDefinitionTemplates = new HashSet<DriftDefinitionTemplate>(1); } template.setResourceType(this); driftDefinitionTemplates.add(template); } public void setDriftDefinitionTemplates(Set<DriftDefinitionTemplate> driftDefinitionTemplates) { this.driftDefinitionTemplates = driftDefinitionTemplates; } @Deprecated public List<ResourceSubCategory> getChildSubCategories() { return null; } @Deprecated public void setChildSubCategories(List<ResourceSubCategory> subCategories) { } @Deprecated public void addChildSubCategory(ResourceSubCategory subCategory) { } /** * Returns the set of bundle types that explicitly support deploying to this resource type. * If this set is empty, any bundle type can attempt deploy to one of this resource type's * destinations (this can be further limited on the destinations themselves by the 'accepts' * property). * <p/> * Note that while the returned set is modifiable, resource type is not to owning side of this * relationship and thus any updates to the relationship are best performed from the * bundle type side. * * @return the set of bundle types explicitly targetting this resource type */ public Set<BundleType> getExplicitlyTargetingBundleTypes() { if (explicitlyTargetingBundleTypes == null) { explicitlyTargetingBundleTypes = new HashSet<BundleType>(); } return explicitlyTargetingBundleTypes; } protected void setExplicitlyTargetingBundleTypes(Set<BundleType> explicitlyTargetingBundleTypes) { this.explicitlyTargetingBundleTypes = explicitlyTargetingBundleTypes; } // NOTE: It's vital that compareTo() is consistent with equals(), otherwise TreeSets containing ResourceTypes, or // TreeMaps with ResourceTypes as keys, will not work reliably. See the Javadoc for Comparable for a precise // definition of "consistent with equals()". @Override public int compareTo(ResourceType that) { if (this.name == null) { return (that.name == null) ? 0 : -1; } int result = (that.name == null) ? 1 : this.name.compareTo(that.name); if (result != 0) { return result; } if (this.plugin == null) { return (that.plugin == null) ? 0 : -1; } return (that.plugin == null) ? 1 : this.plugin.compareTo(that.plugin); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || !(obj instanceof ResourceType)) return false; ResourceType that = (ResourceType) obj; if (this.name != null ? !this.name.equals(that.name) : that.name != null) return false; if (this.plugin != null ? !this.plugin.equals(that.plugin) : that.plugin != null) return false; //only compare id's if they've both been set if (this.id != 0 && that.id != 0 && this.id != that.id) return false; return true; } @Override public int hashCode() { int result; if (name != null && this.plugin != null) { result = (this.name != null ? this.name.hashCode() : 0); result = 31 * result + (this.plugin != null ? plugin.hashCode() : 0); } else { result = 31 * id; } return result; } @Override public String toString() { return "ResourceType[id=" + this.id + ", name=" + this.name + ", plugin=" + this.plugin + ", category=" + this.category + "]"; } }