def _validate_helper(args, config_d, workspace_d, entity_d=None):
    """ Return FISSFC validation information on config for a certain entity """
        # 4 ways to have invalid config:
    invalid_inputs = sorted(config_d["invalidInputs"])
    invalid_outputs = sorted(config_d["invalidOutputs"])

    # Also insert values for invalid i/o
    invalid_inputs = [(i, config_d['methodConfiguration']['inputs'][i]) for i in invalid_inputs]
    invalid_outputs = [(i, config_d['methodConfiguration']['outputs'][i]) for i in invalid_outputs]

    missing_attrs = []
    missing_wksp_attrs = []

    # If an entity was provided, also check to see if that entity has the necessary inputs
    if entity_d:
        entity_type = config_d['methodConfiguration']['rootEntityType']

        # If the attribute is listed here, it has an entry
        entity_attrs = set(entity_d['attributes'])

        # Optimization, only get the workspace attrs if the method config has any
        workspace_attrs = workspace_d['workspace']['attributes']

        # So now iterate over the inputs
        for inp, val in iteritems(config_d['methodConfiguration']['inputs']):
            # Must be an attribute on the entity
            if val.startswith("this."):
                # Normally, the value is of the form 'this.attribute',
                # but for operations on sets, e.g. one can also do
                # 'this.samples.attr'. But even in this case, there must be a
                # 'samples' attribute on the sample set, so checking for the middle
                # value works as expected. Other pathological cases would've been
                # caught above by the validation endpoint
                expected_attr = val.split('.')[1]
                # 'name' is special, it really means '_id', which everything has
                if expected_attr == "name":
                    continue
                if expected_attr not in entity_attrs:
                    missing_attrs.append((inp, val))

            if val.startswith("workspace."):
                # Anything not matching this format will be caught above
                expected_attr = val.split('.')[1]
                if expected_attr not in workspace_attrs:
                    missing_wksp_attrs.append((inp, val))
            # Anything else is a literal

    return invalid_inputs, invalid_outputs, missing_attrs, missing_wksp_attrs
Return FISSFC validation information on config for a certain entity