<commit_before>/*
 *     (C) Copyright 2012 Universidad Politécnica de Madrid
 *
 *     This file is part of Wirecloud Platform.
 *
 *     Wirecloud Platform is free software: you can redistribute it and/or
 *     modify it under the terms of the GNU Affero General Public License as
 *     published by the Free Software Foundation, either version 3 of the
 *     License, or (at your option) any later version.
 *
 *     Wirecloud is distributed in the hope that it will be useful, but WITHOUT
 *     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
 *     License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with Wirecloud Platform.  If not, see
 *     <http://www.gnu.org/licenses/>.
 *
 */

/*global LayoutManagerFactory, opManager, StyledElements, Wirecloud, gettext */
if (!Wirecloud.ui) {
    // TODO this line should live in another file
    Wirecloud.ui = {};
}

var WiringStatus = {
    views: [
        {
            label: 'default',
            igadgets: {
            },
            operators: {
            },
            nextOperatorId: 0
        }
    ],
    operators: {
    },
    connections: [
    ]
};

(function () {

    "use strict";

    /*************************************************************************
     * Constructor
     *************************************************************************/
    var WiringEditor = function WiringEditor(id, options) {
        options['class'] = 'wiring_editor';
        StyledElements.Alternative.call(this, id, options);

        this.addEventListener('show', renewInterface.bind(this));
        this.addEventListener('hide', clearInterface.bind(this));

        this.layout = new StyledElements.BorderLayout();
        this.appendChild(this.layout);

        this.layout.getNorthContainer().addClassName('menubar');
        this.layout.getCenterContainer().addClassName('grid');

        // general highlight button
        this.highlight_button = new StyledElements.StyledButton({
            'title': gettext("general highlight"),
            'class': 'generalHighlight_button',
            'plain': true
        });
        this.highlight_button.insertInto(this.layout.getCenterContainer());
        this.highlight_button.addClassName('activated');
        this.highlight_button.addEventListener('click', function () {
            if (this.generalHighlighted) {
                this.highlight_button.removeClassName('activated');
                this.generalUnhighlight();
                this.generalHighlighted = false;
            } else {
                this.generalHighlight();
                this.highlight_button.addClassName('activated');
                this.generalHighlighted = true;
            }
        }.bind(this), true);

        //canvas for arrows
        this.canvas = new Wirecloud.ui.WiringEditor.Canvas();
        this.canvasElement = this.canvas.getHTMLElement();
        this.layout.getCenterContainer().appendChild(this.canvasElement);

        this.enableAnchors = this.enableAnchors.bind(this);
        this.disableAnchors = this.disableAnchors.bind(this);

        this.arrowCreator = new Wirecloud.ui.WiringEditor.ArrowCreator(this.canvas, this,
            function () {},
            function () {},
            this.enableAnchors,
            function () {},
            //adding arrow to WiringEditor.arrows list
            function (data, theArrow) {
                data.arrows.push(theArrow);
            }
        );
        this._startdrag_map_func = function (anchor) {
            anchor.addEventListener('startdrag', this.disableAnchors);
        }.bind(this);
    };
    WiringEditor.prototype = new StyledElements.Alternative();

    WiringEditor.prototype.view_name = 'wiring';

    /*************************************************************************
     * Private methods
     *************************************************************************/

    /**
     * @Private
     * finds anchors from the serialized string
     */
    var findAnchor = function findAnchor(desc) {
        switch (desc.type) {
        case 'igadget':
            return this.igadgets[desc.igadget].getAnchor(desc.varname);
        case 'ioperator':
            return this.ioperators[desc.ioperator].getAnchor(desc.endpoint);
        }
    };

    /**
     * @Private
     * repaint the wiringEditor interface
     */
    var renewInterface = function renewInterface() {
        var igadgets, igadget, key, i, gadget_interface, minigadget_interface, ioperators, operator,
            operator_interface, operator_instance, operatorKeys, meta, connection, startAnchor, endAnchor,
            arrow, workspace;

        workspace = opManager.activeWorkSpace; // FIXME this is the current way to obtain the current workspace

        this.nextOperatorId = WiringStatus.views[0].nextOperatorId;
        this.targetsOn = this.sourcesOn = true;
        this.targetAnchorList = [];
        this.sourceAnchorList = [];
        this.arrows = [];
        this.igadgets = {};
        this.ioperators = {};
        this.selectedObjects = [];
        this.generalHighlighted = true;

        igadgets = workspace.getIGadgets();

        for (i = 0; i < igadgets.length; i++) {
            igadget = igadgets[i];
            // mini widgets
            minigadget_interface = new Wirecloud.ui.WiringEditor.GadgetInterface(this, igadget, this);
            this.layout.getNorthContainer().appendChild(minigadget_interface);
            // widget
            if (igadget.getId() in WiringStatus.views[0].igadgets) {
                minigadget_interface.disable();
                gadget_interface = this.addIGadget(this, igadget);
                gadget_interface.setPosition(WiringStatus.views[0].igadgets[igadget.getId()]);
            }
        }
        // mini operators
        ioperators = Wirecloud.wiring.OperatorFactory.getAvailableOperators();
        for (key in ioperators) {
            operator = ioperators[key];
            operator_interface = new Wirecloud.ui.WiringEditor.OperatorInterface(this, operator.instanciate(-1), this);
            this.layout.getNorthContainer().appendChild(operator_interface);
        }

        // operators
        for (key in WiringStatus.views[0].operators) {
            operator_instance = WiringStatus.operators[key];
            operator_instance.id = key;

            meta = ioperators[operator_instance.name];
            operator_interface = this.addIOperator(meta, operator_instance);
            operator_interface.setPosition(WiringStatus.views[0].operators[key]);
        }

        // connenctions
        for (i = 0; i < WiringStatus.connections.length; i += 1) {
            connection = WiringStatus.connections[i];
            startAnchor = findAnchor.call(this, connection.source);
            endAnchor = findAnchor.call(this, connection.target);
            arrow = this.canvas.drawArrow(startAnchor.getCoordinates(this.layout.getCenterContainer().wrapperElement),
                 endAnchor.getCoordinates(this.layout.getCenterContainer().wrapperElement));
            arrow.startAnchor = startAnchor;
            startAnchor.addArrow(arrow);
            arrow.endAnchor = endAnchor;
            endAnchor.addArrow(arrow);
            arrow.addClassName('arrow');

            this.arrows.push(arrow);
        }
    };

    /**
     * @Private
     * clean the WiringEditor interface.
     */
    var clearInterface = function clearInterface() {
        var i, key, workspace;

        this.serialize();
        workspace = opManager.activeWorkSpace; // FIXME this is the current way to obtain the current workspace
        workspace.wiring.load(WiringStatus);

        for (i = 0; i < this.arrows.length; i++) {
            this.arrows[i].destroy();
        }
        this.canvas.clear();

        for (key in this.igadgets) {
            this.layout.getCenterContainer().removeChild(this.igadgets[key]);
            this.igadgets[key].destroy();
        }
        for (key in this.ioperators) {
            this.layout.getCenterContainer().removeChild(this.ioperators[key]);
            this.ioperators[key].destroy();
        }

        this.layout.getNorthContainer().clear();
        this.arrows = [];
        this.igadgets = {};
        this.ioperators = {};
    };

    /*************************************************************************
     * Public methods
     *************************************************************************/

    /**
     * Saves the wiring state.
     */
    WiringEditor.prototype.serialize = function serialize() {
        var pos, i, key, gadget, arrow, operator_interface;

        // positions
        WiringStatus = {
            views: [
                {
                    label: 'default',
                    igadgets: {
                    },
                    operators: {
                    },
                    nextOperatorId: this.nextOperatorId
                }
            ],
            operators: {
            },
            connections: [
            ]
        };

        for (key in this.igadgets) {
            gadget = this.igadgets[key];
            pos = gadget.getStylePosition();
            WiringStatus.views[0].igadgets[gadget.getIGadget().getId()] = pos;
        }

        for (i in this.ioperators) {
            operator_interface = this.ioperators[i];
            pos = operator_interface.getStylePosition();
            WiringStatus.operators[operator_interface.getId()] = {"name" : operator_interface.getName(), 'id' : operator_interface.getId()};
            WiringStatus.views[0].operators[operator_interface.getId()] = pos;
        }

        for (i = 0; i < this.arrows.length; i++) {
            arrow = this.arrows[i];
            WiringStatus.connections.push({
                'source': arrow.startAnchor.serialize(),
                'target': arrow.endAnchor.serialize()
            });
        }
    };

    /**
     * general Highlight switch on.
     */
    WiringEditor.prototype.generalHighlight = function generalHighlight() {
        var i, key;

        this.selectedObjects = [];
        for (i in this.ioperators) {
            this.ioperators[i].highlight();
            this.selectedObjects.push(this.ioperators[i]);
        }

        for (key in this.igadgets) {
            this.igadgets[key].highlight();
            this.selectedObjects.push(this.igadgets[key]);
        }
    };

    /**
     * general Highlight switch off.
     */
    WiringEditor.prototype.generalUnhighlight = function generalUnhighlight() {
        var key;

        for (key in this.ioperators) {
            this.ioperators[key].unhighlight();
        }

        for (key in this.igadgets) {
            this.igadgets[key].unhighlight();
        }

        this.selectedObjects = [];
    };

    /**
     * Highlight object.
     */
    WiringEditor.prototype.highlightEntity = function highlightEntity(object) {
        this.selectedObjects.push(object);
    };

    /**
     * Unhighlight object.
     */
    WiringEditor.prototype.unhighlightEntity = function unhighlightEntity(object) {
        var pos = this.selectedObjects.indexOf(object);
        delete this.selectedObjects[pos];
    };

    WiringEditor.prototype.addIGadget = function addIGadget(wiringEditor, igadget) {
        var gadget_interface = new Wirecloud.ui.WiringEditor.GadgetInterface(wiringEditor, igadget, this.arrowCreator);

        this.igadgets[igadget.getId()] = gadget_interface;
        this.layout.getCenterContainer().appendChild(gadget_interface);

        gadget_interface.sourceAnchors.map(this._startdrag_map_func);
        gadget_interface.targetAnchors.map(this._startdrag_map_func);

        this.targetAnchorList = this.targetAnchorList.concat(gadget_interface.targetAnchors);
        this.sourceAnchorList = this.sourceAnchorList.concat(gadget_interface.sourceAnchors);

        return gadget_interface;
    };

    WiringEditor.prototype.addIOperator = function addIOperator(ioperator, initial_status) {
        var instanciated_operator, operator_interface;

        if (initial_status != null) {
            instanciated_operator = ioperator.instanciate(initial_status.id);
        } else {
            instanciated_operator = ioperator.instanciate(this.nextOperatorId);
            this.nextOperatorId++;
        }

        operator_interface = new Wirecloud.ui.WiringEditor.OperatorInterface(this, instanciated_operator, this.arrowCreator);
        this.layout.getCenterContainer().appendChild(operator_interface);

        operator_interface.sourceAnchors.map(this._startdrag_map_func);
        operator_interface.targetAnchors.map(this._startdrag_map_func);

        this.targetAnchorList = this.targetAnchorList.concat(operator_interface.targetAnchors);
        this.sourceAnchorList = this.sourceAnchorList.concat(operator_interface.sourceAnchors);

        this.ioperators[operator_interface.getId()] = operator_interface;
        return operator_interface;
    };

    /**
     * Reenables all anchor disabled previously.
     */
    WiringEditor.prototype.enableAnchors = function enableAnchors() {
        var i;

        if (!this.sourcesOn) {
            for (i = 0; i < this.sourceAnchorList.length; i++) {
                this.sourceAnchorList[i].enable();
                this.sourcesOn = true;
            }
        } else if (!this.targetsOn) {
            for (i = 0; i < this.targetAnchorList.length; i++) {
                this.targetAnchorList[i].enable();
                this.targetsOn = true;
            }
        }
    };

    /**
     * Disables all anchor that cannot be connected to the given anchor.
     */
    WiringEditor.prototype.disableAnchors = function disableAnchors(anchor) {
        var i, anchorList = [];
        if (anchor instanceof Wirecloud.ui.WiringEditor.TargetAnchor) {
            anchorList = this.targetAnchorList;
            this.targetsOn = false;
        } else {
            anchorList = this.sourceAnchorList;
            this.sourcesOn = false;
        }
        for (i = 0; i < anchorList.length; i++) {
            anchorList[i].disable();
        }
    };

    WiringEditor.prototype.removeGadget = function removeGadget(gadget_interface) {
        delete this.igadgets[gadget_interface.getIGadget().getId()];
        this.layout.getCenterContainer().removeChild(gadget_interface);
        gadget_interface.destroy();
    };

    WiringEditor.prototype.removeOperator = function removeOperator(operator_interface) {
        delete this.ioperators[operator_interface.getIOperator().getId()];
        this.layout.getCenterContainer().removeChild(operator_interface);
        operator_interface.destroy();
    };

    WiringEditor.prototype.removeArrow = function removeArrow(arrow) {
        var pos;
        pos = this.arrows.indexOf(arrow);
        this.arrows.splice(pos, 1);
        arrow.destroy();
    };

    /**
     * getBreadcrum
     */
    WiringEditor.prototype.getBreadcrum = function getBreadcrum() {
        var workspace_breadcrum = LayoutManagerFactory.getInstance().viewsByName.workspace.getBreadcrum().slice();

        workspace_breadcrum.push({
            'label': 'wiring'
        });

        return workspace_breadcrum;
    };

    /*************************************************************************
     * Make WiringEditor public
     *************************************************************************/
    Wirecloud.ui.WiringEditor = WiringEditor;

})();
<commit_msg>Save puller positions<commit_after>/*
 *     (C) Copyright 2012 Universidad Politécnica de Madrid
 *
 *     This file is part of Wirecloud Platform.
 *
 *     Wirecloud Platform is free software: you can redistribute it and/or
 *     modify it under the terms of the GNU Affero General Public License as
 *     published by the Free Software Foundation, either version 3 of the
 *     License, or (at your option) any later version.
 *
 *     Wirecloud is distributed in the hope that it will be useful, but WITHOUT
 *     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
 *     License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with Wirecloud Platform.  If not, see
 *     <http://www.gnu.org/licenses/>.
 *
 */

