1 /* 2 * Copyright 2008-2010 smartics, Kronseder & Reiner GmbH 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 17 package de.smartics.maven.issues.bugzilla; 18 19 import java.util.Comparator; 20 import java.util.List; 21 22 import org.apache.commons.logging.Log; 23 import org.apache.commons.logging.LogFactory; 24 import org.apache.maven.artifact.versioning.ArtifactVersion; 25 import org.eclipse.mylyn.internal.bugzilla.core.BugzillaAttribute; 26 import org.eclipse.mylyn.tasks.core.data.TaskAttribute; 27 import org.eclipse.mylyn.tasks.core.data.TaskData; 28 29 import de.smartics.maven.issues.RendererConfig; 30 31 /** 32 * Selects the issues to their categories. 33 * 34 * @author <a href="mailto:robert.reiner@smartics.de">Robert Reiner</a> 35 * @version $Revision:591 $ 36 */ 37 public class VersionedSectioner implements Sectioner<Versions> 38 { 39 // ********************************* Fields ********************************* 40 41 // --- constants ------------------------------------------------------------ 42 43 /** 44 * Reference to the logger for this class. 45 */ 46 private static final Log LOG = LogFactory.getLog(VersionedSectioner.class); 47 48 // --- members -------------------------------------------------------------- 49 50 /** 51 * The configuration to control the processing of the sections. 52 */ 53 private final RendererConfig config; 54 55 /** 56 * The issues to be appointed to the different sections. 57 */ 58 private final List<TaskData> issues; 59 60 /** 61 * The map stores the bugs in the order read from the issue management system 62 * in different sections within different target versions. 63 */ 64 private final Versions versions; 65 66 // ****************************** Initializer ******************************* 67 68 // ****************************** Constructors ****************************** 69 70 /** 71 * Convenience constructor using inverse sort order for versions. 72 * 73 * @param config the configuration to control the processing of the sections. 74 * @param issues the issues to be appointed to the different sections. 75 */ 76 public VersionedSectioner(final RendererConfig config, 77 final List<TaskData> issues) 78 { 79 this.config = config; 80 this.issues = issues; 81 this.versions = new Versions(config.getSections()); 82 } 83 84 /** 85 * Default constructor. 86 * 87 * @param config the configuration to control the processing of the sections. 88 * @param issues the issues to be appointed to the different sections. 89 * @param versionComparator the comparator to use to sort version numbers. A 90 * value of <code>null</code> implies that natural sort order is to 91 * be used. 92 */ 93 public VersionedSectioner(final RendererConfig config, 94 final List<TaskData> issues, 95 final Comparator<ArtifactVersion> versionComparator) 96 { 97 this.config = config; 98 this.issues = issues; 99 this.versions = new Versions(config.getSections(), versionComparator); 100 } 101 102 // ****************************** Inner Classes ***************************** 103 104 // ********************************* Methods ******************************** 105 106 // --- init ----------------------------------------------------------------- 107 108 // --- get&set -------------------------------------------------------------- 109 110 // --- business ------------------------------------------------------------- 111 112 /** 113 * Distributes the issues to the configured sections within their versions. 114 * Issues not defining the property referenced by 115 * {@link RendererConfig#getSectionType()} are skipped as well as issues that 116 * provide a value for that property that is not part of 117 * {@link RendererConfig#getSections()}. If the issue has no version attribute 118 * (target milestone), the issue is also skipped. 119 * 120 * @impl Skipped issues are logged at debug level. 121 * @return the map of versions. 122 */ 123 public Versions run() 124 { 125 final String sectionAttributeKey = config.getSectionType(); 126 final BugzillaAttribute versionAttribute = 127 BugzillaAttribute.TARGET_MILESTONE; 128 for (TaskData issue : issues) 129 { 130 final TaskAttribute root = issue.getRoot(); 131 final ArtifactVersion version = getVersion(root, versionAttribute); 132 if (version != null) 133 { 134 final TaskAttribute attribute = root.getAttribute(sectionAttributeKey); 135 if (attribute != null) 136 { 137 final String section = attribute.getValue(); 138 final boolean added = versions.add(version, section, issue); 139 if (!added && LOG.isDebugEnabled()) 140 { 141 LOG.debug("Issue #" + issue.getTaskId() + " defines attribute '" 142 + sectionAttributeKey + "' as '" + section 143 + "' which is not mapped to a column. Skipped."); 144 } 145 } 146 else 147 { 148 logSkipping(sectionAttributeKey, issue); 149 } 150 } 151 else 152 { 153 logSkipping(versionAttribute.getKey(), issue); 154 } 155 } 156 return versions; 157 } 158 159 /** 160 * Simple helper to log that the given issue was skipped due to a missing 161 * attribute of this issue. 162 * <p> 163 * Logging is run on debug level. 164 * </p> 165 * 166 * @param attributeKey the key of the attribute that was not set and therefore 167 * the issue was skipped. 168 * @param issue the skipped issue. 169 */ 170 private static void logSkipping(final String attributeKey, 171 final TaskData issue) 172 { 173 if (LOG.isDebugEnabled()) 174 { 175 LOG.debug("Issue #" + issue.getTaskId() + " does not define attribute '" 176 + attributeKey + "'. Skipped."); 177 } 178 } 179 180 /** 181 * Returns the value for the version referenced by the 182 * <code>versionAttribute</code>. The value of this attribute is required to 183 * be a version information. Bugzilla supports the version and target 184 * milestone as version values. 185 * 186 * @param rootAttribute the reference to the issues root attribute. 187 * @param versionAttributeDescriptor the key to the attribute to fetch within 188 * the root attribute. 189 * @return the version instance created upon the version attribute's value or 190 * <code>null</code> if that information was not present or not valid. 191 */ 192 private ArtifactVersion getVersion(final TaskAttribute rootAttribute, 193 final BugzillaAttribute versionAttributeDescriptor) 194 { 195 final TaskAttribute attribute = 196 rootAttribute.getAttribute(versionAttributeDescriptor.getKey()); 197 if (attribute != null) 198 { 199 final String versionString = attribute.getValue(); 200 if (versionString != null && !"---".equals(versionString)) 201 { 202 final ArtifactVersion version = 203 config.getVersionFactoryInstance().createVersion(versionString); 204 return version; 205 } 206 } 207 return null; 208 } 209 210 // --- object basics -------------------------------------------------------- 211 212 }