Пример #1
0
    def execute(self):        
        project = config.project

        files = self.params.get('files', None)
        use_tooling_api = config.connection.get_plugin_client_setting('mm_compile_with_tooling_api', False)
        check_for_conflicts = config.connection.get_plugin_client_setting('mm_compile_check_conflicts', False)

        compiling_apex_metadata = True
        for f in files:
            if f.split('.')[-1] not in util.TOOLING_API_EXTENSIONS:
                #cannot use tooling api
                compiling_apex_metadata = False
                break

        #when compiling apex metadata, check to see if it is newer on the server
        if check_for_conflicts and compiling_apex_metadata:
            if 'action' not in self.params or self.params['action'] != 'overwrite':
                has_conflict, msg = config.project.conflict_manager.check_for_conflicts(files)
                if has_conflict:
                    return msg
     
        #use tooling api here, if possible
        if use_tooling_api == True and compiling_apex_metadata and int(float(util.SFDC_API_VERSION)) >= 27:
            if 'metadata_container' not in project.settings or project.settings['metadata_container'] == None:
                container_id = project.sfdc_client.get_metadata_container_id()
                new_settings = project.settings
                new_settings['metadata_container'] = container_id
                project.put_settings_file(new_settings)
            else:
                container_id = project.settings['metadata_container']
            
            file_ext = files[0].split('.')[-1]
            try:
                result = project.sfdc_client.compile_with_tooling_api(files, container_id)
            except MetadataContainerException as e:
                project.sfdc_client.delete_mavensmate_metadatacontainers_for_this_user()
                response = project.sfdc_client.new_metadatacontainer_for_this_user()
                project.update_setting("metadata_container",response["id"])
                #return CompileSelectedMetadataCommand(params=self.params,args=self.args).execute()
                #ensure only a single retry
                result = project.sfdc_client.compile_with_tooling_api(files, response["id"])

            if 'Id' in result and 'State' in result:
                if result['State'] == 'Completed':
                    project.conflict_manager.refresh_local_store(files=files)
                return util.generate_response(result)

        #the user has either chosen not to use the tooling api, or it's non apex metadata
        else:
            try:
                for f in files:
                    if '-meta.xml' in f:
                        corresponding_file = f.split('-meta.xml')[0]
                        if corresponding_file not in files:
                            files.append(corresponding_file)
                for f in files:
                    if '-meta.xml' in f:
                        continue
                    file_ext = f.split('.')[-1]
                    metadata_type = util.get_meta_type_by_suffix(file_ext)
                    if metadata_type == None:
                        if sys.platform == "win32":
                            dir_parts = f.split("\\")
                        else:
                            dir_parts = f.split("/")
                        if 'documents' in dir_parts:
                            metadata_type = util.get_meta_type_by_name("Document") 
                    if metadata_type != None and 'metaFile' in metadata_type and metadata_type['metaFile'] == True:
                        corresponding_file = f + '-meta.xml'
                        if corresponding_file not in files:
                            files.append(corresponding_file)

                metadata_package_dict = util.get_metadata_hash(files)
                #debug(metadata_package_dict)
                tmp = util.put_tmp_directory_on_disk()
                os.makedirs(os.path.join(tmp,"unpackaged"))
                #copy files from project directory to tmp
                for full_file_path in files:
                    if 'package.xml' in full_file_path:
                        continue
                    if config.is_windows: 
                        destination = os.path.join(tmp,'unpackaged',full_file_path.split('\src\\')[1])
                    else:
                        destination = os.path.join(tmp,'unpackaged',full_file_path.split('/src/')[1])
                    destination_directory = os.path.dirname(destination)
                    if not os.path.exists(destination_directory):
                        os.makedirs(destination_directory)
                    shutil.copy2(full_file_path, destination_directory)

                package_xml = util.get_package_xml_contents(metadata_package_dict)
                util.put_package_xml_in_directory(os.path.join(tmp,"unpackaged"), package_xml)
                zip_file = util.zip_directory(tmp, tmp)
                deploy_params = {
                    "zip_file"          : zip_file,
                    "rollback_on_error" : True,
                    "ret_xml"           : True
                }
                deploy_result = project.sfdc_client.deploy(deploy_params)

                d = xmltodict.parse(deploy_result,postprocessor=util.xmltodict_postprocessor)
                result = d["soapenv:Envelope"]["soapenv:Body"]['checkDeployStatusResponse']['result']
                shutil.rmtree(tmp)

                # Get new properties for the files we just compiled
                if result['success'] == True:
                    project.conflict_manager.refresh_local_store(files=files)

                return json.dumps(result)

            except Exception, e:
                try:
                    shutil.rmtree(tmp)
                except:
                    pass
                return util.generate_error_response(e.message)
