/* * FrontlineSMS <http://www.frontlinesms.com> * Copyright 2007, 2008 kiwanja * * This file is part of FrontlineSMS. * * FrontlineSMS 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 3 of the License, or (at * your option) any later version. * * FrontlineSMS 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 FrontlineSMS. If not, see <http://www.gnu.org/licenses/>. */ package net.frontlinesms.data.domain; import javax.persistence.*; import net.frontlinesms.data.EntityField; /** * Object representing a named group of contacts. A group can contain sub-groups * whose membership is entirely independent of the main group. * @author Alex */ @Entity(name=Group.TABLE_NAME) public class Group { //> DATABASE NAMES /** Table name */ public static final String TABLE_NAME = "frontline_group"; /** Database column name for property: {@link #name} */ static final String COLUMN_PATH = "path"; //> CONSTANTS /** Character used to separate paths in the group name */ public static final char PATH_SEPARATOR = '/'; //> ENTITY FIELDS /** Details of the fields that this class has. */ public enum Field implements EntityField<Group> { /** Represents {@link #path} */ PATH(COLUMN_PATH); /** name of a field */ private final String fieldName; /** * Creates a new {@link Field} * @param fieldName name of the field */ Field(String fieldName) { this.fieldName = fieldName; } /** @see EntityField#getFieldName() */ public String getFieldName() { return this.fieldName; } } //> PROPERTIES /** * The path of this group. * This is a {@link #PATH_SEPARATOR}-separated list of this group and its parents. * Empty string denotes the root group. * There is no leading or trailing {@link #PATH_SEPARATOR} */ @Id @Column(name=COLUMN_PATH, unique=true, updatable=false, nullable=false) private String path; private String parentPath; //> CONSTRUCTORS /** Empty constructor for hibernate */ Group() {} private Group(String path) { assert(path.startsWith("" + PATH_SEPARATOR)) : "Path must start with the seprator character '" + PATH_SEPARATOR + "'"; assert(path.indexOf(',') == -1) : "Comma illegal in group name."; this.path = path; this.parentPath = getParentPath(path); } /** * Creates a group with the specified parent and name. * @param parent The parent of the group to be created. * @param name The name of the new group. */ public Group(Group parent, String name) { assert((parent != null && name != null) || (parent == null && name == null)) : "Only the root group should have a null parent, and that should be defined internally."; if(parent == null && name == null) { this.path = ""; } else { if(name.length() == 0) throw new IllegalArgumentException("Group names cannot be empty."); if(name.indexOf(PATH_SEPARATOR) != -1) throw new IllegalArgumentException("Group names cannot contain the path separator character '" + PATH_SEPARATOR + "'"); if(name.indexOf(',') != -1) throw new IllegalArgumentException("Comma character not valid in group name."); if(parent.isRoot()) { this.path = PATH_SEPARATOR + name; } else { this.path = parent.getPath() + PATH_SEPARATOR + name; } } this.parentPath = getParentPath(path); } //> ACCESSOR METHODS /** @return the name of this group */ public String getName() { if(this.isRoot()) return ""; else return this.path.substring(this.path.lastIndexOf(PATH_SEPARATOR) + 1); } /** @return the path of this group */ public String getPath() { return this.path; } /** * Returns the parent of this group. * @return {@link #parent} */ public Group getParent() { if(this.isRoot()) { return null; } else { if(this.parentPath.length() == 0) { return new Group(null, null); } else { return new Group(parentPath); } } } public static String getParentPath(String path) { if(path.length() == 0) return ""; String parentPath = path.substring(0, path.lastIndexOf(PATH_SEPARATOR)); if(parentPath.length() == 0) { return ""; } assert(parentPath.charAt(0) == PATH_SEPARATOR) : "Splitting performed incorrectly on group path."; return parentPath; } /** @return <code>true</code> if this is the root group */ public boolean isRoot() { return this.path.length() == 0; } //> GENERATED CODE /** @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((path == null) ? 0 : path.hashCode()); return result; } /** @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Group other = (Group) obj; if (path == null) { if (other.path != null) return false; } else if (!path.equals(other.path)) return false; return true; } @Override public String toString() { return this.path; } }