Ejemplo n.º 1
0
def translate_collection_adjective(method, resources, sample_values):
    if method not in ['get', 'delete']:
        return None

    if len(resources) != 2:
        return None

    if resources[0].resource_type != ATTRIBUTE_RESOURCE or resources[1].resource_type != COLLECTION:
        return None

    adjective = ParamUtils.normalize(resources[0].name)
    resource = ParamUtils.normalize(resources[1].name)

    for key in ["get ", "set ", "create ", "put ", "delete "]:
        if resource.startswith(key):
            resource = resource[len(key):]

    if is_singular(resource) or ' ' in resource:
        ret = 'get the {} {}'
    else:
        ret = 'get the list of {} {}'

    if method == 'delete':
        ret = 'delete all {} {}'

    return ret.format(adjective, resource)
Ejemplo n.º 2
0
def translate_singleton(method, resources, sample_values):
    if method not in ['get', 'patch', 'delete', 'put']:
        return None

    if len(resources) != 1:
        return None

        # if ':' in resources[0].name:
        # //v1/{name}:setDefault
        # return None

    if resources[0].resource_type != SINGLETON:
        return None

    resource = ParamUtils.normalize(resources[0].name)
    resource = singular(resource)
    # print(resources)
    # print(resource)
    if sample_values:
        vals = param_sampler.sample(resources[0].param, 1)
        val = vals[0] if vals else resources[0].param.name
    else:
        val = resources[0].param.name

    parameter_value = '<< {} >>'.format(val)
    ret = 'get a {} with {} being {}'
    if method == 'patch':
        ret = 'update a {} with {} being {}'
    elif method == 'delete':
        ret = 'delete a {} with {} being {}'
    elif method == 'put':
        ret = 'replace a {} with {} being {}'

    return ret.format(resource, ParamUtils.normalize(resources[0].param.name), parameter_value)
Ejemplo n.º 3
0
def translate_singleton_action(method, resources, sample_values):
    if method not in ['get', 'patch', 'delete', 'put']:
        return None

    if len(resources) != 2:
        return None

    if ACTION_RESOURCE not in resources[0].resource_type or resources[1].resource_type != SINGLETON:
        return None

    resource = ParamUtils.normalize(resources[1].name)
    resource = singular(resource)

    if sample_values:
        vals = param_sampler.sample(resources[1].param.name, 1)
        val = vals[0] if vals else resources[1].param.name
    else:
        val = resources[1].param.name

    parameter_value = '<< {} >>'.format(val)

    verb = ParamUtils.normalize(resources[0].name)
    if verb.endswith('ed'):
        verb = verb[:-1]

    ret = '{} a {} with {} being {}'
    # if method == 'patch':
    #     ret = 'update the {} with {} being {}'
    # elif method == 'delete':
    #     ret = 'delete the {} with {} being {}'
    # elif method == 'put':
    #     ret = 'replace the {} with {} being {}'

    return ret.format(verb, resource, ParamUtils.normalize(resources[1].param.name), parameter_value)
Ejemplo n.º 4
0
    def url_to_resource_sequence(e: Operation, resources: list):

        counter = dict()
        for r in RESOURCE_TYPES:
            counter[r] = 1

        # Remove unknown resources from the beginning of the url
        if resources:
            to_remove = []
            for i, r in enumerate(reversed(resources)):

                if r.resource_type in [UNKNOWN_PARAM_RESOURCE] and i + 1 != len(resources) \
                        and (not r.is_param or not ParamUtils.is_necessary_param(r.name)):
                    to_remove.append(r)
                else:
                    break
            for r in to_remove:
                resources.remove(r)

        # Remove unwanted resources
        resources = list(
            filter(
                lambda r: r.resource_type not in
                [VERSION_RESOURCE, ALL_RESOURCE], resources))

        ret = [e.verb]

        if e.operation_id:
            e.operation_id = e.operation_id.replace("post", "")
            e.operation_id = ParamUtils.normalize(e.operation_id)
            if " by " in e.operation_id:
                e.operation_id = e.operation_id[:e.operation_id.index(" by ")]
            words = e.operation_id.split()
            if len(words) > 1 and is_verb(words[0]):
                ret.append("OperationID")

        # ret.append(str("|"))
        for rs in resources:

            if rs.resource_type == SINGLETON:
                rs_coll_id = '{}_{}'.format(COLLECTION, counter[COLLECTION])
                rs_id = '{}_{}'.format(SINGLETON, counter[SINGLETON])
                counter[COLLECTION] += 1
                ret.append(rs_coll_id)
                ret.append(rs_id)
                rs.ids = [rs_coll_id, rs_id]
            else:
                id = '{}_{}'.format(rs.resource_type,
                                    counter[rs.resource_type])
                ret.append(id)
                rs.ids = [id]

            counter[rs.resource_type] += 1

        if len(ret) == 1:
            return None, resources

        ret = [str(i) for i in ret]
        return " ".join(ret), resources