Пример #2
0
    def execute(self):
        project = config.project
        sfdc_client = config.sfdc_client

        metadata_type                   = self.params.get('metadata_type', None)
        github_template                 = self.params.get('github_template', None)
        params                          = self.params.get('params', None)

        if params == None:
            raise MMException('The payload to create metadata has recently changed. If you are using Sublime Text, you likely need to update your MavensMate plugin to 3.4.8+')

        if "api_name" not in params or params["api_name"] == None:
            return util.generate_error_response("You must provide a name for the new metadata.")

        api_name = params.get('api_name')

        if sfdc_client.does_metadata_exist(object_type=metadata_type, name=api_name) == True:
            mt = util.get_meta_type_by_name(metadata_type)
            filepath = os.path.join(project.location, 'src', mt['directoryName'], api_name+'.'+mt['suffix'])
            fetched = ""
            if not os.path.exists(filepath):
                self.params['files'] = [filepath]
                RefreshSelectedMetadataCommand(params=self.params,args=self.args).execute()
                fetched = ", fetched metadata file from server"
            raise MMException("This API name is already in use in your org" + fetched + ".")      

        tmp, tmp_unpackaged = util.put_tmp_directory_on_disk(True)
        
        util.put_skeleton_files_on_disk(metadata_type, tmp_unpackaged, github_template, params)
        package_xml_body = util.get_package_xml_contents({metadata_type : [ api_name ]})
        util.put_package_xml_in_directory(tmp_unpackaged, package_xml_body)
        zip_file = util.zip_directory(tmp, tmp)
        deploy_params = {
            "zip_file"          : zip_file,
            "rollback_on_error" : True,
            "ret_xml"           : True
        }
        deploy_result = sfdc_client.deploy(deploy_params)
        d = xmltodict.parse(deploy_result,postprocessor=util.xmltodict_postprocessor)
        meta_dir = ""
        files = []
        path = None
        for dirname, dirnames, filenames in os.walk(tmp_unpackaged):
            for filename in filenames:
                if 'package.xml' in filename:
                    continue
                full_file_path = os.path.join(dirname, filename)
                if '-meta.xml' in filename:
                    extension = filename.replace('-meta.xml','').split(".")[-1]
                else:
                    extension = filename.split(".")[-1]
                mt = util.get_meta_type_by_suffix(extension)
                if mt != None: 
                    meta_dir = mt['directoryName']
                    path = os.path.join(project.location, 'src', meta_dir)
                    if not os.path.exists(path):
                        os.makedirs(path)
                    files.append(os.path.join(path, filename))
                elif extension != "xml":
                    continue;
                # only apex files and meta.xml files should make it to here
                shutil.copy(full_file_path, path)
        shutil.rmtree(tmp)
        
        project.update_package_xml_with_metadata(metadata_type, api_name)
        project.conflict_manager.refresh_local_store(files=files)

        return json.dumps(d["soapenv:Envelope"]["soapenv:Body"]['checkDeployStatusResponse']['result'])
