Skip to content
Permalink
Browse files
[JENKINS-11762] Changes to add a configurable display name to jobs
  • Loading branch information
Albert So authored and kohsuke committed Jan 3, 2012
1 parent 05b4665 commit 484d952029b235d889a5d2e4bd9bc44a9707f7ff
@@ -1,8 +1,8 @@
/*
* The MIT License
*
* Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi,
* Daniel Dyer, Tom Huybrechts
* Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi,
* Daniel Dyer, Tom Huybrechts, Yahoo!, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -34,6 +34,7 @@
import hudson.cli.declarative.CLIResolver;
import hudson.model.listeners.ItemListener;
import hudson.model.listeners.SaveableListener;
import hudson.search.SearchIndexBuilder;
import hudson.security.AccessControlled;
import hudson.security.Permission;
import hudson.security.ACL;
@@ -91,6 +92,8 @@
protected volatile String description;

private transient ItemGroup parent;

protected String displayName;

protected AbstractItem(ItemGroup parent, String name) {
this.parent = parent;
@@ -116,9 +119,18 @@ public String getPronoun() {

@Exported
public String getDisplayName() {
if(null!=displayName) {
return displayName;
}
// if the displayName is not set, then return the name as we use to do
return getName();
}


public void setDisplayName(String displayName) throws IOException {
this.displayName = displayName;
save();
}

public File getRootDir() {
return parent.getRootDirFor(this);
}
@@ -548,6 +560,18 @@ public void updateByXml(StreamSource source) throws IOException {
out.abort(); // don't leave anything behind
}
}


/* (non-Javadoc)
* @see hudson.model.AbstractModelObject#getSearchName()
*/
@Override
public String getSearchName() {
// the search name of abstract items should be the name and not display name.
// this will make suggestions use the names and not the display name
// so that the links will 302 directly to the thing the user was finding
return getName();
}

