libreccm-legacy/ccm-ldn-terms/src/com/arsdigita/london/terms/Term.java

536 lines
16 KiB
Java
Executable File

/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library 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 2.1 of
* the License, or (at your option) any later version.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.arsdigita.london.terms;
import org.apache.log4j.Logger;
import org.apache.oro.text.perl.Perl5Util;
import com.arsdigita.categorization.Category;
import com.arsdigita.domain.DataObjectNotFoundException;
import com.arsdigita.domain.DomainCollection;
import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.kernel.ACSObject;
import com.arsdigita.persistence.DataCollection;
import com.arsdigita.persistence.DataObject;
import com.arsdigita.persistence.SessionManager;
import com.arsdigita.util.Assert;
/**
* Instances of this class represent entries in a domain
* of terms.
*
* Although terms are currently modelled using the
* categorization service, it is not neccessarily going
* remain this way, hence the getModel() method is
* protected.
*/
public class Term extends ACSObject {
private static final Logger s_log = Logger.getLogger(Term.class);
// PDF stuff
/** Object type of the associated PDL modell */
public static final String BASE_DATA_OBJECT_TYPE =
"com.arsdigita.london.terms.Term";
/** PDL property to store the unique ID, usually specified by the (formal)
* taxanomie. May be choosen arbitrarily if no formal taxonimie
* is in use. */
public static final String UNIQUE_ID = "uniqueID";
/** PDL property to store whether the term is to be included in the AtoZ
* list of categories. */
public static final String IN_ATOZ = "inAtoZ";
/** PDL property to store the url shortcut for the domain this term is
* part of.*/
public static final String SHORTCUT = "shortcut";
/** PDL property to store the domain this term is belonging to. */
public static final String DOMAIN = "domain";
/** PDL property to store the category used to store the generic
* properties (e.g. name, description, etc) this term. */
public static final String MODEL = "model";
/** Handle to the models (category) name value */
public static final String NAME = MODEL + "." + Category.NAME;
/** Handle to the models (category) description value */
public static final String DESCRIPTION = MODEL + "." + Category.DESCRIPTION;
/**
* Contructor.
*/
Term() {
this(BASE_DATA_OBJECT_TYPE);
}
/**
* Contructor.
*/
protected Term(String type) {
super(type);
}
/**
* Contructor, creating a domain object from the specified data object.
*/
Term(DataObject dobj) {
super(dobj);
}
/**
* @see #create(String, String, boolean, String, Domain)
*/
public static Term create(Integer uniqueID,
String name,
boolean inAtoZ,
String shortcut,
Domain domain) {
return create(String.valueOf(uniqueID), name, inAtoZ, shortcut, domain);
}
/**
* Creates a new term within a domain. All
* parameters are required except for shortcut
*
* @param uniqueID the unique identifier for the term
* @param name the name of the term
* @param inAtoZ whether it is relevant for an A-Z listing
* @param shortcut the url shortcut for the domain
* @param domain the domain containing this term
* @return the newly created term
*/
public static Term create(String uniqueID,
String name,
boolean inAtoZ,
String shortcut,
Domain domain) {
Term term = new Term();
term.set(MODEL, new Category());
term.setUniqueID(uniqueID);
term.setDomain(domain);
term.setName(name);
term.setInAtoZ(inAtoZ);
term.setShortcut(shortcut);
if (s_log.isDebugEnabled()) {
s_log.debug("Created term " + term.getID() + " with unique id " +
uniqueID + " and name " + name + " in domain " +
domain);
}
return term;
}
/**
* Creates a new term using an existing model category.
*/
static Term create(Category cat,
String uniqueID,
boolean inAtoZ,
String shortcut,
Domain domain) {
Term term = new Term();
term.set(MODEL, cat);
term.setUniqueID(uniqueID);
term.setDomain(domain);
term.setName(cat.getName());
term.setInAtoZ(inAtoZ);
term.setShortcut(shortcut);
if (s_log.isDebugEnabled()) {
s_log.debug("Created term " + term.getID() + " with unique id " +
uniqueID + " and name " + cat.getName() + " in domain " +
domain + " using model category: " + cat);
}
return term;
}
/**
* Sets the unique ID
*
* @param uniqueID
*/
private void setUniqueID(String uniqueID) {
Assert.exists(uniqueID, String.class);
set(UNIQUE_ID, uniqueID);
}
/**
* Retrieves the unique identifier for this term.
*/
public String getUniqueID() {
return (String)get(UNIQUE_ID);
}
/**
* Updates the name of this term just by using the underlying
* model (category core service).
*
* @param name the term's new name
*/
public void setName(String name) {
Assert.exists(name, String.class);
getModel().setName(name);
getModel().setURL(cleanURL(name));
}
/**
* Retrieves the name of this term just by retrieving it from the
* underlying model (category service).
*
* @return the name of the term
*/
public String getName() {
return getModel().getName();
}
/**
* Updates the description of this term just by using (delegating) to the
* underlying model (category core service).
*
* @param description the term's new description
*/
public void setDescription(String description) {
Assert.exists(description, String.class);
getModel().setDescription(description);
}
/**
* Retrieves the description of this term just by using (delegate) to the
* underlying model (category core service).
* @return the description of the term
*/
public String getDescription() {
return getModel().getDescription();
}
/**
* Update the flag indicating whether this
* term is suitable for inclusion in an A-Z.
* @param inAtoZ the new value for the flag
*/
public void setInAtoZ(boolean inAtoZ) {
set(IN_ATOZ, Boolean.valueOf(inAtoZ));
}
/**
* Determines whether the term is suitable
* for inclusion in an A-Z.
*/
public boolean isInAtoZ() {
return ((Boolean)get(IN_ATOZ)).booleanValue();
}
/**
* Update the shortcut for this term
* @param the new value for the shortcut
*/
public void setShortcut(String shortcut) {
set(SHORTCUT, shortcut);
}
/**
* Retrieves the URL fragment forming a shortcut
* to this term
*/
public String getShortcut() {
return (String)get(SHORTCUT);
}
/**
* Associates this term to the domain it is going to be a part of.
*
* @param domain
*/
private void setDomain(Domain domain) {
Assert.exists(domain, Domain.class);
setAssociation(DOMAIN, domain);
}
/**
* Retrieves the domain containing this term.
*
* @return the domain containing this term
*/
public Domain getDomain() {
return (Domain)DomainObjectFactory
.newInstance((DataObject)get(DOMAIN));
}
/**
* Fetch an Instance of the underlying model to store / retrieve the
* generic category properties.
*
* @return a Category object.
*/
public Category getModel() {
return (Category)DomainObjectFactory
.newInstance((DataObject)get(MODEL));
}
/**
* Is this term a non-preferred term (synonym)?
* @return <code>true</code> if this term has at least one preferred term, otherwise <code>false</code>.
*/
public boolean isNonPreferredTerm() {
return !isPreferredTerm();
}
/**
* Is this term a preferred term?
*
* @return <code>true</code> if this term has no preferred term,
* otherwise <code>false</code>.
*/
public boolean isPreferredTerm() {
DomainCollection dc = getPreferredTerms();
try
{
return dc.isEmpty();
}
finally {
dc.close();
}
}
/**
* Adds a narrower term to this term
* @param term the narrower term
* @param isDefault whether this is the default broader term
*/
public void addNarrowerTerm(Term term,
boolean isDefault,
boolean isPreferred) {
//Assert.isTrue(term.getDomain().equals(getDomain()),
// "narrower term is in this domain");
if (s_log.isDebugEnabled()) {
s_log.debug("Adding narrower term " + term + " to " +
this + " isDefault?" + isDefault);
}
getModel().addChild(term.getModel());
term.getModel().setEnabled(isPreferred);
if (isDefault) {
term.getModel().setDefaultParentCategory(getModel());
}
}
/**
* Removes a narrower term from this term
* @param term the narrower term to remove
*/
public void removeNarrowerTerm(Term term) {
if (s_log.isDebugEnabled()) {
s_log.debug("Removing narrower term " + term + " from " +
this);
}
getModel().removeChild(term.getModel());
}
/**
* Retrieves the collection of narrower terms
* @return a collection of narrower terms
*/
public DomainCollection getNarrowerTerms() {
DomainCollection terms = getDomain().getTerms();
terms.addEqualsFilter("model.parents.id", getModel().getID());
terms.addEqualsFilter("model.parents.link.relationType", "child");
return terms;
}
/**
* Retrieves the collection of narrower terms
* for which this term is the default parent
* @return a collection of narrower terms
*
*/
public DomainCollection getDefaultNarrowerTerms() {
DomainCollection terms = getNarrowerTerms();
terms.addEqualsFilter("model.parents.link.isDefault", Boolean.TRUE);
return terms;
}
/**
* Retrieves the collection of broader terms
* @return a collection of broader terms
*/
public DomainCollection getBroaderTerms() {
DomainCollection terms = getDomain().getTerms();
terms.addEqualsFilter("model.related.id", getModel().getID());
terms.addEqualsFilter("model.related.link.relationType", "child");
return terms;
}
/**
* Retrieves the default broader term
* @return the default broader term
*/
public Term getBroaderTerm() {
DomainCollection terms = getBroaderTerms();
terms.addEqualsFilter("model.related.link.isDefault", Boolean.TRUE);
if (terms.next()) {
Term term = (Term)terms.getDomainObject();
terms.close();
return term;
}
throw new DataObjectNotFoundException(
"No default broader term for " + getID());
}
/**
* Adds a related term to this term
* @param term the related term
*/
public void addRelatedTerm(Term term) {
if (s_log.isDebugEnabled()) {
s_log.debug("Adding related term " + term + " to " +
this);
}
getModel().addRelatedCategory(term.getModel());
}
/**
* Removes a related term to this term
* @param term the related term
*/
public void removeRelatedTerm(Term term) {
if (s_log.isDebugEnabled()) {
s_log.debug("Removing related term " + term + "from " +
this);
}
getModel().removeRelatedCategory(term.getModel());
}
/**
* Retrieves the related terms within this terms
* domain
* @return the related terms in this domain
*/
public DomainCollection getRelatedTerms() {
DomainCollection terms = getDomain().getTerms();
terms.addEqualsFilter("model.parents.id", getModel().getID());
terms.addEqualsFilter("model.parents.link.relationType", Category.RELATED);
return terms;
}
/**
* Retrieves the related terms within this terms
* domain
* @param domain the domain to retrieve terms in
* @return the related terms in the other domain
*/
public DomainCollection getRelatedTerms(Domain domain) {
DomainCollection terms = domain.getTerms();
terms.addEqualsFilter("model.parents.id", getModel().getID());
terms.addEqualsFilter("model.parents.link.relationType", Category.RELATED);
return terms;
}
/**
* Retrieve the related terms within any domain
* @return the related terms in all domains
*/
public DomainCollection getAllRelatedTerms() {
DataCollection terms = SessionManager.getSession()
.retrieve(BASE_DATA_OBJECT_TYPE);
terms.addEqualsFilter("model.parents.id", getModel().getID());
terms.addEqualsFilter("model.parents.link.relationType", Category.RELATED);
return new DomainCollection(terms);
}
/**
* Adds a preferred term to this synonym term
* @param term the preferred term
*/
public void addPreferredTerm(Term term) {
// XXX currently isDefault attribute is ignored for synonyms
// some "search terms" in LGCL/IPSV have multiple preferred terms,
// unclear which one to take as a preferred choice
getModel().addPreferredCategory(term.getModel());
}
/**
* Removes a preferred term
* @param term the preferred term
*/
public void removePreferredTerm(Term term) {
if (s_log.isDebugEnabled()) {
s_log.debug("Removing preferred term " + term + "from " +
this);
}
getModel().removeRelatedCategory(term.getModel());
}
/**
* Retrieves the preferred terms.
* Empty when the current term is not a synonym.
* @return a collection of preferred terms
*/
public DomainCollection getPreferredTerms() {
DomainCollection terms = getDomain().getTerms();
terms.addEqualsFilter("model.parents.id", getModel().getID());
terms.addEqualsFilter("model.parents.link.relationType", Category.PREFERRED);
return terms;
}
/**
* Retrieves the non-preferred terms.
* Empty when the current term has no synonyms.
* @return a collection of non-preferred terms
*/
public DomainCollection getNonPreferredTerms() {
DomainCollection terms = getDomain().getTerms();
terms.addEqualsFilter("model.related.id", getModel().getID());
terms.addEqualsFilter("model.related.link.relationType", Category.PREFERRED);
return terms;
}
/**
* Classifies an object against this term
* @param obj the object to classify
*/
public void addObject(ACSObject obj) {
getModel().addChild(obj);
}
/**
* Unclassifies an object against this term
* @param obj the object to unclassify
*/
public void removeObject(ACSObject obj) {
getModel().removeChild(obj);
}
private String cleanURL(String name) {
Perl5Util perl5 = new Perl5Util();
return perl5.substitute("s/[^a-zA-Z0-9_]/-/g", name).toLowerCase();
}
}