protected function groupNodesByDataset(&$nodes, $fieldName) {
        $groupedNodes = NULL;

        if (isset($nodes)) {
            foreach ($nodes as $node) {
                $dataset_nid = get_node_field_node_ref($node, $fieldName);

                $groupedNodes[$dataset_nid][] = $node;
            }
        }

        return $groupedNodes;
    }
    public function export(Export\ExportStream $stream, Export\ExportContext $context) {
        $this->datasourceName = $context->get('datasourceName');

        $dashboards = array();
        foreach (gd_dashboard_findall_by_datasource(LOAD_ENTITY,$this->datasourceName) as $dashboard) {
            $export = new stdClass();

            $export->id = (int) $dashboard->nid;
            $export->title = $dashboard->title;

            $export->uuid = get_node_field_value($dashboard,'field_dashboard_uuid',0,'value',true);
            $export->description = get_node_field_value($dashboard,'field_dashboard_desc');
            $export->public = (int) get_node_field_value($dashboard,'field_dashboard_public');
            $export->custom_view = get_node_field_value($dashboard,'field_dashboard_custom_view');
            $export->reports = (array) get_node_field_node_ref($dashboard,'field_dashboard_reports',null);
            $export->config = json_decode(get_node_field_value($dashboard,'field_dashboard_config',0,'value',true));

            $export->alias = array();
            if (!empty($dashboard->field_dashboard_alias)) {
                foreach($dashboard->field_dashboard_alias[$dashboard->language] as $alias) {
                    $export->alias[] = $alias['value'];
                }
            }

            $export->tags = array();
            if (!empty($dashboard->field_dashboard_tags)) {
                foreach($dashboard->field_dashboard_tags[$dashboard->language] as $tag) {
                    $export->tags[] = $tag['tid'];
                }
            }

            // replace report nid with report uuid
            $reportNodes = gd_report_load_multiple($export->reports);
            foreach ( $export->reports as $key => $value ) {
                foreach ( $reportNodes as $node ) {
                    if ( $node->nid == $value ) {
                        $export->reports[$key] = get_node_field_value($node,'field_report_uuid',0,'value',true);
                    }
                }
            }

            // replace references with uuid
            $this->processConfig($export);

            $dashboards[] = $export;
        }
        $stream->set('dashboards',$dashboards);
    }
    public function export(Export\ExportStream $stream, Export\ExportContext $context) {
        $datasource = gd_datasource_get_active();
        $readOnly = gd_datasource_is_property($datasource, 'readonly');
        if ($readOnly) {
            return;
        }

        $metamodel = data_controller_get_metamodel();

        // get reference points that have ref to the dataset in this datamart
        $datasetNames = array();
        foreach ( $stream->get('datasets') as $d ) {
            $datasetNames[] = $d->name;
        }

        $referencePoints = array();
        $referencePointNodes = gd_reference_get_reference_points_by_dataset($datasetNames, LOAD_ENTITY);
        $referencePointNids = array();
        foreach ( $referencePointNodes as $ref_point ) {
            $export = new stdClass();

            $export->id = (int) $ref_point->nid;
            $export->title = $ref_point->title;

            $dataset = $metamodel->getDataset(get_node_field_value($ref_point,'field_ref_point_dataset_sysname',0,'value',true));
            $export->dataset = $dataset->uuid;

            $export->columns = array();
            foreach ( (array) get_node_field_value($ref_point,'field_ref_point_column_sysname',null) as $column ) {
                $export->columns[] = $column;
            }

            $referencePoints[] = $export;
            $referencePointNids[] = (int) $ref_point->nid;
        }

        // find all references with above reference points
        $references = array();
        $referenceNodes = gd_reference_get_references_by_reference_points($referencePointNids, LOAD_ENTITY);
        foreach ( $referenceNodes as $reference ) {
            $export = new stdClass();

            $export->id = (int) $reference->nid;
            $export->title = $reference->title;

            $export->sysname = get_node_field_value($reference,'field_reference_sysname');

            foreach ( (array) get_node_field_node_ref($reference,'field_reference_point',null) as $referencePointNid ) {
                foreach ( $referencePoints as $referencePoint ){
                    if ( $referencePointNid == $referencePoint->id ) {
                        $export->referencePoints[] = $referencePoint;
                    }
                }
            }

            if ( empty($export->referencePoints) ) {
                throw new Exception('Reference missing reference points.');
            }

            $references[] = $export;
        }

        $stream->set('references',$references);
    }
    /**
     * Find existing reference via datasets
     *
     * @param $reference
     * @return null
     * @throws Exception
     */
    protected function findExistingReference ( $reference ) {

        $referenceCandidateNodes = (array) gd_reference_get_references(LOAD_ENTITY);

        // find references with exact same reference points
        $matchedReferences = array();
        foreach ( $referenceCandidateNodes as $referenceCandidateNode ) {
            $match = false;
            // don't go any further if reference point counts don't match
            if ( count((array) get_node_field_node_ref($referenceCandidateNode,'field_reference_point',null)) == count($reference->referencePoints) ) {
                continue;
            }
            // must match all reference points
            foreach ( (array) get_node_field_node_ref($referenceCandidateNode,'field_reference_point',null) as $referencePointNid ) {
                $referencePointNode = node_load($referencePointNid);
                foreach ( $reference->referencePoints as $referencePoint ) {
                    if ( $referencePoint->dataset == get_node_field_value($referencePointNode,'field_ref_point_dataset_sysname') ) {
                        $match = true;
                    } else {
                        $match = false;
                    }
                }
            }

            if ( $match ) {
                $matchedReferences[] = $referenceCandidateNode;
            }
        }

        if ( count($matchedReferences) == 1 ) {
            return $matchedReferences[0];
        } else if ( count($matchedReferences) > 1 ) {
            throw new Exception('More than one identical reference found.');
        } else {
            return null;
        }

    }