/*
* Copyright (C) 2012 maartenl
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package mmud.database.entities.game;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.Set;
import java.util.SortedSet;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import mmud.database.entities.Ownage;
import mmud.database.entities.characters.Person;
import mmud.database.entities.characters.User;
import mmud.exceptions.MudException;
import mmud.rest.services.GuildBean;
import org.eclipse.persistence.annotations.Customizer;
/**
*
* @author maartenl
*/
@Entity
@Table(name = "mm_guilds")
@NamedQueries(
{
@NamedQuery(name = "Guild.findAll", query = "SELECT g FROM Guild g ORDER BY g.title")
,
@NamedQuery(name = "Guild.findByName", query = "SELECT g FROM Guild g WHERE g.name = :name")
,
@NamedQuery(name = "Guild.findByTitle", query = "SELECT g FROM Guild g WHERE g.title = :title")
,
@NamedQuery(name = "Guild.findByDaysguilddeath", query = "SELECT g FROM Guild g WHERE g.daysguilddeath = :daysguilddeath")
,
@NamedQuery(name = "Guild.findByMaxguilddeath", query = "SELECT g FROM Guild g WHERE g.maxguilddeath = :maxguilddeath")
,
@NamedQuery(name = "Guild.findByMinguildmembers", query = "SELECT g FROM Guild g WHERE g.minguildmembers = :minguildmembers")
,
@NamedQuery(name = "Guild.findByMinguildlevel", query = "SELECT g FROM Guild g WHERE g.minguildlevel = :minguildlevel")
,
@NamedQuery(name = "Guild.findByGuildurl", query = "SELECT g FROM Guild g WHERE g.guildurl = :guildurl")
,
@NamedQuery(name = "Guild.findByActive", query = "SELECT g FROM Guild g WHERE g.active = :active")
,
@NamedQuery(name = "Guild.findByCreation", query = "SELECT g FROM Guild g WHERE g.creation = :creation")
,
@NamedQuery(name = "Guild.findGuildHopefuls", query = "SELECT p from User p, p.attributes c WHERE c.charattributePK.name = :attributename and c.value = :guildname and c.valueType = :valuetype")
})
@Customizer(PersonsFilterForGuild.class)
public class Guild implements Serializable, DisplayInterface, Ownage
{
private static final long serialVersionUID = 1L;
private static final String NAME_REGEXP = "[a-zA-Z]{3,}";
private static final String GUILDCOLOUR_REGEXP = "[#a-zA-Z0-9]{3,}";
@Id
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 20)
@Column(name = "name")
@Pattern(regexp = NAME_REGEXP, message = "Invalid guildname. Only letters are allowed, and there should be at least three.")
private String name;
@Size(max = 100)
@Column(name = "title")
private String title;
@Column(name = "daysguilddeath")
private Integer daysguilddeath = 10;
@Column(name = "maxguilddeath")
private Integer maxguilddeath = 10;
@Column(name = "minguildmembers")
private Integer minguildmembers = 20;
@Column(name = "minguildlevel")
private Integer minguildlevel;
@Lob
@Size(max = 65535)
@Column(name = "guilddescription")
private String guilddescription;
@Size(max = 255)
@Column(name = "guildurl")
private String guildurl;
@Size(max = 255)
@Column(name = "imageurl")
private String imageurl;
@Size(max = 100)
@Column(name = "colour")
@Pattern(regexp = GUILDCOLOUR_REGEXP, message = "Invalid guildcolour. Only (at least three) letters are allowed or a hex code.")
private String colour;
@Basic(optional = false)
@NotNull
@Column(name = "active")
private Boolean active;
@Basic(optional = false)
@Column(name = "creation")
@Temporal(TemporalType.TIMESTAMP)
private Date creation;
@Lob
@Size(max = 65535)
@Column(name = "logonmessage")
private String logonmessage;
@OneToMany(mappedBy = "guild")
@OrderBy("name")
private Set<User> activeMembers;
@OneToMany(mappedBy = "guild")
@OrderBy("name")
private Set<User> members;
@JoinColumn(name = "owner", referencedColumnName = "name")
@ManyToOne
private Admin owner;
@JoinColumn(name = "bossname", nullable = false, referencedColumnName = "name")
@ManyToOne(optional = false)
private User boss;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "guild")
@OrderBy("guildrankPK.guildlevel")
private Set<Guildrank> guildrankCollection;
public Guild()
{
}
public Guild(String name)
{
this.name = name;
}
public Guild(String name, Boolean active, Date creation)
{
this.name = name;
this.active = active;
this.creation = creation;
}
/**
* The name of the guild, is also the primary key.
*
* @return the name of the guild.
* @see #getTitle()
*/
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getTitle()
{
return title;
}
@Override
public String getMainTitle()
{
return getTitle();
}
public void setTitle(String title)
{
this.title = title;
}
public Integer getDaysguilddeath()
{
return daysguilddeath;
}
public void setDaysguilddeath(Integer daysguilddeath)
{
this.daysguilddeath = daysguilddeath;
}
public Integer getMaxguilddeath()
{
return maxguilddeath;
}
public void setMaxguilddeath(Integer maxguilddeath)
{
this.maxguilddeath = maxguilddeath;
}
public Integer getMinguildmembers()
{
return minguildmembers;
}
public void setMinguildmembers(Integer minguildmembers)
{
this.minguildmembers = minguildmembers;
}
public Integer getMinguildlevel()
{
return minguildlevel;
}
public void setMinguildlevel(Integer minguildlevel)
{
this.minguildlevel = minguildlevel;
}
public String getDescription()
{
return guilddescription;
}
public void setDescription(String guilddescription)
{
this.guilddescription = guilddescription;
}
public String getHomepage()
{
return guildurl;
}
public void setHomepage(String guildurl)
{
this.guildurl = guildurl;
}
public Boolean getActive()
{
return active;
}
public void setActive(Boolean active)
{
this.active = active;
}
public Date getCreation()
{
return creation;
}
public void setCreation(Date creation)
{
this.creation = creation;
}
public String getLogonmessage()
{
return logonmessage;
}
public void setLogonmessage(String logonmessage)
{
this.logonmessage = logonmessage;
}
public Set<User> getMembers()
{
return members;
}
public Set<User> getActiveMembers()
{
return activeMembers;
}
public void setMembers(SortedSet<User> personCollection)
{
this.members = personCollection;
}
public void setActiveMembers(SortedSet<User> personCollection)
{
this.activeMembers = personCollection;
}
@Override
public Admin getOwner()
{
return owner;
}
@Override
public void setOwner(Admin owner)
{
this.owner = owner;
}
/**
* Returns the guildmaster of this guild.
*
* @return a Person, the guildmaster. Should not be null, ...ever.
*/
public User getBoss()
{
return boss;
}
/**
* Sets the guildmaster of this guild.
*
* @param boss the new guildmaster. Should never be null.
* @throws MudException if new guildmaster is null, or not a member of this
* guild.
*/
public void setBoss(User boss) throws MudException
{
if (boss == null)
{
throw new MudException("There should always be a guildmaster of guild " + getName());
}
if (boss.getGuild() != null
&& (!boss.getGuild().getName().equals(
getName())))
{
throw new MudException(boss.getName() + " cannot be a guildmaster of guild " + getName() + ". Already is a guildmaster of " + boss.getGuild().getName());
}
this.boss = boss;
}
public Collection<Guildrank> getGuildrankCollection()
{
return guildrankCollection;
}
public void setGuildrankCollection(SortedSet<Guildrank> guildrankCollection)
{
this.guildrankCollection = guildrankCollection;
}
/**
* Indicates the colour of the guild chat. The default is green.
*
* @return String indicating either a hexadecimal value (for example #FFFFFF) or
* the name of a colour (for example Blue).
*/
public String getColour()
{
if (colour == null || colour.trim().equals(""))
{
return DEFAULT_GUILDMESSAGE_COLOUR;
}
return colour;
}
public static final String DEFAULT_GUILDMESSAGE_COLOUR = "Green";
/**
* @see #getColour()
* @param colour
*/
public void setColour(String colour)
{
this.colour = colour;
}
@Override
public int hashCode()
{
int hash = 0;
hash += (name != null ? name.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object)
{
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Guild))
{
return false;
}
Guild other = (Guild) object;
if ((this.name == null && other.name != null) || (this.name != null && !this.name.equals(other.name)))
{
return false;
}
return true;
}
@Override
public String toString()
{
return "mmud.database.entities.game.Guild[ name=" + name + " ]";
}
/**
* Returns a description in case the guild is in danger of being purged from
* the database. This is necessary to make sure there is not a plethora of
* guilds with few members.
* <P>
* The following preconditions are in effect:
* <UL>
* <LI>the guild is active
* <LI>there are too few guildmembers (minguildmembers > amountofmembers)
* </UL>
* TODO : remove html tags here, let it return a daysguilddeath or something
*
* @return String indicating if there are too few members, usually should be
* the empty string if all is well.
*/
public String getAlarmDescription()
{
if ((!getActive()) || (getMinguildmembers() <= getMembers().size()))
{
return "";
}
return "The minimum amount of members of this guild is "
+ getMinguildmembers()
+ ".<br/>The guild has too few members, and will be removed in "
+ getDaysguilddeath() + " days.";
}
/**
* Searches and returns the person by name in this guild, or null if not
* found.
*
* @param name the name of the person to look for.
* @return a Person.
*/
public User getMember(String name)
{
for (User person : members)
{
if (person.getName().equalsIgnoreCase(name))
{
return person;
}
}
return null;
}
/**
* Searches and returns the person by name in this guild, or null if not
* found. Only searches for members that are currently playing.
*
* @param name the name of the person to look for.
* @return a Person.
*/
public User getActiveMember(String name)
{
for (User person : activeMembers)
{
if (person.getName().equalsIgnoreCase(name))
{
return person;
}
}
return null;
}
/**
* communication method to everyone in the guild, that is active. The
* message is not parsed. Bear in mind that this method should only be used
* for communication about environmental issues. If the communication
* originates from a User/Person, you should use sendMessage(aPerson,
* aMessage). Otherwise the Ignore functionality will be omitted.
*
* @param aMessage the message
* @throws MudException if the room is not correct
* @see Person#writeMessage(java.lang.String)
*/
public void sendMessage(String aMessage)
throws MudException
{
for (Person myChar : activeMembers)
{
myChar.writeMessage(aMessage);
}
}
/**
* character communication method to everyone in the guild. The message is
* parsed, based on who is sending the message.
* <p>
* Example output: <span style="color:red;">[guild] Karn: Hello, everyone!</br></span></p>
*
* @param aPerson the person who is the source of the message.
* @param aMessage the message
*
* @see Person#writeMessage(mmud.database.entities.characters.Person,
* java.lang.String)
*/
public void sendMessage(Person aPerson, String aMessage) throws MudException
{
String message = "<span style=\"color:" + getColour() + ";\">[guild]<b>" + aPerson.getName() + "</b>: " + aMessage + "</span><br/>\r\n";
for (Person myChar : activeMembers)
{
myChar.writeMessage(aPerson, message);
}
}
@Override
public String getImage()
{
return imageurl;
}
/**
* Sets an url pointing to an image.
*
* @see #getImage()
* @param image
*/
public void setImage(String image)
{
imageurl = image;
}
/**
* Returns the rank based on the rank id/guildlevel. In case the rank id
* does not exist, null will be returned.
*
* @param id the id of the rank/guildlevel
* @return the rank in the guild
*/
public Guildrank getRank(int id)
{
for (Guildrank rank : guildrankCollection)
{
if (rank.getGuildrankPK().getGuildlevel() == id)
{
return rank;
}
}
return null;
}
/**
* This is primarily used for displaying the current status of the guild to
* a member of the guild.
*
* @return a string containing the description of the guild.
*/
@Override
public String getBody() throws MudException
{
StringBuffer result = new StringBuffer();
if (getLogonmessage() != null)
{
result.append("<B>Logonmessage:</B>").append(getLogonmessage()).append("<P>");
}
result.append("<B>Members</B><P><TABLE>");
for (User character : members)
{
result.append("<TR><TD>");
if (character.isActive())
{
result.append("<B>");
}
result.append(character.getName());
result.append("</TD><TD>");
if (character.getGuildrank() != null)
{
Guildrank rank = character.getGuildrank();
result.append(" ").append(rank.getTitle());
} else
{
result.append(" Initiate");
}
if (character.isActive())
{
result.append("</B>");
}
result.append("</TD></TR>");
}
result.append("</TABLE><P><B>Hopefuls</B><BR>");
// TODO
GuildBean guildBean;
try
{
guildBean = (GuildBean) new InitialContext().lookup("java:module/GuildBean");
} catch (NamingException e)
{
throw new MudException("Unable to retrieve guild.", e);
}
for (Person hopefull : guildBean.getGuildHopefuls(this))
{
result.append(hopefull.getName());
result.append(" ");
}
result.append("<P><B>Guildranks</B><BR>");
for (Guildrank rank : guildrankCollection)
{
result.append(rank.getTitle()).append("(").append(rank.getGuildrankPK().getGuildlevel()).append(")<BR>");
}
// TODO
// The guild is <I>" + (isActive() ? "active" : "inactive") + "</I>.<BR>
return "<H1><IMG SRC=\"/images/gif/money.gif\">" + getTitle()
+ "</H1>You" + " are a member of the <I>" + getTitle()
+ "</I> (" + getName() + ").<BR>The current guildmaster is <I>"
+ getBoss().getName() + "</I>.<BR>The guild has " + members.size()
+ " members." + getAlarmDescription() + "<P>" + result + "<P>";
}
/**
* Adds a guildrank.
*
* @param rank the rank to add
* @return true if this set did not already contain the specified element
*/
public boolean addGuildrank(Guildrank rank)
{
return guildrankCollection.add(rank);
}
/**
* Deletes a guildrank.
*
* @param rank the rank to delete
* @return true if this set contained the specified element
*/
public boolean deleteGuildrank(Guildrank rank)
{
return guildrankCollection.remove(rank);
}
}