org.finra.datagenerator.engine.scxml.SCXMLGapper.java Source code

Java tutorial

Introduction

Here is the source code for org.finra.datagenerator.engine.scxml.SCXMLGapper.java

Source

/*
 * Copyright 2014 DataGenerator Contributors
 *
 * 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 org.finra.datagenerator.engine.scxml;

import org.apache.commons.scxml.io.SCXMLParser;
import org.apache.commons.scxml.model.CustomAction;
import org.apache.commons.scxml.model.ModelException;
import org.apache.commons.scxml.model.SCXML;
import org.apache.commons.scxml.model.TransitionTarget;
import org.finra.datagenerator.engine.Frontier;
import org.finra.datagenerator.engine.scxml.tags.CustomTagExtension;
import org.finra.datagenerator.engine.scxml.tags.FileExtension;
import org.finra.datagenerator.engine.scxml.tags.RangeExtension;
import org.finra.datagenerator.engine.scxml.tags.SetAssignExtension;
import org.finra.datagenerator.engine.scxml.tags.SingleValueAssignExtension;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * Provides serialization tools for SCXMLFrontier.
 */
public class SCXMLGapper {
    private SCXML model;

    private void setModel(String model, List<CustomTagExtension> tagExtensionList) {
        List<CustomAction> customActions = new ArrayList<>();

        for (CustomTagExtension tagExtension : tagExtensionList) {
            if (!tagExtension.getTagNameSpace().equals("http://www.w3.org/2005/07/scxml")) {
                CustomAction action = new CustomAction(tagExtension.getTagNameSpace(), tagExtension.getTagName(),
                        tagExtension.getTagActionClass());
                customActions.add(action);
            }
        }

        try {
            InputStream is = new ByteArrayInputStream(model.getBytes());
            this.model = SCXMLParser.parse(new InputSource(is), null, customActions);
        } catch (IOException | SAXException | ModelException e) {
            e.printStackTrace();
        }
    }

    /**
     * Takes a model and an SCXMLFrontier and decomposes the Frontier into a Map of Strings to Strings
     * These strings can be sent over a network to get a Frontier past a 'gap'
     *
     * @param frontier  the Frontier
     * @param modelText the model
     * @return the map of strings representing a decomposition
     */
    public Map<String, String> decompose(Frontier frontier, String modelText) {
        if (!(frontier instanceof SCXMLFrontier)) {
            return null;
        }

        TransitionTarget target = ((SCXMLFrontier) frontier).getRoot().nextState;
        Map<String, String> variables = ((SCXMLFrontier) frontier).getRoot().variables;

        Map<String, String> decomposition = new HashMap<String, String>();
        decomposition.put("target", target.getId());

        StringBuilder packedVariables = new StringBuilder();
        for (Map.Entry<String, String> variable : variables.entrySet()) {
            packedVariables.append(variable.getKey());
            packedVariables.append("::");
            packedVariables.append(variable.getValue());
            packedVariables.append(";");
        }

        decomposition.put("variables", packedVariables.toString());
        decomposition.put("model", modelText);

        return decomposition;
    }

    /**
     * Produces an SCXMLFrontier by reversing a decomposition; the model text is bundled into the decomposition.
     *
     * @param decomposition the decomposition, assembled back into a map
     * @return a rebuilt SCXMLFrontier
     */
    public Frontier reproduce(Map<String, String> decomposition) {
        return reproduce(decomposition, new LinkedList<CustomTagExtension>());
    }

    /**
     * Produces an SCXMLFrontier by reversing a decomposition; the model text is bundled into the decomposition.
     *
     * @param decomposition the decomposition, assembled back into a map
     * @param tagExtensionList custom tags to use in the model
     * @return a rebuilt SCXMLFrontier
     */
    public Frontier reproduce(Map<String, String> decomposition, List<CustomTagExtension> tagExtensionList) {
        tagExtensionList = new LinkedList<>(tagExtensionList);
        tagExtensionList.add(new SetAssignExtension());
        tagExtensionList.add(new SingleValueAssignExtension());
        tagExtensionList.add(new FileExtension());
        tagExtensionList.add(new RangeExtension());

        setModel(decomposition.get("model"), tagExtensionList);
        TransitionTarget target = (TransitionTarget) model.getTargets().get(decomposition.get("target"));

        Map<String, String> variables = new HashMap<>();
        String[] assignments = decomposition.get("variables").split(";");
        for (int i = 0; i < assignments.length; i++) {
            String[] a = assignments[i].split("::");
            if (a.length == 2) {
                variables.put(a[0], a[1]);
            } else {
                variables.put(a[0], "");
            }
        }

        return new SCXMLFrontier(new PossibleState(target, variables), model, tagExtensionList);
    }
}