001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010: package org.mmbase.cache;
011:
012: import java.util.*;
013:
014: import org.mmbase.core.event.*;
015: import org.mmbase.module.core.MMObjectNode;
016: import org.mmbase.storage.search.SearchQuery;
017:
018: import java.util.concurrent.CopyOnWriteArrayList;
019:
020: /**
021: * This class will manage a collection of <code>ReleaseStrategy</code>
022: * instances, and call them hierarchically.
023: *
024: * @since MMBase-1.8
025: * @author Ernst Bunders
026: * @version $Id: ChainedReleaseStrategy.java,v 1.22 2007/02/25 18:18:24 nklasens Exp $
027: */
028: public class ChainedReleaseStrategy extends ReleaseStrategy {
029:
030: private final List<ReleaseStrategy> releaseStrategies = new CopyOnWriteArrayList<ReleaseStrategy>();
031:
032: //this map is used to store the 'enabled' status of wrapped strategies when this one is being disabled
033: //so the old settings can be returned when it is enabled again
034: private final Map<String, Boolean> childStrategyMemory = new HashMap<String, Boolean>();
035:
036: public ChainedReleaseStrategy() {
037: }
038:
039: /**
040: * This method provides a way of globally switching off all strategies this one wraps.
041: * When this strategy is set to 'disabled', the state of all wrapped strategies is being
042: * preserved, so when it is being 'enabled' again, these settings are restored, in stead of
043: * just setting all wrapped strategies to 'enabled'.
044: */
045: // MM: very nice. When is this useful?
046: public void setEnabled(boolean newStatus) {
047: if (newStatus != isEnabled()) {
048: super .setEnabled(newStatus);
049:
050: //if the strategy is enabled and we have recorded settings, we must put them back
051:
052: for (Iterator<ReleaseStrategy> i = iterator(); i.hasNext();) {
053: ReleaseStrategy strategy = i.next();
054:
055: //if it must be switched on, we must use the memeory if present
056: if (newStatus == true) {
057: Boolean memory = childStrategyMemory.get(strategy
058: .getName());
059: strategy.setEnabled(memory == null ? true : memory
060: .booleanValue());
061: } else {
062: //if it must switch of, we must record the status
063: childStrategyMemory.put(strategy.getName(),
064: strategy.isEnabled());
065: strategy.setEnabled(false);
066: strategy.clear();
067: }
068: }
069: }
070: }
071:
072: /**
073: * Adds the strategy if it is not already there. Strategies should only
074: * occur once.
075: *
076: * @param strategy
077: */
078: public void addReleaseStrategy(ReleaseStrategy strategy) {
079: if (!releaseStrategies.contains(strategy)) {
080: releaseStrategies.add(strategy);
081: }
082: }
083:
084: public void removeStrategy(ReleaseStrategy strategy) {
085: releaseStrategies.remove(strategy);
086: }
087:
088: /**
089: * removes all strategies
090: */
091: public void removeAllStrategies() {
092: for (Iterator<ReleaseStrategy> i = iterator(); i.hasNext();) {
093: removeStrategy(i.next());
094: }
095: }
096:
097: /*
098: * (non-Javadoc)
099: *
100: * @see org.mmbase.cache.ReleaseStrategy#getName()
101: */
102: public String getName() {
103: return "Multi Release Strategy";
104: }
105:
106: /*
107: * (non-Javadoc)
108: *
109: * @see org.mmbase.cache.ReleaseStrategy#getDescription()
110: */
111: public String getDescription() {
112: return "This is a wrapper for any number of strategies you would like to "
113: + "combine. it is used as the base strategy for QueryResultCache subclasses.";
114: }
115:
116: public Iterator<ReleaseStrategy> iterator() {
117: return releaseStrategies.iterator();
118: }
119:
120: /*
121: * (non-Javadoc)
122: *
123: * @see org.mmbase.cache.ReleaseStrategy#doEvaluate(org.mmbase.module.core.NodeEvent,
124: * org.mmbase.storage.search.SearchQuery, java.util.List)
125: */
126: protected final boolean doEvaluate(NodeEvent event,
127: SearchQuery query, List<MMObjectNode> cachedResult) {
128: // first do the 'basic' strategy that is allways there. (see constructor)
129: Iterator<ReleaseStrategy> i = releaseStrategies.iterator();
130: // while the outcome of getResult is true (the cache should be flushed), we have to keep trying.
131: while (i.hasNext()) {
132: ReleaseStrategy strategy = i.next();
133: StrategyResult result = strategy.evaluate(event, query,
134: cachedResult);
135: if (!result.shouldRelease())
136: return false;
137: }
138: return true;
139: }
140:
141: protected final boolean doEvaluate(RelationEvent event,
142: SearchQuery query, List<MMObjectNode> cachedResult) {
143: // first do the 'basic' strategy that is allways there. (see constructor)
144: Iterator<ReleaseStrategy> i = releaseStrategies.iterator();
145: // while the outcome of getResult is true (the cache should be flushed), we have to keep trying.
146: while (i.hasNext()) {
147: ReleaseStrategy strategy = i.next();
148: StrategyResult result = strategy.evaluate(event, query,
149: cachedResult);
150: if (!result.shouldRelease())
151: return false;
152: }
153: return true;
154: }
155:
156: public void clear() {
157: super .clear();
158: for (Iterator<ReleaseStrategy> i = iterator(); i.hasNext();) {
159: ReleaseStrategy rs = i.next();
160: rs.clear();
161: }
162: }
163:
164: /**
165: * @since MMBase-1.8.1
166: */
167: public int size() {
168: return releaseStrategies.size();
169: }
170:
171: public String toString() {
172: return "" + releaseStrategies;
173: }
174: }
|