<commit_before><?xml version="1.0" encoding="utf-8"?>
<!--
  //////////////////////////////////////////////////////////////////
  // Copyright (c) 2008-2013 Esri. All Rights Reserved.
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //    http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  ////////////////////////////////////////////////////////////////
-->
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
         xmlns:s="library://ns.adobe.com/flex/spark"
         xmlns:components="com.esri.builder.components.*"
         xmlns:supportClasses="modules.supportClasses.*"
         xmlns:graphics="assets.graphics.*"
         xmlns:views="com.esri.builder.views.*"
         width="100%" height="100%"
         implements="modules.IWidgetView">
    <fx:Script>
        <![CDATA[
            import com.esri.ags.layers.supportClasses.Field;
            import com.esri.ags.layers.supportClasses.LayerDetails;
            import com.esri.ags.tasks.DetailsTask;
            import com.esri.builder.components.ModifyItemEvent;
            import com.esri.builder.components.serviceBrowser.nodes.LayerNode;
            import com.esri.builder.components.serviceBrowser.supportClasses.ServiceBrowserEvent;
            import com.esri.builder.model.Model;
            import com.esri.builder.model.RecentlyUsedURLsModel;
            import com.esri.builder.supportClasses.FieldUtil;
            import com.esri.builder.views.BuilderAlert;

            import modules.IWidgetModel;

            import mx.controls.Alert;
            import mx.events.FlexEvent;
            import mx.rpc.AsyncResponder;
            import mx.rpc.Fault;
            import mx.utils.ObjectUtil;

            import spark.events.GridEvent;

            private const SEARCH_EXPRESSION_SAMPLE:String =
                "PARCELID like \'[value]\'\n" +
                "upper(STATE) LIKE upper(\'[value]\')\n" +
                "upper(NAME) LIKE upper(\'%[value]%\')";

            private var lastLoadedURL:String;

            [Bindable]
            private var layerFields:ArrayList = new ArrayList();
            [Bindable]
            public var searchLayerURL:String;
            [Bindable]
            public var searchLayerName:String;
            [Bindable]
            public var searchLayerLabel:String;
            [Bindable]
            public var searchLayerExpression:String;
            [Bindable]
            public var searchLayerUseProxy:Boolean;
            [Bindable]
            public var searchLayerFields:ArrayList = new ArrayList();
            [Bindable]
            private var searchModel:SearchModel;
            [Bindable]
            private var isInCreateMode:Boolean;
            [Bindable]
            private var hasValidExpression:Boolean;

            private var searchLayerToEdit:SearchLayer;

            public function get widgetModel():IWidgetModel
            {
                return searchModel;
            }

            public function set widgetModel(widgetModel:IWidgetModel):void
            {
                if (widgetModel is SearchModel)
                {
                    searchModel = widgetModel as SearchModel;
                }
                else
                {
                    throw new Error('argument is not an instance of SearchModel');
                }
            }

            public function submit():Boolean
            {
                var wasOKClickedDuringSearchLayerConfiguration:Boolean = (currentState == "configureSearchLayer");
                if (wasOKClickedDuringSearchLayerConfiguration)
                {
                    commitUnsavedSearchLayerEdits();
                }

                if (searchModel.searchLayers.length == 0)
                {
                    BuilderAlert.show(resourceManager.getString('BuilderStrings', 'search.missingSearchLayers'),
                                      resourceManager.getString('BuilderStrings', 'widgetsView.widgetConfigurationError'),
                                      Alert.OK);
                    return false;
                }

                return true;
            }

            private function commitUnsavedSearchLayerEdits():void
            {
                var hasValidEdits:Boolean = (searchLayerURL && searchLayerName);
                if (hasValidEdits)
                {
                    commitSearchLayerEdits();
                }
            }

            public function cancel():void
            {
            }

            private function startEditSearchLayerMode(searchLayerToEdit:SearchLayer):void
            {
                isInCreateMode = false;

                var fields:Array = cloneFields(searchLayerToEdit.fields.source);

                searchLayerURL = searchLayerToEdit.url;
                searchLayerExpression = searchLayerToEdit.expression;
                searchLayerName = searchLayerToEdit.name;
                searchLayerLabel = searchLayerToEdit.textSearchLabel;
                searchLayerUseProxy = searchLayerToEdit.useProxy;
                searchLayerFields.source = fields;

                lastLoadedURL = searchLayerURL;
                getFieldsFromURL();
                validateExpression();

                currentState = "configureSearchLayer";
                displayFieldsDataGrid.updateTitleField(
                    FieldUtil.findFieldByName(fields, searchLayerToEdit.titleField));
                displayFieldsDataGrid.updateOrderByField(
                    FieldUtil.findFieldByName(fields, searchLayerToEdit.orderByField),
                    searchLayerToEdit.orderByFieldDirection);
            }

            private function cloneFields(fields:Array):Array
            {
                var clonedFields:Array = [];

                for each (var field:Field in fields)
                {
                    clonedFields.push(cloneField(field));
                }

                return clonedFields;
            }

            private function cloneField(field:Field):Field
            {
                return ObjectUtil.copy(field) as Field;
            }

            private function getFieldsFromURL():void
            {
                //TODO: use regEx validator
                var urlRE:RegExp = /https?:\/\/([^\s.]+.)+([^\s.]+)/;
                var layerURL:String = searchLayerURL;
                if (urlRE.test(layerURL))
                {
                    var detailsTask:DetailsTask = new DetailsTask();
                    var endsWithLayerIndex:RegExp = /^\s*(.+)\/(\d+)\s*$/;
                    var layerURLAndLayerIndex:Array = endsWithLayerIndex.exec(layerURL) as Array;
                    if (layerURLAndLayerIndex)
                    {
                        detailsTask.url = layerURLAndLayerIndex[1];
                        detailsTask.getDetails(Number(layerURLAndLayerIndex[2]), new AsyncResponder(getDetailsResultHandler, getDetailsFaultHandler, detailsTask));
                    }
                }
            }

            private function getDetailsResultHandler(layerDetails:LayerDetails, detailsTask:DetailsTask):void
            {
                const currentLoadedURL:String = detailsTask.url + "/" + layerDetails.id;
                if (lastLoadedURL != currentLoadedURL)
                {
                    lastLoadedURL = currentLoadedURL;
                    searchLayerFields.removeAll();
                }

                layerFields.source = FieldUtil.getValidFields(layerDetails.fields);
            }

            private function getDetailsFaultHandler(fault:Fault, token:Object):void
            {
                //TODO: log error
            }

            private function addSelectedFields():void
            {
                const selectedFields:Vector.<Object> = fieldsDataGrid.selectedItems;

                for each (var field:Field in selectedFields)
                {
                    const fieldCopy:Field = new Field();
                    fieldCopy.name = field.name;
                    fieldCopy.alias = field.alias;
                    searchLayerFields.addItem(fieldCopy);
                }
            }

            private function fieldsDataGrid_gridDoubleClickHandler(event:GridEvent):void
            {
                addSelectedFields();
            }

            private function okButton_clickHandler(event:MouseEvent):void
            {
                commitSearchLayerEdits();
                currentState = "listSearchLayers";
            }

            private function commitSearchLayerEdits():void
            {
                var newSearchLayer:SearchLayer = createSearchLayer();

                if (isInCreateMode)
                {
                    searchModel.searchLayers.addItem(newSearchLayer);
                }
                else
                {
                    replaceSearchLayer(searchLayerToEdit, newSearchLayer);
                }
            }

            private function createSearchLayer():SearchLayer
            {
                var searchLayer:SearchLayer = new SearchLayer();
                searchLayer.url = searchLayerURL;
                searchLayer.expression = searchLayerExpression;
                searchLayer.textSearchLabel = searchLayerLabel;
                searchLayer.titleField = displayFieldsDataGrid.titleFieldName;
                searchLayer.orderByField = displayFieldsDataGrid.orderByFieldName;
                searchLayer.orderByFieldDirection = displayFieldsDataGrid.orderByFieldDirection;
                searchLayer.name = searchLayerName;
                searchLayer.useProxy = searchLayerUseProxy;
                searchLayer.fields.addAll(searchLayerFields);

                return searchLayer;
            }

            private function replaceSearchLayer(toBeReplaced:SearchLayer, toReplaceBy:SearchLayer):void
            {
                var searchLayers:ArrayList = searchModel.searchLayers;
                var toBeReplacedIndex:int = searchLayers.getItemIndex(toBeReplaced);
                searchLayers.addItemAt(toReplaceBy, toBeReplacedIndex);
                searchLayers.removeItem(toBeReplaced);
            }

            private function cancelButton_clickHandler(event:MouseEvent):void
            {
                currentState = "listSearchLayers";
            }

            private function startCreateSearchLayerMode():void
            {
                isInCreateMode = true;

                searchLayerURL = "http://server.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_Median_Age/MapServer/4";
                searchLayerName = "Name";
                searchLayerLabel = "Label";
                searchLayerExpression = "";
                searchLayerUseProxy = false;
                searchLayerFields.source = [];
                validateExpression();

                layerFields.removeAll();

                currentState = "configureSearchLayer";
            }

            private function validateExpression():void
            {
                const valueToken:RegExp = /.*\[value\].*/g;
                hasValidExpression = searchLayerExpression.length == 0 || valueToken.test(searchLayerExpression);
            }

            protected function serviceBrowser_selectionChangeHandler(event:ServiceBrowserEvent):void
            {
                if (event.hasValidSelection)
                {
                    const selectedLayer:LayerNode = serviceBrowser.serviceSelection.getItemAt(0) as LayerNode;
                    searchLayerURL = selectedLayer.url;
                    getFieldsFromURL();
                    currentState = "configureSearchLayer";
                }
            }

            protected function backButton_clickHandler(event:MouseEvent):void
            {
                currentState = "configureSearchLayer";
            }

            protected function searchLayerURLInput_enterHandler(event:FlexEvent):void
            {
                processServiceLayerURL();
            }

            private function browseForQueryLayers():void
            {
                currentState = "browsingQueryLayers";
                serviceBrowser.browseService();
            }

            private function hasLayerEndPoint():Boolean
            {
                const layerEndPoint:RegExp = / \/ [a-z]+ Server \/ [0-9]+ $ /ix;
                return layerEndPoint.test(searchLayerURL);
            }

            private function processServiceLayerURL():void
            {
                if (hasLayerEndPoint())
                {
                    getFieldsFromURL();
                }
                else
                {
                    browseForQueryLayers();
                }
            }

            private function searchLayerDataGrid_editItemHandler(event:ModifyItemEvent):void
            {
                searchLayerToEdit = event.item as SearchLayer;<commit_msg>Use layer metadata to set better search name default.<commit_after><?xml version="1.0" encoding="utf-8"?>
<!--
  //////////////////////////////////////////////////////////////////
  // Copyright (c) 2008-2013 Esri. All Rights Reserved.
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //    http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  ////////////////////////////////////////////////////////////////
-->
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
         xmlns:s="library://ns.adobe.com/flex/spark"
         xmlns:components="com.esri.builder.components.*"
         xmlns:supportClasses="modules.supportClasses.*"
         xmlns:graphics="assets.graphics.*"
         xmlns:views="com.esri.builder.views.*"
         width="100%" height="100%"
         implements="modules.IWidgetView">
    <fx:Script>
        <![CDATA[
            import com.esri.ags.layers.supportClasses.Field;
            import com.esri.ags.layers.supportClasses.LayerDetails;
            import com.esri.ags.tasks.DetailsTask;
            import com.esri.builder.components.ModifyItemEvent;
            import com.esri.builder.components.serviceBrowser.nodes.LayerNode;
            import com.esri.builder.components.serviceBrowser.supportClasses.ServiceBrowserEvent;
            import com.esri.builder.model.Model;
            import com.esri.builder.model.RecentlyUsedURLsModel;
            import com.esri.builder.supportClasses.FieldUtil;
            import com.esri.builder.views.BuilderAlert;

            import modules.IWidgetModel;

            import mx.controls.Alert;
            import mx.events.FlexEvent;
            import mx.rpc.AsyncResponder;
            import mx.rpc.Fault;
            import mx.utils.ObjectUtil;

            import spark.events.GridEvent;

            private const SEARCH_EXPRESSION_SAMPLE:String =
                "PARCELID like \'[value]\'\n" +
                "upper(STATE) LIKE upper(\'[value]\')\n" +
                "upper(NAME) LIKE upper(\'%[value]%\')";

            private var lastLoadedURL:String;

            [Bindable]
            private var layerFields:ArrayList = new ArrayList();
            [Bindable]
            public var searchLayerURL:String;
            [Bindable]
            public var searchLayerName:String;
            [Bindable]
            public var searchLayerLabel:String;
            [Bindable]
            public var searchLayerExpression:String;
            [Bindable]
            public var searchLayerUseProxy:Boolean;
            [Bindable]
            public var searchLayerFields:ArrayList = new ArrayList();
            [Bindable]
            private var searchModel:SearchModel;
            [Bindable]
            private var isInCreateMode:Boolean;
            [Bindable]
            private var hasValidExpression:Boolean;

            private var searchLayerToEdit:SearchLayer;

            public function get widgetModel():IWidgetModel
            {
                return searchModel;
            }

            public function set widgetModel(widgetModel:IWidgetModel):void
            {
                if (widgetModel is SearchModel)
                {
                    searchModel = widgetModel as SearchModel;
                }
                else
                {
                    throw new Error('argument is not an instance of SearchModel');
                }
            }

            public function submit():Boolean
            {
                var wasOKClickedDuringSearchLayerConfiguration:Boolean = (currentState == "configureSearchLayer");
                if (wasOKClickedDuringSearchLayerConfiguration)
                {
                    commitUnsavedSearchLayerEdits();
                }

                if (searchModel.searchLayers.length == 0)
                {
                    BuilderAlert.show(resourceManager.getString('BuilderStrings', 'search.missingSearchLayers'),
                                      resourceManager.getString('BuilderStrings', 'widgetsView.widgetConfigurationError'),
                                      Alert.OK);
                    return false;
                }

                return true;
            }

            private function commitUnsavedSearchLayerEdits():void
            {
                var hasValidEdits:Boolean = (searchLayerURL && searchLayerName);
                if (hasValidEdits)
                {
                    commitSearchLayerEdits();
                }
            }

            public function cancel():void
            {
            }

            private function startEditSearchLayerMode(searchLayerToEdit:SearchLayer):void
            {
                isInCreateMode = false;

                var fields:Array = cloneFields(searchLayerToEdit.fields.source);

                searchLayerURL = searchLayerToEdit.url;
                searchLayerExpression = searchLayerToEdit.expression;
                searchLayerName = searchLayerToEdit.name;
                searchLayerLabel = searchLayerToEdit.textSearchLabel;
                searchLayerUseProxy = searchLayerToEdit.useProxy;
                searchLayerFields.source = fields;

                lastLoadedURL = searchLayerURL;
                getPropertiesFromLayerMetadata();
                validateExpression();

                currentState = "configureSearchLayer";
                displayFieldsDataGrid.updateTitleField(
                    FieldUtil.findFieldByName(fields, searchLayerToEdit.titleField));
                displayFieldsDataGrid.updateOrderByField(
                    FieldUtil.findFieldByName(fields, searchLayerToEdit.orderByField),
                    searchLayerToEdit.orderByFieldDirection);
            }

            private function cloneFields(fields:Array):Array
            {
                var clonedFields:Array = [];

                for each (var field:Field in fields)
                {
                    clonedFields.push(cloneField(field));
                }

                return clonedFields;
            }

            private function cloneField(field:Field):Field
            {
                return ObjectUtil.copy(field) as Field;
            }

            private function getPropertiesFromLayerMetadata():void
            {
                //TODO: use regEx validator
                var urlRE:RegExp = /https?:\/\/([^\s.]+.)+([^\s.]+)/;
                var layerURL:String = searchLayerURL;
                if (urlRE.test(layerURL))
                {
                    var detailsTask:DetailsTask = new DetailsTask();
                    var endsWithLayerIndex:RegExp = /^\s*(.+)\/(\d+)\s*$/;
                    var layerURLAndLayerIndex:Array = endsWithLayerIndex.exec(layerURL) as Array;
                    if (layerURLAndLayerIndex)
                    {
                        detailsTask.url = layerURLAndLayerIndex[1];
                        detailsTask.getDetails(Number(layerURLAndLayerIndex[2]), new AsyncResponder(getDetailsResultHandler, getDetailsFaultHandler, detailsTask));
                    }
                }
            }

            private function getDetailsResultHandler(layerDetails:LayerDetails, detailsTask:DetailsTask):void
            {
                const currentLoadedURL:String = detailsTask.url + "/" + layerDetails.id;
                if (lastLoadedURL != currentLoadedURL)
                {
                    lastLoadedURL = currentLoadedURL;
                    searchLayerFields.removeAll();
                }

                if (!searchLayerName)
                {
                    searchLayerName = layerDetails.name;
                }

                layerFields.source = FieldUtil.getValidFields(layerDetails.fields);
            }

            private function getDetailsFaultHandler(fault:Fault, token:Object):void
            {
                //TODO: log error
            }

            private function addSelectedFields():void
            {
                const selectedFields:Vector.<Object> = fieldsDataGrid.selectedItems;

                for each (var field:Field in selectedFields)
                {
                    const fieldCopy:Field = new Field();
                    fieldCopy.name = field.name;
                    fieldCopy.alias = field.alias;
                    searchLayerFields.addItem(fieldCopy);
                }
            }

            private function fieldsDataGrid_gridDoubleClickHandler(event:GridEvent):void
            {
                addSelectedFields();
            }

            private function okButton_clickHandler(event:MouseEvent):void
            {
                commitSearchLayerEdits();
                currentState = "listSearchLayers";
            }

            private function commitSearchLayerEdits():void
            {
                var newSearchLayer:SearchLayer = createSearchLayer();

                if (isInCreateMode)
                {
                    searchModel.searchLayers.addItem(newSearchLayer);
                }
                else
                {
                    replaceSearchLayer(searchLayerToEdit, newSearchLayer);
                }
            }

            private function createSearchLayer():SearchLayer
            {
                var searchLayer:SearchLayer = new SearchLayer();
                searchLayer.url = searchLayerURL;
                searchLayer.expression = searchLayerExpression;
                searchLayer.textSearchLabel = searchLayerLabel;
                searchLayer.titleField = displayFieldsDataGrid.titleFieldName;
                searchLayer.orderByField = displayFieldsDataGrid.orderByFieldName;
                searchLayer.orderByFieldDirection = displayFieldsDataGrid.orderByFieldDirection;
                searchLayer.name = searchLayerName;
                searchLayer.useProxy = searchLayerUseProxy;
                searchLayer.fields.addAll(searchLayerFields);

                return searchLayer;
            }

            private function replaceSearchLayer(toBeReplaced:SearchLayer, toReplaceBy:SearchLayer):void
            {
                var searchLayers:ArrayList = searchModel.searchLayers;
                var toBeReplacedIndex:int = searchLayers.getItemIndex(toBeReplaced);
                searchLayers.addItemAt(toReplaceBy, toBeReplacedIndex);
                searchLayers.removeItem(toBeReplaced);
            }

            private function cancelButton_clickHandler(event:MouseEvent):void
            {
                currentState = "listSearchLayers";
            }

            private function startCreateSearchLayerMode():void
            {
                isInCreateMode = true;

                searchLayerURL = "http://server.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_Median_Age/MapServer/4";
                searchLayerName = "";
                searchLayerLabel = "Label";
                searchLayerExpression = "";
                searchLayerUseProxy = false;
                searchLayerFields.source = [];
                validateExpression();

                layerFields.removeAll();

                currentState = "configureSearchLayer";
            }

            private function validateExpression():void
            {
                const valueToken:RegExp = /.*\[value\].*/g;
                hasValidExpression = searchLayerExpression.length == 0 || valueToken.test(searchLayerExpression);
            }

            protected function serviceBrowser_selectionChangeHandler(event:ServiceBrowserEvent):void
            {
                if (event.hasValidSelection)
                {
                    const selectedLayer:LayerNode = serviceBrowser.serviceSelection.getItemAt(0) as LayerNode;
                    searchLayerURL = selectedLayer.url;
                    getPropertiesFromLayerMetadata();
                    currentState = "configureSearchLayer";
                }
            }

            protected function backButton_clickHandler(event:MouseEvent):void
            {
                currentState = "configureSearchLayer";
            }

            protected function searchLayerURLInput_enterHandler(event:FlexEvent):void
            {
                processServiceLayerURL();
            }

            private function browseForQueryLayers():void
            {
                currentState = "browsingQueryLayers";
                serviceBrowser.browseService();
            }

            private function hasLayerEndPoint():Boolean
            {
                const layerEndPoint:RegExp = / \/ [a-z]+ Server \/ [0-9]+ $ /ix;
                return layerEndPoint.test(searchLayerURL);
            }

            private function processServiceLayerURL():void
            {
                if (hasLayerEndPoint())
                {
                    getPropertiesFromLayerMetadata();
                }
                else
                {
                    browseForQueryLayers();
                }
            }

            private function searchLayerDataGrid_editItemHandler(event:ModifyItemEvent):void
            {
                searchLayerToEdit = event.item as SearchLayer;
{'fraction_non_alphanumeric': 0.08658572918218382, 'fraction_numerical': 0.0024579174735587664, 'mean_word_length': 1.5484483249501755, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 2, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 16}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4104405', 'n_tokens_mistral': 6395, 'n_tokens_neox': 5888, 'n_words': 1098}