/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/osp/trunk/glossary/api-impl/src/java/org/theospi/portfolio/help/model/DbGlossary.java $
* $Id: DbGlossary.java 105079 2012-02-24 23:08:11Z ottenhoff@longsight.com $
***********************************************************************************
*
* Copyright (c) 2005, 2006, 2007, 2008 The Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************************/
package org.theospi.portfolio.help.model;
import java.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.sakaiproject.event.api.Event;
import org.sakaiproject.event.cover.EventTrackingService;
import org.sakaiproject.metaobj.shared.mgt.IdManager;
import org.sakaiproject.metaobj.shared.model.Id;
import org.sakaiproject.api.app.scheduler.SchedulerManager;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.quartz.JobDetail;
import org.quartz.SimpleTrigger;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
public class DbGlossary extends HibernateDaoSupport implements Glossary, Observer {
protected final transient Log logger = LogFactory.getLog(getClass());
private Map worksiteGlossary = new Hashtable();
private IdManager idManager;
private List dirtyAddUpdate = new ArrayList();
private List dirtyRemove = new ArrayList();
private SchedulerManager schedulerManager;
private int cacheInterval = 1000 * 10;
private boolean useCache = true;
private String url;
private static final String EVENT_UPDATE_ADD = "org.theospi.glossary.updateAdd";
private static final String EVENT_DELETE = "org.theospi.glossary.delete";
public GlossaryEntry load(Id id) {
GlossaryEntry entry = load(id, true);
getHibernateTemplate().evict(entry);
return entry;
}
protected GlossaryEntry load(Id id, boolean deep) {
try {
GlossaryEntry entry = (GlossaryEntry)getSession().load(GlossaryEntry.class, id);
if (deep) {
entry.setLongDescriptionObject(loadDescription(id));
}
return entry;
} catch (HibernateException e) {
logger.warn("", e);
return null;
}
}
protected GlossaryEntry find(Id id) {
List entries = getHibernateTemplate().find("from GlossaryEntry where id = ?", id);
if (entries.size() > 0) {
return (GlossaryEntry)entries.get(0);
}
return null;
}
protected GlossaryDescription loadDescription(Id entryId) {
Collection entries = getHibernateTemplate().findByNamedQuery("loadDescription",
entryId);
if (entries.size() > 0) {
return (GlossaryDescription)entries.iterator().next();
}
else {
return new GlossaryDescription();
}
}
/**
* find the keyword in the glossary.
* return null if not found.
*
* @param keyword
* @return
*/
public GlossaryEntry find(String keyword, String worksite) {
Collection entries = getHibernateTemplate().findByNamedQuery("findTerms", new Object[]{keyword, worksite});
if (entries.size() == 0) {
return null;
}
else if (entries.size() == 1) {
return (GlossaryEntry)entries.iterator().next();
}
else {
for (Iterator i=entries.iterator();i.hasNext();) {
GlossaryEntry entry = (GlossaryEntry)i.next();
if (entry.getWorksiteId() != null) {
return entry;
}
}
}
return (GlossaryEntry)entries.iterator().next();
}
/**
* returns the list of all GlossaryEntries
*
* @return
*/
public Collection findAll(String keyword, String worksite) {
return getHibernateTemplate().findByNamedQuery("findTerms", new Object[]{keyword, worksite});
}
/**
* returns the list of all GlossaryEntries
*
* @return
*/
public Collection findAll(String worksite) {
return getHibernateTemplate().findByNamedQuery("findAllSiteTerms",
new Object[]{worksite});
}
public Collection findAll() {
return getHibernateTemplate().findByNamedQuery("findAllTerms");
}
public Collection findAllGlobal() {
return getHibernateTemplate().findByNamedQuery("findGlobalTerms");
}
public GlossaryEntry addEntry(GlossaryEntry newEntry) {
getHibernateTemplate().save(newEntry);
newEntry.getLongDescriptionObject().setEntryId(newEntry.getId());
getHibernateTemplate().save(newEntry.getLongDescriptionObject());
updateCache(newEntry, false);
return newEntry;
}
public void removeEntry(GlossaryEntry entry) {
getHibernateTemplate().delete(entry);
GlossaryDescription desc = loadDescription(entry.getId());
getHibernateTemplate().delete(desc);
updateCache(entry, true);
}
public void updateEntry(GlossaryEntry entry) {
getHibernateTemplate().merge(entry);
GlossaryDescription desc = loadDescription(entry.getId());
desc.setLongDescription(entry.getLongDescription());
getHibernateTemplate().merge(desc);
updateCache(entry, false);
}
protected void updateCache(GlossaryEntry entry, boolean remove) {
if (useCache) {
GlossaryTxSync txSync = new GlossaryTxSync(entry, remove);
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.registerSynchronization(txSync);
}
else {
txSync.afterCompletion(GlossaryTxSync.STATUS_COMMITTED);
}
}
}
public Set getSortedWorksiteTerms(String worksiteId) {
Set sortedSet = new TreeSet(new TermComparator());
Map worksiteTerms = getWorksiteGlossary(worksiteId);
if (worksiteTerms != null) {
sortedSet.addAll(worksiteTerms.values());
}
String globalId = null;
Map globalTerms = getWorksiteGlossary(globalId + "");
if (globalTerms != null) {
for (Iterator i=globalTerms.values().iterator();i.hasNext();) {
GlossaryEntry entry = (GlossaryEntry)i.next();
if (!sortedSet.contains(entry)) {
sortedSet.add(entry);
}
}
}
return sortedSet;
}
protected Map getWorksiteGlossary(String worksiteId) {
return getWorksiteGlossary(worksiteId, true);
}
protected Map getWorksiteGlossary(String worksiteId, boolean checkCache) {
if (!useCache) {
logger.warn("using glossary without cache, this could slow down osp tool page loads");
Map terms = new Hashtable();
Collection<GlossaryEntry> entries;
if (worksiteId.equals(null + "")) {
entries = findAllGlobal();
}
else {
entries = findAll(worksiteId);
}
for (Iterator<GlossaryEntry> i = entries.iterator();i.hasNext();) {
GlossaryEntry entry = i.next();
terms.put(entry.getId(), entry);
}
return terms;
}
else {
if (checkCache) {
checkCache();
}
return (Map)worksiteGlossary.get(worksiteId);
}
}
public void checkCache() {
synchronized(dirtyAddUpdate) {
for (Iterator<Id> i=dirtyAddUpdate.iterator();i.hasNext();) {
GlossaryEntry entry = find(i.next());
if (entry != null) {
addUpdateTermCache(entry);
}
}
dirtyAddUpdate.clear();
}
synchronized(dirtyRemove) {
for (Iterator<Id> i=dirtyRemove.iterator();i.hasNext();) {
removeCachedEntry(i.next());
}
dirtyRemove.clear();
}
}
public boolean isPhraseStart(String phraseFragment, String worksite) {
phraseFragment += "%";
Collection entries = getHibernateTemplate().findByNamedQuery("findByPhrase", new Object[]{phraseFragment, worksite});
if (entries.size() > 0) {
return true;
}
return false;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public void importResources(String fromContext, String toContext, List resourceIds) {
Collection orig = findAll(fromContext);
for (Iterator i=orig.iterator();i.hasNext();) {
GlossaryEntry entry = (GlossaryEntry)i.next();
entry.setLongDescriptionObject(loadDescription(entry.getId()));
getHibernateTemplate().evict(entry);
getHibernateTemplate().evict(entry.getLongDescriptionObject());
entry.setWorksiteId(toContext);
entry.setId(null);
getHibernateTemplate().save(entry);
entry.getLongDescriptionObject().setEntryId(entry.getId());
entry.getLongDescriptionObject().setId(null);
getHibernateTemplate().save(entry.getLongDescriptionObject());
addUpdateTermCache(entry);
}
}
public void init() {
if (isUseCache()) {
logger.info("init()");
Collection terms = findAll();
for (Iterator i=terms.iterator();i.hasNext();) {
GlossaryEntry entry = (GlossaryEntry)i.next();
addUpdateTermCache(entry);
}
EventTrackingService.addObserver(this);
}
}
protected void addUpdateTermCache(GlossaryEntry entry) {
String worksiteId = entry.getWorksiteId() + "";
Map worksiteMap = getWorksiteGlossary(worksiteId, false);
if (worksiteMap == null) {
worksiteGlossary.put(worksiteId, new Hashtable());
worksiteMap = getWorksiteGlossary(worksiteId, false);
}
worksiteMap.put(entry.getId(), entry);
}
protected void removeCachedEntry(Id entryId) {
for (Iterator i=worksiteGlossary.values().iterator();i.hasNext();) {
Map map = (Map)i.next();
if (map.remove(entryId) != null) {
// found it
return;
}
}
}
/**
* This method is called whenever the observed object is changed. An
* application calls an <tt>Observable</tt> object's
* <code>notifyObservers</code> method to have all the object's
* observers notified of the change.
*
* This operates within its own Thread so normal rules and conditions don't apply
*
* @param o the observable object.
* @param arg an argument passed to the <code>notifyObservers</code>
* method.
*/
public void update(Observable o, Object arg) {
if (arg instanceof Event) {
Event event = (Event)arg;
if (event.getEvent().equals(EVENT_UPDATE_ADD)) {
synchronized(dirtyAddUpdate) {
dirtyAddUpdate.add(getIdManager().getId(event.getResource()));
}
}
else if (event.getEvent().equals(EVENT_DELETE)) {
synchronized(dirtyRemove) {
dirtyRemove.add(getIdManager().getId(event.getResource()));
}
}
}
}
public IdManager getIdManager() {
return idManager;
}
public void setIdManager(IdManager idManager) {
this.idManager = idManager;
}
private class GlossaryTxSync extends TransactionSynchronizationAdapter {
private GlossaryEntry entry;
private boolean remove = false;
public GlossaryTxSync(GlossaryEntry entry, boolean remove) {
this.entry = entry;
this.remove = remove;
}
public void afterCompletion(int status) {
Event event = null;
if (status == STATUS_COMMITTED && remove) {
event = EventTrackingService.newEvent(EVENT_DELETE, entry.getId().getValue(), false);
}
else if (status == STATUS_COMMITTED) {
event = EventTrackingService.newEvent(EVENT_UPDATE_ADD, entry.getId().getValue(), false);
}
if (event != null) {
EventTrackingService.post(event);
}
}
public GlossaryEntry getEntry() {
return entry;
}
public void setEntry(GlossaryEntry entry) {
this.entry = entry;
}
}
public SchedulerManager getSchedulerManager() {
return schedulerManager;
}
public void setSchedulerManager(SchedulerManager schedulerManager) {
this.schedulerManager = schedulerManager;
}
public int getCacheInterval() {
return cacheInterval;
}
public void setCacheInterval(int cacheInterval) {
this.cacheInterval = cacheInterval;
}
public boolean isUseCache() {
return useCache;
}
public void setUseCache(boolean useCache) {
this.useCache = useCache;
}
}