/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* See LICENSE.txt included in this distribution for the specific
* language governing permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at LICENSE.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
*/
package org.opensolaris.opengrok.configuration;
import java.util.Locale;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
* Placeholder for the information about subgroups of projects and repositories.
*
* Supports natural ordering based on case insensitive group names.
*
* @author Krystof Tulinger
* @version $Revision$
*/
public class Group implements Comparable<Group>, Nameable {
private String name;
/**
* Group regexp pattern.
*
* No project matches the empty pattern of "" however this group can still
* be used as a superior group for other groups (without duplicating the
* projects).
*/
private String pattern = "";
/**
* Compiled group pattern.
*
* We set up the empty compiled pattern by default to "()" to reduce code
* complexity when performing a match for a group without a pattern.
*
* This pattern is updated whenever the string pattern {@link #pattern} is
* updated.
*
* @see #setPattern(String)
*/
private Pattern compiledPattern = Pattern.compile("()");
private Group parent;
private int flag;
private Set<Group> subgroups = new TreeSet<>();
private Set<Group> descendants = new TreeSet<>();
private Set<Project> projects = new TreeSet<>();
private Set<Project> repositories = new TreeSet<>();
private Set<Group> parents;
public Set<Project> getProjects() {
return projects;
}
public void addProject(Project p) {
this.projects.add(p);
}
public void addRepository(Project p) {
this.repositories.add(p);
}
public Set<Group> getDescendants() {
return descendants;
}
public void setDescendants(Set<Group> descendants) {
this.descendants = descendants;
}
public void addDescendant(Group g) {
this.descendants.add(g);
}
public void removeDescendant(Group g) {
this.descendants.remove(g);
}
public Set<Project> getRepositories() {
return repositories;
}
public void setSubgroups(Set<Group> subgroups) {
this.subgroups = subgroups;
}
public void setProjects(Set<Project> projects) {
this.projects = projects;
}
public void setRepositories(Set<Project> repositories) {
this.repositories = repositories;
}
public Set<Group> getSubgroups() {
return subgroups;
}
public void addGroup(Group g) {
g.setParent(this);
subgroups.add(g);
descendants.add(g);
}
public Set<Group> getParents() {
if (parents == null) {
parents = new TreeSet<>();
Group tmp = parent;
while (tmp != null) {
parents.add(tmp);
tmp = tmp.getParent();
}
}
return parents;
}
/**
* Collect all related groups to this group. A related group is
* <ul>
* <li>any anchestor</li>
* <li>any subgroup</li>
* </ul>
*
* @return all collected related groups to this group
*/
public Set<Group> getRelatedGroups() {
Set<Group> groupsTmp = new TreeSet<>();
groupsTmp.addAll(getDescendants());
groupsTmp.addAll(getParents());
return groupsTmp;
}
/**
* Collect all group's projects and repositories included in this group and
* in any subgroup.
*
* @return all collected projects and repositories
*/
public Set<Project> getAllProjects() {
Set<Project> projectsTmp = new TreeSet<>();
for (Project p : getRepositories()) {
projectsTmp.add(p);
}
for (Project p : getProjects()) {
projectsTmp.add(p);
}
for (Group grp : getDescendants()) {
projectsTmp.addAll(grp.getAllProjects());
}
return projectsTmp;
}
public Group getParent() {
return parent;
}
public void setParent(Group parent) {
this.parent = parent;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
public String getPattern() {
return pattern;
}
/**
* Set the group pattern.
*
* @param pattern the regexp pattern for this group
* @throws PatternSyntaxException when the pattern is invalid
*/
public void setPattern(String pattern) throws PatternSyntaxException {
this.compiledPattern = Pattern.compile("(" + pattern + ")");
this.pattern = pattern;
}
public int getFlag() {
return flag;
}
public void setFlag(int flag) {
this.flag = flag;
}
/**
* Test group for a match
*
* @param p project
* @return true if project's description matches the group pattern
*/
public boolean match(Project p) {
return compiledPattern.matcher(p.getName()).matches();
}
@Override
public int compareTo(Group o) {
return getName().toUpperCase(Locale.getDefault())
.compareTo(o.getName().toUpperCase(Locale.getDefault()));
}
@Override
public int hashCode() {
int hash = 3;
hash = 41 * hash + (this.name == null ? 0 : this.name.toUpperCase(Locale.getDefault()).hashCode());
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Group other = (Group) obj;
return !(this.name != other.name
&& (this.name == null
|| !this.name.toUpperCase(Locale.getDefault()).equals(other.name.toUpperCase(Locale.getDefault()))));
}
/**
* Returns group object by its name
*
* @param name name of a group
* @return group that fits the name
*/
public static Group getByName(String name) {
Group ret = null;
RuntimeEnvironment env = RuntimeEnvironment.getInstance();
if (env.hasGroups()) {
for (Group grp : env.getGroups()) {
if (name.equals(grp.getName())) {
ret = grp;
}
}
}
return ret;
}
}