changeset 33:c0a0fa870e6e

commit again
author shoshi
date Fri, 19 Nov 2010 15:31:42 +0900
parents 02ef906d0341
children b8b751a9fafb
files CHANGELOG src/treecms/proto/api/Node.java src/treecms/proto/gui/GUIEditor.java src/treecms/proto/gui/GraphicalMonotonicTreeEditor.java src/treecms/proto/id/IncrementalNodeID.java src/treecms/proto/simple/RandomSimpleTreeBuilder.java src/treecms/proto/simple/SimpleEditor.java src/treecms/proto/simple/SimpleLink.java src/treecms/proto/simple/SimpleNode.java src/treecms/proto/test/SimpleNodeTest1.java
diffstat 10 files changed, 514 insertions(+), 355 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG	Thu Nov 18 19:05:23 2010 +0900
+++ b/CHANGELOG	Fri Nov 19 15:31:42 2010 +0900
@@ -6,6 +6,9 @@
 
 modified Editor API
 	bug fix (not done yet , still buggy)
+	
+modified SimpleNode
+	bug fix , replace(Node,Node) is not working fixed.
 
 2010/11/17
 modified Node API
--- a/src/treecms/proto/api/Node.java	Thu Nov 18 19:05:23 2010 +0900
+++ b/src/treecms/proto/api/Node.java	Fri Nov 19 15:31:42 2010 +0900
@@ -20,6 +20,7 @@
 	
 	public Node addChild(Node _child);
 	public boolean removeChild(Node _child);
+	public void clearChildren();
 	
 	public void up(Node _child);
 	public void down(Node _child);
