eu.atos.sla.service.rest.ModacloudsTranslator.java Source code

Java tutorial

Introduction

Here is the source code for eu.atos.sla.service.rest.ModacloudsTranslator.java

Source

/**
 * Copyright 2014 Atos
 * Contact: Atos <roman.sosa@atos.net>
 *
 *    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 eu.atos.sla.service.rest;

import java.io.StringReader;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;

import eu.atos.sla.datamodel.IAgreement;
import eu.atos.sla.datamodel.IGuaranteeTerm;
import eu.atos.sla.evaluation.constraint.IConstraintEvaluator;
import eu.atos.sla.monitoring.IMetricTranslator;
import eu.atos.sla.monitoring.IMonitoringMetric;

/**
 * Translates a serialized json of metrics (as sent by MC'Monitoring Platform) into 
 * a set of metrics suitable for sla enforcement.
 * 
 * This version is coupled to modaclouds-metrics-observer v1.0.1
 */
public class ModacloudsTranslator implements IMetricTranslator<String> {
    private static final Logger logger = LoggerFactory.getLogger(ModacloudsTranslator.class);

    /**
     * Needed to get the guarantee term that evaluates a particular metric key.
     */
    private final IConstraintEvaluator constraintEvaluator;

    public ModacloudsTranslator(IConstraintEvaluator constraintEvaluator) {
        this.constraintEvaluator = constraintEvaluator;
    }

    @Override
    /**
     * Performs the translation from the data coming from the Monitor and SLA's MonitoringMetric.
     * 
     * The key of each monitor data is the name of the violation (contained in the slo), so each
     * slo containing the key must enforce that metric.
     */
    public Map<IGuaranteeTerm, List<IMonitoringMetric>> translate(IAgreement agreement, String data) {
        MultivaluedMapWrapper<IGuaranteeTerm, IMonitoringMetric> resultWrapper = new MultivaluedMapWrapper<IGuaranteeTerm, IMonitoringMetric>();

        Gson gson = new Gson();
        JsonReader reader = null;
        Type type = new TypeToken<Map<String, Map<String, List<Map<String, String>>>>>() {
        }.getType();
        reader = new JsonReader(new StringReader(data));
        final Map<String, Map<String, List<Map<String, String>>>> json = gson.fromJson(reader, type);

        /*
         * key: name of violation
         */
        final MultivaluedMapWrapper<String, IGuaranteeTerm> metric2terms = initTermsMap(agreement);

        for (Map<String, List<Map<String, String>>> item : json.values()) {
            BindingHelper var = new BindingHelper(item);
            /*
             * get guarantee terms that evaluate that violation
             */
            List<IGuaranteeTerm> terms = metric2terms.get(var.key);

            if (terms == null) {
                logger.warn("List of terms handling " + var.key + " is empty");
                continue;
            }

            resultWrapper.addToKeys(terms, new MonitoringMetric(var));
        }
        logger.debug("Output metricsmap = " + resultWrapper.getMap());
        return resultWrapper.getMap();
    }

    /**
     * Inits a MultivaluedMap with metrickey as key and the terms that evaluate the metrickey as values.
     * @param agreement
     * @return
     */
    private MultivaluedMapWrapper<String, IGuaranteeTerm> initTermsMap(IAgreement agreement) {
        MultivaluedMapWrapper<String, IGuaranteeTerm> result = new MultivaluedMapWrapper<String, IGuaranteeTerm>();

        for (IGuaranteeTerm term : agreement.getGuaranteeTerms()) {
            String variable = constraintEvaluator.getConstraintVariable(term.getServiceLevel());
            result.add(variable, term);
        }
        return result;
    }

    private static final class MonitoringMetric implements IMonitoringMetric {
        private final BindingHelper binding;

        private MonitoringMetric(BindingHelper binding) {
            this.binding = binding;
        }

        @Override
        public String getMetricValue() {
            return binding.value;
        }

        @Override
        public String getMetricKey() {
            return binding.key;
        }

        @Override
        public Date getDate() {
            return binding.date;
        }

        @Override
        public String toString() {
            return String.format("%s[key=%s, value=%s, date=%s]", this.getClass().getName(), this.getMetricKey(),
                    this.getMetricValue(), this.getDate().toString());
        }
    }

    /**
     * Wrapper over a Map that implements a MultivaluedMap, i.e, a single key may have more than one value.
     * 
     * Internally, it is a Map<K, List<V>>. This wrapper simply facilitates the adding operations.
     * 
     * After adding all values, you can work with the result using {@link #getMap()}. Remember that 
     * any key that has no value may return <code>null</code> instead of an empty list.
     *  
     * @param <K> type of key
     * @param <V> type value
     * 
     */
    public static class MultivaluedMapWrapper<K, V> {

        private final Map<K, List<V>> map;

        public MultivaluedMapWrapper() {
            this.map = new HashMap<K, List<V>>();
        }

        public MultivaluedMapWrapper(Map<K, List<V>> map) {
            if (map == null) {
                throw new IllegalArgumentException("map cannot be null");
            }
            this.map = map;
        }

        /**
         * Return the list of values associated to a key, or an empty list. 
         */
        public List<V> get(K key) {
            List<V> list = map.get(key);

            return list == null ? Collections.<V>emptyList() : list;
        }

        /**
         * Add a value to a key
         */
        public void add(K key, V value) {

            List<V> list;
            if (map.containsKey(key)) {
                list = map.get(key);
            } else {
                list = new ArrayList<V>();
                map.put(key, list);
            }
            list.add(value);
        }

        /**
         * Add a value to the given keys
         */
        public void addToKeys(List<K> keys, V value) {

            for (K key : keys) {
                this.add(key, value);
            }
        }

        /**
         * Returns an unmodifiable Map over the internal map.
         */
        public Map<K, List<V>> getMap() {
            return Collections.unmodifiableMap(map);
        }
    }

    private static class BindingHelper {
        private final String key;
        private final String value;
        private final Date date;
        @SuppressWarnings("unused")
        private final String resourceId;

        public BindingHelper(Map<String, List<Map<String, String>>> binding) {
            key = getItem(binding, "http://www.modaclouds.eu/rdfs/1.0/monitoringdata#metric");
            value = getItem(binding, "http://www.modaclouds.eu/rdfs/1.0/monitoringdata#value");
            String dateStr = getItem(binding, "http://www.modaclouds.eu/rdfs/1.0/monitoringdata#timestamp");
            date = new Date(Long.parseLong(dateStr));
            resourceId = getItem(binding, "http://www.modaclouds.eu/rdfs/1.0/monitoringdata#resourceId");
        }

        private String getItem(Map<String, List<Map<String, String>>> binding, String ns) {
            String item = nullable(binding.get(ns)).get(0).get("value");

            return item;
        }

        private List<Map<String, String>> nullable(List<Map<String, String>> list) {
            if (list != null)
                return list;
            else {
                List<Map<String, String>> emptyValueList = new ArrayList<Map<String, String>>();
                Map<String, String> emptyValueMap = new HashMap<String, String>();
                emptyValueMap.put("value", "");
                emptyValueList.add(emptyValueMap);
                return emptyValueList;
            }
        }

    }
}