/*global LayoutManagerFactory, opManager, StyledElements, Wirecloud, gettext */
if (!Wirecloud.ui) {
    // TODO this line should live in another file
    Wirecloud.ui = {};
}

var WiringStatus = {
    views: [
        {
            label: 'default',
            igadgets: {
            },
            operators: {
            },
            nextOperatorId: 0
        }
    ],
    operators: {
    },
    connections: [
    ]
};

(function () {

    "use strict";

    /*************************************************************************
     * Constructor
     *************************************************************************/
    var WiringEditor = function WiringEditor(id, options) {
        options['class'] = 'wiring_editor';
        StyledElements.Alternative.call(this, id, options);

        this.addEventListener('show', renewInterface.bind(this));
        this.addEventListener('hide', clearInterface.bind(this));

        this.layout = new StyledElements.BorderLayout();
        this.appendChild(this.layout);

        this.layout.getNorthContainer().addClassName('menubar');
        this.layout.getCenterContainer().addClassName('grid');

        // general highlight button
        this.highlight_button = new StyledElements.StyledButton({
            'title': gettext("general highlight"),
            'class': 'generalHighlight_button',
            'plain': true
        });
        this.highlight_button.insertInto(this.layout.getCenterContainer());
        this.highlight_button.addClassName('activated');
        this.highlight_button.addEventListener('click', function () {
            if (this.generalHighlighted) {
                this.highlight_button.removeClassName('activated');
                this.generalUnhighlight();
                this.generalHighlighted = false;
            } else {
                this.generalHighlight();
                this.highlight_button.addClassName('activated');
                this.generalHighlighted = true;
            }
        }.bind(this), true);

        //canvas for arrows
        this.canvas = new Wirecloud.ui.WiringEditor.Canvas();
        this.canvasElement = this.canvas.getHTMLElement();
        this.layout.getCenterContainer().appendChild(this.canvasElement);

        this.enableAnchors = this.enableAnchors.bind(this);
        this.disableAnchors = this.disableAnchors.bind(this);

        this.arrowCreator = new Wirecloud.ui.WiringEditor.ArrowCreator(this.canvas, this,
            function () {},
            function () {},
            this.enableAnchors,
            function () {},
            //adding arrow to WiringEditor.arrows list
            function (data, theArrow) {
                data.arrows.push(theArrow);
            }
        );
        this._startdrag_map_func = function (anchor) {
            anchor.addEventListener('startdrag', this.disableAnchors);
        }.bind(this);
    };
    WiringEditor.prototype = new StyledElements.Alternative();

    WiringEditor.prototype.view_name = 'wiring';

    /*************************************************************************
     * Private methods
     *************************************************************************/

    /**
     * @Private
     * finds anchors from the serialized string
     */
    var findAnchor = function findAnchor(desc) {
        switch (desc.type) {
        case 'igadget':
            return this.igadgets[desc.igadget].getAnchor(desc.varname);
        case 'ioperator':
            return this.ioperators[desc.ioperator].getAnchor(desc.endpoint);
        }
    };

    /**
     * @Private
     * repaint the wiringEditor interface
     */
    var renewInterface = function renewInterface() {
        var igadgets, igadget, key, i, gadget_interface, minigadget_interface, ioperators, operator,
            operator_interface, operator_instance, operatorKeys, meta, connection, startAnchor, endAnchor,
            arrow, workspace;

        workspace = opManager.activeWorkSpace; // FIXME this is the current way to obtain the current workspace

        this.nextOperatorId = WiringStatus.views[0].nextOperatorId;
        this.targetsOn = this.sourcesOn = true;
        this.targetAnchorList = [];
        this.sourceAnchorList = [];
        this.arrows = [];
        this.igadgets = {};
        this.ioperators = {};
        this.selectedObjects = [];
        this.generalHighlighted = true;

        igadgets = workspace.getIGadgets();

        for (i = 0; i < igadgets.length; i++) {
            igadget = igadgets[i];
            // mini widgets
            minigadget_interface = new Wirecloud.ui.WiringEditor.GadgetInterface(this, igadget, this);
            this.layout.getNorthContainer().appendChild(minigadget_interface);
            // widget
            if (igadget.getId() in WiringStatus.views[0].igadgets) {
                minigadget_interface.disable();
                gadget_interface = this.addIGadget(this, igadget);
                gadget_interface.setPosition(WiringStatus.views[0].igadgets[igadget.getId()]);
            }
        }
        // mini operators
        ioperators = Wirecloud.wiring.OperatorFactory.getAvailableOperators();
        for (key in ioperators) {
            operator = ioperators[key];
            operator_interface = new Wirecloud.ui.WiringEditor.OperatorInterface(this, operator.instanciate(-1), this);
            this.layout.getNorthContainer().appendChild(operator_interface);
        }

        // operators
        for (key in WiringStatus.views[0].operators) {
            operator_instance = WiringStatus.operators[key];
            operator_instance.id = key;

            meta = ioperators[operator_instance.name];
            operator_interface = this.addIOperator(meta, operator_instance);
            operator_interface.setPosition(WiringStatus.views[0].operators[key]);
        }

        // connenctions
        for (i = 0; i < WiringStatus.connections.length; i += 1) {
            connection = WiringStatus.connections[i];
            startAnchor = findAnchor.call(this, connection.source);
            endAnchor = findAnchor.call(this, connection.target);
            arrow = this.canvas.drawArrow(startAnchor.getCoordinates(this.layout.getCenterContainer().wrapperElement),
                 endAnchor.getCoordinates(this.layout.getCenterContainer().wrapperElement));
            arrow.startAnchor = startAnchor;
            startAnchor.addArrow(arrow);
            arrow.endAnchor = endAnchor;
            endAnchor.addArrow(arrow);
            arrow.addClassName('arrow');
            arrow.setPullerStart(connection.pullerStart);
            arrow.setPullerEnd(connection.pullerEnd);

            this.arrows.push(arrow);
        }
    };

    /**
     * @Private
     * clean the WiringEditor interface.
     */
    var clearInterface = function clearInterface() {
        var i, key, workspace;

        this.serialize();
        workspace = opManager.activeWorkSpace; // FIXME this is the current way to obtain the current workspace
        workspace.wiring.load(WiringStatus);

        for (i = 0; i < this.arrows.length; i++) {
            this.arrows[i].destroy();
        }
        this.canvas.clear();

        for (key in this.igadgets) {
            this.layout.getCenterContainer().removeChild(this.igadgets[key]);
            this.igadgets[key].destroy();
        }
        for (key in this.ioperators) {
            this.layout.getCenterContainer().removeChild(this.ioperators[key]);
            this.ioperators[key].destroy();
        }

        this.layout.getNorthContainer().clear();
        this.arrows = [];
        this.igadgets = {};
        this.ioperators = {};
    };

    /*************************************************************************
     * Public methods
     *************************************************************************/

    /**
     * Saves the wiring state.
     */
    WiringEditor.prototype.serialize = function serialize() {
        var pos, i, key, gadget, arrow, operator_interface;

        // positions
        WiringStatus = {
            views: [
                {
                    label: 'default',
                    igadgets: {
                    },
                    operators: {
                    },
                    nextOperatorId: this.nextOperatorId
                }
            ],
            operators: {
            },
            connections: [
            ]
        };

        for (key in this.igadgets) {
            gadget = this.igadgets[key];
            pos = gadget.getStylePosition();
            WiringStatus.views[0].igadgets[gadget.getIGadget().getId()] = pos;
        }

        for (i in this.ioperators) {
            operator_interface = this.ioperators[i];
            pos = operator_interface.getStylePosition();
            WiringStatus.operators[operator_interface.getId()] = {"name" : operator_interface.getName(), 'id' : operator_interface.getId()};
            WiringStatus.views[0].operators[operator_interface.getId()] = pos;
        }

        for (i = 0; i < this.arrows.length; i++) {
            arrow = this.arrows[i];
            WiringStatus.connections.push({
                'source': arrow.startAnchor.serialize(),
                'target': arrow.endAnchor.serialize(),
                'pullerStart': arrow.getPullerStart(),
                'pullerEnd': arrow.getPullerEnd()
            });
        }
    };

    /**
     * general Highlight switch on.
     */
    WiringEditor.prototype.generalHighlight = function generalHighlight() {
        var i, key;

        this.selectedObjects = [];
        for (i in this.ioperators) {
            this.ioperators[i].highlight();
            this.selectedObjects.push(this.ioperators[i]);
        }

        for (key in this.igadgets) {
            this.igadgets[key].highlight();
            this.selectedObjects.push(this.igadgets[key]);
        }
    };

    /**
     * general Highlight switch off.
     */
    WiringEditor.prototype.generalUnhighlight = function generalUnhighlight() {
        var key;

        for (key in this.ioperators) {
            this.ioperators[key].unhighlight();
        }

        for (key in this.igadgets) {
            this.igadgets[key].unhighlight();
        }

        this.selectedObjects = [];
    };

    /**
     * Highlight object.
     */
    WiringEditor.prototype.highlightEntity = function highlightEntity(object) {
        this.selectedObjects.push(object);
    };

    /**
     * Unhighlight object.
     */
    WiringEditor.prototype.unhighlightEntity = function unhighlightEntity(object) {
        var pos = this.selectedObjects.indexOf(object);
        delete this.selectedObjects[pos];
    };

    WiringEditor.prototype.addIGadget = function addIGadget(wiringEditor, igadget) {
        var gadget_interface = new Wirecloud.ui.WiringEditor.GadgetInterface(wiringEditor, igadget, this.arrowCreator);

        this.igadgets[igadget.getId()] = gadget_interface;
        this.layout.getCenterContainer().appendChild(gadget_interface);

        gadget_interface.sourceAnchors.map(this._startdrag_map_func);
        gadget_interface.targetAnchors.map(this._startdrag_map_func);

        this.targetAnchorList = this.targetAnchorList.concat(gadget_interface.targetAnchors);
        this.sourceAnchorList = this.sourceAnchorList.concat(gadget_interface.sourceAnchors);

        return gadget_interface;
    };

    WiringEditor.prototype.addIOperator = function addIOperator(ioperator, initial_status) {
        var instanciated_operator, operator_interface;

        if (initial_status != null) {
            instanciated_operator = ioperator.instanciate(initial_status.id);
        } else {
            instanciated_operator = ioperator.instanciate(this.nextOperatorId);
            this.nextOperatorId++;
        }

        operator_interface = new Wirecloud.ui.WiringEditor.OperatorInterface(this, instanciated_operator, this.arrowCreator);
        this.layout.getCenterContainer().appendChild(operator_interface);

        operator_interface.sourceAnchors.map(this._startdrag_map_func);
        operator_interface.targetAnchors.map(this._startdrag_map_func);

        this.targetAnchorList = this.targetAnchorList.concat(operator_interface.targetAnchors);
        this.sourceAnchorList = this.sourceAnchorList.concat(operator_interface.sourceAnchors);

        this.ioperators[operator_interface.getId()] = operator_interface;
        return operator_interface;
    };

    /**
     * Reenables all anchor disabled previously.
     */
    WiringEditor.prototype.enableAnchors = function enableAnchors() {
        var i;

        if (!this.sourcesOn) {
            for (i = 0; i < this.sourceAnchorList.length; i++) {
                this.sourceAnchorList[i].enable();
                this.sourcesOn = true;
            }
        } else if (!this.targetsOn) {
            for (i = 0; i < this.targetAnchorList.length; i++) {
                this.targetAnchorList[i].enable();
                this.targetsOn = true;
            }
        }
    };

    /**
     * Disables all anchor that cannot be connected to the given anchor.
     */
    WiringEditor.prototype.disableAnchors = function disableAnchors(anchor) {
        var i, anchorList = [];
        if (anchor instanceof Wirecloud.ui.WiringEditor.TargetAnchor) {
            anchorList = this.targetAnchorList;
            this.targetsOn = false;
        } else {
            anchorList = this.sourceAnchorList;
            this.sourcesOn = false;
        }
        for (i = 0; i < anchorList.length; i++) {
            anchorList[i].disable();
        }
    };

    WiringEditor.prototype.removeGadget = function removeGadget(gadget_interface) {
        delete this.igadgets[gadget_interface.getIGadget().getId()];
        this.layout.getCenterContainer().removeChild(gadget_interface);
        gadget_interface.destroy();
    };

    WiringEditor.prototype.removeOperator = function removeOperator(operator_interface) {
        delete this.ioperators[operator_interface.getIOperator().getId()];
        this.layout.getCenterContainer().removeChild(operator_interface);
        operator_interface.destroy();
    };

    WiringEditor.prototype.removeArrow = function removeArrow(arrow) {
        var pos;
        pos = this.arrows.indexOf(arrow);
        this.arrows.splice(pos, 1);
        arrow.destroy();
    };

    /**
     * getBreadcrum
     */
    WiringEditor.prototype.getBreadcrum = function getBreadcrum() {
        var workspace_breadcrum = LayoutManagerFactory.getInstance().viewsByName.workspace.getBreadcrum().slice();

        workspace_breadcrum.push({
            'label': 'wiring'
        });

        return workspace_breadcrum;
    };

    /*************************************************************************
     * Make WiringEditor public
     *************************************************************************/
    Wirecloud.ui.WiringEditor = WiringEditor;

})();
<|endoftext|>


