view src/treecms/tree/util/NodeChildrenImpl.java @ 20:084de6909451

commit
author shoshi
date Wed, 01 Jun 2011 15:35:50 +0900
parents 168deb591f21
children f3150b37f9be
line wrap: on
line source

package treecms.tree.util;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import treecms.api.NodeChildren;
import treecms.api.NodeContext;
import treecms.api.NodeID;

public class NodeChildrenImpl<T extends NodeContext & NodeChildren<T>> implements NodeChildren<T>
{
	private final Map<String,T> m_map;
	private final List<T> m_list;
	private final List<T> m_readOnlyList;
	
	public NodeChildrenImpl()
	{
		m_map = new ConcurrentHashMap<String,T>();
		m_list = new CopyOnWriteArrayList<T>();
		m_readOnlyList = Collections.unmodifiableList(m_list);
	}
	
	public NodeChildrenImpl(T... _args)
	{
		this();
		for(T i : _args){
			String fid = i.getID().getFamilyID();
			if(!m_map.containsKey(fid)){
				m_map.put(fid,i);
				m_list.add(i);
			}
		}
	}
	
	public NodeChildrenImpl(NodeChildren<T> _list)
	{
		this();
		
		if(_list != null){
			addAll(_list);
		}else{
			throw new NullPointerException("_list is null");
		}
	}
	
	@Override
	public synchronized List<T> getList()
	{
		return m_readOnlyList;
	}
	
	@Override
	public synchronized T replace(T _node)
	{
		String fid = _node.getID().getFamilyID();
		
		T old = m_map.get(fid);
		
		if(old != null){
			m_map.put(fid,_node);
			
			//find index of _node , better put index with node in the map?
			int size = m_list.size();
			for(int i = 0;i < size;i ++){
				T n = m_list.get(i);
				NodeID nid = n.getID();
				if(nid.isFamily(nid)){
					m_list.set(i,_node);
					return old;
				}
			}
			
			throw new IllegalStateException("FamilyID is found on the map but not found on the list");
		}
		return null;
	}
	
	@Override
	public synchronized boolean add(T _n)
	{
		if(!m_map.containsKey(_n.getID().getFamilyID())){
			m_map.put(_n.getID().getFamilyID(),_n);
			return m_list.add(_n);
		}
		return false;
	}
	
	@Override
	public synchronized boolean addAll(NodeChildren<T> _list)
	{
		if(Collections.disjoint(getFamilyIDSet(),_list.getFamilyIDSet())){
		
			HashMap<String,T> map = new HashMap<String,T>();
			for(T item : _list.getList()){
				NodeID id = item.getID();
				map.put(id.getFamilyID(),item);
			}
			
			return m_list.addAll(_list.getList());
		}
		return false;
	}
	
	@Override
	public synchronized T get(int _index)
	{
		return m_list.get(_index);
	}
	
	@Override
	public synchronized T get(String _familyID)
	{
		return m_map.get(_familyID);
	}
	
	@Override
	public synchronized T remove(int _index)
	{
		T n = m_list.remove(_index);
		NodeID id = n.getID();
		if(m_map.remove(id.getFamilyID()) != null){
			return n; 
		}
		
		throw new IllegalStateException("");
	}
	
	@Override
	public synchronized boolean contains(NodeID _id)
	{
		T n = m_map.get(_id);
		NodeID id = n.getID();
		return id.equals(_id);
	}
	
	@Override
	public synchronized void clearChildren()
	{
		m_map.clear();
		m_list.clear();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public synchronized boolean equals(Object _o)
	{
		NodeChildrenImpl<T> list = (NodeChildrenImpl<T>)_o;
		return m_list.equals(list.m_list);
	}
	
	@Override
	public synchronized int hashCode()
	{
		int result = 17;
		result = 37*result + m_list.hashCode();
		result = 37*result + m_map.hashCode();
		return result;
	}

	@Override
	public synchronized Set<String> getFamilyIDSet()
	{
		return m_map.keySet();
	}

	@Override
	public synchronized T remove(String _fid)
	{
		return m_map.remove(_fid);
	}

	@Override
	public synchronized boolean swap(String _fid1, String _fid2)
	{
		if(m_map.containsKey(_fid1) && m_map.containsKey(_fid2)){
			int index1,index2;
			index1 = index2 = -1;
			int size = m_list.size();
			for(int i = 0;i < size;i ++){
				T n = m_list.get(i);
				String fid = n.getID().getFamilyID();
				
				if(fid.equals(_fid1)){
					index1 = i;
				}else if(fid.equals(_fid2)){
					index2 = i;
				}
				
				if(index1 != -1 && index2 != -1){
					Collections.swap(m_list, index1, index2);
					return true;
				}
			}
		}
		return false;
	}
}