public String toString() {
return super.toString()+'['+getFullName()+']';
@@ -941,6 +941,21 @@ private HealthReport getBuildStabilityHealthReport() {
return null;
}

/**
* Takes the displayName request parameter and sets it into the the
* displayName member variable. If the displayName request parameter is a
* 0 length string, then set the displayName member variable to null.
* @param req
* @throws IOException
*/
void setDisplayNameFromRequest(StaplerRequest req) throws IOException {
String displayName = req.getParameter("displayName");
// if displayName is an empty string, just make it null so that we
// use the project name
displayName = Util.nullify(displayName);
setDisplayName(displayName);
}

//
//
// actions
@@ -958,6 +973,8 @@ public synchronized void doConfigSubmit(StaplerRequest req,

keepDependencies = req.getParameter("keepDependencies") != null;

setDisplayNameFromRequest(req);

try {
JSONObject json = req.getSubmittedForm();

@@ -1,7 +1,8 @@
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts
* Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts,
* Yahoo!, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -66,6 +67,8 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import static jenkins.model.Jenkins.*;

@@ -91,6 +94,9 @@
*/
@ExportedBean
public abstract class View extends AbstractModelObject implements AccessControlled, Describable<View>, ExtensionPoint, Saveable {

private final static Logger logger = Logger.getLogger(View.class.getName());

/**
* Container of this view. Set right after the construction
* and never change thereafter.
@@ -672,14 +678,34 @@ public static boolean isApplicable(Collection<? extends Item> items) {
}
}


void addDisplayNamesToSearchIndex(SearchIndexBuilder sib, Collection<TopLevelItem> items) {
for(TopLevelItem item : items) {

if(logger.isLoggable(Level.FINE)) {
logger.fine((String.format("Adding url=%s,displayName=%s",
item.getSearchUrl(), item.getDisplayName())));
}
sib.add(item.getSearchUrl(), item.getDisplayName());
}
}

@Override
public SearchIndexBuilder makeSearchIndex() {
return super.makeSearchIndex()
.add(new CollectionSearchIndex() {// for jobs in the view
SearchIndexBuilder sib = super.makeSearchIndex();
sib.add(new CollectionSearchIndex<TopLevelItem>() {// for jobs in the view
protected TopLevelItem get(String key) { return getItem(key); }
protected Collection<TopLevelItem> all() { return getItems(); }
protected Collection<TopLevelItem> all() { return getItems(); }
@Override
protected String getName(TopLevelItem o) {
// return the name instead of the display for suggestion searching
return o.getName();
}
});

// add the display name for each item in the search index
addDisplayNamesToSearchIndex(sib, getItems());

return sib;
}

/**
@@ -1,7 +1,8 @@
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
* Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi,
* Yahoo!, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,6 +26,7 @@

import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;

import hudson.Util;
import hudson.util.EditDistance;
import java.io.IOException;
import java.util.AbstractList;
@@ -33,6 +35,9 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import org.kohsuke.stapler.Ancestor;
import org.kohsuke.stapler.QueryParameter;
@@ -49,12 +54,17 @@
* @author Kohsuke Kawaguchi
*/
public class Search {
private final static Logger logger = Logger.getLogger(Search.class.getName());

public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
List<Ancestor> l = req.getAncestors();
for( int i=l.size()-1; i>=0; i-- ) {
Ancestor a = l.get(i);
if (a.getObject() instanceof SearchableModelObject) {
SearchableModelObject smo = (SearchableModelObject) a.getObject();
if(logger.isLoggable(Level.FINE)){
logger.fine(String.format("smo.displayName=%s, searchName=%s",smo.getDisplayName(), smo.getSearchName()));
}

SearchIndex index = smo.getSearchIndex();
String query = req.getParameter("q");
@@ -171,12 +181,49 @@ void find(SearchIndex index, String token, List<SearchItem> result) {
}

/**
* Performs a search and returns the match, or null if no match was found.
* When there are mutiple suggested items, this method can narrow down the resultset
* to the SuggestedItem that has a url that contains the query. This is useful is one
* job has a display name that matches another job's project name.
* @param r A list of Suggested items. It is assumed that there is at least one
* SuggestedItem in r.
* @param query A query string
* @return Returns the SuggestedItem which has a search url that contains the query.
* If no SuggestedItems have a search url which contains the query, then the first
* SuggestedItem in the List is returned.
*/
static SuggestedItem findClosestSuggestedItem(List<SuggestedItem> r, String query) {
for(SuggestedItem curItem : r) {
if(logger.isLoggable(Level.FINE)) {
logger.fine(String.format("item's searchUrl:%s;query=%s", curItem.item.getSearchUrl(), query));
}
if(curItem.item.getSearchUrl().contains(Util.rawEncode(query))) {
return curItem;
}
}

// couldn't find an item with the query in the url so just
// return the first one
return r.get(0);
}

/**
* Performs a search and returns the match, or null if no match was found
* or more than one match was found
*/
public static SuggestedItem find(SearchIndex index, String query) {
List<SuggestedItem> r = find(Mode.FIND, index, query);
if(r.isEmpty()) return null;
else return r.get(0);
if(r.isEmpty()){
return null;
}
else if(1==r.size()){
return r.get(0);
}
else {
// we have more than one suggested item, so return the item who's url
// contains the query as this is probably the job's name
return findClosestSuggestedItem(r, query);
}

}

public static List<SuggestedItem> suggest(SearchIndex index, final String tokenList) {
@@ -244,6 +291,18 @@ public int size() {
}
};
}


public String toString() {
StringBuilder s = new StringBuilder("TokenList{");
for(String token : tokens) {
s.append(token);
s.append(",");
}
s.append('}');

return s.toString();
}
}

private static List<SuggestedItem> find(Mode m, SearchIndex index, String tokenList) {
@@ -256,14 +315,19 @@ public int size() {

List<SearchItem> items = new ArrayList<SearchItem>(); // items found in 1 step


if(logger.isLoggable(Level.FINE)) {
logger.fine("tokens="+tokens.toString());
}

// first token
int w=1; // width of token
for (String token : tokens.subSequence(0)) {
items.clear();
m.find(index,token,items);
for (SearchItem si : items)
for (SearchItem si : items) {
paths[w].add(new SuggestedItem(si));
logger.info("found search item:"+si.getSearchName());
}
w++;
}

@@ -285,4 +349,5 @@ public int size() {

return paths[tokens.length()];
}

}

0 comments on commit 484d952

Please sign in to comment.