Add a document to an existing item

        :param item_uri: the URI that references the item
        :type item_uri: String

        :param name: The document name
        :type name: String

        :param metadata: a dictionary of metadata values describing the document
        :type metadata: Dict

        :param content: optional content of the document
        :type content: byte array

        :param docurl: optional url referencing the document
        :type docurl: String

        :param file: optional full path to file to be uploaded
        :type file: String

        :param displaydoc: if True, make this the display document for the item
        :type displaydoc: Boolean
        
        :param preferName: if True, given document name will be the document id rather than
            filename. Useful if you want to upload under a different filename.
        :type preferName: Boolean

        :param contrib_id: if present, add this document to this contribution as well as
            associating it with the item
        :type contrib_id: Integer

        :rtype: String
        :returns: The URL of the newly created document

def add_document(self, item_uri, name, metadata,
                     content=None, docurl=None, file=None,
                     displaydoc=False, preferName=False,
                     contrib_id=None):
        """Add a document to an existing item

        :param item_uri: the URI that references the item
        :type item_uri: String

        :param name: The document name
        :type name: String

        :param metadata: a dictionary of metadata values describing the document
        :type metadata: Dict

        :param content: optional content of the document
        :type content: byte array

        :param docurl: optional url referencing the document
        :type docurl: String

        :param file: optional full path to file to be uploaded
        :type file: String

        :param displaydoc: if True, make this the display document for the item
        :type displaydoc: Boolean
        
        :param preferName: if True, given document name will be the document id rather than
            filename. Useful if you want to upload under a different filename.
        :type preferName: Boolean

        :param contrib_id: if present, add this document to this contribution as well as
            associating it with the item
        :type contrib_id: Integer

        :rtype: String
        :returns: The URL of the newly created document

        """
        
        if not preferName and file is not None:
            docid = os.path.basename(file)
        else:
            docid = name

        docmeta = {"metadata": {"@context": self.context,
                                "@type": "foaf:Document",
                                "dcterms:identifier": docid,
                                }
                  }
        # add in metadata we are passed
        docmeta["metadata"].update(metadata)

        if contrib_id:
            docmeta['contribution_id'] = contrib_id

        if content is not None:
            docmeta['document_content'] = content
        elif docurl is not None:
            docmeta["metadata"]["dcterms:source"] = { "@id": docurl }
        elif file is not None:
            # we only pass the metadata part of the dictionary
            docmeta = docmeta['metadata']
        else:
            raise Exception("One of content, docurl or file must be specified in add_document")

        if file is not None:
            result = self.api_request(item_uri, method='POST', data={'metadata': json.dumps(docmeta)}, file=file)
        else:
            result = self.api_request(item_uri, method='POST', data=json.dumps(docmeta))

        self.__check_success(result)

        if displaydoc:
            itemmeta = {"http://alveo.edu.org/vocabulary/display_document": docid}

            self.modify_item(item_uri, itemmeta)

        doc_uri = item_uri + "/document/" + name
        return doc_uri