/* This file is part of the PolePosition database benchmark http://www.polepos.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.zoodb.test.jdo.pole; import java.util.ArrayList; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.zoodb.api.impl.ZooPC; public class ListHolder extends ZooPC implements CheckSummable { interface Procedure<T> { void apply(T obj); } public static final String ROOT_NAME = "root"; private static IdGenerator _idGenerator = new IdGenerator(); private long _id; private String _name; private List<ListHolder> _list; private static int n = 0; private ListHolder() { n++; } public static ListHolder generate(int depth, int leafs, int reuse){ ListHolder root = generate(new ArrayList<ListHolder>(), depth, leafs, reuse); root._name = ROOT_NAME; System.out.println("nC=" + n); return root; } private static ListHolder generate(List<ListHolder> flatList, int depth, int leafs, int reuse){ if(depth == 0){ return null; } ListHolder listHolder = new ListHolder(); listHolder.setId(_idGenerator.nextId()); flatList.add(listHolder); if(depth == 1){ return listHolder; } listHolder.setList(new ArrayList<ListHolder>()); int childDepth = depth -1; for (int i = leafs -1; i >= 0; i--) { if(i < reuse){ int indexInList = (flatList.size() - i) / 2; if(indexInList < 0){ indexInList = 0; } listHolder.getList().add(flatList.get(indexInList) ); } else { ListHolder child = generate(flatList, childDepth, leafs, reuse); child._name = "child:" + depth + ":" + i; listHolder.getList().add(child); } } return listHolder; } @Override public long checkSum() { zooActivateRead(); return _name.hashCode(); } public void accept(Visitor<ListHolder> visitor) { zooActivateRead(); Set<ListHolder> visited = new HashSet<ListHolder>(); acceptInternal(visited, visitor); } private void acceptInternal(Set<ListHolder> visited, Visitor<ListHolder> visitor){ zooActivateRead(); if(visited.contains(this)){ return; } visitor.visit(this); visited.add(this); if(getList() == null){ return; } Iterator<ListHolder> i = getList().iterator(); while(i.hasNext()){ ListHolder child = i.next(); child.acceptInternal(visited, visitor); } } public int update(int maxDepth, Procedure<ListHolder> storeProcedure) { zooActivateWrite(); Set<ListHolder> visited = new HashSet<ListHolder>(); return updateInternal(visited, maxDepth, 0, storeProcedure); } private int updateInternal(Set<ListHolder> visited, int maxDepth, int depth, Procedure<ListHolder> storeProcedure) { zooActivateWrite(); if(visited.contains(this)){ return 0; } visited.add(this); int updatedCount = 1; if(depth > 0){ _name = "updated " + _name; } if(_list != null){ for (int i = 0; i < _list.size(); i++) { ListHolder child = _list.get(i); updatedCount += child.updateInternal(visited, maxDepth, depth + 1, storeProcedure); } } storeProcedure.apply(this); return updatedCount; } public int delete(int maxDepth, Procedure<ListHolder> deleteProcedure) { zooActivateRead(); // We use an IdentityHashMap here so hashCode is not called on deleted items. Map<ListHolder, ListHolder> visited = new IdentityHashMap<ListHolder, ListHolder>(); return deleteInternal(visited, maxDepth, 0, deleteProcedure); } private int deleteInternal(Map<ListHolder, ListHolder> visited, int maxDepth, int depth, Procedure<ListHolder> deleteProcedure) { if(visited.containsKey(this)){ return 0; } zooActivateRead(); visited.put(this, this); int deletedCount = 1; if(_list != null){ for (int i = 0; i < _list.size(); i++) { ListHolder child = getList().get(i); deletedCount += child.deleteInternal(visited, maxDepth, depth + 1, deleteProcedure); } } deleteProcedure.apply(this); return deletedCount; } private void setId(long id) { zooActivateWrite(); _id = id; } public long getId() { zooActivateRead(); return _id; } private void setList(List<ListHolder> list) { zooActivateWrite(); _list = list; } private List<ListHolder> getList() { zooActivateRead(); return _list; } @Override public boolean equals(Object obj) { zooActivateRead(); if(this == obj){ return true; } if(obj == null){ return false; } if(obj.getClass() != this.getClass()){ return false; } ListHolder other = (ListHolder) obj; return _id == other._id; } @Override public int hashCode() { zooActivateRead(); return (int)_id; } @Override public String toString() { zooActivateRead(); return "ListHolder [_id=" + _id + "]"; } }