--- a/src/treecms/proto/gui/GUIEditor.java	Thu Nov 18 19:05:23 2010 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,321 +0,0 @@
-package treecms.proto.gui;
-
-import java.awt.BorderLayout;
-import java.awt.GridLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.util.concurrent.atomic.AtomicReference;
-
-import javax.swing.JButton;
-import javax.swing.JComponent;
-import javax.swing.JFrame;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JSplitPane;
-import javax.swing.JTable;
-import javax.swing.JTree;
-import javax.swing.border.BevelBorder;
-import javax.swing.border.TitledBorder;
-import javax.swing.event.TreeSelectionEvent;
-import javax.swing.event.TreeSelectionListener;
-import javax.swing.table.DefaultTableModel;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.DefaultTreeModel;
-
-import treecms.proto.api.Editor;
-import treecms.proto.api.Node;
-import treecms.proto.simple.SimpleEditor;
-import treecms.proto.simple.SimpleNode;
-
-public class GUIEditor extends JFrame
-{
-	private static final long serialVersionUID = 1095393471116557554L;
-
-	public static void main(String _args[])
-	{
-		Node root = new SimpleNode();
-		root.setTitle("root");
-		Node c1 = root.addChild(new SimpleNode());
-		c1.setTitle("c1");
-		Node c2 = root.addChild(new SimpleNode());
-		c2.setTitle("c2");
-		
-		
-		Node c11 = c1.addChild(new SimpleNode());
-		c11.setTitle("c11");
-		Node c12 = c1.addChild(new SimpleNode());
-		c12.setTitle("c12");
-		
-		Node c121 = c12.addChild(new SimpleNode());
-		c121.setTitle("c121");
-		
-		AtomicReference<Node> repo = new AtomicReference<Node>(root);
-		
-		new GUIEditor(new SimpleEditor(repo));
-		new GUIEditor(new SimpleEditor(repo));
-	}
-	
-	private static final String WINDOW_TITLE = "Monotonic-Tree Editor";
-	
-	//menu bar
-	private JButton m_commit,m_update,m_check,m_merge;
-	
-	//buttons
-	private JButton m_saveButton,m_clearButton;
-	
-	//contents view
-	private JTree m_tree;
-	
-	//properties view
-	private JTable m_table;
-	
-	//editor
-	private Editor m_editor;
-	
-	public GUIEditor(Editor _editor)
-	{
-		super(WINDOW_TITLE);
-		
-		m_editor = _editor;
-		
-		getContentPane().setLayout(new BorderLayout());
-		
-		JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT,buildTreeViewer(),buildNodeEditor());
-		split.setDividerLocation(400);
-		
-		getContentPane().add(buildMenuBar(),BorderLayout.NORTH);
-		getContentPane().add(split,BorderLayout.CENTER);
-		
-		setSize(500,600);
-		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-		setVisible(true);
-	}
-	
-	public JComponent buildMenuBar()
-	{
-		JPanel panel = new JPanel(new GridLayout(1,4));
-		m_commit = new JButton("commit");
-		m_update = new JButton("update");
-		m_check = new JButton("check");
-		m_merge = new JButton("merge");
-		
-		EditorMenuActionListener listener = new EditorMenuActionListener();
-		m_commit.addActionListener(listener);
-		m_update.addActionListener(listener);
-		m_check.addActionListener(listener);
-		m_merge.addActionListener(listener);
-		
-		panel.add(m_commit);
-		panel.add(m_update);
-		panel.add(m_check);
-		panel.add(m_merge);
-		
-		return panel;
-	}
-	
-	public JComponent buildNodeEditor()
-	{
-		m_table = new JTable(new NodeEditorTableModel());
-		m_saveButton = new JButton("save");
-		m_clearButton = new JButton("clear");
-		
-		EditorButtonActionListener listener = new EditorButtonActionListener();
-		m_saveButton.addActionListener(listener);
-		m_clearButton.addActionListener(listener);
-		
-		JPanel panel = new JPanel(new BorderLayout());
-		panel.setBorder(new TitledBorder("Node Editor"));
-		
-		JPanel btnPanel = new JPanel(new GridLayout(1,2));
-		btnPanel.add(m_saveButton);
-		btnPanel.add(m_clearButton);
-		
-		panel.add(new JScrollPane(m_table),BorderLayout.CENTER);
-		panel.add(btnPanel,BorderLayout.SOUTH);
-		
-		return panel;
-	}
-	
-	private class NodeEditorTableModel extends DefaultTableModel
-	{
-		private static final long serialVersionUID = -7158401828787373107L;
-		
-		private Node m_node;
-		
-		public NodeEditorTableModel()
-		{
-			m_node = null;
-			setColumnIdentifiers(new String[]{"Key","Value"});
-		}
-		
-		public NodeEditorTableModel(Node _node)
-		{
-			this();
-			m_node = _node;
-			printNode();
-		}
-		
-		@Override
-		public boolean isCellEditable(int _row,int _col)
-		{
-			if(_col == 0 || _row == 0){
-				return false; //disable editing id and parameter names
-			}
-			return true;
-		}
-		
-		public void setNode(Node _node)
-		{
-			m_node = _node;
-			printNode();
-		}
-		
-		public void clear()
-		{
-			printNode();
-		}
-		
-		private void printNode()
-		{
-			setRowCount(0);
-			addRow(new String[]{"id",m_node.getID().toString()});
-			addRow(new String[]{"title",m_node.getTitle()});
-			addRow(new String[]{"class",m_node.getClassName()});
-		}
-		
-		public String getTitle()
-		{
-			return (String)getValueAt(1,1);
-		}
-		
-		public String getClassName()
-		{
-			return (String)getValueAt(2,1);
-		}
-		
-		public Node getNode()
-		{
-			return m_node;
-		}
-	}
-	
-	public JComponent buildTreeViewer()
-	{
-		m_tree = new JTree(new ContentsViewerTreeModel(m_editor.useContents()));
-		m_tree.addTreeSelectionListener(new TreeSelectionListener(){
-			@Override
-			public void valueChanged(TreeSelectionEvent _e)
-			{
-				DefaultMutableTreeNode selected = (DefaultMutableTreeNode)m_tree.getLastSelectedPathComponent();
-				if(selected == null){
-					return;
-				}
-				Node node = (Node)selected.getUserObject(); //get node
-				
-				//
-				NodeEditorTableModel model = (NodeEditorTableModel)m_table.getModel();
-				model.setNode(node);
-			}
-		});
-		
-		return new JScrollPane(m_tree);
-	}
-	
-	private class ContentsViewerTreeModel extends DefaultTreeModel
-	{
-		private static final long serialVersionUID = -4710796110922619395L;
-		
-		public ContentsViewerTreeModel(Node _contents)
-		{
-			super(new DefaultMutableTreeNode());
-			setRootNode(_contents,false);
-		}
-
-		public void setRootNode(Node _contents,boolean _reload)
-		{
-			DefaultMutableTreeNode root = (DefaultMutableTreeNode)getRoot();
-			root.removeAllChildren();
-			root.setUserObject(_contents);
-			
-			for(Node child : _contents.getChildren()){
-				treewalk(child,root);
-			}
-			
-			if(_reload){
-				reload();
-			}
-		}
-		
-		private void treewalk(Node _node,DefaultMutableTreeNode _treeNode)
-		{
-			DefaultMutableTreeNode treeChild = new DefaultMutableTreeNode();
-			treeChild.setUserObject(_node);
-			_treeNode.add(treeChild);
-			
-			for(Node child : _node.getChildren()){
-				treewalk(child,treeChild);
-			}
-		}
-	}
-	
-	private class EditorMenuActionListener implements ActionListener
-	{
-		@Override
-		public void actionPerformed(ActionEvent _e)
-		{
-			JButton source = (JButton)_e.getSource();
-			if(source.equals(m_commit)){
-				//commit
-				m_editor.commit(true);
-			}
-			if(source.equals(m_update)){
-				//update
-				m_editor.update();
-				ContentsViewerTreeModel model = (ContentsViewerTreeModel)m_tree.getModel();
-				model.setRootNode(m_editor.useContents(),true);
-			}
-			if(source.equals(m_check)){
-				//check
-				if(m_editor.check()){
-					JOptionPane.showMessageDialog(GUIEditor.this,"updates aviable!","update check",JOptionPane.OK_OPTION);
-				}else{
-					JOptionPane.showMessageDialog(GUIEditor.this,"updates not aviable!","update check",JOptionPane.OK_OPTION);
-				}
-			}
-			if(source.equals(m_merge)){
-				//merge
-				m_editor.merge();
-				ContentsViewerTreeModel model = (ContentsViewerTreeModel)m_tree.getModel();
-				model.setRootNode(m_editor.useContents(),true);
-			}
-		}
-	}
-	
-	private class EditorButtonActionListener implements ActionListener
-	{
-		@Override
-		public void actionPerformed(ActionEvent _e)
-		{
-			JButton source = (JButton)_e.getSource();
-			
-			if(source.equals(m_saveButton)){
-				NodeEditorTableModel tableModel = (NodeEditorTableModel)m_table.getModel();
-				Node target = tableModel.getNode();
-				Node newNode = m_editor.edit(target);
-				newNode.setTitle(tableModel.getTitle());
-				newNode.setClassName(tableModel.getClassName());
-				
-				ContentsViewerTreeModel treeModel = (ContentsViewerTreeModel)m_tree.getModel();
-				treeModel.setRootNode(m_editor.getUncommited(),true);
-			}
-			
-			if(source.equals(m_clearButton)){
-				NodeEditorTableModel tableModel = (NodeEditorTableModel)m_table.getModel();
-				tableModel.clear();
-			}
-		}
-		
-	}
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/treecms/proto/gui/GraphicalMonotonicTreeEditor.java	Fri Nov 19 15:31:42 2010 +0900
@@ -0,0 +1,326 @@
+package treecms.proto.gui;
+
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTable;
+import javax.swing.JTree;
+import javax.swing.border.TitledBorder;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+
+import treecms.proto.api.Editor;
+import treecms.proto.api.Node;
+import treecms.proto.simple.RandomSimpleTreeBuilder;
+import treecms.proto.simple.SimpleEditor;
+import treecms.proto.simple.SimpleNode;
+
+public class GraphicalMonotonicTreeEditor extends JFrame
+{
+	private static final long serialVersionUID = 1095393471116557554L;
+
+	public static void main(String _args[])
+	{
+		AtomicReference<Node> repo = new AtomicReference<Node>(RandomSimpleTreeBuilder.randomTree(2,2,3,3));
+		
+		new GraphicalMonotonicTreeEditor(new SimpleEditor(repo));
+		new GraphicalMonotonicTreeEditor(new SimpleEditor(repo));
+	}
+	
+	private static final String WINDOW_TITLE = "Monotonic-Tree Editor";
+	
+	//menu bar
+	private JButton m_commit,m_update,m_check,m_merge;
+	
+	//buttons
+	private JButton m_saveButton,m_clearButton,m_addButton;
+	
+	//contents view
+	private JTree m_tree;
+	
+	//properties view
+	private JTable m_table;
+	
+	//editor
+	private Editor m_editor;
+	
+	public GraphicalMonotonicTreeEditor(Editor _editor)
+	{
+		super(WINDOW_TITLE);
+		
+		m_editor = _editor;
+		
+		getContentPane().setLayout(new BorderLayout());
+		
+		JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT,buildTreeViewer(),buildNodeEditor());
+		split.setDividerLocation(400);
+		
+		getContentPane().add(buildMenuBar(),BorderLayout.NORTH);
+		getContentPane().add(split,BorderLayout.CENTER);
+		
+		setSize(500,600);
+		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		setVisible(true);
+		
+		for(int i = 0;i < m_tree.getRowCount();i ++){
+			m_tree.expandRow(i);
+		}
+	}
+	
+	public JComponent buildMenuBar()
+	{
+		JPanel panel = new JPanel(new GridLayout(1,4));
+		m_commit = new JButton("commit");
+		m_update = new JButton("update");
+		m_check = new JButton("check");
+		m_merge = new JButton("merge");
+		
+		EditorMenuActionListener listener = new EditorMenuActionListener();
+		m_commit.addActionListener(listener);
+		m_update.addActionListener(listener);
+		m_check.addActionListener(listener);
+		m_merge.addActionListener(listener);
+		
+		panel.add(m_commit);
+		panel.add(m_update);
+		panel.add(m_check);
+		panel.add(m_merge);
+		
+		return panel;
+	}
+	
+	public JComponent buildNodeEditor()
+	{
+		m_table = new JTable(new NodeEditorTableModel());
+		m_saveButton = new JButton("save");
+		m_clearButton = new JButton("clear");
+		m_addButton = new JButton("add child");
+		
+		EditorButtonActionListener listener = new EditorButtonActionListener();
+		m_saveButton.addActionListener(listener);
+		m_clearButton.addActionListener(listener);
+		m_addButton.addActionListener(listener);
+		
+		JPanel panel = new JPanel(new BorderLayout());
+		panel.setBorder(new TitledBorder("Node Editor"));
+		
+		JPanel btnPanel = new JPanel(new GridLayout(1,2));
+		btnPanel.add(m_saveButton);
+		btnPanel.add(m_clearButton);
+		btnPanel.add(m_addButton);
+		
+		panel.add(new JScrollPane(m_table),BorderLayout.CENTER);
+		panel.add(btnPanel,BorderLayout.SOUTH);
+		
+		return panel;
+	}
+	
+	private class NodeEditorTableModel extends DefaultTableModel
+	{
+		private static final long serialVersionUID = -7158401828787373107L;
+		
+		private Node m_node;
+		
+		public NodeEditorTableModel()
+		{
+			m_node = null;
+			setColumnIdentifiers(new String[]{"Key","Value"});
+		}
+		
+		public NodeEditorTableModel(Node _node)
+		{
+			this();
+			m_node = _node;
+			printNode();
+		}
+		
+		@Override
+		public boolean isCellEditable(int _row,int _col)
+		{
+			if(_col == 0 || _row == 0){
+				return false; //disable editing id and parameter names
+			}
+			return true;
+		}
+		
+		public void setNode(Node _node)
+		{
+			m_node = _node;
+			printNode();
+		}
+		
+		public void clear()
+		{
+			printNode();
+		}
+		
+		private void printNode()
+		{
+			setRowCount(0);
+			addRow(new String[]{"id",m_node.getID().toString()});
+			addRow(new String[]{"title",m_node.getTitle()});
+			addRow(new String[]{"class",m_node.getClassName()});
+		}
+		
+		public String getTitle()
+		{
+			return (String)getValueAt(1,1);
+		}
+		
+		public String getClassName()
+		{
+			return (String)getValueAt(2,1);
+		}
+		
+		public Node getNode()
+		{
+			return m_node;
+		}
+	}
+	
+	public JComponent buildTreeViewer()
+	{
+		m_tree = new JTree(new ContentsViewerTreeModel(m_editor.useContents()));
+		m_tree.addTreeSelectionListener(new TreeSelectionListener(){
+			@Override
+			public void valueChanged(TreeSelectionEvent _e)
+			{
+				DefaultMutableTreeNode selected = (DefaultMutableTreeNode)m_tree.getLastSelectedPathComponent();
+				if(selected == null){
+					return;
+				}
+				Node node = (Node)selected.getUserObject(); //get node
+				
+				//
+				NodeEditorTableModel model = (NodeEditorTableModel)m_table.getModel();
+				model.setNode(node);
+			}
+		});
+		
+		return new JScrollPane(m_tree);
+	}
+	
+	private class ContentsViewerTreeModel extends DefaultTreeModel
+	{
+		private static final long serialVersionUID = -4710796110922619395L;
+		
+		public ContentsViewerTreeModel(Node _contents)
+		{
+			super(new DefaultMutableTreeNode());
+			setRootNode(_contents,false);
+		}
+
+		public void setRootNode(Node _contents,boolean _reload)
+		{
+			DefaultMutableTreeNode root = (DefaultMutableTreeNode)getRoot();
+			root.removeAllChildren();
+			root.setUserObject(_contents);
+			
+			for(Node child : _contents.getChildren()){
+				treewalk(child,root);
+			}
+			
+			if(_reload){
+				reload();
+			}
+		}
+		
+		private void treewalk(Node _node,DefaultMutableTreeNode _treeNode)
+		{
+			DefaultMutableTreeNode treeChild = new DefaultMutableTreeNode();
+			treeChild.setUserObject(_node);
+			_treeNode.add(treeChild);
+			
+			for(Node child : _node.getChildren()){
+				treewalk(child,treeChild);
+			}
+		}
+	}
+	
+	private class EditorMenuActionListener implements ActionListener
+	{
+		@Override
+		public void actionPerformed(ActionEvent _e)
+		{
+			JButton source = (JButton)_e.getSource();
+			if(source.equals(m_commit)){
+				//commit
+				m_editor.commit(true);
+			}
+			if(source.equals(m_update)){
+				//update
+				m_editor.update();
+				ContentsViewerTreeModel model = (ContentsViewerTreeModel)m_tree.getModel();
+				model.setRootNode(m_editor.useContents(),true);
+			}
+			if(source.equals(m_check)){
+				//check
+				if(m_editor.check()){
+					JOptionPane.showMessageDialog(GraphicalMonotonicTreeEditor.this,"updates aviable!","update check",JOptionPane.OK_OPTION);
+				}else{
+					JOptionPane.showMessageDialog(GraphicalMonotonicTreeEditor.this,"updates not aviable!","update check",JOptionPane.OK_OPTION);
+				}
+			}
+			if(source.equals(m_merge)){
+				//merge
+				m_editor.merge();
+				ContentsViewerTreeModel model = (ContentsViewerTreeModel)m_tree.getModel();
+				model.setRootNode(m_editor.useContents(),true);
+			}
+			
+			for(int i = 0;i < m_tree.getRowCount();i ++){
+				m_tree.expandRow(i);
+			}
+		}
+	}
+	
+	private class EditorButtonActionListener implements ActionListener
+	{
+		@Override
+		public void actionPerformed(ActionEvent _e)
+		{
+			JButton source = (JButton)_e.getSource();
+			NodeEditorTableModel tableModel = (NodeEditorTableModel)m_table.getModel();
+			
+			if(source.equals(m_saveButton)){
+				Node target = tableModel.getNode();
+				Node newNode = m_editor.edit(target);
+				newNode.setTitle(tableModel.getTitle());
+				newNode.setClassName(tableModel.getClassName());
+				
+				ContentsViewerTreeModel treeModel = (ContentsViewerTreeModel)m_tree.getModel();
+				treeModel.setRootNode(m_editor.getUncommited(),true);
+			}
+			
+			if(source.equals(m_clearButton)){
+				tableModel.clear();
+			}
+			
+			if(source.equals(m_addButton)){
+				Node newNode = m_editor.edit(tableModel.getNode());
+				Node child = newNode.addChild(new SimpleNode());
+				
+				ContentsViewerTreeModel treeModel = (ContentsViewerTreeModel)m_tree.getModel();
+				treeModel.setRootNode(m_editor.getUncommited(),true);
+			}
+			
+			for(int i = 0;i < m_tree.getRowCount();i ++){
+				m_tree.expandRow(i);
+			}
+		}
+		
+	}
+}
--- a/src/treecms/proto/id/IncrementalNodeID.java	Thu Nov 18 19:05:23 2010 +0900
+++ b/src/treecms/proto/id/IncrementalNodeID.java	Fri Nov 19 15:31:42 2010 +0900
@@ -42,14 +42,14 @@
 		if(m_inheritedID.equals(target.m_inheritedID)){
 			long diff = m_version - target.m_version;
 			if(diff == 0){
-				return 0;
+				return 0; // same id
 			}else if(diff < 0){
-				return -1;
+				return -1; // target is newer then this.
 			}else{
-				return 1;
+				return 1; // target is older then this.
 			}
 		}
