Show:
                            var DiagramNode,
                            
                                adjustDiagramNodeOffset = function(diagramNode, offsetXY) {
                                    var dnXY = A.Lang.isArray(diagramNode) ? diagramNode : diagramNode.get('boundingBox').getXY();
                            
                                    return [dnXY[0] + offsetXY[0], dnXY[1] + offsetXY[1]];
                                },
                            
                                pythagoreanDistance = function(p1, p2) {
                                    var dx = p2[0] - p1[0],
                                        dy = p2[1] - p1[1];
                            
                                    return Math.sqrt(dx * dx + dy * dy);
                                },
                            
                                findHotPointBestMatch = function(diagramNode1, diagramNode2) {
                                    var hp1 = diagramNode1.hotPoints,
                                        hp2 = diagramNode2.hotPoints,
                                        xy1 = diagramNode1.get('boundingBox').getXY(),
                                        xy2 = diagramNode2.get('boundingBox').getXY(),
                                        len1, len2, i, j, minDistance = Infinity,
                                        match = [[0, 0], [0, 0]];
                            
                                    for (i = 0, len1 = hp1.length; i < len1; i++) {
                                        var value1 = hp1[i],
                                            adjustedValue1 = adjustDiagramNodeOffset(xy1, value1);
                            
                                        for (j = 0, len2 = hp2.length; j < len2; j++) {
                                            var value2 = hp2[j],
                                                adjustedValue2 = adjustDiagramNodeOffset(xy2, value2),
                                                distance = pythagoreanDistance(adjustedValue2, adjustedValue1);
                            
                                            if (distance < minDistance) {
                                                match[0] = value1;
                                                match[1] = value2;
                                                minDistance = distance;
                                            }
                                        }
                                    }
                            
                                    return match;
                                },
                            
                                isDiagramBuilder = function(val) {
                                    return A.instanceOf(val, A.PropertyBuilder);
                                },
                            
                                isMap = function(val) {
                                    return A.instanceOf(val, A.Map);
                                },
                            
                                CSS_DB_CONTROLS = A.getClassName('diagram', 'builder', 'controls'),
                                CSS_DIAGRAM_NODE = A.getClassName('diagram', 'node'),
                                CSS_DIAGRAM_NODE_LABEL = A.getClassName('diagram', 'node', 'label'),
                                CSS_DIAGRAM_NODE_SELECTED = A.getClassName('diagram', 'node', 'selected'),
                                CSS_DIAGRAM_NODE_SHAPE_BOUNDARY = A.getClassName('diagram', 'node', 'shape', 'boundary');
                            
                            /**
                             * A base class for DiagramNode.
                             *
                             * @class A.DiagramNode
                             * @extends Overlay
                             * @param {Object} config Object literal specifying widget configuration
                             *     properties.
                             * @constructor
                             */
                            DiagramNode = A.Component.create({
                            
                                /**
                                 * Static property provides a string to identify the class.
                                 *
                                 * @property NAME
                                 * @type String
                                 * @static
                                 */
                                NAME: 'diagram-node',
                            
                                /**
                                 * Static property used to define the UI attributes.
                                 *
                                 * @property UI_ATTRS
                                 * @type Array
                                 * @static
                                 */
                                UI_ATTRS: ['highlighted', 'name', 'required', 'selected'],
                            
                                /**
                                 * Static property used to define the default attribute
                                 * configuration for the `A.DiagramNode`.
                                 *
                                 * @property ATTRS
                                 * @type Object
                                 * @static
                                 */
                                ATTRS: {
                            
                                    /**
                                     * Stores an instance of `A.PropertyBuilder`.
                                     *
                                     * @attribute builder
                                     * @type DiagramBuilder
                                     */
                                    builder: {
                                        validator: isDiagramBuilder
                                    },
                            
                                    /**
                                     * A map of connectors.
                                     *
                                     * @attribute connectors
                                     * @writeOnce
                                     */
                                    connectors: {
                                        valueFn: '_connectorsValueFn',
                                        writeOnce: true
                                    },
                            
                                    /**
                                     * A toolbar to represent controls.
                                     *
                                     * @attribute controlsToolbar
                                     * @type Object
                                     */
                                    controlsToolbar: {
                                        validator: A.Lang.isObject,
                                        valueFn: '_controlsToolbarValueFn'
                                    },
                            
                                    /**
                                     * The description of the node.
                                     *
                                     * @attribute description
                                     * @default ''
                                     * @type String
                                     */
                                    description: {
                                        value: '',
                                        validator: A.Lang.isString
                                    },
                            
                                    /**
                                     * Stores an instance of `A.Graphic`.
                                     *
                                     * @attribute graphic
                                     * @type Object
                                     * @writeOnce
                                     */
                                    graphic: {
                                        writeOnce: true,
                                        validator: A.Lang.isObject
                                    },
                            
                                    /**
                                     * The height of the node.
                                     *
                                     * @attribute height
                                     * @default 60
                                     * @type Number
                                     */
                                    height: {
                                        value: 60
                                    },
                            
                                    /**
                                     * Checks if a node is highlighted or not.
                                     *
                                     * @attribute highlighted
                                     * @default false
                                     * @type Boolean
                                     */
                                    highlighted: {
                                        validator: A.Lang.isBoolean,
                                        value: false
                                    },
                            
                                    /**
                                     * The name of the node.
                                     *
                                     * @attribute name
                                     * @type String
                                     */
                                    name: {
                                        valueFn: function() {
                                            var instance = this;
                            
                                            return instance.get('type') + (++A.Env._uidx);
                                        },
                                        validator: A.Lang.isString
                                    },
                            
                                    /**
                                     * Checks if a node is required or not.
                                     *
                                     * @attribute required
                                     * @default false
                                     * @type Boolean
                                     */
                                    required: {
                                        value: false,
                                        validator: A.Lang.isBoolean
                                    },
                            
                                    /**
                                     * Checks if a node is selected or not.
                                     *
                                     * @attribute selected
                                     * @default false
                                     * @type Boolean
                                     */
                                    selected: {
                                        value: false,
                                        validator: A.Lang.isBoolean
                                    },
                            
                                    /**
                                     * A graphic shape to represent a boundary.
                                     *
                                     * @attribute shapeBoundary
                                     * @type Object
                                     */
                                    shapeBoundary: {
                                        validator: A.Lang.isObject,
                                        valueFn: '_valueShapeBoundary'
                                    },
                            
                                    /**
                                     * Represents a stroke to highlight a boundary.
                                     *
                                     * @attribute highlightBoundaryStroke
                                     * @type Object
                                     */
                                    highlightBoundaryStroke: {
                                        validator: A.Lang.isObject,
                                        value: {
                                            weight: 7,
                                            color: '#484B4C',
                                            opacity: 0.25
                                        }
                                    },
                            
                                    /**
                                     * Configuration object to generate the shape invite graphic.
                                     *
                                     * @attribute shapeInvite
                                     * @type Object
                                     */
                                    shapeInvite: {
                                        validator: A.Lang.isObject,
                                        value: {
                                            radius: 12,
                                            type: 'circle',
                                            stroke: {
                                                weight: 6,
                                                color: '#ff6600',
                                                opacity: 0.8
                                            },
                                            fill: {
                                                color: '#ffd700',
                                                opacity: 0.8
                                            }
                                        }
                                    },
                            
                                    /**
                                     * Collection of strings used to label elements of the UI.
                                     *
                                     * @attribute strings
                                     * @type Object
                                     */
                                    strings: {
                                        value: {
                                            closeMessage: 'Close',
                                            connectMessage: 'Connect',
                                            description: 'Description',
                                            editMessage: 'Edit',
                                            name: 'Name',
                                            type: 'Type'
                                        }
                                    },
                            
                                    /**
                                     * Specify the tab order of elements.
                                     *
                                     * @attribute tabIndex
                                     * @default 1
                                     * @type Number
                                     */
                                    tabIndex: {
                                        value: 1
                                    },
                            
                                    /**
                                     * Map of transitions that stores the uid, source and target data from
                                     * connectors.
                                     *
                                     * @attribute transitions
                                     * @default null
                                     * @writeOnce
                                     */
                                    transitions: {
                                        value: null,
                                        writeOnce: true,
                                        setter: '_setTransitions'
                                    },
                            
                                    /**
                                     * The type of the node.
                                     *
                                     * @attribute type
                                     * @default 'node'
                                     * @type String
                                     */
                                    type: {
                                        value: 'node',
                                        validator: A.Lang.isString
                                    },
                            
                                    /**
                                     * The width of the node.
                                     *
                                     * @attribute width
                                     * @default 60
                                     * @type Number
                                     */
                                    width: {
                                        value: 60
                                    },
                            
                                    /**
                                     * Specify the stack order of elements.
                                     *
                                     * @attribute zIndex
                                     * @default 100
                                     * @type Number
                                     */
                                    zIndex: {
                                        value: 100
                                    }
                                },
                            
                                /**
                                 * Static property used to define which component it extends.
                                 *
                                 * @property EXTENDS
                                 * @type String
                                 * @static
                                 */
                                EXTENDS: A.Overlay,
                            
                                /**
                                 * Coordinates to generate a circle graphic.
                                 *
                                 * @property CIRCLE_POINTS
                                 * @type Array
                                 * @static
                                 */
                                CIRCLE_POINTS: [[35, 20], [28, 33], [14, 34], [5, 22], [10, 9], [24, 6], [34, 16], [31, 30], [18, 35], [6, 26], [
                                    7, 12], [20, 5], [33, 12], [34, 26], [22, 35], [9, 30], [6, 16], [16, 6], [30, 9], [35, 22], [26, 34], [
                                    12, 33], [5, 20], [12, 7], [26, 6], [35, 18], [30, 31], [16, 34], [6, 24], [9, 10], [22, 5], [34, 14], [
                                    33, 28], [20, 35], [7, 28], [6, 14], [18, 5], [31, 10], [34, 24], [24, 34], [10, 31], [5, 18], [14, 6], [
                                    28, 8], [35, 20], [28, 33], [14, 34], [5, 22], [10, 8], [25, 6], [34, 16], [31, 30], [18, 35], [6, 26], [
                                    8, 12], [20, 5], [33, 12], [33, 27], [22, 35], [8, 30], [6, 15], [16, 6], [30, 9], [35, 23], [26, 34], [
                                    12, 32], [5, 20], [12, 7], [27, 7], [35, 18], [29, 32], [15, 34]],
                            
                                /**
                                 * Coordinates to generate a diamond graphic.
                                 *
                                 * @property DIAMOND_POINTS
                                 * @type Array
                                 * @static
                                 */
                                DIAMOND_POINTS: [[30, 5], [35, 10], [40, 15], [45, 20], [50, 25], [55, 30], [50, 35], [45, 40], [40, 45], [35,
                                    50], [30, 55], [25, 50], [20, 45], [15, 40], [10, 35], [5, 30], [10, 25], [15, 20], [20, 15], [25, 10]],
                            
                                /**
                                 * Coordinates to generate a square graphic.
                                 *
                                 * @property SQUARE_POINTS
                                 * @type Array
                                 * @static
                                 */
                                SQUARE_POINTS: [[5, 5], [10, 5], [15, 5], [20, 5], [25, 5], [30, 5], [35, 5], [40, 5], [50, 5], [55, 5], [60, 5], [
                                    65, 5], [65, 10], [65, 15], [65, 20], [65, 25], [65, 30], [65, 35], [65, 40], [65, 45], [65, 50], [65,
                                    55], [65, 60], [65, 65], [60, 65], [55, 65], [50, 65], [45, 65], [40, 65], [35, 65], [30, 65], [25, 65], [
                                    20, 65], [15, 65], [10, 65], [5, 65], [5, 60], [5, 55], [5, 50], [5, 45], [5, 40], [5, 35], [5, 30], [5,
                                    25], [5, 20], [5, 15], [5, 10]],
                            
                                /**
                                 * Gets a node by its name.
                                 *
                                 * @method getNodeByName
                                 * @param name
                                 * @private
                                 */
                                getNodeByName: function(name) {
                                    return A.Widget.getByNode('[data-nodeId=' + A.DiagramNode.buildNodeId(name) + ']');
                                },
                            
                                /**
                                 * Gets the node top and left coordinates based on the container.
                                 *
                                 * @method getNodeCoordinates
                                 * @param container
                                 * @param node
                                 * @private
                                 */
                                getNodeCoordinates: function(container, node) {
                                    var nodeXY = A.Lang.isArray(node) ? node : node.getXY();
                                    var containerXY = A.Lang.isArray(container) ? container : container.getXY();
                            
                                    return A.Array.map(containerXY, function(val, i) {
                                        return Math.max(0, val - nodeXY[i]);
                                    });
                                },
                            
                                /**
                                 * Constructs the node id string.
                                 *
                                 * @method buildNodeId
                                 * @param id
                                 * @private
                                 */
                                buildNodeId: function(id) {
                                    return 'diagramNode' + '_' + 'field' + '_' + id.replace(/[^a-z0-9.:_\-]/ig, '_');
                                },
                            
                                prototype: {
                                    LABEL_TEMPLATE: '<div class="' + CSS_DIAGRAM_NODE_LABEL + '">{label}</div>',
                            
                                    boundary: null,
                            
                                    hotPoints: [[0, 0]],
                            
                                    CONTROLS_TEMPLATE: '<div class="' + CSS_DB_CONTROLS + '"></div>',
                            
                                    SERIALIZABLE_ATTRS: ['description', 'name', 'required', 'type', 'width', 'height', 'zIndex', 'xy'],
                            
                                    /**
                                     * Construction logic executed during DiagramNode instantiation.
                                     * Lifecycle.
                                     *
                                     * @method initializer
                                     * @protected
                                     */
                                    initializer: function() {
                                        var instance = this;
                            
                                        instance.after({
                                            'map:remove': A.bind(instance._afterMapRemove, instance),
                                            render: instance._afterRender
                                        });
                            
                                        instance.on({
                                            nameChange: instance._onNameChange
                                        });
                            
                                        instance.publish({
                                            connectDrop: {
                                                defaultFn: instance.connectDrop
                                            },
                                            connectEnd: {
                                                defaultFn: instance.connectEnd
                                            },
                                            connectMove: {
                                                defaultFn: instance.connectMove
                                            },
                                            connectOutTarget: {
                                                defaultFn: instance.connectOutTarget
                                            },
                                            connectOverTarget: {
                                                defaultFn: instance.connectOverTarget
                                            },
                                            connectStart: {
                                                defaultFn: instance.connectStart
                                            },
                                            boundaryMouseEnter: {},
                                            boundaryMouseLeave: {}
                                        });
                            
                                        instance.boundingBox = instance.get('boundingBox');
                                        instance.toolbarContainer = instance.get('toolbarContainer');
                            
                                        instance.boundingBox.addClass(CSS_DIAGRAM_NODE + '-' + instance.get('type'));
                                        instance.boundingBox.setAttribute('draggable', true);
                                    },
                            
                                    /**
                                     * Destructor lifecycle implementation for the `DiagramNode` class.
                                     * Lifecycle.
                                     *
                                     * @method destructor
                                     * @protected
                                     */
                                    destructor: function() {
                                        var instance = this;
                            
                                        instance.eachConnector(function(connector, index, sourceNode) {
                                            sourceNode.removeTransition(connector.get('transition'));
                                        });
                            
                                        instance.invite.destroy();
                                        instance.get('graphic').destroy();
                                        instance.get('builder').removeField(instance);
                                    },
                            
                                    /**
                                     * Adds a transition into the node.
                                     *
                                     * @method addTransition
                                     * @param transition
                                     */
                                    addTransition: function(transition) {
                                        var instance = this,
                                            transitions = instance.get('transitions');
                            
                                        transition = instance.prepareTransition(transition);
                            
                                        if (!transitions.has(transition.uid)) {
                                            transition.uid = A.guid();
                                            transitions.put(transition.uid, transition);
                                        }
                            
                                        return transition;
                                    },
                            
                                    /**
                                     * Aligns a single transition.
                                     *
                                     * @method alignTransition
                                     * @param transition
                                     */
                                    alignTransition: function(transition) {
                                        var instance = this;
                                        var diagramNode = A.DiagramNode.getNodeByName(transition.target);
                            
                                        if (diagramNode) {
                                            var bestMatch = findHotPointBestMatch(instance, diagramNode);
                            
                                            transition = A.merge(transition, {
                                                sourceXY: bestMatch[0],
                                                targetXY: bestMatch[1]
                                            });
                            
                                            instance.getConnector(transition).setAttrs({
                                                p1: adjustDiagramNodeOffset(instance, transition.sourceXY),
                                                p2: adjustDiagramNodeOffset(diagramNode, transition.targetXY)
                                            });
                                        }
                                    },
                            
                                    /**
                                     * Aligns a collection of transitions.
                                     *
                                     * @method alignTransitions
                                     */
                                    alignTransitions: function() {
                                        var instance = this,
                                            transitions = instance.get('transitions');
                            
                                        A.Array.each(transitions.values(), A.bind(instance.alignTransition, instance));
                                    },
                            
                                    /**
                                     * Destroys this instance.
                                     *
                                     * @method close
                                     */
                                    close: function() {
                                        var instance = this;
                            
                                        return instance.destroy();
                                    },
                            
                                    /**
                                     * Checks if a transition is connected, if not creates a new
                                     * `A.Connector` instance.
                                     *
                                     * @method connect
                                     * @param transition
                                     * @param optConnector
                                     */
                                    connect: function(transition, optConnector) {
                                        var instance = this;
                            
                                        transition = instance.addTransition(transition);
                            
                                        var connector = null;
                                        var diagramNode = A.DiagramNode.getNodeByName(transition.target);
                            
                                        if (diagramNode) {
                                            if (!instance.isTransitionConnected(transition)) {
                                                var builder = instance.get('builder');
                                                var bestMatch = findHotPointBestMatch(instance, diagramNode);
                            
                                                A.mix(transition, {
                                                    sourceXY: bestMatch[0],
                                                    targetXY: bestMatch[1]
                                                });
                            
                                                connector = new A.Connector(
                                                    A.merge({
                                                        after: {
                                                            selectedChange: function() {
                                                                instance.alignTransition(transition);
                                                            }
                                                        },
                                                        builder: builder,
                                                        graphic: builder.get('graphic'),
                                                        transition: transition
                                                    }, optConnector)
                                                );
                            
                                                instance.get('connectors').put(transition.uid, connector);
                                            }
                                        }
                            
                                        instance.alignTransition(transition);
                            
                                        return connector;
                                    },
                            
                                    /**
                                     * Calls the `connectNode` method with `publishedTarget` parameter.
                                     *
                                     * @method connectDrop
                                     * @param event
                                     */
                                    connectDrop: function(event) {
                                        var instance = this;
                            
                                        instance.connectNode(event.publishedTarget);
                                    },
                            
                                    /**
                                     * Handles the `connectEnd` event.
                                     *
                                     * @method connectEnd
                                     * @param event
                                     */
                                    connectEnd: function() {
                                        var instance = this;
                                        var builder = instance.get('builder');
                                        var publishedSource = builder.publishedSource;
                            
                                        if (!builder.isAbleToConnect() &&
                                            builder.get('showSuggestConnector') &&
                                            builder.connector.get('visible')) {
                            
                                            builder.showSuggestConnectorOverlay();
                                        }
                                        else {
                                            builder.connector.hide();
                                            publishedSource.invite.set('visible', false);
                                        }
                            
                                        if (builder.get('highlightDropZones')) {
                                            builder.get('fields').each(function(diagramNode) {
                                                diagramNode.set('highlighted', false);
                                            });
                                        }
                                    },
                            
                                    /**
                                     * Sets the connector position based on the mouse X and Y positions.
                                     *
                                     * @method connectMove
                                     * @param event
                                     */
                                    connectMove: function(event) {
                                        var instance = this;
                                        var builder = instance.get('builder');
                                        var mouseXY = event.mouseXY;
                            
                                        builder.connector.set('p2', mouseXY);
                            
                                        if (builder.publishedTarget) {
                                            var invite = instance.invite;
                                            var offset = invite.get('radius') || 0;
                            
                                            if (!invite.get('visible')) {
                                                invite.set('visible', true);
                                            }
                            
                                            invite.setXY([mouseXY[0] - offset, mouseXY[1] - offset]);
                                        }
                                    },
                            
                                    /**
                                     * Prepares the transition and connects a node.
                                     *
                                     * @method connectNode
                                     * @param diagramNode
                                     */
                                    connectNode: function(diagramNode) {
                                        var instance = this;
                                        var dd = instance.boundaryDragDelegate.dd;
                            
                                        instance.connect(
                                            instance.prepareTransition({
                                                sourceXY: A.DiagramNode.getNodeCoordinates(dd.startXY, instance.get('boundingBox')),
                                                target: diagramNode.get('name'),
                                                targetXY: A.DiagramNode.getNodeCoordinates(dd.mouseXY, diagramNode.get('boundingBox'))
                                            })
                                        );
                                    },
                            
                                    /**
                                     * Sets the `publishedTarget` attribute to null and hiddes the
                                     * `publishedSource`'s invite.
                                     *
                                     * @method connectOutTarget
                                     * @param event
                                     */
                                    connectOutTarget: function() {
                                        var instance = this;
                                        var builder = instance.get('builder');
                            
                                        builder.publishedTarget = null;
                                        builder.publishedSource.invite.set('visible', false);
                                    },
                            
                                    /**
                                     * If `publishedSource` is different from the current instance, sets the
                                     * `publishedTarget` to the current instance.
                                     *
                                     * @method connectOverTarget
                                     * @param event
                                     */
                                    connectOverTarget: function() {
                                        var instance = this;
                                        var builder = instance.get('builder');
                            
                                        if (builder.publishedSource !== instance) {
                                            builder.publishedTarget = instance;
                                        }
                                    },
                            
                                    /**
                                     * Highlights each diagram node and fires a `publishedSource` event.
                                     *
                                     * @method connectStart
                                     * @param event
                                     */
                                    connectStart: function(event) {
                                        var instance = this;
                                        var builder = instance.get('builder');
                            
                                        builder.connector.show().set('p1', event.startXY);
                            
                                        if (builder.get('highlightDropZones')) {
                                            builder.get('fields').each(function(diagramNode) {
                                                diagramNode.set('highlighted', true);
                                            });
                                        }
                            
                                        A.DiagramNodeManager.fire('publishedSource', {
                                            publishedSource: instance
                                        });
                                    },
                            
                                    /**
                                     * Checks if a transition is connected, if yes removes the transition.
                                     *
                                     * @method disconnect
                                     * @param transition
                                     */
                                    disconnect: function(transition) {
                                        var instance = this;
                            
                                        if (instance.isTransitionConnected(transition)) {
                                            instance.removeTransition(transition);
                                        }
                                    },
                            
                                    /**
                                     * An utility function to loop through all connectors.
                                     *
                                     * @method eachConnector
                                     * @param fn
                                     */
                                    eachConnector: function(fn) {
                                        var instance = this,
                                            sourceNodes = [],
                                            connectors = [].concat(instance.get('connectors').values()),
                                            tIndex = connectors.length;
                            
                                        A.Array.each(instance.get('builder').getSourceNodes(instance), function(sourceNode) {
                                            var sourceConnectors = sourceNode.get('connectors');
                            
                                            A.Array.each(sourceConnectors.values(), function(connector) {
                                                if (instance.get('name') === connector.get('transition').target) {
                                                    sourceNodes.push(sourceNode);
                                                    connectors.push(connector);
                                                }
                                            });
                                        });
                            
                                        A.Array.each(connectors, function(connector, index) {
                                            fn.call(instance, connector, index, (index < tIndex) ? instance : sourceNodes[index - tIndex]);
                                        });
                            
                                        connectors = sourceNodes = null;
                            
                                        return connectors;
                                    },
                            
                                    /**
                                     * Returns a connector based on the transition uid.
                                     *
                                     * @method getConnector
                                     * @param transition
                                     */
                                    getConnector: function(transition) {
                                        var instance = this;
                            
                                        return instance.get('connectors').getValue(transition.uid);
                                    },
                            
                                    /**
                                     * Returns the `dropContainer` or bounding box's parent node.
                                     *
                                     * @method getContainer
                                     */
                                    getContainer: function() {
                                        var instance = this;
                            
                                        return (instance.get('builder').dropContainer || instance.get('boundingBox').get('parentNode'));
                                    },
                            
                                    /**
                                     * Returns the left and top positions of a node based in its container.
                                     *
                                     * @method getNodeCoordinates
                                     */
                                    getNodeCoordinates: function() {
                                        var instance = this;
                            
                                        return A.DiagramNode.getNodeCoordinates(instance.get('boundingBox'), instance.getContainer());
                                    },
                            
                                    /**
                                     * Gets the list of properties from the property model.
                                     *
                                     * @method getProperties
                                     * @return {Array}
                                     */
                                    getProperties: function() {
                                        var instance = this;
                                        var propertyModel = instance.getPropertyModel();
                            
                                        A.Array.each(propertyModel, function(property) {
                                            var value = instance.get(property.attributeName),
                                                type = A.Lang.type(value);
                            
                                            if (type === 'boolean') {
                                                value = String(value);
                                            }
                            
                                            property.value = value;
                                        });
                            
                                        return propertyModel;
                                    },
                            
                                    /**
                                     * Gets the model defition of a property.
                                     *
                                     * @method getPropertyModel
                                     * @return {Array}
                                     */
                                    getPropertyModel: function() {
                                        var instance = this;
                                        var strings = instance.getStrings();
                            
                                        return [{
                                            attributeName: 'description',
                                            editor: new A.TextAreaCellEditor(),
                                            name: strings.description
                                        }, {
                                            attributeName: 'name',
                                            editor: new A.TextCellEditor({
                                                validator: {
                                                    rules: {
                                                        value: {
                                                            required: true
                                                        }
                                                    }
                                                }
                                            }),
                                            name: strings.name
                                        }, {
                                            attributeName: 'type',
                                            editor: false,
                                            name: strings.type
                                        }];
                                    },
                            
                                    /**
                                     * Checks if boundary is draggable.
                                     *
                                     * @method isBoundaryDrag
                                     * @param drag
                                     * @return {Boolean}
                                     */
                                    isBoundaryDrag: function(drag) {
                                        var instance = this;
                            
                                        return (drag === instance.boundaryDragDelegate.dd);
                                    },
                            
                                    /**
                                     * Checks if a connector has an transition uid property.
                                     *
                                     * @method isTransitionConnected
                                     * @param transition
                                     */
                                    isTransitionConnected: function(transition) {
                                        var instance = this;
                            
                                        return instance.get('connectors').has(transition.uid);
                                    },
                            
                                    /**
                                     * Builds the transition configuration object.
                                     *
                                     * @method prepareTransition
                                     * @param val
                                     */
                                    prepareTransition: function(val) {
                                        var instance = this,
                                            target = val,
                                            transition;
                            
                                        if (A.Lang.isObject(val)) {
                                            target = val.target;
                                        }
                            
                                        A.Array.some(
                                            instance.get('transitions').values(),
                                            function(t) {
                                                transition = (target === t.target) ? t : null;
                            
                                                return transition;
                                            }
                                        );
                            
                                        if (!transition) {
                                            transition = {
                                                source: instance.get('name'),
                                                target: null,
                                                uid: A.guid()
                                            };
                            
                                            if (A.Lang.isString(val)) {
                                                transition.target = val;
                                            }
                                            else if (A.Lang.isObject(val)) {
                                                transition = A.merge(transition, val);
                                            }
                                        }
                            
                                        return transition;
                                    },
                            
                                    /**
                                     * Removes the transition uid from a transition.
                                     *
                                     * @method removeTransition
                                     * @param transition
                                     */
                                    removeTransition: function(transition) {
                                        var instance = this;
                            
                                        return instance.get('transitions').remove(transition.uid);
                                    },
                            
                                    /**
                                     * Renders the `shapeBoundary` attribute.
                                     *
                                     * @method renderShapeBoundary
                                     */
                                    renderShapeBoundary: function() {
                                        var instance = this;
                            
                                        var boundary = instance.boundary =
                                            instance.get('graphic').addShape(instance.get('shapeBoundary'));
                            
                                        return boundary;
                                    },
                            
                                    /**
                                     * Renders the `shapeInvite` attribute.
                                     *
                                     * @method renderShapeInvite
                                     */
                                    renderShapeInvite: function() {
                                        var instance = this;
                            
                                        var invite = instance.invite =
                                            instance.get('builder').get('graphic').addShape(instance.get('shapeInvite'));
                            
                                        invite.set('visible', false);
                            
                                        return invite;
                                    },
                            
                                    /**
                                     * Syncs the connections in the UI.
                                     *
                                     * @method syncConnectionsUI
                                     */
                                    syncConnectionsUI: function() {
                                        var instance = this,
                                            transitions = instance.get('transitions');
                            
                                        A.Array.each(transitions.values(), function(transition) {
                                            instance.connect(transition, transition.connector);
                                        });
                                    },
                            
                                    /**
                                     * Fires after a connector has been removed.
                                     *
                                     * @method _afterConnectorRemove
                                     * @param event
                                     * @protected
                                     */
                                    _afterConnectorRemove: function(event) {
                                        event.value.destroy();
                                    },
                            
                                    /**
                                     * Fires after render is executed.
                                     *
                                     * @method _afterRender
                                     * @param event
                                     * @protected
                                     */
                                    _afterRender: function() {
                                        var instance = this;
                            
                                        instance.setStdModContent(A.WidgetStdMod.BODY, '', A.WidgetStdMod.AFTER);
                                        instance._renderGraphic();
                                        instance._renderControls();
                                        instance._renderLabel();
                                        instance._uiSetHighlighted(instance.get('highlighted'));
                                    },
                            
                                    /**
                                     * Fires after a transition has been removed.
                                     *
                                     * @method _afterTransitionsRemove
                                     * @param event
                                     * @protected
                                     */
                                    _afterTransitionsRemove: function(event) {
                                        var instance = this;
                            
                                        instance.get('connectors').remove(event.value.uid);
                                    },
                            
                                    /**
                                     * Binds mouse enter and mouse leave events in boundary.
                                     *
                                     * @method _bindBoundaryEvents
                                     * @protected
                                     */
                                    _bindBoundaryEvents: function() {
                                        var instance = this;
                            
                                        instance.boundary.detachAll().on({
                                            mouseenter: A.bind(instance._onBoundaryMouseEnter, instance),
                                            mouseleave: A.bind(instance._onBoundaryMouseLeave, instance)
                                        });
                                    },
                            
                                    /**
                                     * Returns a new instance of `A.Map` and bind the after connector remove
                                     * event.
                                     *
                                     * @method _connectorsValueFn
                                     * @param val
                                     * @protected
                                     */
                                    _connectorsValueFn: function() {
                                        var instance = this;
                            
                                        return new A.Map({
                                            after: {
                                                remove: A.bind(instance._afterConnectorRemove, instance)
                                            }
                                        });
                                    },
                            
                                    /**
                                     * Returns a configuration object for the toolbar.
                                     *
                                     * @method _controlsToolbarValueFn
                                     * @param val
                                     * @protected
                                     */
                                    _controlsToolbarValueFn: function() {
                                        var instance = this;
                            
                                        return {
                                            children: [
                                                {
                                                    icon: 'glyphicon glyphicon-remove',
                                                    on: {
                                                        click: A.bind(instance._handleCloseEvent, instance)
                                                    }
                                                }
                                            ]
                                        };
                                    },
                            
                                    /**
                                     * Fires when a close event is dispatched.
                                     *
                                     * @method _handleCloseEvent
                                     * @param event
                                     * @protected
                                     */
                                    _handleCloseEvent: function() {
                                        var instance = this;
                            
                                        instance.get('builder').deleteSelectedNode();
                                    },
                            
                                    /**
                                     * Fires a `connectStart` event with `startXY` parameter.
                                     *
                                     * @method _handleConnectStart
                                     * @param startXY
                                     * @protected
                                     */
                                    _handleConnectStart: function(startXY) {
                                        var instance = this;
                            
                                        instance.fire('connectStart', {
                                            startXY: startXY
                                        });
                                    },
                            
                                    /**
                                     * Fires a `connectMove` event with `startXY` and `publishedSource`
                                     * parameters.
                                     *
                                     * @method _handleConnectMove
                                     * @param mouseXY
                                     * @protected
                                     */
                                    _handleConnectMove: function(mouseXY) {
                                        var instance = this;
                                        var builder = instance.get('builder');
                            
                                        instance.fire('connectMove', {
                                            mouseXY: mouseXY,
                                            publishedSource: builder.publishedSource
                                        });
                                    },
                            
                                    /**
                                     * Checks if source and target are published, if yes a `connectDrop`
                                     * event is fired with `publishedSource` and `publishedTarget`
                                     * parameters. Also fires a `connectEnd` event.
                                     *
                                     * @method _handleConnectEnd
                                     * @protected
                                     */
                                    _handleConnectEnd: function() {
                                        var instance = this;
                                        var builder = instance.get('builder');
                                        var publishedSource = builder.publishedSource;
                                        var publishedTarget = builder.publishedTarget;
                            
                                        if (publishedSource && publishedTarget) {
                                            instance.fire('connectDrop', {
                                                publishedSource: publishedSource,
                                                publishedTarget: publishedTarget
                                            });
                                        }
                            
                                        instance.fire('connectEnd', {
                                            publishedSource: publishedSource
                                        });
                                    },
                            
                                    /**
                                     * Checks if source is published, if yes a `connectOutTarget` event is
                                     * fired with `publishedSource` parameter.
                                     *
                                     * @method _handleConnectOutTarget
                                     * @protected
                                     */
                                    _handleConnectOutTarget: function() {
                                        var instance = this;
                                        var builder = instance.get('builder');
                                        var publishedSource = builder.publishedSource;
                            
                                        if (publishedSource) {
                                            instance.fire('connectOutTarget', {
                                                publishedSource: publishedSource
                                            });
                                        }
                                    },
                            
                                    /**
                                     * Checks if source is published, if yes a `connectOverTarget` event is
                                     * fired with `publishedSource` parameter.
                                     *
                                     * @method _handleConnectOverTarget
                                     * @protected
                                     */
                                    _handleConnectOverTarget: function() {
                                        var instance = this;
                                        var builder = instance.get('builder');
                                        var publishedSource = builder.publishedSource;
                            
                                        if (publishedSource) {
                                            instance.fire('connectOverTarget', {
                                                publishedSource: publishedSource
                                            });
                                        }
                                    },
                            
                                    /**
                                     * Fires when there's drag event happening in the boundary.
                                     *
                                     * @method _onBoundaryDrag
                                     * @param event
                                     * @protected
                                     */
                                    _onBoundaryDrag: function() {
                                        var instance = this;
                                        var dd = instance.boundaryDragDelegate.dd;
                            
                                        instance._handleConnectMove(dd.con._checkRegion(dd.mouseXY));
                                    },
                            
                                    /**
                                     * Fires when a drag event ends in the boundary.
                                     *
                                     * @method _onBoundaryDragEnd
                                     * @param event
                                     * @protected
                                     */
                                    _onBoundaryDragEnd: function(event) {
                                        var instance = this;
                            
                                        instance._handleConnectEnd();
                                        event.target.get('dragNode').show();
                                    },
                            
                                    /**
                                     * Fires when a drag event starts in the boundary.
                                     *
                                     * @method _onBoundaryDragStart
                                     * @param event
                                     * @protected
                                     */
                                    _onBoundaryDragStart: function(event) {
                                        var instance = this;
                            
                                        instance._handleConnectStart(instance.boundaryDragDelegate.dd.startXY);
                                        event.target.get('dragNode').hide();
                                    },
                            
                                    /**
                                     * Fires when mouse enters boundary.
                                     *
                                     * @method _onBoundaryMouseEnter
                                     * @param event
                                     * @protected
                                     */
                                    _onBoundaryMouseEnter: function(event) {
                                        var instance = this;
                            
                                        instance.fire('boundaryMouseEnter', {
                                            domEvent: event
                                        });
                            
                                        instance._handleConnectOverTarget();
                                    },
                            
                                    /**
                                     * Fires when mouse leaves boundary.
                                     *
                                     * @method _onBoundaryMouseLeave
                                     * @param event
                                     * @protected
                                     */
                                    _onBoundaryMouseLeave: function(event) {
                                        var instance = this;
                            
                                        instance.fire('boundaryMouseLeave', {
                                            domEvent: event
                                        });
                            
                                        instance._handleConnectOutTarget();
                                    },
                            
                                    /**
                                     * Fires when the name is changed.
                                     *
                                     * @method _onNameChange
                                     * @param event
                                     * @protected
                                     */
                                    _onNameChange: function(event) {
                                        var instance = this;
                            
                                        instance.eachConnector(function(connector, index, sourceNode) {
                                            var transition = connector.get('transition');
                            
                                            transition[(instance === sourceNode) ? 'source' : 'target'] = event.newVal;
                                            connector.set('transition', transition);
                                        });
                                    },
                            
                                    /**
                                     * Creates a node for the controls and append it to the bounding box.
                                     *
                                     * @method _renderControls
                                     * @protected
                                     */
                                    _renderControls: function() {
                                        var instance = this;
                                        var boundingBox = instance.get('boundingBox');
                            
                                        instance.controlsNode = A.Node.create(instance.CONTROLS_TEMPLATE).appendTo(boundingBox);
                                    },
                            
                                    /**
                                     * Creates an instance of `A.Toolbar` in `controlsToolbar` attribute and
                                     * renders it.
                                     *
                                     * @method _renderControlsToolbar
                                     * @param event
                                     * @protected
                                     */
                                    _renderControlsToolbar: function() {
                                        var instance = this;
                            
                                        instance.controlsToolbar = new A.Toolbar(
                                            instance.get('controlsToolbar')
                                        ).render(instance.controlsNode);
                            
                                        instance._uiSetRequired(instance.get('required'));
                                    },
                            
                                    /**
                                     * Renders the `graphic` attribute.
                                     *
                                     * @method _renderGraphic
                                     * @protected
                                     */
                                    _renderGraphic: function() {
                                        var instance = this;
                            
                                        instance.set(
                                            'graphic',
                                            new A.Graphic({
                                                height: instance.get('height'),
                                                render: instance.bodyNode,
                                                width: instance.get('width')
                                            })
                                        );
                            
                                        instance.renderShapeInvite();
                                        instance.renderShapeBoundary().addClass(CSS_DIAGRAM_NODE_SHAPE_BOUNDARY);
                            
                                        instance._bindBoundaryEvents();
                                        instance._setupBoundaryDrag();
                                    },
                            
                                    /**
                                     * Creates a node for the label and place it after the content box.
                                     *
                                     * @method _renderLabel
                                     * @protected
                                     */
                                    _renderLabel: function() {
                                        var instance = this;
                            
                                        instance.labelNode = A.Node.create(
                                            A.Lang.sub(instance.LABEL_TEMPLATE, {
                                                label: A.Escape.html(instance.get('name'))
                                            })
                                        );
                            
                                        instance.get('contentBox').placeAfter(instance.labelNode);
                                    },
                            
                                    /**
                                     * Set the `transition` attribute.
                                     *
                                     * @method _setTransitions
                                     * @param val
                                     * @protected
                                     * @return {Array}
                                     */
                                    _setTransitions: function(val) {
                                        var instance = this;
                            
                                        if (!isMap(val)) {
                                            var map = new A.Map({
                                                after: {
                                                    remove: A.bind(instance._afterTransitionsRemove, instance)
                                                }
                                            });
                            
                                            A.Array.each(val, function(transition) {
                                                var uid = A.guid();
                            
                                                transition = A.Lang.isObject(transition) ? A.mix(transition, {
                                                    uid: uid
                                                }) : {
                                                    uid: uid,
                                                    target: transition
                                                };
                            
                                                map.put(uid, instance.prepareTransition(transition));
                                            });
                            
                                            val = map;
                                        }
                            
                                        return val;
                                    },
                            
                                    /**
                                     * Creates a new instance of `A.DD.Delegate` in `boundaryDragDelegate`
                                     * attribute.
                                     *
                                     * @method _setupBoundaryDrag
                                     * @protected
                                     */
                                    _setupBoundaryDrag: function() {
                                        var instance = this;
                            
                                        var builder = instance.get('builder');
                            
                                        instance.boundaryDragDelegate = new A.DD.Delegate({
                                            bubbleTargets: instance,
                                            container: instance.bodyNode,
                                            nodes: '.' + CSS_DIAGRAM_NODE_SHAPE_BOUNDARY,
                                            dragConfig: {
                                                useShim: false,
                                                plugins: [
                                                    {
                                                        cfg: {
                                                            constrain: (builder ? builder.get('canvas') : null)
                                                        },
                                                        fn: A.Plugin.DDConstrained
                                                    },
                                                    {
                                                        cfg: {
                                                            scrollDelay: 150
                                                        },
                                                        fn: A.Plugin.DDWinScroll
                                                    },
                                                    {
                                                        cfg: {
                                                            borderStyle: '0px',
                                                            moveOnEnd: false,
                                                            resizeFrame: false
                                                        },
                                                        fn: A.Plugin.DDProxy
                                                    }
                                                ]
                                            },
                                            on: {
                                                'drag:drag': A.bind(instance._onBoundaryDrag, instance),
                                                'drag:end': A.bind(instance._onBoundaryDragEnd, instance),
                                                'drag:start': A.bind(instance._onBoundaryDragStart, instance)
                                            }
                                        });
                            
                                        // Drag _unprep method invoke .detachAll() on the node, so we need
                                        // to rebind the events.
                                        A.Do.after(instance._bindBoundaryEvents, instance.boundaryDragDelegate.dd, '_unprep', instance);
                                    },
                            
                                    /**
                                     * Set the `highlighted` attribute in the UI.
                                     *
                                     * @method _uiSetHighlighted
                                     * @param val
                                     * @protected
                                     */
                                    _uiSetHighlighted: function(val) {
                                        var instance = this;
                            
                                        if (instance.get('rendered')) {
                                            var stroke = val ? instance.get('highlightBoundaryStroke') : instance.get('shapeBoundary' + '.' +
                                                'stroke');
                            
                                            if (stroke) {
                                                instance.boundary.set('stroke', stroke);
                                            }
                                        }
                                    },
                            
                                    /**
                                     * Set the `name` attribute in the UI.
                                     *
                                     * @method _uiSetName
                                     * @param val
                                     * @protected
                                     */
                                    _uiSetName: function(val) {
                                        var instance = this;
                                        var boundingBox = instance.get('boundingBox');
                            
                                        boundingBox.setAttribute('data-nodeId', A.Escape.html(A.DiagramNode.buildNodeId(val)));
                            
                                        if (instance.get('rendered')) {
                                            instance.labelNode.setContent(A.Escape.html(val));
                                        }
                                    },
                            
                                    /**
                                     * Set the `required` attribute in the UI.
                                     *
                                     * @method _uiSetRequired
                                     * @param val
                                     * @protected
                                     */
                                    _uiSetRequired: function() {},
                            
                                    /**
                                     * Set the `selected` attribute in the UI.
                                     *
                                     * @method _uiSetSelected
                                     * @param val
                                     * @protected
                                     */
                                    _uiSetSelected: function(val) {
                                        var instance = this;
                            
                                        instance.get('boundingBox').toggleClass(CSS_DIAGRAM_NODE_SELECTED, val);
                            
                                        if (val && !instance.controlsToolbar) {
                                            instance._renderControlsToolbar();
                                        }
                                    },
                            
                                    /**
                                     * Sets the X and Y position in the UI.
                                     *
                                     * @method _uiSetXY
                                     * @param val
                                     * @protected
                                     */
                                    _uiSetXY: function(val) {
                                        var instance = this;
                                        var containerXY = instance.getContainer().getXY();
                            
                                        this._posNode.setXY([val[0] + containerXY[0], val[1] + containerXY[1]]);
                                    },
                            
                                    /**
                                     * Gets the shape boundary definitions.
                                     *
                                     * @method _valueShapeBoundary
                                     * @protected
                                     */
                                    _valueShapeBoundary: function() {
                                        return {
                                            height: 41,
                                            type: 'rect',
                                            stroke: {
                                                weight: 7,
                                                color: 'transparent',
                                                opacity: 0
                                            },
                                            width: 41
                                        };
                                    }
                                }
                            });
                            
                            A.DiagramNode = DiagramNode;