seaclouds.matchmaker.Matchmaker.java Source code

Java tutorial

Introduction

Here is the source code for seaclouds.matchmaker.Matchmaker.java

Source

/**
 * Copyright 2014 SeaClouds
 * Contact: SeaClouds
 *
 *    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 seaclouds.matchmaker;

import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import com.google.common.io.Closeables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import seaclouds.utils.TOSCAYamlParser;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class Matchmaker {

    static Logger log = LoggerFactory.getLogger(Matchmaker.class);

    public Map<String, Object> match(String reqName, String reqValue, Map reqDescription)
            throws FileNotFoundException {
        // TODO Auto-generated method stub

        System.out.println("-----\nMatchmaking start");

        //TODO: ask the discoverer to find services with reqName and reqValue

        InputStream cloudInput;
        cloudInput = getClass().getResourceAsStream("/computeServices.yaml");

        String nuroCaseYaml = null;
        try {
            nuroCaseYaml = CharStreams.toString(new InputStreamReader(cloudInput, Charsets.UTF_8));
        } catch (IOException e) {
            e.printStackTrace();
        }
        Closeables.closeQuietly(cloudInput);
        TOSCAYamlParser cloudModel = new TOSCAYamlParser(nuroCaseYaml);

        Map<String, Object> cloudOfferedServiceList = cloudModel.getNodeTemplates();
        Map<String, Object> suitableServiceList = new LinkedHashMap<>();
        log.info("\n" + cloudOfferedServiceList.size() + " service(s) available");

        for (Entry<String, Object> service : cloudOfferedServiceList.entrySet()) {

            String serviceName = (String) service.getKey();
            Map<String, Object> serviceDescription = (Map) service.getValue();

            //1. check if the service offers a capability equals to reqName and check if the service is of type included in reqValue
            //note: a service can offer more than a single capability, thus they are stored into a map
            Map<String, Object> capabilitiesList = (Map) serviceDescription.get("capabilities");
            String offServiceType = (String) serviceDescription.get("type");

            if (capabilitiesList.containsKey(reqName) && offServiceType.equals(reqValue)) {
                if (matchProperties(reqDescription, serviceDescription)) {
                    log.info("Service suitable");
                    suitableServiceList.put(serviceName, serviceDescription);
                    //put serviceDescription somewhere or return its unique identifier
                } else {
                    log.info("Service not suitable");
                }
            } else {
                log.info("Service not suitable");
            }
        }

        //TODO: return a map with matching services for each module/requirement

        log.info("-----\nMatchmaking end");
        return suitableServiceList;
    }

    private boolean matchProperties(Map<String, Object> reqDescription, Map<String, Object> serviceDescription) {
        // TODO Auto-generated method stub
        //2. matchmaking properties (reqDescripion vs serviceDescription) //3. matchmaking values
        List reqProperties = (List) reqDescription.get("constraints");
        Map serviceProperties = (Map) serviceDescription.get("properties");
        int suitableProperty = 0;

        for (int i = 0; i < reqProperties.size(); i++) {
            //each property is a map
            Map<String, Object> property = (Map<String, Object>) reqProperties.get(i);

            //read property name
            for (String name : property.keySet()) {
                if (serviceProperties.containsKey(name)) {

                    //extract property values
                    Object reqValue = property.get(name);
                    Object offValue = serviceProperties.get(name);
                    String reqClass = reqValue.getClass().getSimpleName();
                    String offClass = offValue.getClass().getSimpleName();

                    if (reqClass.equals("LinkedHashMap") || offClass.equals("LinkedHashMap")) {
                        if (reqClass.equals(offClass)) {
                            //TODO: both properties contain an operator
                            //only permitted operator for off and req properties is "valid_values"
                            Map<String, Object> mapR = (Map<String, Object>) reqValue;
                            Entry<String, String>[] entryR = (Entry<String, String>[]) mapR.entrySet()
                                    .toArray(new Map.Entry[mapR.size()]);
                            String operatorR = entryR[0].getKey();
                            Object valueR = entryR[0].getValue();

                            Map<String, Object> mapO = (Map<String, Object>) offValue;
                            Entry<String, String>[] entryO = (Entry<String, String>[]) mapO.entrySet()
                                    .toArray(new Map.Entry[mapO.size()]);
                            String operator = entryO[0].getKey();
                            Object value = entryO[0].getValue();

                            //at least one of the values in reqValue should be present in offValue

                            log.info("Not implemented yet");
                        }

                        else if (reqClass.equals("LinkedHashMap")) {
                            //extract operator
                            Map<String, Object> map = (Map<String, Object>) reqValue;
                            Entry<String, String>[] entry = (Entry<String, String>[]) map.entrySet()
                                    .toArray(new Map.Entry[map.size()]);
                            String operator = entry[0].getKey();
                            Object value = entry[0].getValue();

                            if (operatorMatch(value, offValue, operator))
                                suitableProperty++;
                        }

                        else { //offClass contains "valid" operator and reqClass is a string
                            Map<String, Object> map = (Map<String, Object>) offValue;
                            Entry<String, Object>[] entry = (Entry<String, Object>[]) map.entrySet()
                                    .toArray(new Map.Entry[map.size()]);
                            String operator = entry[0].getKey(); //this should be a valid operator
                            List value = (List) entry[0].getValue();

                            Boolean isPresent = false;
                            for (Object element : value) {
                                if (reqValue.equals(element))
                                    isPresent = true;
                            }

                            if (isPresent)
                                suitableProperty++; //not sure if the same function is suitable
                        }
                    }

                    if (reqClass.equals(offClass)) {
                        //exact match
                        if (exactMatch(reqValue, offValue))
                            suitableProperty++;
                    }
                }
            }
        }

        if (suitableProperty == reqProperties.size()) {
            return true;
        } else {
            return false;
        }
    }

    private boolean operatorMatch(Object value, Object offValue, String operator) {
        // TODO Auto-generated method stub
        switch (operator) {

        case "equal":
            return offValue.equals(value);

        case "greater_then":
            if (value.getClass().getSimpleName().equals("Integer")) {
                Integer val = (Integer) value;
                return ((Integer) offValue > val);
            } else if (value.getClass().getSimpleName().equals("Double")) {
                Double val = (Double) value;
                return ((Double) offValue > val);
            } else {
                return false;
            }

        case "greater_or_equal":
            //value comparable
            if (value.getClass().getSimpleName().equals("Integer")) {
                Integer val = (Integer) value;
                return ((Integer) offValue >= val);
            } else if (value.getClass().getSimpleName().equals("Double")) {
                Double val = (Double) value;
                return ((Double) offValue >= val);
            } else {
                return false;
            }

        case "less_than":
            if (value.getClass().getSimpleName().equals("Integer")) {
                Integer val = (Integer) value;
                return (Integer) offValue < val;
            } else if (value.getClass().getSimpleName().equals("Double")) {
                Double val = (Double) value;
                return (Double) offValue < val;
            } else {
                return false;
            }

        case "less_or_equal":
            if (value.getClass().getSimpleName().equals("Integer")) {
                Integer val = (Integer) value;
                return (Integer) offValue <= val;
            } else if (value.getClass().getSimpleName().equals("Double")) {
                Double val = (Double) value;
                return (Double) offValue <= val;
            } else
                return false;

        case "in_range":
            //dual scalar comparable: value is a list with two elements
            List<Object> dualScalar = (List<Object>) value;
            if (dualScalar.get(0).getClass().getSimpleName().equals("Integer")) {
                Integer min = (Integer) dualScalar.get(0);
                Integer max = (Integer) dualScalar.get(1);
                return (Integer) offValue >= min && (Integer) offValue <= max;
            } else if (dualScalar.get(0).getClass().getSimpleName().equals("Double")) {
                Double min = (Double) dualScalar.get(0);
                Double max = (Double) dualScalar.get(1);
                if ((Double) offValue >= min && (Integer) offValue <= max) {
                    log.info("Valid!");
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }

        case "valid_values":
            //TODO
            //any
            //warning: offered can be a single value OR a list '-.-
            //extract the list of validvlues
            //extract the list of offValue (can be a single value)
            Boolean isValid = false;
            //compare each valid value. ; if validvalue is present in offvalue-> isValid = true;
            //return isValid;
            log.info("Operator not implemented yet");
            break;

        case "length":
            //TODO
            //string in the specification (?) integer
            log.info("Operator not implemented yet");
            break;

        case "min_length":
            //TODO
            //as above
            log.info("Operator not implemented yet");
            break;

        case "max_length":
            //TODO
            //as above
            log.info("Operator not implemented yet");
            break;

        default:
            //TODO: handle exception
            log.info("Operator not implemented yet");
            break;
        }
        return false;
    }

    private boolean exactMatch(Object reqValue, Object offValue) {
        // TODO Auto-generated method stub
        if (reqValue.equals(offValue))
            return true;
        else
            return false;
    }

}