001    package nl.cwi.sen1.error.model;
002    
003    import java.util.Enumeration;
004    import java.util.HashMap;
005    import java.util.Iterator;
006    import java.util.LinkedList;
007    import java.util.List;
008    import java.util.Map;
009    
010    import javax.swing.tree.DefaultMutableTreeNode;
011    import javax.swing.tree.MutableTreeNode;
012    
013    import errorapi.types.Error;
014    import errorapi.types.ErrorList;
015    import errorapi.types.Location;
016    import errorapi.types.Subject;
017    import errorapi.types.SubjectList;
018    import errorapi.types.Summary;
019    
020    public class ErrorDecorator {
021            private LocationNode decorateLocation(final Location location) {
022                    return new LocationNode(location);
023            }
024    
025            private SubjectNode decorateSubject(final Subject subject) {
026                    SubjectNode node = new SubjectNode(subject);
027    
028                    if (subject.hasLocation()) {
029                            node.add(decorateLocation(subject.getLocation()));
030                    }
031    
032                    return node;
033            }
034    
035            private ErrorNode decorateError(final Error error, String producer,
036                            String id) {
037                    ErrorNode node = new ErrorNode(error, producer, id);
038                    SubjectList subjectList = error.getList();
039    
040                    while (!subjectList.isEmpty()) {
041                            Subject head = subjectList.getHead();
042                            node.add(decorateSubject(head));
043                            if (head.hasLocation()) {
044                                    node.setLocation(head.getLocation());
045                            }
046                            subjectList = subjectList.getTail();
047                    }
048    
049                    return node;
050            }
051    
052            private boolean collectNodes(DefaultMutableTreeNode top,
053                            List<ErrorNode> list) {
054                    boolean grouped = false;
055    
056                    for (Enumeration<?> e = top.children(); e.hasMoreElements();) {
057                            DefaultMutableTreeNode node = (DefaultMutableTreeNode) e
058                                            .nextElement();
059    
060                            if (node instanceof GroupNode) {
061                                    grouped = true;
062                                    collectNodes(node, list);
063                            } else if (node instanceof ErrorNode) {
064                                    list.add(0, (ErrorNode) node);
065                            }
066                    }
067    
068                    return grouped;
069            }
070    
071            private void setGrouping(DefaultMutableTreeNode top, int grouping) {
072                    List<ErrorNode> list = new LinkedList<ErrorNode>();
073                    collectNodes(top, list);
074                    top.removeAllChildren();
075                    Iterator<?> newChildren;
076    
077                    if (grouping != GroupNode.NO_GROUP) {
078                            Map<String, GroupNode> groups = new HashMap<String, GroupNode>();
079                            groupNodes(list, groups, grouping);
080                            newChildren = groups.values().iterator();
081                    } else {
082                            newChildren = list.iterator();
083                    }
084    
085                    while (newChildren.hasNext()) {
086                            MutableTreeNode node = (MutableTreeNode) newChildren.next();
087                            top.insert(node, 0);
088                    }
089            }
090    
091            private void addToGroup(int grouping, Map<String, GroupNode> groups,
092                            String name, ErrorNode node) {
093                    GroupNode group = groups.get(name);
094                    if (group == null) {
095                            group = new GroupNode(name, grouping);
096                    }
097                    group.insert(node, 0);
098                    groups.put(name, group);
099            }
100    
101            private void groupNodes(List<ErrorNode> list,
102                            Map<String, GroupNode> groups, int grouping) {
103                    for (Iterator<ErrorNode> iter = list.iterator(); iter.hasNext();) {
104                            ErrorNode node = iter.next();
105                            addToGroup(grouping, groups, getErrorGroup(node, grouping), node);
106                    }
107            }
108    
109            public void addErrors(DefaultMutableTreeNode top, Summary summary) {
110                    String producer = summary.getProducer();
111                    String id = summary.getId();
112    
113                    for (ErrorList errorList = summary.getList(); !errorList.isEmpty(); errorList = errorList
114                                    .getTail()) {
115                            Error head = errorList.getHead();
116    
117                            if (!(top.getChildCount() > 100)) {
118                                    insert(top, decorateError(head, producer, id));
119                            }
120                    }
121            }
122    
123            private String getErrorGroup(ErrorNode node, int grouping) {
124                    switch (grouping) {
125                    case GroupNode.FILE_GROUP:
126                            Location loc = node.getLocation();
127                            return loc != null ? loc.getFilename() : "Unknown file";
128                    case GroupNode.DESCRIPTION_GROUP:
129                            return node.toString();
130                    default:
131                            return "";
132                    }
133            }
134    
135            private void insert(DefaultMutableTreeNode top, ErrorNode node) {
136                    int grouping = GroupNode.NO_GROUP;
137    
138                    for (Enumeration<?> e = top.children(); e.hasMoreElements();) {
139                            DefaultMutableTreeNode child = (DefaultMutableTreeNode) e
140                                            .nextElement();
141    
142                            if (child instanceof GroupNode) {
143                                    GroupNode group = (GroupNode) child;
144                                    grouping = group.getGroupType();
145                                    if (group.getGroupName().equals(getErrorGroup(node, grouping))) {
146                                            group.insert(node, 0);
147                                            return;
148                                    }
149                            }
150                    }
151    
152                    if (grouping != GroupNode.NO_GROUP) {
153                            GroupNode group = new GroupNode(getErrorGroup(node, grouping),
154                                            grouping);
155                            group.insert(node, 0);
156                            top.insert(group, 0);
157                    } else {
158                            top.insert(node, 0);
159                    }
160            }
161    
162            private void removeNodes(DefaultMutableTreeNode top,
163                            List<ErrorNode> toBeRemoved) {
164                    Iterator<ErrorNode> iter = toBeRemoved.iterator();
165                    while (iter.hasNext()) {
166                            DefaultMutableTreeNode node = iter.next();
167                            if (top.isNodeChild(node))
168                                    top.remove(node);
169                    }
170            }
171    
172            public void removeAllMatchingErrors(DefaultMutableTreeNode top, String path) {
173                    List<ErrorNode> allNodes = new LinkedList<ErrorNode>();
174                    boolean grouped = collectNodes(top, allNodes);
175                    List<ErrorNode> toBeRemoved = new LinkedList<ErrorNode>();
176    
177                    Iterator<ErrorNode> errors = allNodes.iterator();
178                    while (errors.hasNext()) {
179                            ErrorNode error = errors.next();
180                            Location loc = error.getLocation();
181    
182                            if (loc != null && loc.hasFilename()
183                                            && path.equals(loc.getFilename())) {
184                                    toBeRemoved.add(error);
185                            }
186                    }
187    
188                    if (grouped) {
189                            List<GroupNode> groupToBeRemoved = new LinkedList<GroupNode>();
190    
191                            for (Enumeration<?> e = top.children(); e.hasMoreElements();) {
192                                    GroupNode group = (GroupNode) e.nextElement();
193                                    removeNodes(group, toBeRemoved);
194                                    if (group.isLeaf()) {
195                                            groupToBeRemoved.add(group);
196                                    }
197                            }
198                    } else {
199                            removeNodes(top, toBeRemoved);
200                    }
201            }
202    
203            public void removeAllMatchingErrors(DefaultMutableTreeNode top,
204                            String producer, String id) {
205                    List<ErrorNode> allNodes = new LinkedList<ErrorNode>();
206                    boolean grouped = collectNodes(top, allNodes);
207                    List<ErrorNode> toBeRemoved = new LinkedList<ErrorNode>();
208    
209                    Iterator<ErrorNode> errors = allNodes.iterator();
210                    while (errors.hasNext()) {
211                            ErrorNode error = errors.next();
212    
213                            if (producer.equals(error.getProducer())
214                                            && id.equals(error.getId())) {
215                                    toBeRemoved.add(error);
216                            }
217                    }
218    
219                    if (grouped) {
220                            List<GroupNode> groupToBeRemoved = new LinkedList<GroupNode>();
221    
222                            for (Enumeration<?> e = top.children(); e.hasMoreElements();) {
223                                    GroupNode group = (GroupNode) e.nextElement();
224                                    removeNodes(group, toBeRemoved);
225                                    if (group.isLeaf()) {
226                                            groupToBeRemoved.add(group);
227                                    }
228                            }
229    
230                            for (Iterator<GroupNode> iter = groupToBeRemoved.iterator(); iter
231                                            .hasNext();) {
232                                    top.remove(iter.next());
233                            }
234                    } else {
235                            removeNodes(top, toBeRemoved);
236                    }
237            }
238    
239            public void groupOnDescription(DefaultMutableTreeNode top) {
240                    setGrouping(top, GroupNode.DESCRIPTION_GROUP);
241            }
242    
243            public void groupOnFile(DefaultMutableTreeNode top) {
244                    setGrouping(top, GroupNode.FILE_GROUP);
245            }
246    
247            public void unGroup(DefaultMutableTreeNode top) {
248                    setGrouping(top, GroupNode.NO_GROUP);
249            }
250    }