/** * @param node Node whose value is studied * @return */ private static Multimap<SuggestionType, Object> getSuggestionForNode(TreeNode node) { // For storing the suggestion type and the payload Multimap<SuggestionType, Object> suggestionsMultimap = ArrayListMultimap.create(); final String EMPTY = ""; try { InitialContext ic = new InitialContext(); ProjectSimilarityService projectSimilarityService = (ProjectSimilarityService) ic.lookup("java:module/ProjectSimilarityService"); QualityObjectiveSimilarityService qoSimilarityService = (QualityObjectiveSimilarityService) ic.lookup("java:module/QualityObjectiveSimilarityService"); // TODO: Finding similar metrics if (node instanceof QualityObjective) { QualityObjective qo = (QualityObjective) node; Float value = qo.getValue(); // If the value of a quality objective cannot be computed, // attempt to obtain a suggestion if (value == null || value.isNaN()) { // Attempt to find a suitable project Project proj = qo.getProject(); Project similarProject = null; if (proj != null) { // Get a list of similar projects List<Project> similarProjects = projectSimilarityService.getSimilarProjects(proj); if (similarProjects != null && similarProjects.size() > 0) { // For now obtain the first suitable project similarProject = similarProjects.get(0); } } // If a suitable similar project was found, search for similar Quality Objective(s) to be // suggested if (similarProject != null) { // Get similar QOs from a similar project List<QualityObjective> qos = qoSimilarityService.getSimilarQOs(qo, similarProject); // If results were found, construct a suggestion (for now obtain the first one). if (qos != null && qos.size() > 0) { suggestionsMultimap.put(SuggestionType.QO_REPLACE, qos.get(0)); return suggestionsMultimap; } } // Otherwise suggest the QO to be removed suggestionsMultimap.put(SuggestionType.QO_REMOVE, null); return suggestionsMultimap; } } // if a metric has no value / the value is 0, return a suggestion to // remove the metric if (node instanceof Metric) { Metric metric = (Metric) node; Float value = metric.getValue(); if (value == null || value.isNaN() || value.isInfinite()) { suggestionsMultimap.put(SuggestionType.METRIC_REMOVE, null); return suggestionsMultimap; } } } catch (NamingException e) { e.printStackTrace(); } // If no suggestion is to be provided, return an empty string // (overwrite the possible existing suggestion). suggestionsMultimap.put(SuggestionType.NO_SUGGESTION, ""); return suggestionsMultimap; }
/** * Traverse the tree in postorder and update tree values * * @param node */ private static void postorderWithParticularNode(TreeNode node, TreeNode projectTreeNode) { if (node == null) { return; } if (projectTreeNode == null) { return; } logger.debug("------------postorder: " + projectTreeNode.getName() + "---------------"); logger.debug("Traversing project tree in postorder..." + projectTreeNode.toString()); // Update the value try { InitialContext ic = new InitialContext(); AdapterDataService adapterDataService = new AdapterDataService(); TreeNodeService treeNodeService = (TreeNodeService) ic.lookup("java:module/TreeNodeService"); if (projectTreeNode instanceof Metric) { Metric metric = (Metric) projectTreeNode; logger.debug("Recomputing the value of the Metric " + projectTreeNode); Float value = null; if (metric.getMetricSource() == MetricSource.Manual) { metric.updateQualityStatus(); } else { value = adapterDataService.getMetricValue( metric.getMetricSource(), metric.getMetricType(), metric.getProject()); metric.setValue(value); } metric.setLastUpdated(getLatestTreeUpdateDate()); metric.addHistoricValue(); // End Metric node treatment } else if (projectTreeNode instanceof QualityIndicator) { logger.info("Recomputing the value of the Quality Indicator " + projectTreeNode); QualityIndicator qi = (QualityIndicator) projectTreeNode; if (qi.getUseFormula()) { String formulaToEval = Formula.parseFormula(qi.getViewFormula()); if (formulaToEval != null && !formulaToEval.isEmpty()) { Float computedValue = Formula.evalFormula(formulaToEval); if (computedValue != null && !computedValue.isNaN()) { qi.setValue(computedValue); qi.setLastUpdated(getLatestTreeUpdateDate()); treeNodeService.update(qi); } } } else { float achieved = 0; float denominator = 0; for (final TreeNode me : qi.getChildren()) { float weight = ((Metric) me).getWeight(); if (me.getQualityStatus() == QualityStatus.Green) { achieved += weight; } denominator += weight; } if (denominator == 0) qi.getChildren().size(); qi.setValue(achieved * 100 / denominator); } qi.setLastUpdated(getLatestTreeUpdateDate()); qi.addHistoricValue(); // End Q.Indicator node treatment } else if (projectTreeNode instanceof QualityObjective) { logger.info("Recomputing the value of the Quality Objective " + projectTreeNode); QualityObjective qo = (QualityObjective) projectTreeNode; if (qo.getUseFormula()) { String formulaToEval = Formula.parseFormula(qo.getViewFormula()); if (formulaToEval != null && !formulaToEval.isEmpty()) { Float computedValue = Formula.evalFormula(formulaToEval); if (computedValue != null && !computedValue.isNaN()) { qo.setValue(computedValue); qo.setLastUpdated(getLatestTreeUpdateDate()); } } } else { float denominator = 0; float achieved = 0; for (final TreeNode qi : qo.getChildren()) { float weight = ((QualityIndicator) qi).getWeight(); if (qi.getQualityStatus() == QualityStatus.Green) { achieved += weight; } denominator += weight; } qo.setValue(achieved * 100 / denominator); } qo.setLastUpdated(getLatestTreeUpdateDate()); qo.addHistoricValue(); // End Quality Objective node treatment } else if (projectTreeNode instanceof Project) { logger.info("Recomputing the value of the Project " + projectTreeNode); Project prj = (Project) projectTreeNode; double qoValueSum = 0; double denominator = 0; for (Object o : projectTreeNode.getChildren()) { QualityObjective qo = (QualityObjective) o; if (qo.getWeight() == 0) { continue; } qoValueSum += qo.getValue() * (prj.isFormulaAverage() ? qo.getWeight() : 1); denominator += prj.isFormulaAverage() ? qo.getWeight() : 1; } // bad idea to divide something under 0 if (denominator == 0) { denominator = 1; } Double computedValue = qoValueSum / denominator; if (computedValue != null && !computedValue.isNaN() && !computedValue.isInfinite()) { prj.setValue(computedValue); } prj.setLastUpdated(getLatestTreeUpdateDate()); prj.addHistoricValue(); logger.debug(" [" + qoValueSum + "] denominator [" + denominator + "] " + computedValue); // End Project node treatment } // Get a (possible) suggestion for the tree node Multimap<?, ?> suggestions = getSuggestionForNode(projectTreeNode); // TODO: take all the suggestions into account Object[] types = suggestions.keys().toArray(); Object[] suggestionsValues = suggestions.values().toArray(); if (types.length > 0) { // for now use the first item as suggestion SuggestionType stype = (SuggestionType) types[0]; projectTreeNode.setSuggestionType(stype); if (suggestionsValues[0] != null && !suggestionsValues[0].equals("")) { projectTreeNode.setSuggestionValue((String) suggestionsValues[0]); } } treeNodeService.update(projectTreeNode); } catch (NamingException e) { e.printStackTrace(); } // Iterate the node children TreeNode nodeChild = projectTreeNode.getParent(); UQasarUtil.postorderWithParticularNode(projectTreeNode, nodeChild); return; }