/* * Copyright 2005-2016 Sixth and Red River Software, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.sixrr.metrics.profile; import com.sixrr.metrics.Metric; import com.sixrr.metrics.MetricCategory; import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintWriter; import java.util.*; public class MetricsProfileImpl implements MetricsProfile { private String name; private final Map<String, MetricInstance> id2instance = new HashMap<String, MetricInstance>(); private MetricDisplaySpecification displaySpecification = new MetricDisplaySpecification(); private boolean builtIn = false; public MetricsProfileImpl(String name, List<MetricInstance> metrics) { this.name = name; for (MetricInstance metricInstance : metrics) { id2instance.put(metricInstance.getMetric().getID(), metricInstance); } } @Override public void addMetricInstance(@NotNull MetricInstance metricInstance) { id2instance.put(metricInstance.getMetric().getID(), metricInstance); } @Override public MetricDisplaySpecification getDisplaySpecification() { return displaySpecification; } @Override public void copyFrom(List<MetricInstance> metricInstances) { for (MetricInstance newMetricInstance : metricInstances) { final MetricInstance metricInstance = getMetricInstance(newMetricInstance.getMetric()); if (metricInstance != null) { metricInstance.copyFrom(newMetricInstance); } } } @Override public boolean isBuiltIn() { return builtIn; } @Override public void setBuiltIn(boolean builtIn) { this.builtIn = builtIn; } @Override public void setName(String newProfileName) { name = newProfileName; } @Override public String getName() { return name; } @Override public List<MetricInstance> getMetricInstances() { final ArrayList<MetricInstance> result = new ArrayList<MetricInstance>(id2instance.values()); Collections.sort(result); return result; } @Override public MetricsProfileImpl clone() throws CloneNotSupportedException { final MetricsProfileImpl out = (MetricsProfileImpl) super.clone(); out.id2instance.clear(); for (Map.Entry<String, MetricInstance> entry : id2instance.entrySet()) { out.id2instance.put(entry.getKey(), entry.getValue().clone()); } out.displaySpecification = new MetricDisplaySpecification(); return out; } @Override @Nullable public MetricInstance getMetricInstance(Metric metric) { return getMetricInstance(metric.getID()); } @Override @Nullable public MetricInstance getMetricInstance(String metricID) { return id2instance.get(metricID); } @SuppressWarnings("HardCodedStringLiteral") @Nullable public static MetricsProfile loadFromFile(File file, MetricRepository metrics) { final Document doc; try { final SAXBuilder builder = new SAXBuilder(); doc = builder.build(file); } catch (Exception e) { return null; } final Element profileRoot = doc.getRootElement(); final String profileName = profileRoot.getAttributeValue("name"); final List<Element> children = profileRoot.getChildren("METRIC"); final List<MetricInstance> profileMetrics = new ArrayList<MetricInstance>(200); for (final Element metricElement : children) { final MetricInstance metric = parseMetric(metricElement, metrics); if (metric != null) { profileMetrics.add(metric); } } final MetricsProfileImpl profile = new MetricsProfileImpl(profileName, profileMetrics); final Element displaySpecElement = profileRoot.getChild("DISPLAY_SPEC"); if (displaySpecElement != null) { parseDisplaySpec(displaySpecElement, profile.getDisplaySpecification()); } return profile; } @SuppressWarnings({"HardCodedStringLiteral"}) private static void parseDisplaySpec(Element displaySpecElement, MetricDisplaySpecification spec) { for (MetricCategory category : MetricCategory.values()) { final String tag = category.name(); final Element element = displaySpecElement.getChild(tag.toUpperCase()); if (element == null) { continue; } final MetricTableSpecification specification = spec.getSpecification(category); specification.setAscending("true".equals(element.getAttributeValue("ascending"))); specification.setSortColumn(Integer.parseInt(element.getAttributeValue("sort_column"))); specification.setColumnOrder(parseStringList(element.getAttributeValue("column_order"))); specification.setColumnWidths(parseIntList(element.getAttributeValue("column_widths"))); } } private static List<Integer> parseIntList(String value) { if (value != null && !value.isEmpty()) { final StringTokenizer tokenizer = new StringTokenizer(value, "|"); final List<Integer> out = new ArrayList<Integer>(32); while (tokenizer.hasMoreTokens()) { final String token = tokenizer.nextToken(); final Integer intValue = new Integer(token); out.add(intValue); } return out; } else { return Collections.emptyList(); } } private static List<String> parseStringList(String value) { if (value != null && !value.isEmpty()) { final StringTokenizer tokenizer = new StringTokenizer(value, "|"); final List<String> out = new ArrayList<String>(32); while (tokenizer.hasMoreTokens()) { final String token = tokenizer.nextToken(); out.add(token); } return out; } else { return Collections.emptyList(); } } @SuppressWarnings({"HardCodedStringLiteral"}) @Nullable private static MetricInstance parseMetric(Element metricElement, MetricRepository metrics) { final String className = metricElement.getAttributeValue("className"); final String lowerThresholdEnabledString = metricElement.getAttributeValue("lowerThresholdEnabled"); boolean lowerThresholdEnabled = false; if (lowerThresholdEnabledString != null) { lowerThresholdEnabled = "true".equals(lowerThresholdEnabledString); } final String lowerThresholdString = metricElement.getAttributeValue("lowerThreshold"); double lowerThreshold = 0.0; if (lowerThresholdString != null) { lowerThreshold = Double.parseDouble(lowerThresholdString); } final String upperThresholdEnabledString = metricElement.getAttributeValue("upperThresholdEnabled"); boolean upperThresholdEnabled = false; if (upperThresholdEnabledString != null) { upperThresholdEnabled = "true".equals(upperThresholdEnabledString); } final String upperThresholdString = metricElement.getAttributeValue("upperThreshold"); double upperThreshold = 0.0; if (upperThresholdString != null) { upperThreshold = Double.parseDouble(upperThresholdString); } boolean enabled = false; final String enabledString = metricElement.getAttributeValue("enabled"); if (enabledString != null) { enabled = "true".equals(enabledString); } final Metric metric = metrics.getMetric(className); if (metric == null) { return null; } final MetricInstance metricInstance = new MetricInstanceImpl(metric); metricInstance.setEnabled(enabled); metricInstance.setLowerThreshold(lowerThreshold); metricInstance.setLowerThresholdEnabled(lowerThresholdEnabled); metricInstance.setUpperThreshold(upperThreshold); metricInstance.setUpperThresholdEnabled(upperThresholdEnabled); return metricInstance; } @Override @SuppressWarnings({"HardCodedStringLiteral"}) public void writeToFile(File profileFile) throws FileNotFoundException { final PrintWriter writer = new PrintWriter(new FileOutputStream(profileFile)); try { writer.println("<METRICS_PROFILE name = \"" + name + "\">"); writeDisplaySpec(writer, displaySpecification); for (final MetricInstance metric : getMetricInstances()) { writeMetric(metric, writer); } writer.println("</METRICS_PROFILE>"); } finally { writer.close(); } } @SuppressWarnings({"HardCodedStringLiteral"}) private static void writeDisplaySpec(PrintWriter writer, MetricDisplaySpecification displaySpecification) { writer.println("\t<DISPLAY_SPEC>"); final MetricCategory[] categories = MetricCategory.values(); for (MetricCategory category : categories) { printTableSpec(displaySpecification, category, writer); } writer.println("\t</DISPLAY_SPEC>"); } @SuppressWarnings({"HardCodedStringLiteral"}) private static void printTableSpec(MetricDisplaySpecification displaySpecification, MetricCategory category, PrintWriter writer) { final MetricTableSpecification projectSpec = displaySpecification.getSpecification(category); final List<String> columnOrder = projectSpec.getColumnOrder(); final List<Integer> columnWidths = projectSpec.getColumnWidths(); final String tag = category.name().toUpperCase(); writer.println("\t\t<" + tag + " ascending = \"" + projectSpec.isAscending() + "\" sort_column = \"" + projectSpec.getSortColumn() + "\" " + "column_order = \"" + writeListAsString(columnOrder) + "\" column_widths = \"" + writeListAsString(columnWidths) + "\" />"); } private static String writeListAsString(List<?> list) { final StringBuffer out = new StringBuffer(); for (Iterator<?> iterator = list.iterator(); iterator.hasNext();) { final Object element = iterator.next(); out.append(element); if (iterator.hasNext()) { out.append('|'); } } return out.toString(); } @SuppressWarnings({"HardCodedStringLiteral"}) private static void writeMetric(MetricInstance metric, PrintWriter writer) { final Class<? extends Metric> metricClass = metric.getMetric().getClass(); writer.println("\t<METRIC className = \"" + metricClass.getName() + "\" enabled = \"" + metric.isEnabled() + "\" lowerThreshold = \"" + metric.getLowerThreshold() + "\" " + "lowerThresholdEnabled = \"" + metric.isLowerThresholdEnabled() + "\" upperThreshold = \"" + metric.getUpperThreshold() + "\" " + "upperThresholdEnabled = \"" + metric.isUpperThresholdEnabled() + "\" />"); } @Override public String toString() { return name + (builtIn ? " (built-in)" : ""); } }