28
|
1 package treecms.proto.simple;
|
|
2
|
|
3 import java.util.List;
|
|
4 import java.util.concurrent.atomic.AtomicReference;
|
|
5 import java.util.LinkedList;
|
|
6 import treecms.proto.api.Editor;
|
|
7 import treecms.proto.api.Node;
|
|
8
|
|
9 public class SimpleEditor implements Editor
|
|
10 {
|
32
|
11 private AtomicReference<Node> m_repository;
|
|
12 private Node m_tip,m_latest;
|
28
|
13
|
|
14 private LinkedList<Node> m_log;
|
|
15
|
|
16 public SimpleEditor(AtomicReference<Node> _contents)
|
|
17 {
|
32
|
18 m_repository = _contents;
|
|
19 m_tip = m_repository.get();
|
|
20 m_latest = m_tip;
|
28
|
21 m_log = new LinkedList<Node>();
|
|
22 }
|
|
23
|
|
24 public boolean checkUpdate()
|
|
25 {
|
32
|
26 return !m_repository.compareAndSet(m_latest,m_latest);
|
28
|
27 }
|
|
28
|
|
29 public boolean commit(boolean _force)
|
|
30 {
|
29
|
31 if(_force){
|
32
|
32 m_repository.set(m_tip);
|
29
|
33 update();
|
|
34 return true;
|
|
35 }
|
32
|
36 return m_repository.compareAndSet(m_latest,m_tip);
|
29
|
37 }
|
|
38
|
|
39 public void merge()
|
|
40 {
|
|
41 LinkedList<Node> log = new LinkedList<Node>(m_log);
|
32
|
42
|
|
43 update(); //update first.
|
29
|
44 for(Node node : log){
|
32
|
45 edit(node); //edit again;
|
29
|
46 }
|
28
|
47 }
|
|
48
|
|
49 public void discard()
|
|
50 {
|
32
|
51 m_tip = m_latest;
|
28
|
52 m_log.clear();
|
|
53 }
|
|
54
|
|
55 @Override
|
|
56 public Node useContents()
|
|
57 {
|
32
|
58 return m_latest;
|
28
|
59 }
|
|
60
|
|
61 @Override
|
|
62 public void login(String user, String pass)
|
|
63 {
|
|
64 }
|
|
65
|
|
66 @Override
|
|
67 public void logout()
|
|
68 {
|
|
69 }
|
|
70
|
|
71 @Override
|
|
72 public Node edit(Node _target)
|
|
73 {
|
|
74 LinkedList<Node> path = findPath(m_tip,_target);
|
|
75 if(path.isEmpty()){
|
|
76 return null;
|
|
77 }
|
|
78
|
|
79 LinkedList<Node> change = new LinkedList<Node>();
|
|
80 Node root = path.poll().cloneNode();
|
|
81 change.add(root);
|
|
82 cloneTree(path,root,change);
|
|
83
|
|
84 m_tip = root;
|
32
|
85 m_log.add(change.peekLast()); //add to change log.
|
|
86
|
28
|
87 return change.peekLast();
|
|
88 }
|
|
89
|
|
90 private void cloneTree(LinkedList<Node> _path,Node _parent,LinkedList<Node> _change)
|
|
91 {
|
|
92 List<Node> children = _parent.getChildren();
|
|
93 Node target = _path.poll();
|
|
94 if(target == null){
|
|
95 return;
|
|
96 }
|
|
97 for(int i = 0;i < children.size();i ++){
|
|
98 Node _child = children.get(i);
|
|
99 if(_child.getID().compare(target.getID()) != -2){
|
|
100 //clone node
|
|
101 Node clone = _child.cloneNode();
|
|
102 _change.add(clone);
|
|
103
|
|
104 //remove old node from clonedTree
|
32
|
105 _parent.replace(_child,clone);
|
28
|
106
|
|
107 cloneTree(_path,clone,_change);
|
|
108 break;
|
|
109 }
|
|
110 }
|
|
111 }
|
|
112
|
|
113 private LinkedList<Node> findPath(Node _root,Node _child)
|
|
114 {
|
|
115 LinkedList<Node> list = new LinkedList<Node>();
|
|
116 findPath(_root,_child,list);
|
|
117 list.addFirst(_root);
|
|
118 return list;
|
|
119 }
|
|
120
|
|
121 private boolean findPath(Node _root,Node _child,LinkedList<Node> _list)
|
|
122 {
|
|
123 if(_root == _child){
|
|
124 return true;
|
|
125 }
|
|
126
|
|
127 for(Node child : _root.getChildren()){
|
|
128 if(findPath(child,_child,_list)){
|
|
129 _list.addFirst(child);
|
|
130 return true;
|
|
131 }
|
|
132 }
|
|
133 return false;
|
|
134 }
|
|
135
|
|
136 @Override
|
|
137 public Node getUncommited()
|
|
138 {
|
32
|
139 return m_tip;
|
28
|
140 }
|
|
141
|
|
142 @Override
|
|
143 public boolean update()
|
|
144 {
|
|
145 discard();
|
32
|
146 m_latest = m_repository.get();
|
|
147 m_tip = m_latest;
|
|
148 return true;
|
28
|
149 }
|
|
150
|
|
151 @Override
|
|
152 public boolean check()
|
|
153 {
|
32
|
154 return checkUpdate();
|
28
|
155 }
|
|
156 }
|