# HG changeset patch # User shoshi # Date 1307364544 -32400 # Node ID f3150b37f9be97d510c7bae2d4712ceb4c89e9e3 # Parent 084de69094513ba9206fcf1db168eea3249e75b3 commit diff -r 084de6909451 -r f3150b37f9be src/treecms/api/Forest.java --- a/src/treecms/api/Forest.java Wed Jun 01 15:35:50 2011 +0900 +++ b/src/treecms/api/Forest.java Mon Jun 06 21:49:04 2011 +0900 @@ -1,9 +1,12 @@ package treecms.api; +import treecms.tree.util.NodeData; + public interface Forest { MonotonicTree get(NodeID _id); MonotonicTree getTip(String _uuid); MonotonicTree create(); + MonotonicTree create(NodeData _data); MonotonicTree getMainTree(); } diff -r 084de6909451 -r f3150b37f9be src/treecms/api/MonotonicTreeNode.java --- a/src/treecms/api/MonotonicTreeNode.java Wed Jun 01 15:35:50 2011 +0900 +++ b/src/treecms/api/MonotonicTreeNode.java Mon Jun 06 21:49:04 2011 +0900 @@ -7,5 +7,6 @@ */ public interface MonotonicTreeNode extends NodeContext , NodeAttributes , NodeChildren { + public Node getNode(); public MonotonicTreeNode getParent(); } diff -r 084de6909451 -r f3150b37f9be src/treecms/api/Node.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/treecms/api/Node.java Mon Jun 06 21:49:04 2011 +0900 @@ -0,0 +1,5 @@ +package treecms.api; + +public interface Node extends NodeContext , NodeAttributes , NodeChildren +{ +} diff -r 084de6909451 -r f3150b37f9be src/treecms/memory/OnMemoryForest.java --- a/src/treecms/memory/OnMemoryForest.java Wed Jun 01 15:35:50 2011 +0900 +++ b/src/treecms/memory/OnMemoryForest.java Mon Jun 06 21:49:04 2011 +0900 @@ -1,191 +1,74 @@ package treecms.memory; import java.util.Map; -import java.util.Random; -import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import treecms.api.Forest; -import treecms.api.MonotonicTreeNode; +import treecms.api.Node; import treecms.api.NodeID; import treecms.api.MonotonicTree; -import treecms.tree.id.AbstractRandomNodeID; +import treecms.tree.id.RandomNodeID; import treecms.tree.util.NodeData; -/** - * Forestのオンメモリ上の実装. - * @author shoshi - */ public class OnMemoryForest implements Forest { - //Nodeのマップ private final Map m_table; - //最新版Nodeのマップ private final Map m_tipTable; + private final OnMemoryMonotonicTree m_mainTree; - //MainTreeのUUID - private final String m_mainID; - - /** - * コンストラクタ - */ public OnMemoryForest() { m_table = new ConcurrentHashMap(); m_tipTable = new ConcurrentHashMap(); - m_mainID = createNode(null,null).getID().getFamilyID(); + OnMemoryNode root = (OnMemoryNode)create(); + m_mainTree = new OnMemoryMonotonicTree(root); } - /** - * 新しくNodeを作成します - * @param _id Nodeに適用されるNodeID - * @param _newData Nodeが保持するNodeData - * @return 作成されたOnMemoryNode - */ - public OnMemoryNode createNode(NodeID _id,NodeData _newData) + private NodeID createID(String _fid) { - NodeID newID = (_id != null) ? _id : createID(); - NodeData newData = (_newData != null) ? _newData : new NodeData(); - - //newIDとnewDataを元にOnMemoryNodeを生成する. - OnMemoryNode newNode = new OnMemoryNode(this,newID,newData); - - //登録 - m_table.put(newID,newNode); - m_tipTable.put(newID.getFamilyID(),newNode); - - return newNode; - } - - /** - * 新しいNodeIDを作成します - * @return 新しいNodeID - */ - private NodeID createID() - { - return new RandomNodeID(null); + return new RandomNodeID(_fid); } - /** - * NodeIDに対応するNodeを取得します - * @return NodeIDに対応するNode - */ @Override public MonotonicTree get(NodeID _id) { - return m_table.get(_id); + OnMemoryNode node = m_table.get(_id); + return new OnMemoryMonotonicTree(node); } - /** - * 新しくNodeを作成します. - * @return 新しいNode - */ @Override public MonotonicTree create() { - return createNode(null,null); - } - - /** - * NodeDataを保持した新しいNodeを作成します - * @return NodeDataを保持した新しいNode - */ - @Override - public SingleNode create(NodeData _data) - { - return createNode(null,_data); + OnMemoryNode node = createNode(createID(null),null); + OnMemoryMonotonicTree tree = new OnMemoryMonotonicTree(node); + return tree; } - /** - * 最新のNodeを取得します. - * @return UUIDに対応する最新のNode - */ @Override - public SingleNode getTip(String _uuid) + public MonotonicTree create(NodeData _data) { - return m_tipTable.get(_uuid); + OnMemoryNode node = createNode(null,_data); + return new OnMemoryMonotonicTree(node); } - /** - * MainTreeを取得します。 - * @return このForestのMainTree - */ + @Override + public MonotonicTree getTip(String _fid) + { + OnMemoryNode node = m_tipTable.get(_fid); + return new OnMemoryMonotonicTree(node); + } + @Override public MonotonicTree getMainTree() { - return new OnMemoryTree(m_tipTable.get(m_mainID)); - } - - @Override - public SingleNode create(NodeID _id,NodeData _data) - { - return createNode(_id,_data); + return m_mainTree; } - /** - * ランダムにバージョン番号を生成するNodeIDです.ファクトリを内包します. - * @author shoshi - */ - private static class RandomNodeID extends AbstractRandomNodeID + public OnMemoryNode createNode(NodeID _newID,NodeData _newData) { - /** - * UUID - */ - private String m_uuid; - - /** - * バージョン番号(ランダム値) - */ - private long m_version; - - /** - * コンストラクタ - * @param _uuid 継承するUUID - */ - public RandomNodeID(String _uuid) - { - m_uuid = (_uuid != null) ? _uuid : UUID.randomUUID().toString(); - m_version = (new Random()).nextLong(); - } - - /** - * 新しいRandomNodeIDを作成します。 - * @return 新しいRandomNodeID - */ - @Override - public NodeID create() - { - return new RandomNodeID(null); - } - - /** - * UUIDを継承したRandomNodeIDを作成します. - * @return 新しいRandomNodeID - */ - @Override - public NodeID update() - { - return new RandomNodeID(m_uuid); - } - - /** - * UUIDを取得します. - * @return UUID - */ - @Override - public String getUUID() - { - return m_uuid; - } - - /** - * バージョンを取得します. - * @return バージョン - */ - @Override - public String getVersion() - { - return Long.toHexString(m_version); - } + OnMemoryNode newNode = new OnMemoryNode(this,_newID,_newData); + m_table.put(newNode.getID(),newNode); + m_tipTable.put(newNode.getID().getFamilyID(),newNode); + return newNode; } } diff -r 084de6909451 -r f3150b37f9be src/treecms/memory/OnMemoryMonotonicTree.java --- a/src/treecms/memory/OnMemoryMonotonicTree.java Wed Jun 01 15:35:50 2011 +0900 +++ b/src/treecms/memory/OnMemoryMonotonicTree.java Mon Jun 06 21:49:04 2011 +0900 @@ -1,62 +1,65 @@ package treecms.memory; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + import treecms.api.MonotonicTree; - import treecms.api.MonotonicTreeNode; -import treecms.api.SingleNode; -import treecms.api.Tree; +import treecms.api.Node; import treecms.merger.Merger; import treecms.merger.ReplaceMerger; public class OnMemoryMonotonicTree implements MonotonicTree { - private volatile OnMemoryTree m_tree; private OnMemoryNode m_old; private OnMemoryMonotonicTreeNode m_root; - private static final Merger m_merger = new ReplaceMerger(); + + private static final Merger m_merger = new ReplaceMerger(); - public OnMemoryMonotonicTree(OnMemoryTree _tree) + private final ConcurrentMap m_members; + private final OnMemoryMonotonicTree m_tree; //Remote Repository + + public OnMemoryMonotonicTree(OnMemoryNode _root) { - m_tree = _tree; - m_old = (OnMemoryNode)m_tree.getRoot().getNode(); + m_tree = null; + m_old = _root; m_root = new OnMemoryMonotonicTreeNode((OnMemoryNode)m_old,null); + m_members = new ConcurrentHashMap(); + } + + public OnMemoryMonotonicTree(OnMemoryMonotonicTree _tree) + { + this((OnMemoryNode)_tree.getRoot().getNode()); } @Override public boolean commit(boolean _force) { - return m_tree.compareAndSwapRootNode(m_old,(OnMemoryNode)m_root.getNode(),_force); + return true; } @Override public boolean pull() { - m_old = (OnMemoryNode)m_tree.getRoot().getNode(); + OnMemoryNode node = (OnMemoryNode)m_tree.getRoot().getNode(); + OnMemoryMonotonicTreeNode node = new OnMemoryMonotonicTreeNode(); return true; } @Override public boolean check() { - return m_tree.compareAndSwapRootNode(m_old,m_old,false); + return m_tree.getRoot().getNode().equals(m_old); } @Override public void merge() { - //merge here - m_old = (OnMemoryNode)m_merger.merge(m_tree.getRoot().getNode(),m_root.getNode()); } @Override public MonotonicTreeNode getRoot() { - return this.m_root; - } - - @Override - public Tree getTree() - { - return (Tree)m_tree; + return m_root; } } diff -r 084de6909451 -r f3150b37f9be src/treecms/memory/OnMemoryMonotonicTreeNode.java --- a/src/treecms/memory/OnMemoryMonotonicTreeNode.java Wed Jun 01 15:35:50 2011 +0900 +++ b/src/treecms/memory/OnMemoryMonotonicTreeNode.java Mon Jun 06 21:49:04 2011 +0900 @@ -11,6 +11,7 @@ import treecms.api.Forest; import treecms.api.MonotonicTreeNode; +import treecms.api.Node; import treecms.api.NodeAttributes; import treecms.api.NodeChildren; import treecms.api.NodeID; @@ -23,20 +24,20 @@ */ public class OnMemoryMonotonicTreeNode implements MonotonicTreeNode { - private OnMemoryNode m_node; + private Node m_node; private static final AtomicReferenceFieldUpdater m_parentUpdater = AtomicReferenceFieldUpdater.newUpdater(OnMemoryMonotonicTreeNode.class,OnMemoryMonotonicTreeNode.class,"m_parent"); private OnMemoryMonotonicTreeNode m_parent; - private final Map m_cache; + private final Map m_cache; public OnMemoryMonotonicTreeNode(OnMemoryNode _target,OnMemoryMonotonicTreeNode _parent) { m_node = _target; m_parent = _parent; - m_cache = new ConcurrentHashMap(); + m_cache = new ConcurrentHashMap(); } @Override @@ -72,7 +73,7 @@ @Override public synchronized void put(ByteBuffer _key, ByteBuffer _value) { - NodeData d = new NodeData(m_node); + NodeData d = new NodeData(m_node,m_node); d.put(_key,_value); cloneAndTransmit(d); @@ -81,7 +82,7 @@ @Override public synchronized void putAll(NodeAttributes _map) { - NodeData d = new NodeData(m_node); + NodeData d = new NodeData(m_node,m_node); d.putAll(_map); cloneAndTransmit(d); @@ -90,7 +91,7 @@ @Override public synchronized void remove(ByteBuffer _key) { - NodeData d = new NodeData(m_node); + NodeData d = new NodeData(m_node,m_node); d.remove(_key); cloneAndTransmit(d); @@ -99,7 +100,7 @@ @Override public synchronized void removeAll(Set _keys) { - NodeData d = new NodeData(m_node); + NodeData d = new NodeData(m_node,m_node); d.removeAll(_keys); cloneAndTransmit(d); @@ -108,32 +109,22 @@ @Override public synchronized void clearAttributes() { - NodeData d = new NodeData(m_node); + NodeData d = new NodeData(m_node,m_node); d.clearAttributes(); cloneAndTransmit(d); } - public synchronized void cloneAndTransmit(NodeData _d) + public synchronized void cloneAndTransmit(NodeData _d) { OnMemoryForest f = (OnMemoryForest)m_node.getForest(); - OnMemoryNode clone = f.createNode(m_node.getID().update(),_d); + Node clone = f.createNode(m_node.getID().update(),_d); transmit(m_node,clone); m_node = clone; } - /** - * このMonotonicNodeに変更が加えられたら,こちらのメソッドが呼び出されます. - * 非破壊的に変更するために,SingleLinkedNodeのクローンを作成し,親にも複製を依頼します. - * - * RootNodeまで伝搬すると親のNodeはnullとなる.親Nodeは担当するMonotonicTreeのオブジェクトを保持しており,そこにRootNodeが変更されたことを通知する. - * 通知が終わり,処理が戻ってきた時に自身のOnMemoryNodeをクローンした新しいものに書き換えます. - * - * _fromがnullの場合は,自身が編集元であることを示します. - * @param _from 編集元のOnMemoryMonotonicTreeNode - */ - public synchronized void transmit(OnMemoryNode _orig,OnMemoryNode _edit) + public synchronized void transmit(Node _orig,Node _edit) { OnMemoryForest f = (OnMemoryForest)m_node.getForest(); OnMemoryNode clone = f.createNode(m_node.getID().update(),null); @@ -160,11 +151,17 @@ } @Override + public synchronized Node getNode() + { + return m_node; + } + + @Override public synchronized List getList() { //NodeのリストよりMonotonicTreeNodeのリストを作成する. NodeChildren res = new NodeChildrenImpl(); - for(Iterator it = m_node.getList().iterator();it.hasNext();){ + for(Iterator it = m_node.getList().iterator();it.hasNext();){ OnMemoryNode n = (OnMemoryNode)it.next(); res.add(getCache(n)); } @@ -176,7 +173,7 @@ public synchronized boolean add(MonotonicTreeNode _n) { OnMemoryMonotonicTreeNode mono = (OnMemoryMonotonicTreeNode)_n; - NodeData d = new NodeData(m_node); + NodeData d = new NodeData(m_node,m_node); boolean ret = d.add(mono.m_node); if(ret){ cloneAndTransmit(d); @@ -189,13 +186,13 @@ public synchronized boolean addAll(NodeChildren _list) { //MotonicTreeNodeのリストからNodeのリストを作成する. - NodeChildren c = new NodeChildrenImpl(); + NodeChildren c = new NodeChildrenImpl(); for(Iterator it = _list.getList().iterator();it.hasNext();){ OnMemoryMonotonicTreeNode mono = (OnMemoryMonotonicTreeNode)it.next(); c.add(mono.m_node); } - NodeData d = new NodeData(m_node); + NodeData d = new NodeData(m_node,m_node); boolean ret = d.addAll(c); if(ret){ cloneAndTransmit(d); @@ -207,8 +204,8 @@ @Override public synchronized MonotonicTreeNode remove(int _index) { - NodeData d = new NodeData(m_node); - OnMemoryNode n = d.remove(_index); + NodeData d = new NodeData(m_node,m_node); + OnMemoryNode n = (OnMemoryNode) d.remove(_index); if(n != null){ cloneAndTransmit(d); return new OnMemoryMonotonicTreeNode((OnMemoryNode)n,null); @@ -220,7 +217,7 @@ @Override public synchronized void clearChildren() { - NodeData d = new NodeData(m_node); + NodeData d = new NodeData(m_node,m_node); d.clearChildren(); cloneAndTransmit(d); @@ -241,7 +238,7 @@ @Override public synchronized MonotonicTreeNode get(int _index) { - OnMemoryNode n = m_node.get(_index); + OnMemoryNode n = (OnMemoryNode) m_node.get(_index); return getCache(n); } @@ -249,8 +246,8 @@ public synchronized MonotonicTreeNode replace(MonotonicTreeNode _newChild) { OnMemoryMonotonicTreeNode mono = (OnMemoryMonotonicTreeNode)_newChild; - NodeData d = new NodeData(m_node); - OnMemoryNode n = d.replace(mono.m_node); + NodeData d = new NodeData(m_node,m_node); + OnMemoryNode n = (OnMemoryNode) d.replace(mono.m_node); if(n != null){ cloneAndTransmit(d); @@ -281,7 +278,7 @@ @Override public synchronized MonotonicTreeNode get(String _fid) { - OnMemoryNode n = m_node.get(_fid); + OnMemoryNode n = (OnMemoryNode) m_node.get(_fid); OnMemoryMonotonicTreeNode mono = getCache(n); return mono; @@ -290,8 +287,8 @@ @Override public synchronized MonotonicTreeNode remove(String _fid) { - NodeData d = new NodeData(m_node); - OnMemoryNode n = d.remove(_fid); + NodeData d = new NodeData(m_node,m_node); + OnMemoryNode n = (OnMemoryNode) d.remove(_fid); cloneAndTransmit(d); diff -r 084de6909451 -r f3150b37f9be src/treecms/memory/OnMemoryNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/treecms/memory/OnMemoryNode.java Mon Jun 06 21:49:04 2011 +0900 @@ -0,0 +1,166 @@ +package treecms.memory; + +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Map; +import java.util.Set; +import treecms.api.Forest; +import treecms.api.Node; +import treecms.api.NodeAttributes; +import treecms.api.NodeChildren; +import treecms.api.NodeID; +import treecms.tree.util.NodeData; + +class OnMemoryNode implements Node +{ + private final OnMemoryForest m_forest; + private final NodeID m_id; + private final NodeData m_data; + + private static final String ERR_READONLY = "this is a readonly node."; + + public OnMemoryNode(OnMemoryForest _forest,NodeID _id,NodeData _newData) + { + m_id = _id; + m_forest = _forest; + m_data = new NodeData(_newData); + } + + @Override + public NodeID getID() + { + return m_id; + } + + @Override + public Forest getForest() + { + return m_forest; + } + + @Override + public List getList() + { + return m_data.getList(); + } + + @Override + public Map asMap() + { + return m_data.asMap(); + } + + @Override + public Set getKeySet() + { + return m_data.getKeySet(); + } + + @Override + public ByteBuffer get(ByteBuffer _name) + { + return m_data.get(_name); + } + + @Override + public NodeAttributes getAll() + { + return m_data.getAll(); + } + + @Override + public Set getFamilyIDSet() + { + return m_data.getFamilyIDSet(); + } + + @Override + public Node get(String _uuid) + { + return m_data.get(_uuid); + } + + @Override + public Node get(int _index) + { + return m_data.get(_index); + } + + @Override + public boolean contains(NodeID _id) + { + return m_data.contains(_id); + } + + @Override + public boolean add(Node _child) + { + throw new UnsupportedOperationException(ERR_READONLY); + } + + @Override + public boolean addAll(NodeChildren _list) + { + throw new UnsupportedOperationException(ERR_READONLY); + } + + @Override + public Node remove(String _uuid) + { + throw new UnsupportedOperationException(ERR_READONLY); + } + + @Override + public Node remove(int _index) + { + throw new UnsupportedOperationException(ERR_READONLY); + } + + @Override + public Node replace(Node _new) + { + throw new UnsupportedOperationException(ERR_READONLY); + } + + @Override + public boolean swap(String _uuid, String _uuid2) + { + throw new UnsupportedOperationException(ERR_READONLY); + } + + @Override + public void clearChildren() + { + throw new UnsupportedOperationException(ERR_READONLY); + } + + @Override + public void put(ByteBuffer _name, ByteBuffer _value) + { + throw new UnsupportedOperationException(ERR_READONLY); + } + + @Override + public void putAll(NodeAttributes _attrs) + { + throw new UnsupportedOperationException(ERR_READONLY); + } + + @Override + public void remove(ByteBuffer _name) + { + throw new UnsupportedOperationException(ERR_READONLY); + } + + @Override + public void removeAll(Set _keySet) + { + throw new UnsupportedOperationException(ERR_READONLY); + } + + @Override + public void clearAttributes() + { + throw new UnsupportedOperationException(ERR_READONLY); + } +} diff -r 084de6909451 -r f3150b37f9be src/treecms/test/SwingTest1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/treecms/test/SwingTest1.java Mon Jun 06 21:49:04 2011 +0900 @@ -0,0 +1,37 @@ +package treecms.test; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.*; + +public class SwingTest1 +{ + public static void main(String _args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException + { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + JFrame f = new JFrame(""); + JButton btn = new JButton("btn!"); + Container cnt = f.getContentPane(); + cnt.setLayout(new BorderLayout()); + cnt.add(btn,BorderLayout.CENTER); + + + final JPopupMenu menu = new JPopupMenu(); + JMenuItem item = new JMenuItem("test1"); + menu.add(item); + + btn.addActionListener(new ActionListener(){ + @Override + public void actionPerformed(ActionEvent e) + { + menu.setVisible(true); + } + }); + + f.setVisible(true); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } +} diff -r 084de6909451 -r f3150b37f9be src/treecms/tree/id/AbstractNodeID.java --- a/src/treecms/tree/id/AbstractNodeID.java Wed Jun 01 15:35:50 2011 +0900 +++ b/src/treecms/tree/id/AbstractNodeID.java Mon Jun 06 21:49:04 2011 +0900 @@ -6,7 +6,7 @@ { public abstract NodeID create(); public abstract NodeID update(); - public abstract String getUUID(); + public abstract String getFamilyID(); public abstract String getVersion(); public abstract boolean isFamily(NodeID _id); @@ -14,17 +14,22 @@ @Override public String toString() { - return (new StringBuffer(getUUID())).append('@').append(getVersion()).toString(); + return (new StringBuffer(getFamilyID())).append('@').append(getVersion()).toString(); } + private int m_hashCode = -1; + @Override public int hashCode() { - int hash = 17; - hash = 37*hash + getUUID().hashCode(); - hash = 37*hash + getVersion().hashCode(); + if(m_hashCode == -1){ + int hash = 17; + hash = 37*hash + getFamilyID().hashCode(); + hash = 37*hash + getVersion().hashCode(); + m_hashCode = hash; + } - return hash; + return m_hashCode; } @Override diff -r 084de6909451 -r f3150b37f9be src/treecms/tree/id/RandomNodeID.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/treecms/tree/id/RandomNodeID.java Mon Jun 06 21:49:04 2011 +0900 @@ -0,0 +1,41 @@ +package treecms.tree.id; + +import java.util.Random; +import java.util.UUID; +import treecms.api.NodeID; + +public class RandomNodeID extends AbstractRandomNodeID +{ + private String m_fid; + private long m_version; + + public RandomNodeID(String _fid) + { + m_fid = (_fid != null) ? _fid : UUID.randomUUID().toString(); + m_version = (new Random()).nextLong(); + } + + @Override + public NodeID create() + { + return new RandomNodeID(null); + } + + @Override + public NodeID update() + { + return new RandomNodeID(m_fid); + } + + @Override + public String getFamilyID() + { + return m_fid; + } + + @Override + public String getVersion() + { + return Long.toHexString(m_version); + } +} \ No newline at end of file diff -r 084de6909451 -r f3150b37f9be src/treecms/tree/util/NodeChildrenImpl.java --- a/src/treecms/tree/util/NodeChildrenImpl.java Wed Jun 01 15:35:50 2011 +0900 +++ b/src/treecms/tree/util/NodeChildrenImpl.java Mon Jun 06 21:49:04 2011 +0900 @@ -92,6 +92,10 @@ @Override public synchronized boolean addAll(NodeChildren _list) { + if(_list == this){ + return false; + } + if(Collections.disjoint(getFamilyIDSet(),_list.getFamilyIDSet())){ HashMap map = new HashMap();