Ejemplo n.º 5
0
def translate_collection_verb(method, resources, sample_values):
    if method not in ['get', 'post', 'delete']:
        return None

    if len(resources) != 2:
        return None

    if resources[0].resource_type != ACTION_RESOURCE or resources[1].resource_type != COLLECTION:
        return None

    verb = ParamUtils.normalize(resources[0].name)
    resource = ParamUtils.normalize(resources[1].name)

    return '{} the {}'.format(verb, resource)
Ejemplo n.º 6
0
def translate_singleton_collection_adjective(method, resources, sample_values):
    if method not in ['get', 'post', 'delete']:
        return None

    if len(resources) != 3:
        return None

    if resources[2].resource_type != SINGLETON or resources[1].resource_type != COLLECTION or \
                    resources[0].resource_type != ATTRIBUTE_RESOURCE:
        return None

    resource = ParamUtils.normalize(singular(resources[2].name))
    resource2 = ParamUtils.normalize(resources[1].name)
    # param_value = '<<{}>>'.format(resources[2][1]['val'])

    if sample_values:
        vals = param_sampler.sample(resources[2].param.name, 1)
        val = vals[0] if vals else resources[2].param.name
    else:
        val = resources[2].param.name

    param_value = '<< {} >>'.format(val)

    adjective = ParamUtils.normalize(resources[0].name)

    # ret = '{} the {} of the {} with {} being {}'

    # if method == 'post':
    #     resource = singular(resource)
    #     resource2 = singular(resource2)
    #     ret = '{} a {} for the {} with {} being {}'
    # elif method == 'delete':
    #     resource = singular(resource)
    #     ret = '{} the {} of the {} with {} being {}'

    if is_singular(resource2):
        ret = 'get the {} {} of a {} with {} being {}'
    else:
        ret = 'get the list of {} {} of a {} with {} being {}'

    if method == 'post':
        resource = singular(resource)
        resource2 = singular(resource2)
        ret = 'create all {} {} for a {} with {} being {}'
    elif method == 'delete':
        resource = singular(resource)
        ret = 'delete all {} {} of a {} with {} being {}'

    return ret.format(adjective, resource2, resource, ParamUtils.normalize(resources[2].param.name), param_value)
Ejemplo n.º 7
0
def entity_phrase(param: Param):
    # value = self.param_sampler.sample(param, 1)
    # value = value[0] if value else "---"
    name = ParamUtils.human_readable_name(param)
    # todo : shorten when value is too lengthy
    # todo : not using = when it is possible (verb, boolean)
    return "{} being << {} >>".format(name, str(param.name))
Ejemplo n.º 8
0
    def analyse(self):
        for url in sorted(self.doc.paths):
            title = self.doc.specification['info']['title']
            api_url = self.doc.specification['host'] + self.doc.specification['basePath']
            protocols = self.doc.specification['schemes']
            api = API(title, api_url, protocols, self.operations)
            path = self.doc.paths[url]
            for m in sorted(path.keys()):
                if m in ['get', 'post', 'put', 'delete', 'patch']:
                    method = path[m]
                    params = self.process_parameters(method.get('parameters'), auth_tokens=self.auth_tokens)
                    summary = method.get('summary')
                    desc = method.get('description')
                    ok_response = method.get("responses")
                    operation_id = method.get("operationId")
                    response_desc = ""
                    # if ok_response:
                    #     response_desc = method.get('responses').get("200", {}).get("description", "")

                    if m != 'get':
                        params.extend(self.process_body_parameters(url, m, auth_tokens=self.auth_tokens))

                    # if len(url) > 2 and url.endswith('\\') and url.startswith('\\'):
                    #     url = url.replace(self.doc.base_path, '')
                    op = Operation(m, url, summary, desc, response_desc, params, operation_id=operation_id,
                                   base_path=self.base_path())

                    operation_id = ParamUtils.normalize(operation_id)
                    if operation_id:
                        op.intent = operation_id.replace(" ", "_")
                    else:
                        op.intent = m + "_" + url.replace("/", " ").replace(" ", "_").replace("{", "").replace("}", "")
                    self.operations.append(op)

        return api
