/**
* Copyright (c) 2009 Juwi MacMillan Group GmbH
*
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.
*/
/*
* Created on 27.06.2005
*/
package de.juwimm.cms.gui.tree;
import static de.juwimm.cms.client.beans.Application.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import org.apache.log4j.Logger;
import de.juwimm.cms.client.beans.Beans;
import de.juwimm.cms.util.Communication;
import de.juwimm.cms.vo.SiteValue;
import de.juwimm.cms.vo.ViewDocumentValue;
import de.juwimm.swing.DropDownHolder;
/**
* Helper for storing a InternalLinkTreeModel for a given ViewDocument.<br/>
* Once you have created an instance, you can invalidate the stored model. If you access the stored model,<br/>
* it revalidates itsself when not valid any more.
*
* @author <a href="mailto:carsten.schalm@juwimm.com">Carsten Schalm</a>
* company Juwi|MacMillan Group Gmbh, Walsrode, Germany
* @version $Id$
*/
public class InternalLinkCache {
private static Logger log = Logger.getLogger(InternalLinkCache.class);
private Communication comm = ((Communication) getBean(Beans.COMMUNICATION));
/*
* key = DropDownHolder with Site
* value = HashMap with key = DropDownHolder(ViewDocument) value = LinkTreeModelDecorator
*/
private HashMap<DropDownHolder, HashMap<DropDownHolder, LinkTreeModelDecorator>> siteViewDocumentCache;
/**
* Creates a new InternalLinkCache and fills it with all sites, the user has access to.
*/
public InternalLinkCache() {
this.siteViewDocumentCache = new HashMap<DropDownHolder, HashMap<DropDownHolder, LinkTreeModelDecorator>>();
SiteValue[] sites = this.comm.getAllRelatedSites(this.comm.getSiteId());
if (sites != null) {
for (int i = sites.length - 1; i >= 0; i--) {
DropDownHolder siteDdh = new DropDownHolder(sites[i], sites[i].getName());
HashMap<DropDownHolder, LinkTreeModelDecorator> viewDocumentsMap = new HashMap<DropDownHolder, LinkTreeModelDecorator>();
ViewDocumentValue[] vds = this.comm.getAllViewDocuments4Site(sites[i].getSiteId());
if (vds != null) {
for (int j = vds.length - 1; j >= 0; j--) {
DropDownHolder vdddh = new DropDownHolder(vds[j], vds[j].getViewType() + ", " + vds[j].getLanguage());
viewDocumentsMap.put(vdddh, null);
}
}
this.siteViewDocumentCache.put(siteDdh, viewDocumentsMap);
}
}
}
private HashMap<DropDownHolder, LinkTreeModelDecorator> getViewDocuments4Site(int siteId) {
HashMap<DropDownHolder, LinkTreeModelDecorator> viewDocumentsCache = null;
Iterator it = this.siteViewDocumentCache.keySet().iterator();
while (it.hasNext()) {
DropDownHolder ddh = (DropDownHolder) it.next();
if (((SiteValue) ddh.getObject()).getSiteId() == siteId) {
viewDocumentsCache = this.siteViewDocumentCache.get(ddh);
break;
}
}
return viewDocumentsCache;
}
/**
* Add an new model to the cache.
* @param key
* @param model
*/
public void addLinkTree(int siteId, DropDownHolder key, InternallinkTreeModel model) {
if(this.getViewDocuments4Site(siteId)==null){
SiteValue newSite=this.comm.getSite(siteId);
DropDownHolder siteDdh=new DropDownHolder(newSite, newSite.getName());
HashMap<DropDownHolder, LinkTreeModelDecorator> viewDocumentsMap = new HashMap<DropDownHolder, LinkTreeModelDecorator>();
this.siteViewDocumentCache.put(siteDdh, viewDocumentsMap);
}
this.getViewDocuments4Site(siteId).put(key, new LinkTreeModelDecorator(model));
}
/**
* Clean the cache for the selected site.
*/
public void clearCache(int siteId) {
if(this.getViewDocuments4Site(siteId)!=null){
this.getViewDocuments4Site(siteId).clear();
System.gc();
}
}
/**
* Get all sites contained in the cache.
* @return a set of DropDownHolder
*/
public Set<DropDownHolder> getSites() {
return this.siteViewDocumentCache.keySet();
}
/**
* Get all viewdocuments contained in the cache for the selected site.
* @return a set of DropDownHolder
*/
public Set<DropDownHolder> getViewDocuments(int siteId) {
HashMap<DropDownHolder, LinkTreeModelDecorator> vdSet = this.getViewDocuments4Site(siteId);
if (vdSet != null)
return vdSet.keySet();
return null;
}
/**
* Get the model for the key. If no model exists, the cache fetches, stores and returns the model for this key.
* @param siteId
* @param key
* @return
*/
public InternallinkTreeModel getModel(int siteId, DropDownHolder key) {
LinkTreeModelDecorator model = this.getViewDocuments4Site(siteId).get(key);
if (model == null || !model.isModuleValid() || model.getModel() == null) {
revalidate(siteId, key);
model = this.getViewDocuments4Site(siteId).get(key);
}
return model.getModel();
}
private void revalidate(int siteId, DropDownHolder key) {
ViewDocumentValue vd = (ViewDocumentValue) key.getObject();
InternallinkTreeModel model = null;
try {
log.info("Loading TreeModel \"" + key.toString() + "\" for Internal Link... Please wait :)");
model = new InternallinkTreeModel(new PageNode(this.comm.getViewComponent(vd.getViewId())));
} catch (Exception e) {
log.error("Error on fetching TreeModel for InternalLink: " + e.getMessage());
}
if (model != null) {
this.getViewDocuments4Site(siteId).remove(key);
this.addLinkTree(siteId, key, model);
}
}
/**
* Invalidate the model for the given key.<br/>
* Force the cache to update the state of the model on the next access.
* @param key
*/
public void invalidateModel(int siteId, DropDownHolder key) {
LinkTreeModelDecorator current = this.getViewDocuments4Site(siteId).get(key);
if (current != null) current.invalidate();
}
public DropDownHolder getSiteDropDownHolder(int siteId) {
Iterator it = this.siteViewDocumentCache.keySet().iterator();
while (it.hasNext()) {
DropDownHolder ddh = (DropDownHolder) it.next();
if (((SiteValue) ddh.getObject()).getSiteId() == siteId) {
return ddh;
}
}
return null;
}
public DropDownHolder getViewDocumentDropDownHolder(int siteId, int viewDocumentId) {
Set<DropDownHolder> viewDocuments = this.getViewDocuments(siteId);
if (viewDocuments != null) {
Iterator it = viewDocuments.iterator();
while (it.hasNext()) {
DropDownHolder ddh = (DropDownHolder) it.next();
if (((ViewDocumentValue) ddh.getObject()).getViewDocumentId() == viewDocumentId) {
return ddh;
}
}
}
return null;
}
/**
* Inner class for storing a InternalLinkTreeModel and a validity-state.
*/
private class LinkTreeModelDecorator {
private InternallinkTreeModel model;
private boolean valid;
public LinkTreeModelDecorator(InternallinkTreeModel model) {
this.model = model;
this.valid = true;
}
public boolean isModuleValid() {
return this.valid;
}
public InternallinkTreeModel getModel() {
return this.model;
}
public void invalidate() {
this.valid = false;
}
}
}