/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* 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.
*
******************************************************************************/
package org.pentaho.di.core.xml;
import java.util.ArrayList;
import java.util.Hashtable;
/**
* Singleton to help speed up lookups in an XML DOM tree.<br>
* The theory is that you often loop over occurrences of a certain tag in a Node.<br>
* If there are 20 occurrences, you go from index 0..19.<br>
* Every time we do the following<br>
* - found node 0<br>
* - found node 0, 1<br>
* - found node 0, 1, 2<br>
* - ...<br>
* So the time to search node index 19 is 20 times larger on average then index 0.<br>
* <br>
* We can solve this by caching the position of index 18 and by starting back at that position.<br>
* <br>
* This class is a singleton to keep everyting 100% compatible with the rest of the codebase. <br>
*
* @author Matt
* @since 22-Apr-2006
*/
public class XMLHandlerCache {
public static final int MAX_NUMBER_OF_ENTRIES = 500;
private static XMLHandlerCache cache;
private Hashtable<XMLHandlerCacheEntry, Integer> hashtable;
private ArrayList<XMLHandlerCacheEntry> list;
private int cacheHits;
private XMLHandlerCache() {
hashtable = new Hashtable<XMLHandlerCacheEntry, Integer>( MAX_NUMBER_OF_ENTRIES );
list = new ArrayList<XMLHandlerCacheEntry>( MAX_NUMBER_OF_ENTRIES );
cacheHits = 0;
}
public static final synchronized XMLHandlerCache getInstance() {
if ( cache != null ) {
return cache;
}
cache = new XMLHandlerCache();
return cache;
}
/**
* Store a cache entry
*
* @param entry
* The cache entry to store
*/
public synchronized void storeCache( XMLHandlerCacheEntry entry, int lastChildNr ) {
hashtable.put( entry, Integer.valueOf( lastChildNr ) );
list.add( entry );
if ( list.size() > MAX_NUMBER_OF_ENTRIES ) {
// Simple: the oldest is the first in the list
XMLHandlerCacheEntry cacheEntry = list.get( 0 );
// Remove this one from the cache...
hashtable.remove( cacheEntry );
// Remove from the list
list.remove( 0 );
}
}
/**
* Retrieve the last child were we left off...
*
* @param entry
* The cache entry to look for.
* @return the last child position or -1 if nothing was found.
*/
public int getLastChildNr( XMLHandlerCacheEntry entry ) {
Integer lastChildNr = hashtable.get( entry );
if ( lastChildNr != null ) {
cacheHits++;
return lastChildNr.intValue();
}
return -1;
}
/**
* @return the number of cache hits for your statistical pleasure.
*/
public int getCacheHits() {
return cacheHits;
}
/**
* Allows you to (re-)set the number of cache hits
*
* @param cacheHits
* the number of cache hits.
*/
public void setCacheHits( int cacheHits ) {
this.cacheHits = cacheHits;
}
/**
* Clears the cache
*
*/
public synchronized void clear() {
this.hashtable.clear();
this.list.clear();
}
}