<commit_before>(function() {
    'use strict';

    if (!global.cloudcmd)
        return console.log(
             '# server.js'                                      + '\n'  +
             '# -----------'                                    + '\n'  +
             '# Module is part of Cloud Commander,'             + '\n'  +
             '# easy to use web server.'                        + '\n'  +
             '# http://cloudcmd.io'                             + '\n');

    var main                = global.cloudcmd.main,

        DIR                 = main.DIR,
        LIBDIR              = main.LIBDIR,
        SRVDIR              = main.SRVDIR,

        URL                 = main.url,
        Path                = main.path,
        Querystring         = main.querystring,

        Minify              = main.minify,
        CloudFunc           = main.cloudfunc,
        AppCache            = main.appcache,
        Socket              = main.socket,

        zlib                = main.zlib,
        http                = main.http,
        https               = main.https,
        Util                = main.util,
        express             = main.express,
        expressApp          = express.getApp(controller),
        files               = main.files,

        Server, Rest, Route;

    /* базовая инициализация  */
    function init(pAppCachProcessing) {
        var config = main.config;

        /* создаём файл app cache */
        if (config.appcache  && AppCache && config.server )
            Util.exec( pAppCachProcessing );
    }

    /**
     * start server function
     * @param pConfig
     * @param pProcessing {index, appcache, rest}
     */
    function start(pProcessing) {
        var lConfig         = main.config;

        if (!pProcessing)
            pProcessing = {};

        Rest            =   pProcessing.rest;
        Route           =   pProcessing.route;

        init(pProcessing.appcache);

        var lPort       =   process.env.PORT            ||  /* c9           */
                            process.env.app_port        ||  /* nodester     */
                            process.env.VCAP_APP_PORT   ||  /* cloudfoundry */
                            lConfig.port,

            lIP         =   process.env.IP              ||  /* c9           */
                            lConfig.ip                  ||
                            (main.WIN32 ? '127.0.0.1' : '0.0.0.0'),

            lSSL        = pProcessing.ssl,
            lSSLPort    = lConfig.sslPort,
            lHTTP       = 'http://',
            lHTTPS      = 'https://',

            lSockets    = function(pServer) {
                var lListen, msg, status;

                if (lConfig.socket && Socket)
                    lListen = Socket.listen(pServer);

                status  = lListen ? 'on' : 'off';
                msg     = CloudFunc.formatMsg('sockets', '', status);

                Util.log(msg);
            },

            lHTTPServer = function() {
                Server =  http.createServer(expressApp || controller);
                Server.on('error', Util.log);
                Server.listen(lPort, lIP);
                lServerLog(lHTTP, lPort);
                lSockets(Server);
            },

            lServerLog  = function(pHTTP, pPort) {
                Util.log('* Server running at ' + pHTTP + lIP + ':' + pPort);
            };
        /* server mode or testing mode */
        if (lConfig.server) {
            if (lSSL) {
                Util.log('* Redirection http -> https is setted up');
                lServerLog(lHTTP, lPort);
                var lRedirectServer =  http.createServer( function(pReq, pRes) {
                     var lURL,
                        lHost       = pReq.headers.host,
                        lParsed     = URL.parse(lHost),
                        lHostName   = lParsed.protocol;

                    lURL            = lHTTPS + lHostName + lSSLPort + pReq.url;

                    main.redirect({
                        response: pRes,
                        url: lURL
                    });
                });

                lRedirectServer.listen(lPort, lIP);

                Server  =  https.createServer(lSSL, controller);
                Server.on('error', function (pError) {
                    Util.log('Could not use https port: ' + lSSLPort);
                    Util.log(pError);
                    lRedirectServer.close();
                    Util.log('* Redirection http -> https removed');
                    lHTTPServer();
                });

                lSockets(Server);

                Server.listen(lSSLPort, lIP);
                lServerLog(lHTTPS, lSSLPort);
            } else
                lHTTPServer();
        } else
            Util.log('Cloud Commander testing mode');
    }

    /**
     * Главная функция, через которую проихсодит
     * взаимодействие, обмен данными с клиентом
     * @param req - запрос клиента (Request)
     * @param res - ответ сервера (Response)
     */
    function controller(pReq, pRes) {
        /* Читаем содержимое папки, переданное в url */
        var lRet, lName, lMin, lCheck, lResult,
            lConfig     = main.config,
            lParsedUrl  = URL.parse(pReq.url),
            lQuery      = lParsedUrl.search || '',
            lPath       = lParsedUrl.pathname;

        /* added supporting of Russian language in directory names */
        lPath = Querystring.unescape(lPath);

        if (!expressApp)
            Util.log(pReq.method + ' ' + lPath + lQuery);

        var lData = {
            name        : lPath,
            request     : pReq,
            response    : pRes
        };

        if (lConfig.rest )
            lRet = Util.exec(Rest, lData);

        if (!lRet && Route)
            lRet = Util.exec(Route, lData);

        if (!lRet)
            lRet = combine(lData);

        if (!lRet) {
            lName = lData.name;

            /* watching is file changed */
            if (lConfig.appcache)
                AppCache.watch(lName);

            lName   = Path.join(DIR, lName);
            lMin    = lConfig.minify,
            lCheck  = Util.checkExtension(lName, ['.js', '.css', '.html']);
            lResult = lMin && lCheck;

            Util.ifExec(!lResult,
                function(pParams) {
                    var lSendName = pParams && pParams.name || lName;

                    main.sendFile({
                        name        : lSendName,
                        cache       : lConfig.cache,
                        gzip        : true,
                        request     : pReq,
                        response    : pRes
                    });
            }, function(pCallBack) {
                Minify.optimize(lName, {
                    callback    : pCallBack,
                    returnName  : true
                });
            });
        }
    }

    function minify(name) {
        return function(callback) {
            Minify.optimize(name, {
                callback    : callback
            });
        };
    }

    function combine(params) {
        var names, i, n, name, minName, stream,
            funcs       = [],
            config      = main.config,
            dir         = DIR,
            gzip        = zlib.createGzip(),
            p           = params,
            isGzip      = main.isGZIP(p.request),
            path        = params.name,
            COMBINE     = '/combine/',
            isCombine   = Util.isContainStrAtBegin(path, COMBINE),
            readPipe    = function() {
                main.mainSetHeader({
                    name        : names[0],
                    cache       : config.cache,
                    gzip        : isGzip,
                    request     : p.request,
                    response    : p.response
                });

                if (!isGzip)
                    stream = p.response;
                else
                    stream = gzip;

                files.readPipe({
                    names       : names,
                    dir         : dir,
                    write       : stream,
                    callback    : function(error) {
                        if (error)
                            main.sendError(params, error);
                    }
                });

                if (isGzip)
                    gzip.pipe(p.response);
            };

        if (isCombine) {
            path        = Util.removeStrOneTime(path, COMBINE);
            names       = path.split(':');
            n           = names.length;

            if (!config.minify)
                readPipe();
            else {
                for (i = 0; i < n; i++) {
                    name        = Path.join(DIR, names[i]);
                    minName     = Minify.getName(name);

                    if (name !== minName) {
                        names[i] = minName;
                        dir = '';
                    }

                    funcs.push(minify(name));
                }
                Util.asyncCall(funcs, readPipe);
            }
        }

        return isCombine;
    }

    exports.start           = start;

})();
<commit_msg>feature(server) add checkExtension<commit_after>(function() {
    'use strict';

    if (!global.cloudcmd)
        return console.log(
             '# server.js'                                      + '\n'  +
             '# -----------'                                    + '\n'  +
             '# Module is part of Cloud Commander,'             + '\n'  +
             '# easy to use web server.'                        + '\n'  +
             '# http://cloudcmd.io'                             + '\n');

    var main                = global.cloudcmd.main,

        DIR                 = main.DIR,
        LIBDIR              = main.LIBDIR,
        SRVDIR              = main.SRVDIR,

        URL                 = main.url,
        Path                = main.path,
        Querystring         = main.querystring,

        Minify              = main.minify,
        CloudFunc           = main.cloudfunc,
        AppCache            = main.appcache,
        Socket              = main.socket,

        zlib                = main.zlib,
        http                = main.http,
        https               = main.https,
        Util                = main.util,
        express             = main.express,
        expressApp          = express.getApp(controller),
        files               = main.files,

        Server, Rest, Route;

    /* базовая инициализация  */
    function init(pAppCachProcessing) {
        var config = main.config;

        /* создаём файл app cache */
        if (config.appcache  && AppCache && config.server )
            Util.exec( pAppCachProcessing );
    }

    /**
     * start server function
     * @param pConfig
     * @param pProcessing {index, appcache, rest}
     */
    function start(pProcessing) {
        var lConfig         = main.config;

        if (!pProcessing)
            pProcessing = {};

        Rest            =   pProcessing.rest;
        Route           =   pProcessing.route;

        init(pProcessing.appcache);

        var lPort       =   process.env.PORT            ||  /* c9           */
                            process.env.app_port        ||  /* nodester     */
                            process.env.VCAP_APP_PORT   ||  /* cloudfoundry */
                            lConfig.port,

            lIP         =   process.env.IP              ||  /* c9           */
                            lConfig.ip                  ||
                            (main.WIN32 ? '127.0.0.1' : '0.0.0.0'),

            lSSL        = pProcessing.ssl,
            lSSLPort    = lConfig.sslPort,
            lHTTP       = 'http://',
            lHTTPS      = 'https://',

            lSockets    = function(pServer) {
                var lListen, msg, status;

                if (lConfig.socket && Socket)
                    lListen = Socket.listen(pServer);

                status  = lListen ? 'on' : 'off';
                msg     = CloudFunc.formatMsg('sockets', '', status);

                Util.log(msg);
            },

            lHTTPServer = function() {
                Server =  http.createServer(expressApp || controller);
                Server.on('error', Util.log);
                Server.listen(lPort, lIP);
                lServerLog(lHTTP, lPort);
                lSockets(Server);
            },

            lServerLog  = function(pHTTP, pPort) {
                Util.log('* Server running at ' + pHTTP + lIP + ':' + pPort);
            };
        /* server mode or testing mode */
        if (lConfig.server) {
            if (lSSL) {
                Util.log('* Redirection http -> https is setted up');
                lServerLog(lHTTP, lPort);
                var lRedirectServer =  http.createServer( function(pReq, pRes) {
                     var lURL,
                        lHost       = pReq.headers.host,
                        lParsed     = URL.parse(lHost),
                        lHostName   = lParsed.protocol;

                    lURL            = lHTTPS + lHostName + lSSLPort + pReq.url;

                    main.redirect({
                        response: pRes,
                        url: lURL
                    });
                });

                lRedirectServer.listen(lPort, lIP);

                Server  =  https.createServer(lSSL, controller);
                Server.on('error', function (pError) {
                    Util.log('Could not use https port: ' + lSSLPort);
                    Util.log(pError);
                    lRedirectServer.close();
                    Util.log('* Redirection http -> https removed');
                    lHTTPServer();
                });

                lSockets(Server);

                Server.listen(lSSLPort, lIP);
                lServerLog(lHTTPS, lSSLPort);
            } else
                lHTTPServer();
        } else
            Util.log('Cloud Commander testing mode');
    }

    /**
     * Главная функция, через которую проихсодит
     * взаимодействие, обмен данными с клиентом
     * @param req - запрос клиента (Request)
     * @param res - ответ сервера (Response)
     */
    function controller(pReq, pRes) {
        /* Читаем содержимое папки, переданное в url */
        var lRet, lName, lMin, lCheck, lResult,
            lConfig     = main.config,
            lParsedUrl  = URL.parse(pReq.url),
            lQuery      = lParsedUrl.search || '',
            lPath       = lParsedUrl.pathname;

        /* added supporting of Russian language in directory names */
        lPath = Querystring.unescape(lPath);

        if (!expressApp)
            Util.log(pReq.method + ' ' + lPath + lQuery);

        var lData = {
            name        : lPath,
            request     : pReq,
            response    : pRes
        };

        if (lConfig.rest )
            lRet = Util.exec(Rest, lData);

        if (!lRet && Route)
            lRet = Util.exec(Route, lData);

        if (!lRet)
            lRet = combine(lData);

        if (!lRet) {
            lName = lData.name;

            /* watching is file changed */
            if (lConfig.appcache)
                AppCache.watch(lName);

            lName   = Path.join(DIR, lName);
            lMin    = lConfig.minify,
            lCheck  = checkExtension(lName);
            lResult = lMin && lCheck;

            Util.ifExec(!lResult,
                function(pParams) {
                    var lSendName = pParams && pParams.name || lName;

                    main.sendFile({
                        name        : lSendName,
                        cache       : lConfig.cache,
                        gzip        : true,
                        request     : pReq,
                        response    : pRes
                    });
            }, function(pCallBack) {
                Minify.optimize(lName, {
                    callback    : pCallBack,
                    returnName  : true
                });
            });
        }
    }

    function minify(name) {
        return function(callback) {
            Minify.optimize(name, {
                callback    : callback
            });
        };
    }

    function combine(params) {
        var names, i, n, name, minName, stream, check,
            funcs       = [],
            config      = main.config,
            dir         = DIR,
            gzip        = zlib.createGzip(),
            p           = params,
            isGzip      = main.isGZIP(p.request),
            path        = params.name,
            COMBINE     = '/combine/',
            isCombine   = Util.isContainStrAtBegin(path, COMBINE),
            readPipe    = function() {
                main.mainSetHeader({
                    name        : names[0],
                    cache       : config.cache,
                    gzip        : isGzip,
                    request     : p.request,
                    response    : p.response
                });

                if (!isGzip)
                    stream = p.response;
                else
                    stream = gzip;

                files.readPipe({
                    names       : names,
                    dir         : dir,
                    write       : stream,
                    callback    : function(error) {
                        if (error)
                            main.sendError(params, error);
                    }
                });

                if (isGzip)
                    gzip.pipe(p.response);
            };

        if (isCombine) {
            path        = Util.removeStrOneTime(path, COMBINE);
            names       = path.split(':');
            n           = names.length;

            if (!config.minify)
                readPipe();
            else {
                for (i = 0; i < n; i++) {
                    name        = Path.join(DIR, names[i]);
                    check       = checkExtension(name);

                    if (check) {
                        minName = Minify.getName(name);

                        if (name !== minName) {
                            names[i] = minName;
                            dir = '';
                        }
                    }

                    funcs.push(minify(name));
                }
                Util.asyncCall(funcs, readPipe);
            }
        }

        return isCombine;
    }

    function checkExtension(name) {
        var ret;

        ret = Util.checkExtension(name, ['.js', '.css', '.html']);

        return ret;c
    }

    exports.start           = start;

})();
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.crunch.ruler',
  name: 'SetUCJStatusOnPut',

  implements: [
    'foam.nanos.ruler.RuleAction'
  ],

  javaImports: [
    'foam.core.ContextAgent',
    'foam.core.X',
    'foam.dao.ArraySink',
    'foam.dao.DAO',
    'foam.nanos.crunch.Capability',
    'foam.nanos.crunch.CapabilityCapabilityJunction',
    'foam.nanos.crunch.CapabilityJunctionStatus',
    'foam.nanos.crunch.UserCapabilityJunction',
    'java.util.List',
    'static foam.mlang.MLang.*'
  ],

  methods: [
    {
      name: 'applyAction',
      javaCode: `
        agency.submit(x, new ContextAgent() {
          X systemX = ruler.getX();
          @Override
          public void execute(X x) {
            UserCapabilityJunction ucj = (UserCapabilityJunction) obj;

            CapabilityJunctionStatus chainedStatus = checkPrereqsChainedStatus(x, ucj);

            if ( ucj.getStatus() != CapabilityJunctionStatus.PENDING && ucj.getStatus() != CapabilityJunctionStatus.APPROVED ) return;

            // the following should be checked if the result of previous rule ( validateUCJDataOnPut )
            // is not ACTION_REQUIRED. In the ACTION_REQUIRED case, the ucj should be put into the
            // dao without any additional checks

            Capability capability = (Capability) ucj.findTargetId(systemX);

            boolean reviewRequired = capability.getReviewRequired();
            boolean wasApproved = ucj.getStatus() == CapabilityJunctionStatus.APPROVED;

            // Update current UCJ status

            ucj.setStatus(chainedStatus);
            if ( chainedStatus == CapabilityJunctionStatus.PENDING && reviewRequired && wasApproved ) {
              ucj.setStatus(CapabilityJunctionStatus.APPROVED);
            } else if ( chainedStatus == CapabilityJunctionStatus.GRANTED && reviewRequired ) {
              ucj.setStatus(wasApproved ? CapabilityJunctionStatus.GRANTED : CapabilityJunctionStatus.PENDING);
            }
          }
        }, "set ucj status on put");
      `
    },
    {
      name: 'checkPrereqsChainedStatus',
      args: [
        {
          name: 'x',
          type: 'Context'
        },
        {
          name: 'ucj',
          type: 'foam.nanos.crunch.UserCapabilityJunction'
        }
      ],
      type: 'CapabilityJunctionStatus',
      documentation: `
        Check statuses of all prerequisite capabilities - returning:
        GRANTED: If all pre-reqs are in granted status
        PENDING: At least one pre-req is still in pending status
        ACTION_REQUIRED: If not any of the above
      `,
      javaCode: `
        boolean allGranted = true;
        DAO userCapabilityJunctionDAO = (DAO) x.get("userCapabilityJunctionDAO");
        DAO capabilityDAO = (DAO) x.get("capabilityDAO");
        Capability cap = (Capability) capabilityDAO.find(ucj.getTargetId());
        return cap.getPrereqsChainedStatus(x, ucj);
      `
    },
    {
      name: 'getPrereqs',
      args: [
        {
          name: 'x',
          type: 'Context'
        },
        {
          name: 'ucj',
          type: 'foam.nanos.crunch.UserCapabilityJunction'
        }
      ],
      javaType: 'java.util.List<CapabilityCapabilityJunction>',
      documentation: `
        Returns the list of prerequisiteCapabilityJunctions for the target capability of the ucj
      `,
      javaCode: `
        DAO prerequisiteCapabilityJunctionDAO = (DAO) x.get("prerequisiteCapabilityJunctionDAO");

        // get a list of the prerequisite junctions where the current capability is the dependent
        List<CapabilityCapabilityJunction> ccJunctions = (List<CapabilityCapabilityJunction>) ((ArraySink) prerequisiteCapabilityJunctionDAO
        .where(EQ(CapabilityCapabilityJunction.SOURCE_ID, ucj.getTargetId()))
        .select(new ArraySink()))
        .getArray();

        return ccJunctions;
      `
    },
  ]
});
<commit_msg>remove unused code<commit_after>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.crunch.ruler',
  name: 'SetUCJStatusOnPut',

  implements: [
    'foam.nanos.ruler.RuleAction'
  ],

  javaImports: [
    'foam.core.ContextAgent',
    'foam.core.X',
    'foam.dao.ArraySink',
    'foam.dao.DAO',
    'foam.nanos.crunch.Capability',
    'foam.nanos.crunch.CapabilityCapabilityJunction',
    'foam.nanos.crunch.CapabilityJunctionStatus',
    'foam.nanos.crunch.UserCapabilityJunction',
    'java.util.List',
    'static foam.mlang.MLang.*'
  ],

  methods: [
    {
      name: 'applyAction',
      javaCode: `
        agency.submit(x, new ContextAgent() {
          X systemX = ruler.getX();
          @Override
          public void execute(X x) {
            UserCapabilityJunction ucj = (UserCapabilityJunction) obj;

            CapabilityJunctionStatus chainedStatus = checkPrereqsChainedStatus(x, ucj);

            if ( ucj.getStatus() != CapabilityJunctionStatus.PENDING && ucj.getStatus() != CapabilityJunctionStatus.APPROVED ) return;

            // the following should be checked if the result of previous rule ( validateUCJDataOnPut )
            // is not ACTION_REQUIRED. In the ACTION_REQUIRED case, the ucj should be put into the
            // dao without any additional checks

            Capability capability = (Capability) ucj.findTargetId(systemX);

            boolean reviewRequired = capability.getReviewRequired();
            boolean wasApproved = ucj.getStatus() == CapabilityJunctionStatus.APPROVED;

            // Update current UCJ status

            ucj.setStatus(chainedStatus);
            if ( chainedStatus == CapabilityJunctionStatus.PENDING && reviewRequired && wasApproved ) {
              ucj.setStatus(CapabilityJunctionStatus.APPROVED);
            } else if ( chainedStatus == CapabilityJunctionStatus.GRANTED && reviewRequired ) {
              ucj.setStatus(wasApproved ? CapabilityJunctionStatus.GRANTED : CapabilityJunctionStatus.PENDING);
            }
          }
        }, "set ucj status on put");
      `
    },
    {
      name: 'checkPrereqsChainedStatus',
      args: [
        {
          name: 'x',
          type: 'Context'
        },
        {
          name: 'ucj',
          type: 'foam.nanos.crunch.UserCapabilityJunction'
        }
      ],
      type: 'CapabilityJunctionStatus',
      documentation: `
        Check statuses of all prerequisite capabilities - returning:
        GRANTED: If all pre-reqs are in granted status
        PENDING: At least one pre-req is still in pending status
        ACTION_REQUIRED: If not any of the above
      `,
      javaCode: `
        DAO userCapabilityJunctionDAO = (DAO) x.get("userCapabilityJunctionDAO");
        DAO capabilityDAO = (DAO) x.get("capabilityDAO");
        Capability cap = (Capability) capabilityDAO.find(ucj.getTargetId());
        return cap.getPrereqsChainedStatus(x, ucj);
      `
    },
    {
      name: 'getPrereqs',
      args: [
        {
          name: 'x',
          type: 'Context'
        },
        {
          name: 'ucj',
          type: 'foam.nanos.crunch.UserCapabilityJunction'
        }
      ],
      javaType: 'java.util.List<CapabilityCapabilityJunction>',
      documentation: `
        Returns the list of prerequisiteCapabilityJunctions for the target capability of the ucj
      `,
      javaCode: `
        DAO prerequisiteCapabilityJunctionDAO = (DAO) x.get("prerequisiteCapabilityJunctionDAO");

        // get a list of the prerequisite junctions where the current capability is the dependent
        List<CapabilityCapabilityJunction> ccJunctions = (List<CapabilityCapabilityJunction>) ((ArraySink) prerequisiteCapabilityJunctionDAO
        .where(EQ(CapabilityCapabilityJunction.SOURCE_ID, ucj.getTargetId()))
        .select(new ArraySink()))
        .getArray();

        return ccJunctions;
      `
    },
  ]
});
<|endoftext|>


