PageRenderTime 15ms CodeModel.GetById 1ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/hudson-core/src/main/java/hudson/model/ListView.java

http://github.com/hudson/hudson
Java | 282 lines | 167 code | 37 blank | 78 comment | 34 complexity | a24b5b53154c26635315a6e0c5c84f57 MD5 | raw file
  1/*
  2 * The MIT License
  3 * 
  4 * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi,
  5 * Erik Ramfelt, Seiji Sogabe, Martin Eigenbrodt, Alan Harder
  6 *
  7 * Permission is hereby granted, free of charge, to any person obtaining a copy
  8 * of this software and associated documentation files (the "Software"), to deal
  9 * in the Software without restriction, including without limitation the rights
 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 11 * copies of the Software, and to permit persons to whom the Software is
 12 * furnished to do so, subject to the following conditions:
 13 * 
 14 * The above copyright notice and this permission notice shall be included in
 15 * all copies or substantial portions of the Software.
 16 * 
 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 23 * THE SOFTWARE.
 24 */
 25package hudson.model;
 26
 27import hudson.Extension;
 28import hudson.Util;
 29import hudson.model.Descriptor.FormException;
 30import hudson.util.CaseInsensitiveComparator;
 31import hudson.util.DescribableList;
 32import hudson.util.FormValidation;
 33import hudson.views.ListViewColumn;
 34import hudson.views.ViewJobFilter;
 35import org.kohsuke.stapler.DataBoundConstructor;
 36import org.kohsuke.stapler.QueryParameter;
 37import org.kohsuke.stapler.StaplerRequest;
 38import org.kohsuke.stapler.StaplerResponse;
 39
 40import javax.servlet.ServletException;
 41import java.io.IOException;
 42import java.util.ArrayList;
 43import java.util.LinkedHashSet;
 44import java.util.List;
 45import java.util.SortedSet;
 46import java.util.TreeSet;
 47import java.util.regex.Pattern;
 48import java.util.regex.PatternSyntaxException;
 49
 50/**
 51 * Displays {@link Job}s in a flat list view.
 52 *
 53 * @author Kohsuke Kawaguchi
 54 */
 55public class ListView extends View implements Saveable {
 56
 57    /**
 58     * List of job names. This is what gets serialized.
 59     */
 60    /*package*/ final SortedSet<String> jobNames = new TreeSet<String>(CaseInsensitiveComparator.INSTANCE);
 61    
 62    private DescribableList<ViewJobFilter, Descriptor<ViewJobFilter>> jobFilters;
 63
 64    private DescribableList<ListViewColumn, Descriptor<ListViewColumn>> columns;
 65
 66    /**
 67     * Include regex string.
 68     */
 69    private String includeRegex;
 70    
 71    /**
 72     * Compiled include pattern from the includeRegex string.
 73     */
 74    private transient Pattern includePattern;
 75
 76    /**
 77     * Filter by enabled/disabled status of jobs.
 78     * Null for no filter, true for enabled-only, false for disabled-only.
 79     */
 80    private Boolean statusFilter;
 81
 82    @DataBoundConstructor
 83    public ListView(String name) {
 84        super(name);
 85        initColumns();
 86        initJobFilters();
 87    }
 88
 89    public ListView(String name, ViewGroup owner) {
 90        this(name);
 91        this.owner = owner;
 92    }
 93
 94    public void save() throws IOException {
 95        // persistence is a part of the owner.
 96        // due to the initialization timing issue, it can be null when this method is called.
 97        if (owner!=null)
 98            owner.save();
 99    }
100
101    private Object readResolve() {
102        if(includeRegex!=null)
103            includePattern = Pattern.compile(includeRegex);
104        initColumns();
105        initJobFilters();
106        return this;
107    }
108
109    protected void initColumns() {
110        if (columns == null)
111            columns = new DescribableList<ListViewColumn, Descriptor<ListViewColumn>>(this,ListViewColumn.createDefaultInitialColumnList());
112    }
113
114    protected void initJobFilters() {
115        if (jobFilters == null)
116            jobFilters = new DescribableList<ViewJobFilter, Descriptor<ViewJobFilter>>(this);
117    }
118
119    /**
120     * Used to determine if we want to display the Add button.
121     */
122    public boolean hasJobFilterExtensions() {
123    	return !ViewJobFilter.all().isEmpty();
124    }
125
126    public DescribableList<ViewJobFilter, Descriptor<ViewJobFilter>> getJobFilters() {
127    	return jobFilters;
128    }
129    
130    public Iterable<ListViewColumn> getColumns() {
131        return columns;
132    }
133    
134    /**
135     * Returns a read-only view of all {@link Job}s in this view.
136     *
137     * <p>
138     * This method returns a separate copy each time to avoid
139     * concurrent modification issue.
140     */
141    public synchronized List<TopLevelItem> getItems() {
142        SortedSet<String> names = new TreeSet<String>(jobNames);
143
144        if (includePattern != null) {
145            for (TopLevelItem item : Hudson.getInstance().getItems()) {
146                String itemName = item.getName();
147                if (includePattern.matcher(itemName).matches()) {
148                    names.add(itemName);
149                }
150            }
151        }
152
153        List<TopLevelItem> items = new ArrayList<TopLevelItem>(names.size());
154        for (String n : names) {
155            TopLevelItem item = Hudson.getInstance().getItem(n);
156            // Add if no status filter or filter matches enabled/disabled status:
157            if(item!=null && (statusFilter == null || !(item instanceof AbstractProject)
158                              || ((AbstractProject)item).isDisabled() ^ statusFilter))
159                items.add(item);
160        }
161
162        // check the filters
163        Iterable<ViewJobFilter> jobFilters = getJobFilters();
164        List<TopLevelItem> allItems = Hudson.getInstance().getItems();
165    	for (ViewJobFilter jobFilter: jobFilters) {
166    		items = jobFilter.filter(items, allItems, this);
167    	}
168        // for sanity, trim off duplicates
169        items = new ArrayList<TopLevelItem>(new LinkedHashSet<TopLevelItem>(items));
170        
171        return items;
172    }
173
174    public boolean contains(TopLevelItem item) {
175        return jobNames.contains(item.getName());
176    }
177
178    /**
179     * Adds the given item to this view.
180     *
181     * @since 1.389
182     */
183    public void add(TopLevelItem item) throws IOException {
184        jobNames.add(item.getName());
185        save();
186    }
187
188    public String getIncludeRegex() {
189        return includeRegex;
190    }
191
192    /**
193     * Filter by enabled/disabled status of jobs.
194     * Null for no filter, true for enabled-only, false for disabled-only.
195     */
196    public Boolean getStatusFilter() {
197        return statusFilter;
198    }
199
200    public synchronized Item doCreateItem(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
201        Item item = Hudson.getInstance().doCreateItem(req, rsp);
202        if(item!=null) {
203            jobNames.add(item.getName());
204            owner.save();
205        }
206        return item;
207    }
208
209    @Override
210    public synchronized void onJobRenamed(Item item, String oldName, String newName) {
211        if(jobNames.remove(oldName) && newName!=null)
212            jobNames.add(newName);
213    }
214
215    /**
216     * Handles the configuration submission.
217     *
218     * Load view-specific properties here.
219     */
220    @Override
221    protected void submit(StaplerRequest req) throws ServletException, FormException, IOException {
222        jobNames.clear();
223        for (TopLevelItem item : Hudson.getInstance().getItems()) {
224            if(req.getParameter(item.getName())!=null)
225                jobNames.add(item.getName());
226        }
227
228        if (req.getParameter("useincluderegex") != null) {
229            includeRegex = Util.nullify(req.getParameter("includeRegex"));
230            if (includeRegex == null)
231                includePattern = null;
232            else
233                includePattern = Pattern.compile(includeRegex);
234        } else {
235            includeRegex = null;
236            includePattern = null;
237        }
238
239        if (columns == null) {
240            columns = new DescribableList<ListViewColumn,Descriptor<ListViewColumn>>(this);
241        }
242        columns.rebuildHetero(req, req.getSubmittedForm(), ListViewColumn.all(), "columns");
243        
244        if (jobFilters == null) {
245        	jobFilters = new DescribableList<ViewJobFilter,Descriptor<ViewJobFilter>>(this);
246        }
247        jobFilters.rebuildHetero(req, req.getSubmittedForm(), ViewJobFilter.all(), "jobFilters");
248
249        String filter = Util.fixEmpty(req.getParameter("statusFilter"));
250        statusFilter = filter != null ? "1".equals(filter) : null;
251    }
252
253    @Extension
254    public static final class DescriptorImpl extends ViewDescriptor {
255        public String getDisplayName() {
256            return Messages.ListView_DisplayName();
257        }
258
259        /**
260         * Checks if the include regular expression is valid.
261         */
262        public FormValidation doCheckIncludeRegex( @QueryParameter String value ) throws IOException, ServletException, InterruptedException  {
263            String v = Util.fixEmpty(value);
264            if (v != null) {
265                try {
266                    Pattern.compile(v);
267                } catch (PatternSyntaxException pse) {
268                    return FormValidation.error(pse.getMessage());
269                }
270            }
271            return FormValidation.ok();
272        }
273    }
274
275    /**
276     * @deprecated as of 1.391
277     *  Use {@link ListViewColumn#createDefaultInitialColumnList()}
278     */
279    public static List<ListViewColumn> getDefaultColumns() {
280        return ListViewColumn.createDefaultInitialColumnList();
281    }
282}