Ejemplo n.º 9
0
    def common_param_sampler(param: Param, n: int):
        gold_values = {
            'email': 'user{}@company.com',
            'username': '******',
        }

        values = []
        if gold_values.get(param.name):
            p = gold_values.get(param.name)
            for i in range(1, n + 1):
                values.append(p.format(i))

        if ParamUtils.is_identifier(param.name):
            for i in range(1, n + 1):
                values.append(i)

        fake = Faker()
        if 'date' in param.name:
            for i in range(1, n + 1):
                values.append(
                    fake.date_between(start_date='today', end_date='+1y'))

            values = [str(v) for v in values]

        if param.type in {'integer', 'number'}:
            s = randint(0, 2000)
            values = [str(i) for i in range(s, n + s)]

        if param.type == 'boolean':
            values = ['false', 'true']

        return set(values)
Ejemplo n.º 10
0
    def swagger_sampler(self, param: Param, n: int):

        p = (ParamUtils.normalize(param.name), param.type)
        if p not in self.values:
            return []

        examples = self.values[p]
        return [a[0] for a in examples.most_common(n)]
Ejemplo n.º 11
0
    def to_expression(e: Operation, templates: list, post_editing=False):
        resources = extract_resources(e)
        _, resources = Templatetizer.url_to_resource_sequence(e, resources)

        template = Templatetizer.__best_template(templates, resources)

        if e.operation_id:
            words = ParamUtils.normalize(e.operation_id).split()
            if len(words) > 1 and is_verb(words[0]):
                template = template.replace(
                    "OperationID", ParamUtils.normalize(e.operation_id))

        # if len(resources) == 1 and "SingleResource" in template:
        #     template = template.replace("SingleResource", ParamUtils.normalize(resources[0].name))

        for rs in resources:
            if len(rs.ids) > 1:
                rs_coll_id = rs.ids[0]
                rs_id = rs.ids[1]
                if rs_coll_id:
                    template = template.replace(rs_coll_id, str(rs.name))
                if rs_id:
                    template = template.replace(rs_id, str(rs.param.name))
            else:
                rs_id = rs.ids
                template = template.replace(rs_id[0], rs.name)

        tokens = template.replace(" << ", " <<").replace(" >>",
                                                         ">>").split(" ")
        ret = []
        for t in tokens:
            if not t.startswith("<<") and not Resource.is_resource_identifier(
                    t):
                ret.append(ParamUtils.normalize(t))
            else:
                ret.append(t)

        ret = " ".join(ret).replace("<<", "<< ").replace(">>", " >>").strip()

        if post_editing:
            ret = remove_extra_params(ret)
            ret = remove_dangling_words(ret)
            ret = edit_grammar(ret)
            ret = append_parameters(ret, resources)

        return ret.replace(" get ", " ")
Ejemplo n.º 12
0
def translate_collection(method, resources, sample_values):
    if method not in ['get', 'post', 'delete']:
        return None

    if len(resources) != 1:
        return None

        # if ':' in resources[0].name:
        # //v1/{name}:setDefault
        # return None

    if resources[0].resource_type == ACTION_RESOURCE:
        ret = ParamUtils.normalize(resources[0].name)

        for w in ret.split():
            if not ParamUtils.is_necessary_param(w):
                return None

        if not ret or not is_verb(ret.split()[0]) or ret.endswith('ing') or ret.endswith('s'):
            return None

        return ret

    if resources[0].resource_type != COLLECTION:
        return None

    resource = ParamUtils.normalize(resources[0].name)

    for key in ["get ", "set ", "create ", "put ", "delete "]:
        if resource.startswith(key):
            resource = resource[len(key):]

    if is_singular(resource) or ' ' in resource:
        ret = 'get the {}'
    else:
        ret = 'get the list of {}'

    if method == 'post':
        resource = singular(resource)
        ret = 'create a {}'
    elif method == 'delete':
        ret = 'delete all {}'

    return ret.format(resource)