<commit_before>// Copyright 2016 the project authors as listed in the AUTHORS file.
// All rights reserved. Use of this source code is governed by the
// license that can be found in the LICENSE file.
"use strict";
const fs = require('fs');
const https = require('https');
const mqtt = require('mqtt');
const notify = require('micro-app-notify-client');
const path = require('path');
const socketio = require('socket.io');
const twilio = require('twilio');

///////////////////////////////////////////////
// micro-app framework methods
///////////////////////////////////////////////
const Server = function() {
}

Server.getDefaults = function() {
  return { 'title': 'Cooking with Node' };
}

Server.handleSupportingPages = function(request, response) {
  if (request.url.indexOf("warnSound") > -1) {
    const soundFile = fs.readFileSync(Server.config.warnSound);
    response.writeHead(200, {'Content-Type': 'text/html'});
    response.end(soundFile);
    return true;
  } else if (request.url.indexOf("targetSound") > -1) {
    const soundFile = fs.readFileSync(Server.config.targetSound);
    response.writeHead(200, {'Content-Type': 'text/html'});
    response.end(soundFile);
    return true;
  } else if (request.url.indexOf('skin.css') > -1) {
    const cssFile = fs.readFileSync(Server.config.skin);
    response.writeHead(200, {'Content-Type': 'text/css'});
    response.end(cssFile);
    return true;
  }
  return false;
}

