def addRelation(self, virtual_path: str, relation_type: str, origin: str = "") -> None:
        if not self._stream:
            raise ValueError("Can't add a relation to a closed file.")
        if self._mode == OpenMode.ReadOnly:
            raise ReadOnlyError(virtual_path)
        virtual_path = self._processAliases(virtual_path)

        # First check if it already exists.
        if origin not in self._relations:
            self._relations[origin] = ET.Element("Relationships",
                                                 xmlns="http://schemas.openxmlformats.org/package/2006/relationships")
        else:
            for relationship in self._relations[origin].iterfind("Relationship"):
                if "Target" in relationship.attrib and relationship.attrib["Target"] == virtual_path:
                    raise OPCError("Relation for virtual path {target} already exists.".format(target=virtual_path))

        # Find a unique name.
        unique_id = 0
        while True:
            for relationship in self._relations[origin].iterfind("Relationship"):
                if "Id" in relationship.attrib and relationship.attrib["Id"] == "rel" + str(unique_id):
                    break
            else:  # Unique ID didn't exist yet! It's safe to use
                break
            unique_id += 1
        unique_name = "rel" + str(unique_id)

        # Create the element itself.
        ET.SubElement(self._relations[origin], "Relationship", Target=virtual_path, Type=relation_type, Id=unique_name)
 def setMetadata(self, metadata: Dict[str, Any]) -> None:
     if not self._stream:
         raise ValueError("Can't change metadata in a closed file.")
     if self._mode == OpenMode.ReadOnly:
         raise ReadOnlyError()
     metadata = {self._processAliases(virtual_path): metadata[virtual_path] for virtual_path in metadata}
     self._metadata.update(metadata)
 def setData(self, data: Dict[str, Any]) -> None:
     if not self._stream:
         raise ValueError("Can't change the data in a closed file.")
     if self._mode == OpenMode.ReadOnly:
         raise ReadOnlyError()
     for virtual_path, value in data.items():
         if virtual_path.startswith(
                 self._metadata_prefix):  # Detect metadata by virtue of being in the Metadata folder.
             self.setMetadata({virtual_path: value[len(self._metadata_prefix):]})
         else:  # Virtual file resources.
             self.getStream(virtual_path).write(value)
    def addContentType(self, extension: str, mime_type: str) -> None:
        if not self._stream:
            raise ValueError("Can't add a content type to a closed file.")
        if self._mode == OpenMode.ReadOnly:
            raise ReadOnlyError()
        assert self._content_types_element is not None

        # First check if it already exists.
        for content_type in self._content_types_element.iterfind("Default"):
            if "Extension" in content_type.attrib and content_type.attrib["Extension"] == extension:
                raise OPCError("Content type for extension {extension} already exists.".format(extension=extension))

        ET.SubElement(self._content_types_element, "Default", Extension=extension, ContentType=mime_type)