def resolve_placeholders(path, placeholder_dict):
    """
    **Purpose**: Substitute placeholders in staging attributes of a Task with actual paths to the corresponding tasks.

    :arguments:
        :path: string describing the staging paths, possibly containing a placeholder
        :placeholder_dict: dictionary holding the values for placeholders

    """

    try:

        if isinstance(path, unicode):
            path = str(path)

        if not isinstance(path, str):
            raise TypeError(expected_type=str, actual_type=type(path))

        if '$' not in path:
            return path

        # Extract placeholder from path
        if len(path.split('>')) == 1:
            placeholder = path.split('/')[0]
        else:
            if path.split('>')[0].strip().startswith('$'):
                placeholder = path.split('>')[0].strip().split('/')[0]
            else:
                placeholder = path.split('>')[1].strip().split('/')[0]

        # SHARED
        if placeholder == "$SHARED":
            return path.replace(placeholder, 'pilot://')

        # Expected placeholder format:
        # $Pipeline_{pipeline.uid}_Stage_{stage.uid}_Task_{task.uid}

        broken_placeholder = placeholder.split('/')[0].split('_')

        if not len(broken_placeholder) == 6:
            raise ValueError(
                obj='placeholder',
                attribute='task',
                expected_value='$Pipeline_(pipeline_name)_Stage_(stage_name)_Task_(task_name) or $SHARED',
                actual_value=broken_placeholder)

        pipeline_name = broken_placeholder[1]
        stage_name = broken_placeholder[3]
        task_name = broken_placeholder[5]
        resolved_placeholder = None

        if pipeline_name in placeholder_dict.keys():
            if stage_name in placeholder_dict[pipeline_name].keys():
                if task_name in placeholder_dict[pipeline_name][stage_name].keys():
                    resolved_placeholder = path.replace(placeholder, placeholder_dict[
                                                        pipeline_name][stage_name][task_name]['path'])
                else:
                    logger.warning('%s not assigned to any task in Stage %s Pipeline %s' %
                                   (task_name, stage_name, pipeline_name))
            else:
                logger.warning('%s not assigned to any Stage in Pipeline %s' % (
                    stage_name, pipeline_name))
        else:
            logger.warning('%s not assigned to any Pipeline' % (pipeline_name))

        if not resolved_placeholder:
            logger.warning('No placeholder could be found for task name %s \
                        stage name %s and pipeline name %s. Please be sure to \
                        use object names and not uids in your references,i.e, \
                        $Pipeline_(pipeline_name)_Stage_(stage_name)_Task_(task_name)')
            raise ValueError(
                obj='placeholder',
                attribute='task',
                expected_value='$Pipeline_(pipeline_name)_Stage_(stage_name)_Task_(task_name) or $SHARED',
                actual_value=broken_placeholder)

        return resolved_placeholder

    except Exception, ex:

        logger.exception('Failed to resolve placeholder %s, error: %s' %(path, ex))
        raise