Ejemplo n.º 13
0
def translate_singleton_collection(method, resources, sample_values):
    if method not in ['get', 'post', 'delete']:
        return None

    if len(resources) != 2:
        return None

        # if ':' in resources[0].name:
        # //v1/{name}:setDefault
        # return None

    if resources[0].resource_type != COLLECTION or resources[1].resource_type != SINGLETON:
        return None

    resource = ParamUtils.normalize(singular(resources[1].name))
    resource2 = ParamUtils.normalize(resources[0].name)

    if sample_values:
        vals = param_sampler.sample(resources[1].param, 1)
        val = vals[0] if vals else resources[1].param.name
    else:
        val = resources[1].param.name

    param_value = '<< {} >>'.format(val)

    # param_value = '<<{}>>'.format(resources[1].param.name)

    if is_singular(resource2):
        ret = 'get the {} of a {} with {} being {}'
    else:
        ret = 'get the list of {} of a {} with {} being {}'

    if method == 'post':
        resource = singular(resource)
        resource2 = singular(resource2)
        ret = 'create a {} for a {} with {} being {}'
    elif method == 'delete':
        resource = singular(resource)
        ret = 'delete the {} of a {} with {} being {}'

    return ret.format(resource2, resource, ParamUtils.normalize(resources[1].param.name), param_value)
Ejemplo n.º 14
0
def translate_singleton_singleton_action(method, resources, sample_values):
    if method not in ['get', 'patch', 'delete', 'put']:
        return None

    if len(resources) != 3:
        return None

    if resources[2].resource_type != SINGLETON or resources[1].resource_type != SINGLETON \
            or "Controller" not in resources[0].resource_type:
        return None

    resource2 = ParamUtils.normalize(singular(resources[2].name))
    resource1 = ParamUtils.normalize(singular(resources[1].name))

    if sample_values:
        vals = param_sampler.sample(resources[1].param.name, 1)
        val = vals[0] if vals else resources[1].param.name
    else:
        val = resources[1].param.name

    parameter_value1 = '<< {} >>'.format(val)

    if sample_values:
        vals = param_sampler.sample(resources[2].param.name, 1)
        val = vals[0] if vals else resources[2].param.name
    else:
        val = resources[2].param.name

    parameter_value2 = '<< {} >>'.format(val)

    verb = ParamUtils.normalize(resources[1].name)
    if verb.endswith('ed'):
        verb = verb[:-1]

    ret = '{} a {} with {} being {} for a {} with {} being {}'

    return ret.format(verb, resource1, ParamUtils.normalize(resources[1].param.name), parameter_value1,
                      resource2, ParamUtils.normalize(resources[1].param.name), parameter_value2)
Ejemplo n.º 15
0
def extract_resources(e: Operation):
    """
    returns a dictionary containing pairs of resources and their ids
    :param e: 
    :return: 

    """

    url, base_path = PathUtils.remove_non_informative_segments(
        e.url, e.base_path)
    segments = PathUtils.extract_segments(url)

    skip = False
    ret = []
    for i in reversed(range(0, len(segments))):
        if skip:
            skip = False
            continue

        current, previous = segments[i], None if i == 0 else segments[i - 1]
        resource = Resource(name=current, resource_type=UNKNOWN_RESOURCE)

        tagged = nlp.pos_tag(resource.name)
        resource.resource_type = __resource_type(previous, current,
                                                 tagged[0][1], e.url)
        resource.is_param = ParamUtils.is_param(current)

        if resource.is_param:
            resource.param = __find_param(current[1:-1], e.params)

        if resource.resource_type == SINGLETON:
            resource.name = previous
            skip = True
        elif resource.is_param:
            resource.name = current[1:-1]

        ret.append(resource)

    reversed(ret)

    for seg in base_path.split('/'):
        if seg:
            if is_noun(seg):
                ret.append(Resource(name=seg,
                                    resource_type=BASE_NOUN_RESOURCE))
            elif is_verb(seg):
                ret.append(Resource(name=seg,
                                    resource_type=BASE_VERB_RESOURCE))

    return ret