Пример #3
0
    def retrieve(self, **kwargs):
        # request = {
        #   'RetrieveRequest': {
        #     'unpackaged': {
        #       'types': {
        #         'ApexTrigger': '*'
        #       }
        #     },
        #     'apiVersion': {
        #       25.0
        #     }
        #   }
        # }
        # package = {
        #     'unpackaged' : {
        #         'types' : [
        #             {
        #                 "members": "*",
        #                 "name": "ApexClass"
        #             }
        #         ]
        #     }
        # }
        package_dict = None
        request_payload = None

        debug('retrieve request: ')
        debug(kwargs['package'])

        if 'package' in kwargs and type(kwargs['package']) is not dict:
            #if package is location of package.xml, we'll parse the xml and create a request
            package_dict = xmltodict.parse(util.get_file_as_string(kwargs['package']))
            api_version = package_dict['Package']['version']
            package_dict['unpackaged'] = package_dict.pop('Package')
            package_dict['unpackaged'].pop('version')
            package_dict['unpackaged'].pop("@xmlns", None)
            package_dict['unpackaged'].pop("#text", None)
            package_dict['apiVersion'] = api_version
            types = package_dict['unpackaged']['types']
            if type(types) is not list:
                types = [types]
            if type(package_dict['unpackaged']['types']) is not list:
                package_dict['unpackaged']['types'] = [package_dict['unpackaged']['types']]
            requested_types = []
            if 'type' in kwargs and kwargs['type'] != None and kwargs['type'] != '': #if the request is for a certain type, only request that type
                for i, val in enumerate(types):
                    if val['name'] == kwargs['type']:
                        requested_types.append(val)
                package_dict['unpackaged']['types'] = requested_types
                types = requested_types
            for i, val in enumerate(types):
                try:
                    package_dict['unpackaged']['types'][i].pop("#text", None)
                except:
                    package_dict['unpackaged']['types'].pop("#text", None)

            #if custom object is asterisked, we need to explictly retrieve standard objects
            for t in package_dict['unpackaged']['types']:
                if 'name' in t:
                    metadata_type_def = util.get_meta_type_by_name(t['name'])
                    if metadata_type_def is not None and 'inFolder' in metadata_type_def and metadata_type_def['inFolder']: #TODO: right now this skips retrieval of unknown types, we should use describe data
                        if 'members' in t and type(t['members']) is not list:
                            if t['members'] == "*" or t['members'] == []:
                                mlist = self.listMetadata(t['name'], False)
                                objs = []
                                for obj in mlist:
                                    objs.append(obj['fullName'])
                                objs.sort()
                                t['members'] = objs
                    elif t['name'] == 'CustomObject':
                        if 'members' in t and type(t['members']) is not list:
                            if t['members'] == "*":
                                mlist = self.listMetadata('CustomObject', False)
                                objs = []
                                for obj in mlist:
                                    if ('__c') not in mlist:
                                        objs.append(obj['fullName'])
                                objs.append("*")
                                objs.sort()
                                t['members'] = objs

            request_payload = package_dict

        elif 'package' in kwargs and type(kwargs['package']) is dict:
            package = kwargs['package']
            if package == {}:
                raise MMException('Invalid package')
            if 'unpackaged' not in package:
                #{ "ApexClass"    : ["MultiselectControllerTest","MultiselectController"] }
                type_array = []
                for i, metadata_type in enumerate(package):
                    member_value = package[metadata_type]
                    type_array.append({ "name" : metadata_type, "members" : member_value })

                package = {
                    'unpackaged' : {
                        'types' : type_array
                    },
                    'apiVersion' : util.SFDC_API_VERSION
                }

            #if custom object is asterisked, we need to explictly retrieve standard objects
            for t in package['unpackaged']['types']:
                debug('----> ')
                debug(t)
                if 'name' in t:
                    metadata_type_def = util.get_meta_type_by_name(t['name'])
                    debug(metadata_type_def)
                    if metadata_type_def is not None and 'inFolder' in metadata_type_def and metadata_type_def['inFolder']: #TODO: right now this skips retrieval of unknown types, we should use describe data
                        if 'members' in t and (t['members'] == "*" or t['members'] == []):
                            #list_request_name = self.__transformFolderMetadataNameForListRequest(t['name'])
                            #mlist = self.listMetadata(list_request_name, False)
                            mlist = self.listMetadataAdvanced(t['name'])
                            objs = []
                            for obj in mlist:
                                debug('---obj')
                                debug(obj)
                                objs.append(obj['title'])
                                if 'children' in obj and type(obj['children'] is list):
                                    for child in obj['children']:
                                        objs.append(obj['title']+"/"+child['title'])
                            objs.sort()
                            t['members'] = objs
                    elif t['name'] == 'CustomObject':
                        if 'members' in t and type(t['members']) is not list:
                            if t['members'] == "*":
                                mlist = self.listMetadata('CustomObject', False)
                                objs = []
                                for obj in mlist:
                                    if ('__c') not in mlist:
                                        objs.append(obj['fullName'])
                                objs.append("*")
                                objs.sort()
                                t['members'] = objs

            request_payload = package
            debug('---request payload---')
            debug(request_payload)
        result = self._handleResultTyping(self._sforce.service.retrieve(request_payload))

        debug('result of retrieve: \n\n')
        debug(result)

        if result.done == False:
            debug('---> result is not done')
            if int(float(util.SFDC_API_VERSION)) > 30:
                return self._waitForRetrieveRequest(result.id) # will loop until done
            else:
                self._waitForRetrieveRequest(result.id) # will loop until done
                return self._getRetrieveBody(result.id)
        else:
            return result