let replacements;
Server.getTemplateReplacments = function() {
  if (replacements === undefined) {
    const config = Server.config;

    replacements = [{ 'key': '<DASHBOARD_TITLE>', 'value': config.title },
                    { 'key': '<UNIQUE_WINDOW_ID>', 'value': config.title },
                    { 'key': '<PAGE_WIDTH>', 'value': Server.config.windowSize.y },
                    { 'key': '<PAGE_HEIGHT>', 'value': Server.config.windowSize.x }];

  }
  return replacements;
}

const toF = function(temp) {
  return Math.ceil((temp*1.8 + 32));
}

const toC = function(temp) {
  return parseFloat(((temp -32)/1.8).toFixed(2));
}

const convertTemp = function(scaleC, temp) {
  if (scaleC) {
    return parseFloat(temp.toFixed(2));
  } else {
    return toF(temp);
  }
}

const getDefaultTempShift = function(config) {
  return config.defaultTempShift || -17;
}

Server.startServer = function(server) {
  const config = Server.config;
//  let currentTemp = 0;
  const probes = new Object();
  const probesHistory = new Object();

  // set defaults
  if (config.warn === undefined) {
    config.warn = 5.6;
  }

  if (config.warnSound === undefined) {
    config.warnSound = path.join(__dirname,'alert-temp.mp3');
  }

  if (config.targetSound === undefined) {
    config.targetSound = path.join(__dirname,'target-temp.mp3');
  }

  if (config.skin === undefined) {
    config.skin = path.join(__dirname,'skin.css');
  }

  let scaleC = config.scaleC;
  if (scaleC === undefined) {
    scaleC = true;
  }

  if (config.estimateWindow === undefined) {
    config.estimateWindow = 10;
  }

  const toF = function(temp) {
    return Math.ceil((temp*1.8 + 32));
  }

  const calculateRemainingTime = function(history) {
    let remainingTime = '?';
    const historyLength = history.temps.length;
    const lastMeasurementTime = history.timestamps[historyLength - 1];
    const windowStart = lastMeasurementTime - config.estimateWindow * 60;
    const currentTemp = history.temps[historyLength -1];
    const degreesRemaining = history.targets[historyLength - 1] - currentTemp;
    if ((degreesRemaining > 0) && (historyLength > 1)) {
      let tempAtWindowStart = 0;
      let timeAtWindowStart = 0;
      for (let i = historyLength -2; i >= 0; i = i -1) {
        if (history.timestamps[i] > windowStart) {
          tempAtWindowStart = history.temps[i];
          timeAtWindowStart = history.timestamps[i];
        } else {
          break;
        }
      }
      const tempChangeOverWindow = currentTemp - tempAtWindowStart;
      const measurementTime = lastMeasurementTime - timeAtWindowStart;
      if (tempChangeOverWindow > 0) {
        // simple linear prediciton based on change over last window
        remainingTime = (degreesRemaining/
                          (tempChangeOverWindow/(measurementTime/60))).toFixed(0);
      }
    }
    return remainingTime;
  }

  // if we are in test mode add the initial test probes
  if (config.test) {
    require('./test-probes.js')(probes, probesHistory, scaleC);
  }

  const targetTemps = new Object();
  for (let i = 0; i < config.targetTemps.length; i++) {
    const meatTemps = new Object;
    for (let j = 0; j < config.targetTemps[i].temps.length; j++) {
      const key = Object.keys(config.targetTemps[i].temps[j]);
      meatTemps[key] = config.targetTemps[i].temps[j][key];
    }
    targetTemps[config.targetTemps[i].name] = meatTemps;
  }

  const eventSocket = socketio.listen(server);

  // setup mqtt
  let mqttOptions;
  if (config.mqtt.serverUrl.indexOf('mqtts') > -1) {
    mqttOptions = { key: fs.readFileSync(path.join(__dirname, 'mqttclient', '/client.key')),
                    cert: fs.readFileSync(path.join(__dirname, 'mqttclient', '/client.cert')),
                    ca: fs.readFileSync(path.join(__dirname, 'mqttclient', '/ca.cert')),
                    checkServerIdentity: function() { return undefined }
    }
  }
  const mqttClient = mqtt.connect(config.mqtt.serverUrl, mqttOptions);

  mqttClient.on('connect',function() {
    mqttClient.subscribe(config.mqtt.mqttTopic);
  });

  const SANITY_TEMP = 300;
  mqttClient.on('message', function(topic, message) {
    // decode the message
    message = message.toString();
    const TEMP_PREFIX = 'temp: '
    const deviceId = message.substring(message.indexOf('[') + 1, message.indexOf(']'));
    const temp = parseFloat(message.substring(message.indexOf(TEMP_PREFIX) + TEMP_PREFIX.length));
    const timestamp = new Date().getTime()/1000;

    if (temp <= SANITY_TEMP) {
      let deviceEntry = probes[deviceId];
      if (deviceEntry === undefined) {
        let tempShiftAmount = 0;
        if( config.shiftTemp) {
          tempShiftAmount = getDefaultTempShift(config);
        };
        deviceEntry = {type: 'temp', id: deviceId, temp: temp + tempShiftAmount, timestamp: timestamp,
                       meat: 'beef', taste: 'medium', scaleC: scaleC,
                       shiftTemp: config.shiftTemp || false, tempShiftAmount: tempShiftAmount };
        probes[deviceId] = deviceEntry;
        probesHistory[deviceId] = { timestamps: [timestamp], temps: [temp], targets: [] };
      } else {
        deviceEntry.temp = temp + deviceEntry.tempShiftAmount;
        deviceEntry.timestamp = timestamp;
        probesHistory[deviceId].timestamps.push(timestamp);
        probesHistory[deviceId].temps.push(temp + deviceEntry.tempShift);
      }
      deviceEntry.target = targetTemps[deviceEntry.meat][deviceEntry.taste];
      probesHistory[deviceId].targets.push(deviceEntry.target);
      deviceEntry.estimate = calculateRemainingTime(probesHistory[deviceId]);

      eventSocket.emit('data', deviceEntry);
    }
  });

  eventSocket.on('connection', function(ioclient) {
    eventSocket.to(ioclient.id).emit('tastes', config.targetTemps);
    eventSocket.to(ioclient.id).emit('cleanup-all');
    eventSocket.to(ioclient.id).emit('chartData', probesHistory);
    for (let deviceId in probes) {
      if (probes.hasOwnProperty(deviceId)) {
        eventSocket.to(ioclient.id).emit('data', probes[deviceId]);
      }
    }

    ioclient.on('new-meat', function(deviceId, meat) {
      probes[deviceId].meat = meat;
      let newTarget = targetTemps[meat][probes[deviceId].taste];
      if (newTarget === undefined) {
        const taste = Object.keys(targetTemps[meat])[0];
        newTarget = targetTemps[meat][taste];
        probes[deviceId].taste = taste;
      }
      probes[deviceId].target = newTarget;

      eventSocket.emit('data', probes[deviceId]);
    });

    ioclient.on('new-taste', function(deviceId, taste) {
      const meat = probes[deviceId].meat;
      let newTarget = targetTemps[meat][taste];
      if (newTarget === undefined) {
        taste = Object.keys(targetTemps[meat])[0];
        newTarget = targetTemps[meat][taste];
      }
      probes[deviceId].taste = taste;
      probes[deviceId].target = newTarget;

      eventSocket.emit('data', probes[deviceId]);
    });

    ioclient.on('scaleC', function(deviceId, scaleC) {
      if (probes[deviceId].scaleC != scaleC) {
        probes[deviceId].scaleC = scaleC;
        eventSocket.emit('data', probes[deviceId]);
      }
    });

    ioclient.on('shift', function(deviceId, shiftTemp) {
      if (probes[deviceId].shiftTemp !== shiftTemp) {
        probes[deviceId].shiftTemp = shiftTemp;
        if (shiftTemp) {
          probes[deviceId].tempShiftAmount = getDefaultTempShift(config);
          probes[deviceId].temp = probes[deviceId].temp + probes[deviceId].tempShiftAmount;
        } else {
          probes[deviceId].temp = probes[deviceId].temp - probes[deviceId].tempShiftAmount;
          probes[deviceId].tempShiftAmount = 0;
        }
        eventSocket.emit('data', probes[deviceId]);
      }
    });
  });

  // setup timer to do cleanup and threshold checks
  setInterval(function() {
    for (let deviceId in probes) {
      if (probes.hasOwnProperty(deviceId)) {
        // when a probe is active we'll get updates regularly.  if we
        // don't get data for config.cleanupInterval then assume probe
        // was turned off and stop showing it
        const currentTime = (new Date()).getTime()/1000;
        if ((probes[deviceId].timestamp + config.cleanupInterval) < currentTime) {
          eventSocket.emit('cleanup', probes[deviceId]);
          delete probes[deviceId];
          delete probesHistory[deviceId];
        } else if (probes[deviceId].status !== 'alert') {
          if (probes[deviceId].temp >= probes[deviceId].target) {
            probes[deviceId].status = 'alert';
            eventSocket.emit('data', probes[deviceId]);

            // send out other alerts
            const alertMessage = deviceId + ': at target temp';
            notify.sendNotification(config, alertMessage);
          } else if ((probes[deviceId].status !== 'warn') &&
                     ((probes[deviceId].temp + config.warn) >= probes[deviceId].target)) {
            probes[deviceId].status = 'warn';
            eventSocket.emit('data', probes[deviceId]);

            // send out other alerts
            const warnMessage = deviceId + ': ' + convertTemp(probes[deviceId].scaleC, config.warn) + ' degrees to go';
            notify.sendNotification(config, warnMessage);
          }
        }
      }
    }
  }, 5 * 1000);
};

