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