-		return -2;
+		return -2; //wrong inherited id
 	}
 	
 	@Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/treecms/proto/simple/RandomSimpleTreeBuilder.java	Fri Nov 19 15:31:42 2010 +0900
@@ -0,0 +1,78 @@
+package treecms.proto.simple;
+
+import java.util.Random;
+
+import treecms.proto.api.Node;
+
+public class RandomSimpleTreeBuilder
+{
+	public static void main(String _args[])
+	{
+		SimpleNode root = RandomSimpleTreeBuilder.randomTree(2,2,3,3);
+		print(0,root);
+	}
+	
+	public static void print(int _indent,Node _parent)
+	{
+		for(int i = 0;i < _indent;i ++){
+			System.out.print("\t");
+		}
+		System.out.println(_parent.getTitle());
+		
+		for(Node child : _parent.getChildren()){
+			print(_indent + 1,child);
+		}
+	}
+	
+	public static SimpleNode randomTree(int _maxRow,int _maxCol)
+	{
+		return randomTree(0,0,_maxRow,_maxCol);
+	}
+	
+	public static SimpleNode randomTree(int _minRow,int _minCol,int _maxRow,int _maxCol)
+	{
+		RandomSimpleTreeBuilder builder = new RandomSimpleTreeBuilder(_minRow,_minCol,_maxRow,_maxCol);
+		return builder.generate();
+	}
+	
+	private int m_minRow,m_minCol;
+	private int m_maxRow,m_maxCol;
+	
+	private RandomSimpleTreeBuilder(int _minRow,int _minCol,int _maxRow,int _maxCol)
+	{
+		m_minRow = _minRow;
+		m_minCol = _minCol;
+		m_maxRow = _maxRow;
+		m_maxCol = _maxCol;
+	}
+	
+	public SimpleNode generate()
+	{
+		SimpleNode root = new SimpleNode();
+		root.setTitle("root");
+		
+		Random rand = new Random();
+		int childs = m_minCol + rand.nextInt(m_maxCol)*(1 - m_minCol/(1 + m_maxCol));
+		for(int i = 1;i < childs;i ++){
+			SimpleNode child = (SimpleNode)root.addChild(new SimpleNode());
+			child.setTitle("c"+i);
+			generate(child,1,rand);
+		}
+		return root;
+	}
+	
+	private void generate(SimpleNode _parent,int _row,Random _rand)
+	{
+		if(_row >= m_maxRow || _rand.nextInt(m_maxRow) == 0){
+			return;
+		}
+		
+		int childs = m_minCol + _rand.nextInt(m_maxCol)*(1 - m_minCol/(1 + m_maxCol));
+		for(int i = 1;i < childs;i ++){
+			SimpleNode child = (SimpleNode)_parent.addChild(new SimpleNode());
+			child.setTitle(_parent.getTitle()+i);
+			generate(child,_row + 1,_rand);
+		}
+	}
+	
+}
--- a/src/treecms/proto/simple/SimpleEditor.java	Thu Nov 18 19:05:23 2010 +0900
+++ b/src/treecms/proto/simple/SimpleEditor.java	Fri Nov 19 15:31:42 2010 +0900
@@ -9,53 +9,66 @@
 public class SimpleEditor implements Editor
 {
 	private AtomicReference<Node> m_repository;
-	private Node m_tip,m_latest;
 	
-	private LinkedList<Node> m_log;
+	private Node m_uncommitted; // uncommitted version
+	private Node m_tip; // tip version
+	
+	private LinkedList<Pair<Node,Node>> m_editLog; // there is noting for it but to do.
 	
 	public SimpleEditor(AtomicReference<Node> _contents)
 	{
 		m_repository = _contents;
 		m_tip = m_repository.get();
-		m_latest = m_tip;
-		m_log = new LinkedList<Node>();
+		m_uncommitted = m_tip;
+		m_editLog = new LinkedList<Pair<Node,Node>>();
 	}
 	
-	public boolean checkUpdate()
+	@Override
+	public boolean check()
 	{
-		return !m_repository.compareAndSet(m_latest,m_latest);
+		return !m_repository.compareAndSet(m_tip,m_tip); //CAS same value to check update.
 	}
 	
 	public boolean commit(boolean _force)
 	{
 		if(_force){
-			m_repository.set(m_tip);
+			m_repository.set(m_uncommitted); // force commit
 			update();
 			return true;
 		}
-		return m_repository.compareAndSet(m_latest,m_tip);
+		
+		//will be success when nobody committed before.
+		return m_repository.compareAndSet(m_tip,m_uncommitted);
 	}
 	
 	public void merge()
 	{
-		LinkedList<Node> log = new LinkedList<Node>(m_log);
+		LinkedList<Pair<Node,Node>> log = new LinkedList<Pair<Node,Node>>(m_editLog); //backup
 		
-		update(); //update first.
-		for(Node node : log){
-			edit(node); //edit again;
+		update();
+		for(Pair<Node,Node> pair: log){
+			Node target = pair.getLeft();
+			Node clone = pair.getRight();
+			Node newNode = edit(target); //edit again;
+			
+			//set parameters
+			newNode.setClassName(clone.getClassName());
+			newNode.setTitle(clone.getTitle());
+			
 		}
 	}
 	
 	public void discard()
 	{
-		m_tip = m_latest;
-		m_log.clear();
+		//delete all uncommitted changes.
+		m_uncommitted = m_tip;
+		m_editLog.clear();
 	}
 
 	@Override
 	public Node useContents()
 	{
-		return m_latest;
+		return m_uncommitted; 
 	}
 
 	@Override
@@ -71,7 +84,7 @@
 	@Override
 	public Node edit(Node _target)
 	{
-		LinkedList<Node> path = findPath(m_tip,_target);
+		LinkedList<Node> path = findPath(m_uncommitted,_target);
 		if(path.isEmpty()){
 			return null;
 		}
@@ -81,10 +94,13 @@
 		change.add(root);
 		cloneTree(path,root,change);
 		
-		m_tip = root;
-		m_log.add(change.peekLast()); //add to change log.
+		m_uncommitted = root;
+		
+		Node clone = change.peekLast();
 		
-		return change.peekLast();
+		m_editLog.add(new Pair<Node,Node>(_target,clone)); // left -> target , right -> clone
+		
+		return clone;
 	}
 	
 	private void cloneTree(LinkedList<Node> _path,Node _parent,LinkedList<Node> _change)
@@ -113,14 +129,15 @@
 	private LinkedList<Node> findPath(Node _root,Node _child)
 	{
 		LinkedList<Node> list = new LinkedList<Node>();
-		findPath(_root,_child,list);
-		list.addFirst(_root);
+		if(findPath(_root,_child,list)){
+			list.addFirst(_root);
+		}
 		return list;
 	}
 	
 	private boolean findPath(Node _root,Node _child,LinkedList<Node> _list)
 	{
-		if(_root == _child){
+		if(_root.getID().compare(_child.getID()) != -2){
 			return true;
 		}
 		
@@ -136,21 +153,47 @@
 	@Override
 	public Node getUncommited()
 	{
-		return m_tip;
+		return m_uncommitted;
 	}
 
 	@Override
 	public boolean update()
 	{
 		discard();
-		m_latest = m_repository.get();
-		m_tip = m_latest;
-		return true;
+		m_tip = m_repository.get();
+		m_uncommitted = m_tip;
+		return true; // !?!?
 	}
 
-	@Override
-	public boolean check()
+	private class Pair<L,R>
 	{
-		return checkUpdate();
+		private L m_left;
+		private R m_right;
+		
+		public Pair(L _left,R _right)
+		{
+			m_left = _left;
+			m_right = _right;
+		}
+		
+		public L getLeft()
+		{
+			return m_left;
+		}
+		
+		public R getRight()
+		{
+			return m_right;
+		}
+		
+		public void setLeft(L _left)
+		{
+			m_left = _left;
+		}
+		
+		public void setRight(R _right)
+		{
+			m_right = _right;
+		}
 	}
 }
--- a/src/treecms/proto/simple/SimpleLink.java	Thu Nov 18 19:05:23 2010 +0900
+++ b/src/treecms/proto/simple/SimpleLink.java	Fri Nov 19 15:31:42 2010 +0900
@@ -124,4 +124,10 @@
 	{
 		return;
 	}
+
+	@Override
+	public void clearChildren()
+	{
+		return;
+	}
 }
--- a/src/treecms/proto/simple/SimpleNode.java	Thu Nov 18 19:05:23 2010 +0900
+++ b/src/treecms/proto/simple/SimpleNode.java	Fri Nov 19 15:31:42 2010 +0900
@@ -134,15 +134,19 @@
 	@Override
 	public void replace(Node _target, Node _newChild)
 	{
+		Node target = _target;
 		LinkedList<Node> children = new LinkedList<Node>();
 		
 		for(Node child : m_children){
-			if(child == _target){
+			if(child == target){
 				children.add(_newChild);
+				target = _newChild;
 				continue;
 			}
 			children.add(child);
 		}
+		
+		m_children = new CopyOnWriteArrayList<Node>(children);
 	}
 
 	@Override
@@ -170,4 +174,10 @@
 	{
 		return getTitle()+"["+getID().toString()+"]";
 	}
+
+	@Override
+	public void clearChildren()
+	{
+		m_children.clear();
+	}
 }
--- a/src/treecms/proto/test/SimpleNodeTest1.java	Thu Nov 18 19:05:23 2010 +0900
+++ b/src/treecms/proto/test/SimpleNodeTest1.java	Fri Nov 19 15:31:42 2010 +0900
@@ -106,4 +106,17 @@
 		Assert.assertEquals(children.get(1),m_child3);
 		Assert.assertEquals(children.get(2),m_child2);
 	}
+	
+	@Test
+	public void testReplaceOperation()
+	{
+		//replace
+		Node node = new SimpleNode();
+		m_target.replace(m_child2,node);
+		
+		List<Node> children = m_target.getChildren();
+		Assert.assertEquals(children.get(0),m_child1);
+		Assert.assertEquals(children.get(1),node);
+		Assert.assertEquals(children.get(2),m_child3);
+	}
 }