if (require.main === module) {
  const microAppFramework = require('micro-app-framework');
  microAppFramework(path.join(__dirname), Server);
}

module.exports = Server;
<commit_msg>src: remove unused variable<commit_after>// Copyright 2016 the project authors as listed in the AUTHORS file.
// All rights reserved. Use of this source code is governed by the
// license that can be found in the LICENSE file.
"use strict";
const fs = require('fs');
const https = require('https');
const mqtt = require('mqtt');
const notify = require('micro-app-notify-client');
const path = require('path');
const socketio = require('socket.io');
const twilio = require('twilio');

///////////////////////////////////////////////
// micro-app framework methods
///////////////////////////////////////////////
const Server = function() {
}

Server.getDefaults = function() {
  return { 'title': 'Cooking with Node' };
}

Server.handleSupportingPages = function(request, response) {
  if (request.url.indexOf("warnSound") > -1) {
    const soundFile = fs.readFileSync(Server.config.warnSound);
    response.writeHead(200, {'Content-Type': 'text/html'});
    response.end(soundFile);
    return true;
  } else if (request.url.indexOf("targetSound") > -1) {
    const soundFile = fs.readFileSync(Server.config.targetSound);
    response.writeHead(200, {'Content-Type': 'text/html'});
    response.end(soundFile);
    return true;
  } else if (request.url.indexOf('skin.css') > -1) {
    const cssFile = fs.readFileSync(Server.config.skin);
    response.writeHead(200, {'Content-Type': 'text/css'});
    response.end(cssFile);
    return true;
  }
  return false;
}