Ejemplo n.º 16
0
    def generate_template(e: Operation, resources: dict):

        if not resources:
            return e.canonical_expr

        replst = list()
        if e.operation_id:
            e.operation_id = e.operation_id.replace("post", "")
            e.operation_id = ParamUtils.normalize(e.operation_id)
            if " by " in e.operation_id:
                e.operation_id = e.operation_id[:e.operation_id.index(" by ")]
            words = e.operation_id.split()
            if len(words) > 1 and is_verb(words[0]):
                e.operation_id = ParamUtils.normalize(e.operation_id)
                if e.operation_id.startswith(
                        "add") and "new" not in e.operation_id:
                    e.operation_id = "add a new" + e.operation_id[3:]
                replst.append((e.operation_id.strip(), "OperationID"))
        # if len(resources) == 1:
        #     res = resources[0]
        #     if res.resource_type not in [COLLECTION, SINGLETON] and not res.is_param:
        #         replst.append((ParamUtils.normalize(res.name), "SingleResource"))

        can_expr = e.canonical_expr.lower()
        for r in resources:
            for rpl in Templatetizer.__replacements(r):
                replst.append((rpl[0], rpl[1]))

        replst.sort(key=lambda s: len(s[0]), reverse=True)

        can_expr = " {} ".format(can_expr.lower())
        for rpl in replst:
            if " {} ".format(rpl[0]) in can_expr:
                can_expr = can_expr.replace(" {} ".format(rpl[0]),
                                            " {} ".format(rpl[1]))

        return re.sub(r'\s+', ' ', can_expr).strip()  # Remove extra spaces
Ejemplo n.º 17
0
    def wikidata_sampler(self, param: Param, n: int):

        values = []
        result = self.wikidata_server.query(
            'SELECT ?item WHERE {?item rdfs:label "' +
            ParamUtils.normalize(param.name, lemmatize=True) + '"@en}')

        for item in result['results']['bindings']:
            qid = item['item']['value'].replace(
                'http://www.wikidata.org/entity/', '')
            q = 'SELECT ?itemLabel WHERE {  ?item wdt:P31 wd:' + qid + '.  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }}'
            result = self.wikidata_server.query(q)
            for item2 in result['results']['bindings']:
                if item2['itemLabel']['type'] == 'literal':
                    values.append(item2['itemLabel']['value'])
        return values
Ejemplo n.º 18
0
def append_parameters(text, resources):
    for r in resources:
        if r.resource_type in [
                ATTRIBUTE_RESOURCE, COUNT_RESOURCE, SEARCH_RESOURCE,
                FILE_EXTENSION_RESOURCE, AUTH_RESOURCE, SWAGGER_RESOURCE,
                FILTER_RESOURCE, ALL_RESOURCE, VERSION_RESOURCE,
                BASE_VERB_RESOURCE, BASE_NOUN_RESOURCE
        ]:
            continue

        param = r.param
        if param and param.name:
            if "<< " + param.name + " >>" in text:
                continue
            else:
                text += " by {} being << {} >>".format(
                    ParamUtils.human_readable_name(param), param.name)

    return text
