Skip to content

Commit

Permalink
[JENKINS-31162] Big review of the current approach
Browse files Browse the repository at this point in the history
  • Loading branch information
recena committed Mar 18, 2016
1 parent 3f95997 commit a552cdb
Show file tree
Hide file tree
Showing 68 changed files with 230 additions and 643 deletions.
17 changes: 17 additions & 0 deletions core/src/main/java/hudson/model/FreeStyleProject.java
Expand Up @@ -65,12 +65,29 @@ public DescriptorImpl getDescriptor() {
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();

public static final class DescriptorImpl extends AbstractProjectDescriptor {

public String getDisplayName() {
return Messages.FreeStyleProject_DisplayName();
}

public FreeStyleProject newInstance(ItemGroup parent, String name) {
return new FreeStyleProject(parent,name);
}

@Override
public String getDescription() {
return Messages.FreeStyleProject_Description();
}

@Override
public String getCategoryId() {
return "itemcategory-standaloneprojects";
}

@Override
public String getIconFilePathPattern() {
return Jenkins.RESOURCE_PATH + "images/:size/freestyleproject.png";
}

}
}
10 changes: 5 additions & 5 deletions core/src/main/java/hudson/model/ItemGroupMixIn.java
Expand Up @@ -344,17 +344,17 @@ public synchronized TopLevelItem createProject( TopLevelItemDescriptor type, Str
*/
public static Categories getCategories(Authentication a, ItemGroup c) {
Categories categories = new Categories();
int weight = ItemCategory.MIN_WEIGHT;
for (TopLevelItemDescriptor descriptor : DescriptorVisibilityFilter.apply(c, Items.all(a, c))) {
String effectiveClazz = ItemCategoryConfigurator.getEffectiveClazz(descriptor);
ItemCategory ic = ItemCategoryConfigurator.getCategory(descriptor);
Map<String, Serializable> metadata = new HashMap<String, Serializable>();

// Information about Item.
metadata.put("class", effectiveClazz);
metadata.put("weight", ItemCategoryConfigurator.getWeight(descriptor));
metadata.put("class", descriptor.getId());
metadata.put("weight", ++weight);
metadata.put("displayName", descriptor.getDisplayName());
metadata.put("description", ItemCategoryConfigurator.getDescription(descriptor));
metadata.put("iconFilePathPattern", ItemCategoryConfigurator.getIconFilePathPattern(descriptor));
metadata.put("description", descriptor.getDescription());
metadata.put("iconFilePathPattern", descriptor.getIconFilePathPattern());

Category category = categories.getItem(ic.getId());
if (category != null) {
Expand Down
71 changes: 71 additions & 0 deletions core/src/main/java/hudson/model/TopLevelItemDescriptor.java
Expand Up @@ -25,15 +25,28 @@

import hudson.ExtensionList;
import jenkins.model.Jenkins;
import jenkins.model.item_category.ItemCategory;
import org.acegisecurity.AccessDeniedException;
import org.apache.commons.jelly.Script;
import org.apache.commons.jelly.XMLOutput;
import org.kohsuke.stapler.MetaClass;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.WebApp;
import org.kohsuke.stapler.jelly.DefaultScriptInvoker;
import org.kohsuke.stapler.jelly.JellyClassTearOff;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.io.StringWriter;

/**
* {@link Descriptor} for {@link TopLevelItem}s.
*
* @author Kohsuke Kawaguchi
*/
public abstract class TopLevelItemDescriptor extends Descriptor<TopLevelItem> {

protected TopLevelItemDescriptor(Class<? extends TopLevelItem> clazz) {
super(clazz);
}
Expand Down Expand Up @@ -113,6 +126,64 @@ public String getDisplayName() {
return super.getDisplayName();
}

/**
* A description of this kind of item type. This description can contain HTML code but it is recommend to use text plain
* in order to avoid how it should be represented.
*
* @return A string, an empty string by default.
*
* @since TODO
*/
@Nonnull
public String getDescription() {
try {
WebApp webapp = WebApp.getCurrent();
MetaClass meta = webapp.getMetaClass(this);
Script s = meta.loadTearOff(JellyClassTearOff.class).findScript("newInstanceDetail");
if (s == null) {
return "";
}
DefaultScriptInvoker dsi = new DefaultScriptInvoker();
StringWriter sw = new StringWriter();
XMLOutput xml = dsi.createXMLOutput(sw, true);
dsi.invokeScript(Stapler.getCurrentRequest(), Stapler.getCurrentResponse(), s, this, xml);
return sw.toString();
} catch (Exception e) {
return "";
}
}

/**
* Used to categorize this kind of item type. @see {@link ItemCategory}
*
* @return A string with the category identifier, {@link ItemCategory.UncategorizedCategory#getId()} by default.
*
* @since TODO
*/
@Nonnull
public String getCategoryId() {
return new ItemCategory.UncategorizedCategory().getId();
}

/**
* @since TODO
*/
@CheckForNull
public String getIconFilePathPattern() {
return null;
}

/**
* @since TODO
*/
@CheckForNull
public String getIconFilePath(String size) {
if (getIconFilePathPattern().isEmpty()) {
return getIconFilePathPattern().replace(":size", size);
}
return null;
}

/**
* @deprecated since 2007-01-19.
* This is not a valid operation for {@link Item}s.
Expand Down
42 changes: 37 additions & 5 deletions core/src/main/java/jenkins/model/item_category/ItemCategory.java
Expand Up @@ -12,12 +12,12 @@
*/
public abstract class ItemCategory implements ModelObject, ExtensionPoint {

public static int MIN_WEIGHT = Integer.MIN_VALUE;
public static int MIN_WEIGHT = 0;

public static int MIN_TOSHOW = 1;

/**
* Identifier, e.g. "category-id-basicprojects", etc.
* Identifier, e.g. "category-id-standaloneprojects", etc.
*
* @return the identifier
*/
Expand Down Expand Up @@ -52,7 +52,7 @@ public static final class UncategorizedCategory extends ItemCategory {

@Override
public String getId() {
return "category-id-uncategorized";
return "itemcategory-uncategorized";
}

@Override
Expand All @@ -67,14 +67,46 @@ public String getDisplayName() {

@Override
public int getWeight() {
return Integer.MIN_VALUE;
return ItemCategory.MIN_WEIGHT;
}

@Override
public int getMinToShow() {
return 1;
return ItemCategory.MIN_TOSHOW;
}

}

/**
* A generic {@link ItemCategory}
*/
@Extension
public static final class StandaloneProjectCategory extends ItemCategory {

@Override
public String getId() {
return "itemcategory-standaloneprojects";
}

@Override
public String getDescription() {
return Messages.ItemCategory_StandaloneProjects_Description();
}

@Override
public String getDisplayName() {
return Messages.ItemCategory_StandaloneProjects_DisplayName();
}

@Override
public int getWeight() {
return ItemCategory.MIN_WEIGHT;
}

@Override
public int getMinToShow() {
return ItemCategory.MIN_TOSHOW;
}

}
}
Expand Up @@ -45,163 +45,26 @@ public static ItemCategory getCategory(@Nonnull TopLevelItemDescriptor descripto
throw new IllegalStateException("At least, must exist the category: " + ItemCategory.UncategorizedCategory.class);
}

/**
* Provides the weight for the requested item. Helpful to order a list.
*
* @param descriptor the item it is asking about.
*
* @return the weight or null
*/
@CheckForNull
protected abstract Integer getWeightFor(@Nonnull TopLevelItemDescriptor descriptor);

/**
* Finds the weight specified by the first configurator.
* If none can be found {@link Integer#MIN_VALUE} is returned. {@see DefaultConfigurator#getWeightFor}.
*
* @param descriptor the item it is asking about.
*
* @return the weight
*/
@Nonnull
public static Integer getWeight(@Nonnull TopLevelItemDescriptor descriptor) {
for (ItemCategoryConfigurator m : all()) {
Integer weight = m.getWeightFor(descriptor);
if (weight != null) {
return weight;
}
}
throw new IllegalStateException("At least, a default value must exist for weight field");
}

/**
* Provides the description for the requested item or null if this configurator doesn't have one.
*
* @param descriptor the item it is asking about.
*
* @return A {@link ItemCategory} or null
*/
@CheckForNull
protected abstract String getDescriptionFor(@Nonnull TopLevelItemDescriptor descriptor);

/**
* Finds the weight specified by the first configurator.
* If none can be found a empty string is returned. {@see DefaultConfigurator#getDescriptionFor}.
*
* @param descriptor the item it is asking about.
*
* @return A {@link ItemCategory}
*/
@Nonnull
public static String getDescription(@Nonnull TopLevelItemDescriptor descriptor) {
for (ItemCategoryConfigurator m : all()) {
String description = m.getDescriptionFor(descriptor);
if (description != null) {
return description;
}
}
throw new IllegalStateException("At least, a default value must exist for description field");
}

/**
* Provides the effective clazz for the requested item or null if this configurator doesn't have one.
*
* @param descriptor the item it is asking about.
*
* @return A string or null
*/
@CheckForNull
protected abstract String getEffectiveClazzFor(@Nonnull TopLevelItemDescriptor descriptor);

/**
* Finds the effective clazz specified by the first configurator.
* If none can be found a empty string with {@code descriptor.clazz.getName();} is returned. {@see DefaultConfigurator#getEffectiveClazzFor}.
*
* @param descriptor the item it is asking about.
*
* @return A string
*/
@Nonnull
public static String getEffectiveClazz(@Nonnull TopLevelItemDescriptor descriptor) {
for (ItemCategoryConfigurator m : all()) {
String clazz = m.getEffectiveClazzFor(descriptor);
if (clazz != null) {
return clazz;
}
}
throw new IllegalStateException("At least, a default value must exist for clazz field");
}

/**
* Provides the icon path pattern for the requested item or null if this configurator doesn't have one.
* For example: /plugin/shortname-of-myplugin/icons/item/:size:/myitem.pngm where :size should be replaced by the
* consumer using the standard sizes in Jenkins: 16x16, 24x24, etc...
*
* @param descriptor the item it is asking about.
*
* @return A string or null
*/
@CheckForNull
protected abstract String getIconFilePathPatternFor(@Nonnull TopLevelItemDescriptor descriptor);

/**
* Finds the icon path pattern specified by the first configurator.
* If none can be found a empty string is returned. {@see DefaultConfigurator#getIconFilePathFor}.
*
* @param descriptor the item it is asking about.
*
* @return A string
*/
@Nonnull
public static String getIconFilePathPattern(@Nonnull TopLevelItemDescriptor descriptor) {
for (ItemCategoryConfigurator m : all()) {
String path = m.getIconFilePathPatternFor(descriptor);
if (path != null) {
return path;
}
}
throw new IllegalStateException("At least, a default value must exist for icon path pattern");
}

public static Collection<ItemCategoryConfigurator> all() {
return ExtensionList.lookup(ItemCategoryConfigurator.class);
}

/**
* Default configurator with the lowest ordinal that simply returns default values.
* Default configurator with the lowest ordinal.
*/
@Extension(ordinal = Integer.MIN_VALUE)
public static final class DefaultConfigurator extends ItemCategoryConfigurator {

@Nonnull
@Override
public ItemCategory getCategoryFor(@Nonnull TopLevelItemDescriptor descriptor) {
for (ItemCategory c : ExtensionList.lookup(ItemCategory.class)) {
if (c.getId().equals(descriptor.getCategoryId())) {
return c;
}
}
return ExtensionList.lookup(ItemCategory.UncategorizedCategory.class).iterator().next();
}

@Nonnull
@Override
public Integer getWeightFor(@Nonnull TopLevelItemDescriptor descriptor) {
return Integer.MIN_VALUE;
}

@Nonnull
@Override
public String getDescriptionFor(@Nonnull TopLevelItemDescriptor descriptor) {
return "";
}

@Nonnull
@Override
public String getEffectiveClazzFor(@Nonnull TopLevelItemDescriptor descriptor) {
return descriptor.clazz.getName();
}

@Nonnull
@Override
public String getIconFilePathPatternFor(@Nonnull TopLevelItemDescriptor descriptor) {
return "";
}

}
}
Expand Up @@ -24,5 +24,5 @@ THE SOFTWARE.

<?jelly escape-by-default='true'?>
<div>
${%body}
${it.description}
</div>

0 comments on commit a552cdb

Please sign in to comment.