'Add a descriptor to persistence as an element
of the course. Return the resulting post saved version with populated locators.
:param course_key: If it has a version_guid and a course org + course + run + branch, this
method ensures that the version is the head of the given course branch before making the change.
raises InsufficientSpecificationError if there is no course locator.
raises VersionConflictError if the version_guid of the course_or_parent_locator is not the head
of the its course unless force is true.
:param force: fork the structure and don\'t update the course draftVersion if the above
:param continue_revision: for multistep transactions, continue revising the given version rather than creating
a new version. Setting force to True conflicts with setting this to True and will cause a VersionConflictError
:param definition_locator: should either be None to indicate this is a brand new definition or
a pointer to the existing definition to which this block should point or from which this was derived
or a LocalId to indicate that it\'s new.
If fields does not contain any Scope.content, then definition_locator must have a value meaning that this
block points
to the existing definition. If fields contains Scope.content and definition_locator is not None, then
the Scope.content fields are assumed to be a new payload for definition_locator.
:param block_id: if provided, must not already exist in the structure. Provides the block id for the
new item in this structure. Otherwise, one is computed using the category appended w/ a few digits.
This method creates a new version of the course structure unless the course has a bulk_write operation
active.
It creates and inserts the new block, makes the block point
to the definition which may be new or a new version of an existing or an existing.
Rules for course locator:
* If the course locator specifies a org and course and run and either it doesn\'t
specify version_guid or the one it specifies == the current head of the branch,
it progresses the course to point
to the new head and sets the active version to point to the new head
* If the locator has a org and course and run but its version_guid != current head, it raises VersionConflictError.
NOTE: using a version_guid will end up creating a new version of the course. Your new item won\'t be in
the course id\'d by version_guid but instead in one w/ a new version_guid. Ensure in this case that you get
the new version_guid from the locator in the returned object!'

@contract(returns='XBlock')
def create_item(self, user_id, course_key, block_type, block_id=None, definition_locator=None, fields=None, asides=None, force=False, **kwargs):

    with self.bulk_operations(course_key):
        fields = (fields or {})
        fields.update((kwargs.pop('metadata', {}) or {}))
        definition_data = kwargs.pop('definition_data', {})
        if definition_data:
            if (not isinstance(definition_data, dict)):
                definition_data = {'data': definition_data}
            fields.update(definition_data)
        index_entry = self._get_index_if_valid(course_key, force)
        structure = self._lookup_course(course_key).structure
        partitioned_fields = self.partition_fields_by_scope(block_type, fields)
        new_def_data = partitioned_fields.get(Scope.content, {})
        if ((definition_locator is None) or isinstance(definition_locator.definition_id, LocalId)):
            definition_locator = self.create_definition_from_data(course_key, new_def_data, block_type, user_id)
        elif new_def_data:
            (definition_locator, _) = self.update_definition_from_data(course_key, definition_locator, new_def_data, user_id)
        new_structure = self.version_structure(course_key, structure, user_id)
        new_id = new_structure['_id']
        if (block_id is not None):
            block_key = BlockKey(block_type, block_id)
            if (block_key in new_structure['blocks']):
                raise DuplicateItemError(block_id, self, 'structures')
        else:
            block_key = self._generate_block_key(new_structure['blocks'], block_type)
        block_fields = partitioned_fields.get(Scope.settings, {})
        if (Scope.children in partitioned_fields):
            block_fields.update(partitioned_fields[Scope.children])
        self._update_block_in_structure(new_structure, block_key, self._new_block(user_id, block_type, block_fields, definition_locator.definition_id, new_id, asides=asides))
        self.update_structure(course_key, new_structure)
        if (index_entry is not None):
            if (fields is not None):
                self._update_search_targets(index_entry, fields)
            self._update_head(course_key, index_entry, course_key.branch, new_id)
            item_loc = BlockUsageLocator(course_key.version_agnostic(), block_type=block_type, block_id=block_key.id)
        else:
            item_loc = BlockUsageLocator(CourseLocator(version_guid=new_id), block_type=block_type, block_id=block_key.id)
        if isinstance(course_key, LibraryLocator):
            self._flag_library_updated_event(course_key)
        return self.get_item(item_loc)
