/* * RHQ Management Platform * Copyright (C) 2005-2008 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.content; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.OrderBy; import javax.persistence.PrePersist; import javax.persistence.PreUpdate; import javax.persistence.SequenceGenerator; import javax.persistence.Table; import javax.persistence.Transient; import javax.xml.bind.annotation.XmlTransient; import org.jetbrains.annotations.NotNull; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.resource.Resource; /** * A repo represents a set of related {@link PackageVersion}s. The packages in this repo are populated by its * {@link ContentSource}s. The relationship with content sources is weak; that is, content sources can come and go, even * as the packages contained in the repo remain. * * @author Jason Dobies * @author John Mazzitelli * @author Lukas Krejci */ @Entity @NamedQueries( { @NamedQuery(name = Repo.QUERY_FIND_ALL_IMPORTED_REPOS_ADMIN, query = "SELECT c FROM Repo c WHERE c.candidate = false"), @NamedQuery(name = Repo.QUERY_FIND_ALL_IMPORTED_REPOS, query = "SELECT c FROM Repo c" // + " WHERE c.isPrivate = false OR c.owner = :subject"), @NamedQuery(name = Repo.QUERY_FIND_BY_IDS, query = "SELECT c FROM Repo c WHERE c.id IN ( :ids )"), @NamedQuery(name = Repo.QUERY_FIND_BY_NAME, query = "SELECT c FROM Repo c WHERE c.name = :name"), @NamedQuery(name = Repo.QUERY_FIND_IMPORTED_BY_CONTENT_SOURCE_ID_FETCH_CCS, query = "SELECT c FROM Repo c LEFT JOIN FETCH c.repoContentSources ccs WHERE ccs.contentSource.id = :id AND c.candidate = false"), @NamedQuery(name = Repo.QUERY_FIND_IMPORTED_BY_CONTENT_SOURCE_ID, query = "SELECT c FROM Repo c LEFT JOIN c.repoContentSources ccs WHERE ccs.contentSource.id = :id AND c.candidate = false"), @NamedQuery(name = Repo.QUERY_FIND_CANDIDATE_BY_CONTENT_SOURCE_ID, query = "SELECT c FROM Repo c LEFT JOIN c.repoContentSources ccs WHERE ccs.contentSource.id = :id AND c.candidate = true"), @NamedQuery(name = Repo.QUERY_FIND_SUBSCRIBER_RESOURCES, query = "SELECT rc.resource FROM ResourceRepo rc WHERE rc.repo.id = :id"), @NamedQuery(name = Repo.QUERY_FIND_REPOS_BY_RESOURCE_ID, query = "SELECT c " + "FROM ResourceRepo rc JOIN rc.repo c WHERE rc.resource.id = :resourceId "), @NamedQuery(name = Repo.QUERY_FIND_REPO_COMPOSITES_BY_RESOURCE_ID, query = "SELECT new org.rhq.core.domain.content.composite.RepoComposite( " + "c, " + "(SELECT COUNT(cpv.packageVersion) FROM RepoPackageVersion cpv WHERE cpv.repo.id = c.id) " + ") " + "FROM ResourceRepo rc JOIN rc.repo c LEFT JOIN c.repoPackageVersions pv " + "WHERE rc.resource.id = :resourceId " + "GROUP BY c, c.name, c.description, c.creationDate, c.lastModifiedDate"), @NamedQuery(name = Repo.QUERY_FIND_REPO_COMPOSITES_BY_RESOURCE_ID_COUNT, query = "SELECT COUNT( rc.repo ) " + "FROM ResourceRepo rc WHERE rc.resource.id = :resourceId "), @NamedQuery(name = Repo.QUERY_FIND_AVAILABLE_REPO_COMPOSITES_BY_RESOURCE_ID_ADMIN, query = "SELECT new org.rhq.core.domain.content.composite.RepoComposite( " + "c, " + "(SELECT COUNT(cpv.packageVersion) FROM RepoPackageVersion cpv WHERE cpv.repo.id = c.id) " + ") " + "FROM Repo AS c " + "WHERE c.id NOT IN ( SELECT rc.repo.id FROM ResourceRepo rc WHERE rc.resource.id = :resourceId ) " + "AND c.candidate = false " + "GROUP BY c, c.name, c.description, c.creationDate, c.lastModifiedDate"), @NamedQuery(name = Repo.QUERY_FIND_AVAILABLE_REPO_COMPOSITES_BY_RESOURCE_ID_ADMIN_COUNT, query = "SELECT COUNT( c ) " + "FROM Repo AS c " + "WHERE c.id NOT IN ( SELECT rc.repo.id FROM ResourceRepo rc WHERE rc.resource.id = :resourceId ) " + "AND c.candidate = false "), @NamedQuery(name = Repo.QUERY_FIND_AVAILABLE_REPO_COMPOSITES_BY_RESOURCE_ID, query = "SELECT new org.rhq.core.domain.content.composite.RepoComposite( " + "c, " + "(SELECT COUNT(cpv.packageVersion) FROM RepoPackageVersion cpv WHERE cpv.repo.id = c.id) " + ") " + "FROM Repo AS c " + "WHERE c.id NOT IN ( SELECT rc.repo.id FROM ResourceRepo rc WHERE rc.resource.id = :resourceId ) " + "AND c.candidate = false " + "AND c.owner = :subject " + "GROUP BY c, c.name, c.description, c.creationDate, c.lastModifiedDate"), @NamedQuery(name = Repo.QUERY_FIND_AVAILABLE_REPO_COMPOSITES_BY_RESOURCE_ID_COUNT, query = "SELECT COUNT( c ) " + "FROM Repo AS c " + "WHERE c.id NOT IN ( SELECT rc.repo.id FROM ResourceRepo rc WHERE rc.resource.id = :resourceId ) " + "AND c.candidate = false AND c.owner = :subject"), @NamedQuery(name = Repo.QUERY_FIND_CANDIDATES_WITH_ONLY_CONTENT_SOURCE, query = "SELECT r FROM Repo r " // + "WHERE r.candidate = true " // + "AND 1 = (SELECT COUNT(rcs.repo) FROM RepoContentSource rcs " // + " WHERE rcs.repo.id = r.id " // + " AND rcs.contentSource.id = :contentSourceId) " // + "AND 1 = (SELECT COUNT(rcs.repo) FROM RepoContentSource rcs" // + " WHERE rcs.repo.id = r.id) "), @NamedQuery(name = Repo.QUERY_CHECK_REPO_VISIBLE_BY_SUBJECT_ID, query = "SELECT COUNT(r) FROM Repo r" // + " WHERE r.id = :repoId" + " AND r.isPrivate = false OR r.owner.id = :subjectId"), @NamedQuery(name = Repo.QUERY_CHECK_REPO_OWNED_BY_SUBJECT_ID, query = "SELECT COUNT(r) FROM Repo r" // + " WHERE r.id = :repoId" + " AND r.owner.id = :subjectId"), @NamedQuery(name = Repo.QUERY_UPDATE_REMOVE_OWNER_FROM_REPOS_OWNED_BY_SUBJECT, query = "" + "UPDATE Repo r SET r.owner = null WHERE r.owner.id = :ownerId") }) @SequenceGenerator(allocationSize = org.rhq.core.domain.util.Constants.ALLOCATION_SIZE, name = "RHQ_REPO_ID_SEQ", sequenceName = "RHQ_REPO_ID_SEQ") @Table(name = "RHQ_REPO") public class Repo implements Serializable { // Constants -------------------------------------------- public static final String QUERY_FIND_ALL_IMPORTED_REPOS_ADMIN = "Repo.findAllImportedReposAdmin"; public static final String QUERY_FIND_ALL_IMPORTED_REPOS = "Repo.findAllImportedRepos"; public static final String QUERY_FIND_BY_IDS = "Repo.findByIds"; public static final String QUERY_FIND_BY_NAME = "Repo.findByName"; public static final String QUERY_FIND_IMPORTED_BY_CONTENT_SOURCE_ID_FETCH_CCS = "Repo.findByContentSourceIdFetchCCS"; public static final String QUERY_FIND_IMPORTED_BY_CONTENT_SOURCE_ID = "Repo.findByContentSourceId"; public static final String QUERY_FIND_CANDIDATE_BY_CONTENT_SOURCE_ID = "Repo.findCandidateByContentSourceId"; public static final String QUERY_FIND_SUBSCRIBER_RESOURCES = "Repo.findSubscriberResources"; public static final String QUERY_FIND_REPOS_BY_RESOURCE_ID = "Repo.findReposByResourceId"; public static final String QUERY_FIND_REPO_COMPOSITES_BY_RESOURCE_ID = "Repo.findRepoCompositesByResourceId"; public static final String QUERY_FIND_REPO_COMPOSITES_BY_RESOURCE_ID_COUNT = "Repo.findRepoCompositesByResourceId_count"; public static final String QUERY_FIND_AVAILABLE_REPO_COMPOSITES_BY_RESOURCE_ID_ADMIN = "Repo.findAvailableRepoCompositesByResourceIdAdmin"; public static final String QUERY_FIND_AVAILABLE_REPO_COMPOSITES_BY_RESOURCE_ID_ADMIN_COUNT = "Repo.findAvailableRepoCompositesByResourceIdAdmin_count"; public static final String QUERY_FIND_AVAILABLE_REPO_COMPOSITES_BY_RESOURCE_ID = "Repo.findAvailableRepoCompositesByResourceId"; public static final String QUERY_FIND_AVAILABLE_REPO_COMPOSITES_BY_RESOURCE_ID_COUNT = "Repo.findAvailableRepoCompositesByResourceId_count"; public static final String QUERY_FIND_CANDIDATES_WITH_ONLY_CONTENT_SOURCE = "Repo.findCandidatesWithOnlyContentSource"; public static final String QUERY_CHECK_REPO_VISIBLE_BY_SUBJECT_ID = "Repo.findVisibleReposBySubjectId"; public static final String QUERY_CHECK_REPO_OWNED_BY_SUBJECT_ID = "Repo.isRepoOwnedBySubjectId"; public static final String QUERY_UPDATE_REMOVE_OWNER_FROM_REPOS_OWNED_BY_SUBJECT = "Repo.removeOwnerFromReposOwnerBySubject"; private static final long serialVersionUID = 1L; // Attributes -------------------------------------------- @Column(name = "ID", nullable = false) @GeneratedValue(strategy = GenerationType.AUTO, generator = "RHQ_REPO_ID_SEQ") @Id private int id; @Column(name = "NAME", nullable = false) private String name; @Column(name = "DESCRIPTION", nullable = true) private String description; @Column(name = "CREATION_TIME", nullable = false) private long creationDate; @Column(name = "LAST_MODIFIED_TIME", nullable = false) private long lastModifiedDate; @Column(name = "IS_CANDIDATE", nullable = false) private boolean candidate; @Column(name = "SYNC_SCHEDULE", nullable = true) private String syncSchedule = "0 0 3 * * ?"; @OneToMany(mappedBy = "repo", fetch = FetchType.LAZY) private Set<ResourceRepo> resourceRepos; @XmlTransient @OneToMany(mappedBy = "repo", fetch = FetchType.LAZY, cascade = CascadeType.ALL) private Set<RepoContentSource> repoContentSources; @XmlTransient @OneToMany(mappedBy = "repo", fetch = FetchType.LAZY) private Set<RepoPackageVersion> repoPackageVersions; @XmlTransient @OneToMany(mappedBy = "repo", fetch = FetchType.LAZY, cascade = CascadeType.ALL) private Set<RepoRepoGroup> repoRepoGroups; @XmlTransient @OneToMany(mappedBy = "repo", fetch = FetchType.LAZY) private Set<RepoRepoRelationship> repoRepoRelationships; @XmlTransient @OneToMany(mappedBy = "repo", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) @OrderBy("startTime DESC") // latest appears first, oldest last private List<RepoSyncResults> syncResults; @XmlTransient @OneToMany(mappedBy = "repo", fetch = FetchType.LAZY, cascade = CascadeType.ALL) private Set<RepoDistribution> repoDistributions; @XmlTransient @OneToMany(mappedBy = "repo", fetch = FetchType.LAZY, cascade = CascadeType.ALL) private Set<RepoAdvisory> repoAdvisories; @Transient private String syncStatus; @ManyToOne @JoinColumn(name = "OWNER_ID", referencedColumnName = "ID", nullable = true) private Subject owner; @Column(name = "IS_PRIVATE", nullable = false) private boolean isPrivate = true; // Constructor ---------------------------------------- public Repo() { // for JPA use } public Repo(String name) { this.name = name; } // Public -------------------------------------------- public int getId() { return id; } public void setId(int id) { this.id = id; } /** * Programmatic name of the repo. */ public String getName() { return name; } public void setName(String name) { this.name = name; } /** * User specified description of the repo. */ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } /** * Timestamp of when this repo was created. */ public long getCreationDate() { return creationDate; } public void setCreationDate(long creationDate) { this.creationDate = creationDate; } /** * Timestamp of the last time the {@link #getContentSources() sources} of this repo was changed. It is not * necessarily the last time any other part of this repo object was changed (for example, this last modified date * does not necessarily correspond to the time when the description was modified). */ public long getLastModifiedDate() { return lastModifiedDate; } public void setLastModifiedDate(long lastModifiedDate) { this.lastModifiedDate = lastModifiedDate; } /** * Indicates if the repo is an imported (i.e. subscribable) repo in RHQ or is just a candidate for import, such as * those introduced by a content source. */ public boolean isCandidate() { return candidate; } public void setCandidate(boolean candidate) { this.candidate = candidate; } /** * Periodically, the Repo will be asked to synchronize with the remote ContentProviders associated with it * This attribute defines the schedule, as a cron string. The default will be set for everyday at * 3:00am local time. If this content source should never automatically sync, this should be null, but * an empty string would also indicate this, too. * * @return sync schedule as a cron string or null if the sync should not automatically occur */ public String getSyncSchedule() { return syncSchedule; } public void setSyncSchedule(String syncSchedule) { if (syncSchedule != null && syncSchedule.trim().length() == 0) { syncSchedule = null; } this.syncSchedule = syncSchedule; } /** * Returns the explicit mapping entities. * * @return the mapping entities * * @see #getResources() */ public Set<ResourceRepo> getResourceRepos() { return resourceRepos; } /** * The resources subscribed to this repo. * * <p>The returned set is not backed by this entity - if you want to alter the set of associated resources, use * {@link #getResourceRepos()} or {@link #addResource(Resource)}, {@link #removeResource(Resource)}.</p> */ public Set<Resource> getResources() { HashSet<Resource> resources = new HashSet<Resource>(); if (resourceRepos != null) { for (ResourceRepo rc : resourceRepos) { resources.add(rc.getResourceRepoPK().getResource()); } } return resources; } /** * Directly subscribe a resource to this repo. * * @param resource * * @return the mapping that was added */ public ResourceRepo addResource(Resource resource) { if (this.resourceRepos == null) { this.resourceRepos = new HashSet<ResourceRepo>(); } ResourceRepo mapping = new ResourceRepo(resource, this); this.resourceRepos.add(mapping); return mapping; } /** * Unsubscribes the resource from this repo, if it exists. If it was already subscribed, the mapping that was * removed is returned; if not, <code>null</code> is returned. * * @param resource the resource to unsubscribe from this repo * * @return the mapping that was removed or <code>null</code> if the resource was not subscribed to this repo */ public ResourceRepo removeResource(Resource resource) { if ((this.resourceRepos == null) || (resource == null)) { return null; } ResourceRepo doomed = null; for (ResourceRepo rc : this.resourceRepos) { if (resource.equals(rc.getResourceRepoPK().getResource())) { doomed = rc; break; } } if (doomed != null) { this.resourceRepos.remove(doomed); } return doomed; } /** * Returns the explicit mapping entities. * * @return the mapping entities * * @see #getContentSources() */ public Set<RepoContentSource> getRepoContentSources() { return repoContentSources; } /** * Returns the explicit mapping entities. * * @return the mapping entities * * @see #getContentSources() */ public Set<RepoDistribution> getRepoDistributions() { return repoDistributions; } public Set<RepoAdvisory> getRepoAdvisories() { return repoAdvisories; } public void setRepoAdvisories(Set<RepoAdvisory> repoAdvisories) { this.repoAdvisories = repoAdvisories; } /** * Get the overall sync status of this Repository. This is a summation of all the syncs. * * There is a weight to the status since this returns the most 'relevant' status: * * 1) ContentSourceSyncStatus.FAILURE * 2) ContentSourceSyncStatus.INPROGRESS * 3) ContentSourceSyncStatus.SUCCESS * * @return String summary of the status of this Repository */ @Transient public String getSyncStatus() { return this.syncStatus; } /** * The content sources that this repo serves up. These are the content sources that provide or provided packages * for this repo. This relationship is weak; a content source may not be in this set but the packages it loaded * into this repo may still exist. * * <p>The returned set is not backed by this entity - if you want to alter the set of associated content sources, * use {@link #getRepoContentSources()} or {@link #addContentSource(ContentSource)}, * {@link #removeContentSource(ContentSource)}.</p> */ public Set<ContentSource> getContentSources() { HashSet<ContentSource> contentSources = new HashSet<ContentSource>(); if (repoContentSources != null) { for (RepoContentSource ccs : repoContentSources) { contentSources.add(ccs.getRepoContentSourcePK().getContentSource()); } } return contentSources; } /** * Directly assign a content source to this repo. * * @param contentSource * * @return the mapping that was added */ public RepoContentSource addContentSource(ContentSource contentSource) { if (this.repoContentSources == null) { this.repoContentSources = new HashSet<RepoContentSource>(); } RepoContentSource mapping = new RepoContentSource(this, contentSource); this.repoContentSources.add(mapping); return mapping; } /** * Removes the content source from this repo, if it exists. If it does exist, the mapping that was removed is * returned; if the given content source did not exist as one that is a member of this repo, <code>null</code> is * returned. * * @param contentSource the content source to remove from this repo * * @return the mapping that was removed or <code>null</code> if the content source was not mapped to this repo */ public RepoContentSource removeContentSource(ContentSource contentSource) { if ((this.repoContentSources == null) || (contentSource == null)) { return null; } RepoContentSource doomed = null; for (RepoContentSource ccs : this.repoContentSources) { if (contentSource.equals(ccs.getRepoContentSourcePK().getContentSource())) { doomed = ccs; break; } } if (doomed != null) { this.repoContentSources.remove(doomed); } return doomed; } /** * Returns the explicit mapping entities. * * @return the mapping entities * * @see #getPackageVersions() */ public Set<RepoPackageVersion> getRepoPackageVersions() { return repoPackageVersions; } /** * The package versions that this repo serves up. Subscribers to this repo will have access to the returned * set of package versions. These are package versions that were directly assigned to the repo and those that * were assigned via its relationship with its content sources. This is the relationship that should be consulted * when determining what package versions this repo exposes - do not look at the indirect relationship from * content sources to package versions. When content sources are assigned to this repo, this package version * relationship will be automatically managed. * * <p>The returned set is not backed by this entity - if you want to alter the set of associated package versions, * use {@link #getRepoPackageVersions()} or {@link #addPackageVersion(PackageVersion)}, * {@link #removePackageVersion(PackageVersion)}.</p> */ public Set<PackageVersion> getPackageVersions() { HashSet<PackageVersion> packageVersions = new HashSet<PackageVersion>(); if (repoPackageVersions != null) { for (RepoPackageVersion cpv : repoPackageVersions) { packageVersions.add(cpv.getRepoPackageVersionPK().getPackageVersion()); } } return packageVersions; } /** * Directly assign a package version to this repo. * * @param packageVersion * * @return the mapping that was added */ public RepoPackageVersion addPackageVersion(PackageVersion packageVersion) { if (this.repoPackageVersions == null) { this.repoPackageVersions = new HashSet<RepoPackageVersion>(); } RepoPackageVersion mapping = new RepoPackageVersion(this, packageVersion); this.repoPackageVersions.add(mapping); return mapping; } /** * Removes the package version from this repo, if it exists. If it does exist, the mapping that was removed is * returned; if the given package version did not exist as one that is a member of this repo, <code>null</code> * is returned. * * @param packageVersion the package version to remove from this repo * * @return the mapping that was removed or <code>null</code> if the package version was not mapped to this repo */ public RepoPackageVersion removePackageVersion(PackageVersion packageVersion) { if ((this.repoPackageVersions == null) || (packageVersion == null)) { return null; } RepoPackageVersion doomed = null; for (RepoPackageVersion cpv : this.repoPackageVersions) { if (packageVersion.equals(cpv.getRepoPackageVersionPK().getPackageVersion())) { doomed = cpv; break; } } if (doomed != null) { this.repoPackageVersions.remove(doomed); } return doomed; } /** * Returns the explicit mapping entities. * * @return the mapping entities * * @see #getRepoGroups() */ public Set<RepoRepoGroup> getRepoRepoGroups() { return repoRepoGroups; } /** * The repogroups that this repo belongs to. * * <p>The returned set is not backed by this entity - if you want to alter * the set of associated repogroups, * use {@link #getRepoRepoGroups()} or {@link #addRepoGroup(RepoGroup)}, * {@link #removeRepoGroup(RepoGroup)}.</p> */ public Set<RepoGroup> getRepoGroups() { HashSet<RepoGroup> repoGroups = new HashSet<RepoGroup>(); if (repoRepoGroups != null) { for (RepoRepoGroup rrg : repoRepoGroups) { repoGroups.add(rrg.getRepoRepoGroupPK().getRepoGroup()); } } return repoGroups; } /** * Directly assign a repogroup to this repo. * * @param repoGroup * * @return the mapping that was added */ public RepoRepoGroup addRepoGroup(RepoGroup repoGroup) { if (this.repoRepoGroups == null) { this.repoRepoGroups = new HashSet<RepoRepoGroup>(); } RepoRepoGroup mapping = new RepoRepoGroup(this, repoGroup); this.repoRepoGroups.add(mapping); return mapping; } /** * Removes association with a repo group, if it exists. If it does exist, the mapping that was removed is * returned; if the given repo group did not exist as one that is a associated to this repo, <code>null</code> is * returned. * * @param repoGroup the repo group to disassociate from this repo * * @return the mapping that was removed or <code>null</code> if the repo group was not associated with this repo */ public RepoRepoGroup removeRepoGroup(RepoGroup repoGroup) { if ((this.repoRepoGroups == null) || (repoGroup == null)) { return null; } RepoRepoGroup doomed = null; for (RepoRepoGroup rrg : this.repoRepoGroups) { if (repoGroup.equals(rrg.getRepoRepoGroupPK().getRepoGroup())) { doomed = rrg; break; } } if (doomed != null) { this.repoRepoGroups.remove(doomed); } return doomed; } /** * Returns the explicit mapping entities. * * @return the mapping entities * * @see #getRepoRelationships() */ public Set<RepoRepoRelationship> getRepoRepoRelationships() { return repoRepoRelationships; } /** * The reporelationships that this repo belongs to. * * <p>The returned set is not backed by this entity - if you want to alter * the set of associated repoRelationships, * use {@link #getRepoRepoRelationships()} or {@link #addRepoRelationship(RepoRelationship)}, * {@link #removeRepoRelationship(RepoRelationship)}.</p> */ public Set<RepoRelationship> getRepoRelationships() { HashSet<RepoRelationship> repoRelationships = new HashSet<RepoRelationship>(); if (repoRepoRelationships != null) { for (RepoRepoRelationship rrr : repoRepoRelationships) { repoRelationships.add(rrr.getRepoRepoRelationshipPK().getRepoRelationship()); } } return repoRelationships; } /** * Directly assign a reporelationship to this repo. * * @param repoRelationship * * @return the mapping that was added */ public RepoRepoRelationship addRepoRelationship(RepoRelationship repoRelationship) { if (this.repoRepoRelationships == null) { this.repoRepoRelationships = new HashSet<RepoRepoRelationship>(); } RepoRepoRelationship mapping = new RepoRepoRelationship(this, repoRelationship); this.repoRepoRelationships.add(mapping); return mapping; } /** * Removes association with a repo relationship, if it exists. If it does exist, the mapping that was removed is * returned; if the given repo relationship did not exist as one that is a associated to this repo, <code>null</code> is * returned. * * @param repoRelationship the repo relationship to disassociate from this repo * * @return the mapping that was removed or <code>null</code> if the repo relationship was not associated with this repo */ public RepoRepoRelationship removeRepoRelationship(RepoRelationship repoRelationship) { if ((this.repoRepoRelationships == null) || (repoRelationship == null)) { return null; } RepoRepoRelationship doomed = null; for (RepoRepoRelationship rrr : this.repoRepoRelationships) { if (repoRelationship.equals(rrr.getRepoRepoRelationshipPK().getRepoRelationship())) { doomed = rrr; break; } } if (doomed != null) { this.repoRepoRelationships.remove(doomed); } return doomed; } @Override public String toString() { return "Repo: id=[" + this.id + "], name=[" + this.name + "]"; } @Override public int hashCode() { int result = 1; result = (31 * result) + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if ((obj == null) || (!(obj instanceof Repo))) { return false; } final Repo other = (Repo) obj; if (name == null) { if (other.name != null) { return false; } } else if (!name.equals(other.name)) { return false; } return true; } @PrePersist void onPersist() { this.lastModifiedDate = this.creationDate = System.currentTimeMillis(); } @PreUpdate void onUpdate() { this.lastModifiedDate = System.currentTimeMillis(); } /** * Set the sync status for this repo. * @param syncStatusIn */ @Transient public void setSyncStatus(String syncStatusIn) { this.syncStatus = syncStatusIn; } public void addSyncResult(RepoSyncResults syncResult) { if (this.syncResults == null) { this.syncResults = new ArrayList<RepoSyncResults>(); } this.syncResults.add(syncResult); syncResult.setRepo(this); } /** * The list of sync results - order ENSURED by the incrementing ID of this object */ @NotNull public List<RepoSyncResults> getSyncResults() { if (this.syncResults == null) { this.syncResults = new ArrayList<RepoSyncResults>(); return this.syncResults; } Collections.sort(syncResults, new Comparator<RepoSyncResults>() { public int compare(RepoSyncResults c1, RepoSyncResults c2) { Integer id1 = c1.getId(); Integer id2 = c2.getId(); return id1.compareTo(id2); } }); return syncResults; } /** * @return the owner */ public Subject getOwner() { return owner; } /** * @param owner the owner to set */ public void setOwner(Subject owner) { this.owner = owner; } /** * Private repositories are only accessible by their owners or * {@link org.rhq.core.domain.authz.Permission#MANAGE_REPOSITORIES RepositoryManagers}. * Private repositories without an owner are only accessible by the RepositoryManagers. * <p> * A public repository (whether owned by a specific user or not) is accessible by anyone. * * @return whether this repository is private */ public boolean isPrivate() { return isPrivate; } /** * @see #isPrivate() */ public void setPrivate(boolean priv) { this.isPrivate = priv; } }