Ejemplo n.º 19
0
    def __replacements(resource):

        ret = []
        ids = resource.ids
        r_name = resource.name

        if len(ids) == 1:
            pairs = [(r_name, ids[0])]
        else:
            pairs = [(r_name, ids[0]), (resource.param.name, ids[1]),
                     (resource.param.name.replace(singular(r_name),
                                                  ""), ids[1])]

        if resource.resource_type == COUNT_RESOURCE:
            pairs.append(("count", COUNT_RESOURCE))
        elif resource.resource_type == SEARCH_RESOURCE:
            pairs.append(("search", SEARCH_RESOURCE))
            pairs.append(("query", SEARCH_RESOURCE))

        for name, id in pairs:
            if not name:
                continue
            names = set()
            for n in [
                    name,
                    name.replace('get', '').replace('create',
                                                    '').replace('remove', '')
            ]:
                names.add(n)
                names.add(n.lower())
                names.add(n.replace("_", " ").lower())
                names.add(ParamUtils.normalize(n))
                names.add(
                    ParamUtils.normalize(ParamUtils.normalize(n),
                                         lemmatize=True))
                names.add(ParamUtils.normalize(n, lemmatize=True))
                for str in combinations(ParamUtils.normalize(n).split()):
                    names.add(str)
                for str in combinations(
                        ParamUtils.normalize(n, lemmatize=True).split()):
                    names.add(str)

            names = list(names)
            names.sort(key=lambda s: len(s), reverse=True)
            for name in names:
                ret.append((name, id))

        return ret
Ejemplo n.º 20
0
    def to_intent(self, operation, path_params):
        """
        returns the intent of the Operation and path_params which have not been used in the intent
        :return: path_params, intent
        """

        intent = self.extract_intent(operation.summary)
        if not intent:
            intent = self.extract_intent(operation.desc)

        # if not intent:
        #     intent = get_intent(Operation.response_desc)
        if not intent or len(intent) < 8:
            return path_params, None

        # todo: remove unnecessary words
        if intent.endswith('.'):
            intent = intent[:-1]

        for verb in ['return', 'retrieve', "read", "fetch"]:
            if intent.startswith(verb):
                intent = 'get' + intent[len(verb):]

        for verb in ['add']:
            if intent.startswith(verb):
                intent = 'create' + intent[len(verb):]

        for verb in ['remove']:
            if intent.startswith(verb):
                intent = 'delete' + intent[len(verb):]

        for i in range(2):
            intent = ParamUtils.normalize(intent)
        # TODO: more robost approaches to defeat misppelling

        path_params, intent = self.replace_path_params(intent, operation,
                                                       path_params)
        return path_params, intent
Ejemplo n.º 21
0
 def __init__(self):
     self.paramUtils = ParamUtils()
Ejemplo n.º 22
0
def __resource_type(previous, segment, current_tag, url):
    """
    :return: is singleton, Collection, sub-Collection
    """

    current = segment
    is_param = ParamUtils.is_param(current)
    if is_param:
        current = current[1:-1]
    current = ParamUtils.normalize(current)

    if not is_param:
        if current.startswith("by"):
            return FILTER_RESOURCE
        if current.startswith("search") or current.endswith("search") or current.startswith(
                "query") or current.endswith("query"):
            return SEARCH_RESOURCE
        if "count" == current:
            return COUNT_RESOURCE
        if "all" == current:
            return ALL_RESOURCE
        if ParamUtils.is_authentication(current):
            return AUTH_RESOURCE
        if current in {"swagger", "yaml"}:
            return SWAGGER_RESOURCE
        if current in {'pdf', 'json', 'xml', 'txt', 'doc', 'docx', 'jpeg', 'jpg', 'gif', 'png', 'xls', 'tsv', 'csv',
                       'fmw'}:
            return FILE_EXTENSION_RESOURCE

    if is_param and current in {"format"}:
        return FILE_EXTENSION_RESOURCE

    if is_param and previous:

        if current in previous:
            return SINGLETON

        if (current_tag.startswith('NNS') or is_plural(previous)) and ParamUtils.is_identifier(current):
            return SINGLETON

        if (current.endswith('name') or current.endswith('type')) and "{}.".format(segment) not in url:
            return SINGLETON

        if singular(previous) in current:
            return SINGLETON

        if editdistance.eval(current, previous) / (len(current) + len(previous)) < 0.4:
            return SINGLETON

    if current_tag.startswith('NNS') or is_plural(current):
        return COLLECTION

    if current_tag.startswith('jj') or is_adjective(current) or \
            current.endswith('ed') or (current_tag.startswith('VB') and current.startswith('is')):
        return ATTRIBUTE_RESOURCE

    if (current_tag.startswith('VB') or is_verb(current)) and not is_param:
        return ACTION_RESOURCE

    words = current.split()
    if len(words) > 1 and is_verb(words[0]) and not is_param:
        return METHOD_NAME_RESOURCE

    if is_param:
        return UNKNOWN_PARAM_RESOURCE

    if ParamUtils.is_version(current):
        return VERSION_RESOURCE

    return UNKNOWN_RESOURCE