Пример #4
0
    def listMetadataAdvanced(self, metadata_type):
        try:
            metadata_type_def = util.get_meta_type_by_name(metadata_type)
            if metadata_type_def == None:
                return []
            has_children_metadata = False
            if 'childXmlNames' in metadata_type_def and type(metadata_type_def['childXmlNames']) is list:
                has_children_metadata = True
            is_folder_metadata = 'inFolder' in metadata_type_def and metadata_type_def['inFolder']
            if is_folder_metadata == True:
                metadata_request_type = self.__transformFolderMetadataNameForListRequest(metadata_type)
            else:
                metadata_request_type = metadata_type
            list_response = self.listMetadata(metadata_request_type, True, util.SFDC_API_VERSION)
            debug('--------------->')
            debug(list_response)
            if type(list_response) is not list:
                list_response = [list_response]
            #print list_response
            object_hash = {} #=> {"Account" => [ {"fields" => ["foo", "bar"]}, "listviews" => ["foo", "bar"] ], "Contact" => ... }

            if has_children_metadata == True and len(list_response) > 0: #metadata objects like customobject, workflow, etc.
                request_names = []
                for element in list_response:
                    #if element['fullName'] != 'PersonAccount':
                    request_names.append(element['fullName'])
                retrieve_result = self.retrieve(package={
                    metadata_request_type : request_names
                })
                #print '>>>> ',retrieve_result
                tmp = util.put_tmp_directory_on_disk()
                util.extract_base64_encoded_zip(retrieve_result.zipFile, tmp)

                #iterate extracted directory
                for dirname, dirnames, filenames in os.walk(os.path.join(tmp,"unpackaged",metadata_type_def['directoryName'])):
                    for f in filenames:
                        #f => Account.object
                        full_file_path = os.path.join(dirname, f)
                        data = util.parse_xml_from_file(full_file_path)
                        c_hash = {}
                        for child_type in metadata_type_def['childXmlNames']:
                            child_type_def = util.get_meta_type_by_name(child_type)
                            if child_type_def == None: #TODO handle newer child types
                                continue
                            tag_name = child_type_def['tagName']
                            items = []
                            try:
                                if tag_name in data[metadata_request_type]:
                                    if type(data[metadata_request_type][tag_name]) is not list:
                                        data[metadata_request_type][tag_name] = [data[metadata_request_type][tag_name]]
                                    for i, val in enumerate(data[metadata_request_type][tag_name]):
                                        items.append(val['fullName'])
                            except BaseException, e:
                                #print 'exception >>>> ', e.message
                                pass

                            c_hash[tag_name] = items

                        base_name = f.split(".")[0]
                        object_hash[base_name] = c_hash

                shutil.rmtree(tmp)
            #print '>>> ',object_hash
            return_elements = []
            for element in list_response:
                if config.connection.get_plugin_client_setting('mm_ignore_managed_metadata') == True:
                    if 'manageableState' in element and element["manageableState"] != "unmanaged":
                        continue

                children = []
                full_name = element['fullName']
                #if full_name == "PersonAccount":
                #    full_name = "Account"
                #print 'processing: ', element
                if has_children_metadata == True:
                    if not full_name in object_hash:
                        continue
                    object_detail = object_hash[full_name]
                    if object_detail == None:
                        continue

                    for child in metadata_type_def['childXmlNames']:
                        child_type_def = util.get_meta_type_by_name(child)
                        if child_type_def == None: #TODO: handle more complex types
                            continue
                        tag_name = child_type_def['tagName']
                        if len(object_detail[tag_name]) > 0:
                            gchildren = []
                            for gchild_el in object_detail[tag_name]:
                                gchildren.append({
                                    "text"      : gchild_el,
                                    "isFolder"  : False,
                                    "checked"   : False,
                                    "level"     : 4,
                                    "leaf"      : True,
                                    "id"        : metadata_type_def['xmlName']+"."+full_name+"."+tag_name+"."+gchild_el,
                                    "select"    : False,
                                    "title"     : gchild_el
                                })
                                children = sorted(children, key=itemgetter('text'))

                            children.append({
                                "text"      : child_type_def['tagName'],
                                "isFolder"  : True,
                                "cls"       : "folder",
                                "children"  : gchildren,
                                "checked"   : False,
                                "level"     : 3,
                                "id"        : metadata_type_def['xmlName']+"."+full_name+"."+tag_name,
                                "select"    : False,
                                "title"     : child_type_def['tagName']
                            })

                #if this type has folders, run queries to grab all metadata in the folders
                if is_folder_metadata == True:
                    if config.connection.get_plugin_client_setting('mm_ignore_managed_metadata', True):
                        if 'manageableState' in element and element["manageableState"] != "unmanaged":
                            continue
                    #print element["fullName"]
                    list_request = {
                        "type"      : metadata_type,
                        "folder"    : element["fullName"]
                    }
                    list_basic_response = self.listMetadata(list_request, True, config.connection.sfdc_api_version)

                    if type(list_basic_response) is not list:
                        list_basic_response = [list_basic_response]

                    for folder_element in list_basic_response:
                        children.append({
                            "text"      : folder_element['fullName'].split("/")[1],
                            "leaf"      : True,
                            "isFolder"  : False,
                            "checked"   : False,
                            "level"     : 3,
                            "id"        : folder_element['fullName'].replace('/', '.'),
                            "select"    : False,
                            "title"     : folder_element['fullName'].split("/")[1]

                        })

                children = sorted(children, key=itemgetter('text'))
                is_leaf = True
                cls = ''
                if is_folder_metadata:
                    is_leaf = False
                    cls = 'folder'
                if has_children_metadata:
                    is_leaf = False
                    cls = 'folder'
                if metadata_type_def['xmlName'] == 'Workflow':
                    is_leaf = True
                    cls = ''
                #print '>>> ',element
                return_elements.append({
                    "text"      : element['fullName'],
                    "isFolder"  : is_folder_metadata or has_children_metadata,
                    "cls"       : cls,
                    "leaf"      : is_leaf,
                    "children"  : children,
                    "checked"   : False,
                    "level"     : 2,
                    "id"        : metadata_type_def['xmlName']+'.'+full_name.replace(' ', ''),
                    "select"    : False,
                    "title"     : element['fullName']
                })

            return_elements = sorted(return_elements, key=itemgetter('text'))
            # if list_response == []:
            #     return list_response

            # return list_response
            return return_elements
