replaced <code></code> with more concise {@code}
[idea/community.git] / platform / indexing-impl / src / com / intellij / ide / todo / TodoFilter.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.ide.todo;
17
18 import com.intellij.openapi.diagnostic.Logger;
19 import com.intellij.psi.PsiFile;
20 import com.intellij.psi.search.PsiTodoSearchHelper;
21 import com.intellij.psi.search.TodoPattern;
22 import com.intellij.util.ArrayUtilRt;
23 import com.intellij.util.containers.SmartHashSet;
24 import org.jdom.Element;
25 import org.jetbrains.annotations.NotNull;
26
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Set;
31
32 public class TodoFilter implements Cloneable {
33   private static final Logger LOG = Logger.getInstance("#com.intellij.ide.todo.TodoFilter");
34
35   private static final String ATTRIBUTE_NAME = "name";
36   private static final String ELEMENT_PATTERN = "pattern";
37   private static final String ATTRIBUTE_INDEX = "index";
38
39   private String myName;
40   private Set<TodoPattern> myTodoPatterns;
41
42   public TodoFilter() {
43     setName("");
44     myTodoPatterns = new SmartHashSet<>();
45   }
46
47   public TodoFilter(@NotNull Element element, @NotNull List<TodoPattern> patterns) {
48     setName("");
49     myTodoPatterns = new SmartHashSet<>();
50     readExternal(element, patterns);
51   }
52
53   /**
54    * @return {@code true} if and only if specified {@code psiFile} has
55    * {@code TodoItem}s accepted by the filter.
56    */
57   public boolean accept(PsiTodoSearchHelper searchHelper, PsiFile psiFile) {
58     for (Iterator<TodoPattern> i = iterator(); i.hasNext(); ) {
59       TodoPattern todoPattern = i.next();
60       if (searchHelper.getTodoItemsCount(psiFile, todoPattern) > 0) {
61         return true;
62       }
63     }
64     return false;
65   }
66
67   /**
68    * @return filter's name. That is not {@code null} string.
69    */
70   public String getName() {
71     return myName;
72   }
73
74   public void setName(@NotNull String name) {
75     myName = name;
76   }
77
78   /**
79    * @return {@code true} if and only if filters contains specified {@code pattern}.
80    */
81   public boolean contains(TodoPattern pattern) {
82     return myTodoPatterns.contains(pattern);
83   }
84
85   /**
86    * Adds specified {@code pattern} to the set of containing patterns.
87    */
88   public void addTodoPattern(TodoPattern pattern) {
89     LOG.assertTrue(!myTodoPatterns.contains(pattern));
90     myTodoPatterns.add(pattern);
91   }
92
93   /**
94    * Adds specified {@code pattern} from the set of containing patterns.
95    */
96   public void removeTodoPattern(TodoPattern pattern) {
97     LOG.assertTrue(myTodoPatterns.contains(pattern));
98     myTodoPatterns.remove(pattern);
99   }
100
101   /**
102    * @return iterator of containing patterns.
103    */
104   public Iterator<TodoPattern> iterator() {
105     return myTodoPatterns.iterator();
106   }
107
108   /**
109    * @return {@code true} if and only if filter contains no {@code TodoPattern}s.
110    */
111   public boolean isEmpty() {
112     return myTodoPatterns.isEmpty();
113   }
114
115   private void readExternal(@NotNull Element element, @NotNull List<TodoPattern> patterns) {
116     myName = element.getAttributeValue(ATTRIBUTE_NAME);
117     if (myName == null) {
118       throw new IllegalArgumentException();
119     }
120
121     myTodoPatterns.clear();
122     for (Element child : element.getChildren(ELEMENT_PATTERN)) {
123       try {
124         int index = Integer.parseInt(child.getAttributeValue(ATTRIBUTE_INDEX));
125         if (index < 0 || index > patterns.size() - 1) {
126           continue;
127         }
128         TodoPattern pattern = patterns.get(index);
129         if (myTodoPatterns.contains(pattern)) {
130           continue;
131         }
132         myTodoPatterns.add(pattern);
133       }
134       catch (NumberFormatException ignored) {
135       }
136     }
137   }
138
139   /**
140    * @param element  in which all data will be stored
141    * @param patterns all available patterns
142    */
143   public void writeExternal(Element element, TodoPattern[] patterns) {
144     element.setAttribute(ATTRIBUTE_NAME, myName);
145     for (TodoPattern pattern : myTodoPatterns) {
146       int index = ArrayUtilRt.find(patterns, pattern);
147       LOG.assertTrue(index != -1);
148       Element child = new Element(ELEMENT_PATTERN);
149       child.setAttribute(ATTRIBUTE_INDEX, Integer.toString(index));
150       element.addContent(child);
151     }
152   }
153
154   public int hashCode() {
155     int hashCode = myName.hashCode();
156     for (TodoPattern myTodoPattern : myTodoPatterns) {
157       hashCode += myTodoPattern.hashCode();
158     }
159     return hashCode;
160   }
161
162   public boolean equals(Object obj) {
163     if (!(obj instanceof TodoFilter)) {
164       return false;
165     }
166     TodoFilter filter = (TodoFilter)obj;
167
168     if (!myName.equals(filter.myName)) {
169       return false;
170     }
171
172     if (myTodoPatterns.size() != filter.myTodoPatterns.size()) {
173       return false;
174     }
175
176     for (TodoPattern pattern : myTodoPatterns) {
177       if (!filter.contains(pattern)) {
178         return false;
179       }
180     }
181
182     return true;
183   }
184
185   @Override
186   public TodoFilter clone() {
187     try {
188       TodoFilter filter = (TodoFilter)super.clone();
189       filter.myTodoPatterns = new HashSet<>(myTodoPatterns);
190       return filter;
191     }
192     catch (CloneNotSupportedException e) {
193       LOG.error(e);
194       return null;
195     }
196   }
197 }