Ejemplo n.º 23
0
    def replace_path_params(self, intent, e: Operation, path_params):

        def find_resource(param, resources):

            if resources:
                for r in resources:
                    if r.is_param and r.param.name == param:
                        return r

            return None

        ret_path_params = []
        resources = extract_resources(e)
        for p in path_params:

            pname = p.name
            res = find_resource(pname, resources)

            if not res:
                ret_path_params.append(p)
                continue

            rname = res.name
            rname_normalized = ParamUtils.normalize(rname)
            pname_normalized = ParamUtils.normalize(pname)

            try:
                regex_str = "{} by(.+){}".format(rname, pname)
                regex = re.compile(regex_str)

                matched_1 = regex.search(intent)
                if matched_1:
                    matched_1 = matched_1.group(0)
                    matched_1 = matched_1.replace(rname + " by ", "")
                else:
                    matched_1 = ' '
            except:
                matched_1 = ' '

            try:
                regex_str_2 = "{} by(.+){}".format(ParamUtils.normalize(rname, lemmatize=True),
                                                   ParamUtils.normalize(pname, lemmatize=True))
                regex2 = re.compile(regex_str_2)
                matched_2 = regex2.search(intent)
                if matched_2:
                    matched_2 = matched_2.group(0)
                    matched_2 = matched_2.replace(ParamUtils.normalize(rname, lemmatize=True) + " by ", "")
                else:
                    matched_2 = ' '
            except:
                matched_2 = ' '

            if not rname:
                rname = pname
            if not rname_normalized:
                rname_normalized = pname_normalized

            R1 = self.__cfg_list_to_str({" ", matched_1, matched_2, rname, " ".join(rname_normalized.split()),
                                         " ".join(ParamUtils.normalize(rname, lemmatize=True).split())})

            R2 = self.__cfg_list_to_str({' ', pname, pname_normalized, ParamUtils.normalize(pname, lemmatize=True),
                                         " ".join(pname_normalized.split()), " ".join(pname_normalized.split()),
                                         " ".join(ParamUtils.normalize(pname, lemmatize=True).split()),
                                         "id", "name", "type", "resource", "item"})

            Plst = {' ', 'by', "via", "with", "based on", "with specific", "based on", "with specific", "matching",
                    "with a given", "with given", "given", "given a"}
            P = self.__cfg_list_to_str(Plst)

            grammar = """S -> R1 P R2\nR1 -> {}\nR2 -> {}\nP  -> {}""".format(R1, R2, P)
            grammar = CFG.fromstring(grammar)

            possible_phrases = []
            for phr in generate(grammar):
                phr = " ".join(phr).strip()

                if not phr or phr in Plst:
                    continue

                possible_phrases.append(phr)
                possible_phrases.append(ParamUtils.normalize(phr))

            possible_phrases.sort(key=len, reverse=True)
            possible_phrases = list(filter(lambda a: len(a) > 2, possible_phrases))

            found = False
            intent += " "  # important do not remove
            for phrase in possible_phrases:
                if " {} ".format(phrase) in intent or intent.endswith(phrase):
                    replacement = entity_phrase(p)

                    # if phrase in replacement:
                    replacement = phrase + " by " + replacement

                    # if not phrase.endswith(" with"):
                    #     phrase += " with "
                    # replacement = phrase + replacement

                    if phrase + "'s" in intent or phrase + " of " in intent:
                        intent = intent + " with " + entity_phrase(p)
                        break

                    intent = replace_last(intent, phrase + " ", replacement + " ")
                    found = True
                    break

            if not found:
                ret_path_params.append(p)

        regex = re.compile('(by|based|based on|via|with) (id|specific id|given id|the given id|a specific id)$',
                           re.IGNORECASE)
        intent = regex.sub('', intent)

        return ret_path_params, intent