Пример #5
0
    def retrieve(self, **kwargs):
        # request = {
        #   'RetrieveRequest': {
        #     'unpackaged': {
        #       'types': {
        #         'ApexTrigger': '*'
        #       }
        #     },
        #     'apiVersion': {
        #       25.0
        #     }
        #   }
        # }
        # package = {
        #     'unpackaged' : {
        #         'types' : [
        #             {
        #                 "members": "*",
        #                 "name": "ApexClass"
        #             }
        #         ]
        #     }
        # }
        package_dict = None
        request_payload = None

        debug('retrieve request: ')
        debug(kwargs['package'])

        if 'package' in kwargs and type(kwargs['package']) is not dict:
            #if package is location of package.xml, we'll parse the xml and create a request
            package_dict = xmltodict.parse(util.get_file_as_string(kwargs['package']))
            api_version = package_dict['Package']['version']
            package_dict['unpackaged'] = package_dict.pop('Package')
            package_dict['unpackaged'].pop('version')
            package_dict['unpackaged'].pop("@xmlns", None)
            package_dict['unpackaged'].pop("#text", None)
            package_dict['apiVersion'] = api_version
            
            if 'types' not in package_dict['unpackaged']:
                # raise MMException('Invalid package.xml. Please ensure your package ')
                package_dict['unpackaged']['types'] = []
            
            types = package_dict['unpackaged']['types']
            
            if type(types) is not list:
                types = [types]
            if type(package_dict['unpackaged']['types']) is not list:
                package_dict['unpackaged']['types'] = [package_dict['unpackaged']['types']]
            
            requested_types = []
            if 'type' in kwargs and kwargs['type'] != None and kwargs['type'] != '': #if the request is for a certain type, only request that type
                for i, val in enumerate(types):
                    if val['name'] == kwargs['type']:
                        requested_types.append(val)
                package_dict['unpackaged']['types'] = requested_types
                types = requested_types
            for i, val in enumerate(types):
                try:
                    package_dict['unpackaged']['types'][i].pop("#text", None)
                except:
                    package_dict['unpackaged']['types'].pop("#text", None)

            #if custom object is asterisked, we need to explictly retrieve standard objects
            for t in package_dict['unpackaged']['types']:
                if 'name' in t:
                    metadata_type_def = util.get_meta_type_by_name(t['name'])
                    if metadata_type_def is not None and 'inFolder' in metadata_type_def and metadata_type_def['inFolder']: #TODO: right now this skips retrieval of unknown types, we should use describe data
                        if 'members' in t and type(t['members']) is not list:
                            if t['members'] == "*" or t['members'] == []:
                                mlist = self.listMetadata(t['name'], False)
                                objs = []
                                for obj in mlist:
                                    objs.append(obj['fullName'])
                                objs.sort()
                                t['members'] = objs
                    elif t['name'] == 'CustomObject':
                        if 'members' in t and type(t['members']) is not list:
                            if t['members'] == "*":
                                mlist = self.listMetadata('CustomObject', False)
                                objs = []
                                for obj in mlist:
                                    if ('__c') not in mlist:
                                        objs.append(obj['fullName'])
                                objs.append("*")
                                objs.sort()
                                t['members'] = objs

            request_payload = package_dict

        elif 'package' in kwargs and type(kwargs['package']) is dict:
            package = kwargs['package']
            if package == {}:
                raise MMException('Invalid package')
            if 'unpackaged' not in package:
                #{ "ApexClass"    : ["MultiselectControllerTest","MultiselectController"] }
                type_array = []
                for i, metadata_type in enumerate(package):
                    member_value = package[metadata_type]
                    type_array.append({ "name" : metadata_type, "members" : member_value })

                package = {
                    'unpackaged' : {
                        'types' : type_array
                    },
                    'apiVersion' : util.SFDC_API_VERSION
                }

            #if custom object is asterisked, we need to explictly retrieve standard objects
            for t in package['unpackaged']['types']:
                debug('----> ')
                debug(t)
                if 'name' in t:
                    metadata_type_def = util.get_meta_type_by_name(t['name'])
                    debug(metadata_type_def)
                    if metadata_type_def is not None and 'inFolder' in metadata_type_def and metadata_type_def['inFolder']: #TODO: right now this skips retrieval of unknown types, we should use describe data
                        if 'members' in t and (t['members'] == "*" or t['members'] == []):
                            #list_request_name = self.__transformFolderMetadataNameForListRequest(t['name'])
                            #mlist = self.listMetadata(list_request_name, False)
                            mlist = self.listMetadataAdvanced(t['name'])
                            objs = []
                            for obj in mlist:
                                debug('---obj')
                                debug(obj)
                                objs.append(obj['title'])
                                if 'children' in obj and type(obj['children'] is list):
                                    for child in obj['children']:
                                        objs.append(obj['title']+"/"+child['title'])
                            objs.sort()
                            t['members'] = objs
                    elif t['name'] == 'CustomObject':
                        if 'members' in t and type(t['members']) is not list:
                            if t['members'] == "*":
                                mlist = self.listMetadata('CustomObject', False)
                                objs = []
                                for obj in mlist:
                                    if ('__c') not in mlist:
                                        objs.append(obj['fullName'])
                                objs.append("*")
                                objs.sort()
                                t['members'] = objs

            request_payload = package
            debug('---request payload---')
            debug(request_payload)
        result = self._handleResultTyping(self._sforce.service.retrieve(request_payload))

        debug('result of retrieve: \n\n')
        debug(result)

        if result.done == False:
            debug('---> result is not done')
            if int(float(util.SFDC_API_VERSION)) > 30:
                return self._waitForRetrieveRequest(result.id) # will loop until done
            else:
                self._waitForRetrieveRequest(result.id) # will loop until done
                return self._getRetrieveBody(result.id)
        else:
            return result
