def _create_or_update(self, mn_client, cn_client, data_object):
     """ Either update the specified pid if it already exists or create a new one.
     """
     if not data_object:
         raise Exception("data object cannot be null")
     if not data_object.pid:
         raise Exception("data object must have a pid")
     if not data_object.fname:
         raise Exception("data object must have a file to write")
     if not data_object.meta:
         raise Exception("data object must have system metadata")
     curr_sysmeta = utils.get_sysmeta_by_pid(data_object.pid, True, cn_client, mn_client)
     # Create
     if not curr_sysmeta:
         with open(utils.expand_path(data_object.fname), "r") as f:
             try:
                 return mn_client.create(data_object.pid, f, data_object.meta)
             except DataONEException as e:
                 raise Exception("Unable to create Science Object on Member Node\n{0}".format(e.friendly_format()))
     # Update
     else:
         data_object.meta.serialVersion = curr_sysmeta.serialVersion + 1
         with open(utils.expand_path(data_object.fname), "r") as f:
             try:
                 return mn_client.update(data_object.pid, f, data_object.pid, data_object.meta)
             except DataONEException as e:
                 raise Exception("Unable to update Science Object on Member Node\n{0}".format(e.friendly_format()))
     # Nothing good happened.
     return None
    def _get_by_pid(self, pid, sysmeta=None, mn_client=None, cn_client=None):
        """ Return DataObject
        """
        if pid is None:
            raise Exception("Missing pid")

        fname = utils.get_object_by_pid(pid, resolve=True, mn_client=mn_client, cn_client=cn_client)
        if fname:
            meta = sysmeta
            if not meta:
                meta = utils.get_sysmeta_by_pid(pid, True)
            url = utils.create_get_url_for_pid(mn_client.base_url, pid)
            return DataObject(pid, False, fname, url, meta, meta.formatId, None)
        else:
            return None
    def scimeta_add(self, pid, file_name=None, format_id=None, **kwargs):
        """ Add a scimeta object.
        """
        if not pid:
            raise Exception("Missing the pid")
        # if (self.scimeta and not
        #                       cli_util.confirm('Do you wish to delete the existing science metadata object?')):
        #   return
        else:
            self.scimeta = None

        if not file_name:
            new_meta = utils.get_sysmeta_by_pid(pid, True)
            if not new_meta:
                raise Exception("Couldn't find scimeta in DataONE, and there was no file specified.")
            if not self._is_metadata_format(new_meta.formatId):
                raise Exception('"%s" is not an allowable science metadata type.' % new_meta.formatId)
            new_pid = new_meta.identifier.value()
            if new_pid != pid:
                pid = new_pid

            self.scimeta = self._get_by_pid(pid, new_meta)
            authMN = new_meta.authoritativeMemberNode
            if authMN:
                baseURL = utils.get_baseUrl(authMN.value())
                if baseURL:
                    self.scimeta.url = utils.create_get_url_for_pid(baseURL, pid)

        else:
            complex_path = utils.create_complex_path(file_name)
            if not os.path.exists(complex_path.path):
                raise Exception("%s: file not found" % complex_path.path)
            if not format_id:
                format_id = complex_path.formatId
            if not format_id and configuration.check("format"):
                format_id = configuration.format
            if not format_id:
                raise Exception("The object format could not be determined and was not defined.")
            if not self._is_metadata_format(format_id):
                raise Exception('"%s" is not an allowable science metadata type.' % new_meta.formatId)
                return
            #
            sysmeta = utils.create_sysmeta_from_path(pid, complex_path.path, format_id=format_id, **kwargs)
            self.scimeta = DataObject(pid, True, complex_path.path, None, sysmeta, format_id)
        scidata_list = self._find_scidata(self.scimeta)
        if scidata_list:
            for scidata in scidata_list:
                self.scidata_add(scidata.pid, scidata.fname)
    def scidata_add(self, pid, file_name=None, format_id=None, **kwargs):
        """ Add a science data object to the list.
        """
        if not pid:
            raise Exception("Missing the pid")

        if file_name:
            # if utils.get_sysmeta_by_pid(pid):
            #   if not cli_util.confirm('That pid (%s) already exists in DataONE.  Continue?' % pid):
            #     return
            #   raise Exception("The identifer (%s) already exists in DataONE." % pid)

            complex_path = utils.create_complex_path(file_name)
            if not format_id:
                format_id = complex_path.formatId
            if not format_id and configuration.check("format"):
                format_id = configuration.format
            if not format_id:
                raise Exception("The object format could not be determined and was not defined.")
            meta = utils.create_sysmeta_from_path(pid, complex_path.path, format_id=format_id, **kwargs)
            self.scidata_dict[pid] = DataObject(pid, True, complex_path.path, None, meta, format_id)

        else:
            sysmeta = utils.get_sysmeta_by_pid(pid, True)
            if not sysmeta:
                raise Exception("The identifier (%s) was not found in DataONE." % pid)
            else:
                pid = sysmeta.identifier.value()
                # if pid in self.scidata_dict:
                #   if not cli_util.confirm('That science data object (%s) is already in the package.  Replace?' % pid):
                #     return
                # Get the scidata object.
                scidata = self._get_by_pid(pid, sysmeta)
                authMN = sysmeta.authoritativeMemberNode
                if authMN:
                    baseURL = utils.get_baseUrl(authMN.value())
                    if baseURL:
                        scidata.url = utils.create_get_url_for_pid(baseURL, pid)
                self.scidata_dict[pid] = scidata
    def load(self):
        """ Get the object referred to by pid and make sure it is a
            package.
        """
        if self.pid is None:
            raise Exception("Missing pid")
        sysmeta = utils.get_sysmeta_by_pid(self.pid)
        if not sysmeta:
            raise Exception('Couldn\'t find "%s" in DataONE.' % self.pid)
        if sysmeta.formatId != RDFXML_FORMATID:
            raise Exception('Package must be in RDF/XML format (not "%s").' % sysmeta.formatId)

        rdf_xml_file = utils.get_object_by_pid(self.pid)
        if not self._parse_rdf_xml(rdf_xml_file):
            raise Exception('Unable to load package "%s".' % self.pid)
        self.original_pid = self.pid
        self.sysmeta = sysmeta

        self.scimeta = self._download_object(self.scimeta)
        loaded_scidata = {}
        for pid, scidata in self.scidata_dict.iteritems():
            loaded_scidata[pid] = self._download_object(scidata)
        self.scidata_dict = loaded_scidata
        return self