blob: 55799e2486ba0ded2d7961e0b1f4260f3094cecd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.common.internal.emf.resource;
import java.util.ArrayList;
import java.util.Collection;
import org.xml.sax.Attributes;
/**
* Provides an instance pool of reusable CacheEventNodes. The pool will default to 10 live
* instances. When its available instances reach five times its initial capacity, it will shrink
* itself down to the initial capacity.
*
* @author mdelder
*/
public class CacheEventPool {
public static final int DEFAULT_CAPACITY = 10;
public static final int DEFAULT_CAPACITY_INCREMENT = 25;
private int poolCapacity = DEFAULT_CAPACITY;
private CacheEventStack availablePool = null;
private Collection inusePool = null;
public CacheEventPool() {
this(DEFAULT_CAPACITY);
}
/**
* Create a CacheEventPOol with the given initial capacity
*
* @param initialCapacity
* The number of available instances to create.
*/
public CacheEventPool(int initialCapacity) {
poolCapacity = (initialCapacity > 0) ? initialCapacity : DEFAULT_CAPACITY;
availablePool = new CacheEventStack();
inusePool = new ArrayList(poolCapacity);
}
/**
* Create a CacheEventNode (CENO) initialized to use the given resource as its EMF Owner.
*
* THIS METHOD SHOULD ONLY BE USED TO CREATE ROOT NODES.
*
* @param resource
* the resource that will be populated
* @return a CacheEventNode to serve as the root.
*/
public CacheEventNode createCacheEventNode(TranslatorResource resource) {
CacheEventNode adapter = fetchFreeNode();
adapter.init(resource);
return adapter;
}
/**
* Create child CacheEventNodes (CENOs) that will branch from the given parent.
*
* @param parent
* the containing CENO
* @param nodeName
* The value of the XML element node name
* @param attributes
* The attributes that were part of the given XML element
* @return A CENO that has been properly initialized.
*/
public CacheEventNode createCacheEventNode(CacheEventNode parent, String nodeName, Attributes attributes) {
CacheEventNode adapter = fetchFreeNode();
adapter.init(parent, nodeName, attributes);
return adapter;
}
/**
* Release the CacheEventNode CENO back to the pool of availabe instances. This method should
* not be invoked directly. CENOs which are acquired from a given pool will automatically
* release themselves when necessary.
*
* @param adapter
*/
public void releaseNode(CacheEventNode adapter) {
freeNode(adapter);
}
/**
* freezePool() should be invoked to free any unused resources. After freezePool has been
* invoked, warmPool() will need to be invoked before the pool can be used again.
*
*/
public void freezePool() {
availablePool.clear();
availablePool = null;
}
/**
* warmPool() must be invoked to notify the pool it is about to be used. This should occur only
* once per document rendering. Until the pool is in use, it contains no available
* CacheEventNodes (CENOs) in order to limit the size of the in-memory footprint of the
* EMF2SAXWriter.
*
*/
public void warmPool() {
ensureMinimumCapacity();
}
private CacheEventNode fetchFreeNode() {
CacheEventNode result = null;
if (availablePool == null || availablePool.isEmpty())
warmPool();
result = availablePool.pop();
inusePool.add(result);
return result;
}
private void freeNode(CacheEventNode adapter) {
if (inusePool.remove(adapter))
availablePool.push(adapter);
//else
// throw new IllegalStateException("Adapter not contained in pool!");
if (availablePool.size() > (5 * poolCapacity)) {
availablePool.clear();
ensureMinimumCapacity();
}
}
private void ensureMinimumCapacity() {
if (availablePool == null) {
availablePool = new CacheEventStack();
}
if (availablePool.size() < poolCapacity) {
final int minimumCapacity = poolCapacity - availablePool.size();
for (int i = 0; i < minimumCapacity; i++)
availablePool.push(new CacheEventNode(this));
}
}
}