let replacements;
Server.getTemplateReplacments = function() {
  if (replacements === undefined) {
    const config = Server.config;

    replacements = [{ 'key': '<DASHBOARD_TITLE>', 'value': config.title },
                    { 'key': '<UNIQUE_WINDOW_ID>', 'value': config.title },
                    { 'key': '<PAGE_WIDTH>', 'value': Server.config.windowSize.y },
                    { 'key': '<PAGE_HEIGHT>', 'value': Server.config.windowSize.x }];

  }
  return replacements;
}

const toF = function(temp) {
  return Math.ceil((temp*1.8 + 32));
}

const toC = function(temp) {
  return parseFloat(((temp -32)/1.8).toFixed(2));
}

const convertTemp = function(scaleC, temp) {
  if (scaleC) {
    return parseFloat(temp.toFixed(2));
  } else {
    return toF(temp);
  }
}

const getDefaultTempShift = function(config) {
  return config.defaultTempShift || -17;
}

Server.startServer = function(server) {
  const config = Server.config;
  const probes = new Object();
  const probesHistory = new Object();

  // set defaults
  if (config.warn === undefined) {
    config.warn = 5.6;
  }

  if (config.warnSound === undefined) {
    config.warnSound = path.join(__dirname,'alert-temp.mp3');
  }

  if (config.targetSound === undefined) {
    config.targetSound = path.join(__dirname,'target-temp.mp3');
  }

  if (config.skin === undefined) {
    config.skin = path.join(__dirname,'skin.css');
  }

  let scaleC = config.scaleC;
  if (scaleC === undefined) {
    scaleC = true;
  }

  if (config.estimateWindow === undefined) {
    config.estimateWindow = 10;
  }

  const toF = function(temp) {
    return Math.ceil((temp*1.8 + 32));
  }

  const calculateRemainingTime = function(history) {
    let remainingTime = '?';
    const historyLength = history.temps.length;
    const lastMeasurementTime = history.timestamps[historyLength - 1];
    const windowStart = lastMeasurementTime - config.estimateWindow * 60;
    const currentTemp = history.temps[historyLength -1];
    const degreesRemaining = history.targets[historyLength - 1] - currentTemp;
    if ((degreesRemaining > 0) && (historyLength > 1)) {
      let tempAtWindowStart = 0;
      let timeAtWindowStart = 0;
      for (let i = historyLength -2; i >= 0; i = i -1) {
        if (history.timestamps[i] > windowStart) {
          tempAtWindowStart = history.temps[i];
          timeAtWindowStart = history.timestamps[i];
        } else {
          break;
        }
      }
      const tempChangeOverWindow = currentTemp - tempAtWindowStart;
      const measurementTime = lastMeasurementTime - timeAtWindowStart;
      if (tempChangeOverWindow > 0) {
        // simple linear prediciton based on change over last window
        remainingTime = (degreesRemaining/
                          (tempChangeOverWindow/(measurementTime/60))).toFixed(0);
      }
    }
    return remainingTime;
  }

  // if we are in test mode add the initial test probes
  if (config.test) {
    require('./test-probes.js')(probes, probesHistory, scaleC);
  }

  const targetTemps = new Object();
  for (let i = 0; i < config.targetTemps.length; i++) {
    const meatTemps = new Object;
    for (let j = 0; j < config.targetTemps[i].temps.length; j++) {
      const key = Object.keys(config.targetTemps[i].temps[j]);
      meatTemps[key] = config.targetTemps[i].temps[j][key];
    }
    targetTemps[config.targetTemps[i].name] = meatTemps;
  }

  const eventSocket = socketio.listen(server);

  // setup mqtt
  let mqttOptions;
  if (config.mqtt.serverUrl.indexOf('mqtts') > -1) {
    mqttOptions = { key: fs.readFileSync(path.join(__dirname, 'mqttclient', '/client.key')),
                    cert: fs.readFileSync(path.join(__dirname, 'mqttclient', '/client.cert')),
                    ca: fs.readFileSync(path.join(__dirname, 'mqttclient', '/ca.cert')),
                    checkServerIdentity: function() { return undefined }
    }
  }
  const mqttClient = mqtt.connect(config.mqtt.serverUrl, mqttOptions);

  mqttClient.on('connect',function() {
    mqttClient.subscribe(config.mqtt.mqttTopic);
  });

  const SANITY_TEMP = 300;
  mqttClient.on('message', function(topic, message) {
    // decode the message
    message = message.toString();
    const TEMP_PREFIX = 'temp: '
    const deviceId = message.substring(message.indexOf('[') + 1, message.indexOf(']'));
    const temp = parseFloat(message.substring(message.indexOf(TEMP_PREFIX) + TEMP_PREFIX.length));
    const timestamp = new Date().getTime()/1000;

    if (temp <= SANITY_TEMP) {
      let deviceEntry = probes[deviceId];
      if (deviceEntry === undefined) {
        let tempShiftAmount = 0;
        if( config.shiftTemp) {
          tempShiftAmount = getDefaultTempShift(config);
        };
        deviceEntry = {type: 'temp', id: deviceId, temp: temp + tempShiftAmount, timestamp: timestamp,
                       meat: 'beef', taste: 'medium', scaleC: scaleC,
                       shiftTemp: config.shiftTemp || false, tempShiftAmount: tempShiftAmount };
        probes[deviceId] = deviceEntry;
        probesHistory[deviceId] = { timestamps: [timestamp], temps: [temp], targets: [] };
      } else {
        deviceEntry.temp = temp + deviceEntry.tempShiftAmount;
        deviceEntry.timestamp = timestamp;
        probesHistory[deviceId].timestamps.push(timestamp);
        probesHistory[deviceId].temps.push(temp + deviceEntry.tempShift);
      }
      deviceEntry.target = targetTemps[deviceEntry.meat][deviceEntry.taste];
      probesHistory[deviceId].targets.push(deviceEntry.target);
      deviceEntry.estimate = calculateRemainingTime(probesHistory[deviceId]);

      eventSocket.emit('data', deviceEntry);
    }
  });

  eventSocket.on('connection', function(ioclient) {
    eventSocket.to(ioclient.id).emit('tastes', config.targetTemps);
    eventSocket.to(ioclient.id).emit('cleanup-all');
    eventSocket.to(ioclient.id).emit('chartData', probesHistory);
    for (let deviceId in probes) {
      if (probes.hasOwnProperty(deviceId)) {
        eventSocket.to(ioclient.id).emit('data', probes[deviceId]);
      }
    }

    ioclient.on('new-meat', function(deviceId, meat) {
      probes[deviceId].meat = meat;
      let newTarget = targetTemps[meat][probes[deviceId].taste];
      if (newTarget === undefined) {
        const taste = Object.keys(targetTemps[meat])[0];
        newTarget = targetTemps[meat][taste];
        probes[deviceId].taste = taste;
      }
      probes[deviceId].target = newTarget;

      eventSocket.emit('data', probes[deviceId]);
    });

    ioclient.on('new-taste', function(deviceId, taste) {
      const meat = probes[deviceId].meat;
      let newTarget = targetTemps[meat][taste];
      if (newTarget === undefined) {
        taste = Object.keys(targetTemps[meat])[0];
        newTarget = targetTemps[meat][taste];
      }
      probes[deviceId].taste = taste;
      probes[deviceId].target = newTarget;

      eventSocket.emit('data', probes[deviceId]);
    });

    ioclient.on('scaleC', function(deviceId, scaleC) {
      if (probes[deviceId].scaleC != scaleC) {
        probes[deviceId].scaleC = scaleC;
        eventSocket.emit('data', probes[deviceId]);
      }
    });

    ioclient.on('shift', function(deviceId, shiftTemp) {
      if (probes[deviceId].shiftTemp !== shiftTemp) {
        probes[deviceId].shiftTemp = shiftTemp;
        if (shiftTemp) {
          probes[deviceId].tempShiftAmount = getDefaultTempShift(config);
          probes[deviceId].temp = probes[deviceId].temp + probes[deviceId].tempShiftAmount;
        } else {
          probes[deviceId].temp = probes[deviceId].temp - probes[deviceId].tempShiftAmount;
          probes[deviceId].tempShiftAmount = 0;
        }
        eventSocket.emit('data', probes[deviceId]);
      }
    });
  });

  // setup timer to do cleanup and threshold checks
  setInterval(function() {
    for (let deviceId in probes) {
      if (probes.hasOwnProperty(deviceId)) {
        // when a probe is active we'll get updates regularly.  if we
        // don't get data for config.cleanupInterval then assume probe
        // was turned off and stop showing it
        const currentTime = (new Date()).getTime()/1000;
        if ((probes[deviceId].timestamp + config.cleanupInterval) < currentTime) {
          eventSocket.emit('cleanup', probes[deviceId]);
          delete probes[deviceId];
          delete probesHistory[deviceId];
        } else if (probes[deviceId].status !== 'alert') {
          if (probes[deviceId].temp >= probes[deviceId].target) {
            probes[deviceId].status = 'alert';
            eventSocket.emit('data', probes[deviceId]);

            // send out other alerts
            const alertMessage = deviceId + ': at target temp';
            notify.sendNotification(config, alertMessage);
          } else if ((probes[deviceId].status !== 'warn') &&
                     ((probes[deviceId].temp + config.warn) >= probes[deviceId].target)) {
            probes[deviceId].status = 'warn';
            eventSocket.emit('data', probes[deviceId]);

            // send out other alerts
            const warnMessage = deviceId + ': ' + convertTemp(probes[deviceId].scaleC, config.warn) + ' degrees to go';
            notify.sendNotification(config, warnMessage);
          }
        }
      }
    }
  }, 5 * 1000);
};

if (require.main === module) {
  const microAppFramework = require('micro-app-framework');
  microAppFramework(path.join(__dirname), Server);
}

module.exports = Server;
<|endoftext|>