Пример #6
0
    def listMetadataAdvanced(self, metadata_type):
        try:
            metadata_type_def = util.get_meta_type_by_name(metadata_type)
            if metadata_type_def == None:
                return []
            has_children_metadata = False
            if 'childXmlNames' in metadata_type_def and type(metadata_type_def['childXmlNames']) is list:
                has_children_metadata = True
            is_folder_metadata = 'inFolder' in metadata_type_def and metadata_type_def['inFolder']
            if is_folder_metadata == True:
                metadata_request_type = self.__transformFolderMetadataNameForListRequest(metadata_type)
            else:
                metadata_request_type = metadata_type
            list_response = self.listMetadata(metadata_request_type, True, util.SFDC_API_VERSION)
            debug('--------------->')
            debug(list_response)
            if type(list_response) is not list:
                list_response = [list_response]
            #print list_response
            object_hash = {} #=> {"Account" => [ {"fields" => ["foo", "bar"]}, "listviews" => ["foo", "bar"] ], "Contact" => ... }

            if has_children_metadata == True and len(list_response) > 0: #metadata objects like customobject, workflow, etc.
                request_names = []
                for element in list_response:
                    #if element['fullName'] != 'PersonAccount':
                    request_names.append(element['fullName'])
                retrieve_result = self.retrieve(package={
                    metadata_request_type : request_names
                })
                #print '>>>> ',retrieve_result
                tmp = util.put_tmp_directory_on_disk()
                util.extract_base64_encoded_zip(retrieve_result.zipFile, tmp)

                #iterate extracted directory
                for dirname, dirnames, filenames in os.walk(os.path.join(tmp,"unpackaged",metadata_type_def['directoryName'])):
                    for f in filenames:
                        #f => Account.object
                        full_file_path = os.path.join(dirname, f)
                        data = util.parse_xml_from_file(full_file_path)
                        c_hash = {}
                        for child_type in metadata_type_def['childXmlNames']:
                            child_type_def = util.get_meta_type_by_name(child_type)
                            if child_type_def == None: #TODO handle newer child types
                                continue
                            tag_name = child_type_def['tagName']
                            items = []
                            try:
                                if tag_name in data[metadata_request_type]:
                                    if type(data[metadata_request_type][tag_name]) is not list:
                                        data[metadata_request_type][tag_name] = [data[metadata_request_type][tag_name]]
                                    for i, val in enumerate(data[metadata_request_type][tag_name]):
                                        items.append(val['fullName'])
                            except BaseException, e:
                                #print 'exception >>>> ', e.message
                                pass

                            c_hash[tag_name] = items

                        base_name = f.split(".")[0]
                        object_hash[base_name] = c_hash

                shutil.rmtree(tmp)
            #print '>>> ',object_hash
            return_elements = []
            for element in list_response:
                if config.connection.get_plugin_client_setting('mm_ignore_managed_metadata') == True:
                    if 'manageableState' in element and element["manageableState"] != "unmanaged":
                        continue

                children = []
                full_name = element['fullName']
                #if full_name == "PersonAccount":
                #    full_name = "Account"
                #print 'processing: ', element
                if has_children_metadata == True:
                    if not full_name in object_hash:
                        continue
                    object_detail = object_hash[full_name]
                    if object_detail == None:
                        continue

                    for child in metadata_type_def['childXmlNames']:
                        child_type_def = util.get_meta_type_by_name(child)
                        if child_type_def == None: #TODO: handle more complex types
                            continue
                        tag_name = child_type_def['tagName']
                        if len(object_detail[tag_name]) > 0:
                            gchildren = []
                            for gchild_el in object_detail[tag_name]:
                                gchildren.append({
                                    "text"      : gchild_el,
                                    "isFolder"  : False,
                                    "checked"   : False,
                                    "level"     : 4,
                                    "leaf"      : True,
                                    "id"        : metadata_type_def['xmlName']+"."+full_name+"."+tag_name+"."+gchild_el,
                                    "select"    : False,
                                    "title"     : gchild_el
                                })
                                children = sorted(children, key=itemgetter('text'))

                            children.append({
                                "text"      : child_type_def['tagName'],
                                "isFolder"  : True,
                                "cls"       : "folder",
                                "children"  : gchildren,
                                "checked"   : False,
                                "level"     : 3,
                                "id"        : metadata_type_def['xmlName']+"."+full_name+"."+tag_name,
                                "select"    : False,
                                "title"     : child_type_def['tagName']
                            })

                #if this type has folders, run queries to grab all metadata in the folders
                if is_folder_metadata == True:
                    if config.connection.get_plugin_client_setting('mm_ignore_managed_metadata', True):
                        if 'manageableState' in element and element["manageableState"] != "unmanaged":
                            continue
                    #print element["fullName"]
                    list_request = {
                        "type"      : metadata_type,
                        "folder"    : element["fullName"]
                    }
                    list_basic_response = self.listMetadata(list_request, True, config.connection.sfdc_api_version)

                    if type(list_basic_response) is not list:
                        list_basic_response = [list_basic_response]

                    for folder_element in list_basic_response:
                        children.append({
                            "text"      : folder_element['fullName'].split("/")[1],
                            "leaf"      : True,
                            "isFolder"  : False,
                            "checked"   : False,
                            "level"     : 3,
                            "id"        : folder_element['fullName'].replace('/', '.'),
                            "select"    : False,
                            "title"     : folder_element['fullName'].split("/")[1]

                        })

                children = sorted(children, key=itemgetter('text'))
                is_leaf = True
                cls = ''
                if is_folder_metadata:
                    is_leaf = False
                    cls = 'folder'
                if has_children_metadata:
                    is_leaf = False
                    cls = 'folder'
                if metadata_type_def['xmlName'] == 'Workflow':
                    is_leaf = True
                    cls = ''
                #print '>>> ',element
                return_elements.append({
                    "text"      : element['fullName'],
                    "isFolder"  : is_folder_metadata or has_children_metadata,
                    "cls"       : cls,
                    "leaf"      : is_leaf,
                    "children"  : children,
                    "checked"   : False,
                    "level"     : 2,
                    "id"        : metadata_type_def['xmlName']+'.'+full_name.replace(' ', ''),
                    "select"    : False,
                    "title"     : element['fullName']
                })

            return_elements = sorted(return_elements, key=itemgetter('text'))
            # if list_response == []:
            #     return list_response

            # return list_response
            return return_elements