public Date[] modifyDatastreamControlGroup(Context context, String pid, String dsID, String controlGroup, boolean addXMLHeader, boolean reformat, boolean setMIMETypeCharset) throws ServerException {

        DOWriter w = null;

        try {

            logger.debug("Entered modifyDatastreamControlGroup");

            // FIXME: see FCREPO-765 - add proper auth when migrating this to an Admin module, for now use same permissions as reloading policies
            m_authz.enforceReloadPolicies(context);

            if (!controlGroup.equals("M"))
                throw new GeneralException("Invalid target controlGroup " + controlGroup + ".  Only \"M\" is currently supported");

            try {
                w = m_manager.getWriter(false, context, pid);
            } catch (ObjectNotInLowlevelStorageException e ){
                throw new ObjectNotFoundException("Object " + pid + " does not exist.");
            }

            Datastream currentDS = w.GetDatastream(dsID, null);
            if (currentDS == null) {
                    throw new DatastreamNotFoundException("Datastream " + dsID + " not found");
            }

            if (currentDS.DSControlGrp.equals("X")) {

                // take a copy of the existing datastream versions
                Date[] versions = w.getDatastreamVersions(dsID);
                Map<Date, Datastream> copyDS = new HashMap<Date, Datastream>(versions.length);
                for (Date version: versions) {
                    Datastream d = w.GetDatastream(dsID, version);
                    copyDS.put(version, d.copy());
                }

                // purge the existing datastream (all versions)
                w.removeDatastream(dsID, null, null);

                // add back each datastream version in reverse order as managed content
                // (order might not strictly be necessary)
                Arrays.sort(versions);
                for (int i = versions.length - 1; i >= 0; i--) {

                    // get a managed content copy of this datastream version
                    DatastreamXMLMetadata existing = (DatastreamXMLMetadata)copyDS.get(versions[i]);
                    DatastreamManagedContent newDS = new DatastreamManagedContent();
                    existing.copy(newDS);

                    // X control group will have been copied over by above, reset it
                    newDS.DSControlGrp = controlGroup;

                    // probably not necessary, but just in case...
                    newDS.DSLocation = null;
                    newDS.DSLocationType = null;

                    // add character encoding to mime type (will always be UTF-8 as it has come from X datastream in FOXML)
                    if (setMIMETypeCharset) {
                        if (newDS.DSMIME != null && !newDS.DSMIME.isEmpty() & !newDS.DSMIME.contains("charset=")) {
                            newDS.DSMIME = newDS.DSMIME + "; charset=UTF-8";
                        } else {
                            newDS.DSMIME = "text/xml; charset=UTF-8";
                        }
                    }

                    InputStream byteContent;
                    long byteLength;

                    // Note: use getContentStream() rather than getting bytes directly, as this is how
                    // X datastreams are disseminated (we want the M content to be identical on
                    // dissemination)
                    if (reformat) {
                        ReadableByteArrayOutputStream out = new ReadableByteArrayOutputStream(2048);
                        this.getXML(existing.getContentStream(), out, addXMLHeader);
                        out.close();
                        byteContent = out.toInputStream();
                        byteLength = out.length();
                    } else {
                        // add just the XML header declaring encoding, if requested
                        if (addXMLHeader) {
                            byteContent = new SequenceInputStream(
                                    new ByteArrayInputStream(xmlHeader),
                                    existing.getContentStream());
                            byteLength = xmlHeader.length + existing.DSSize;
                        } else {
                            byteContent = existing.getContentStream();
                            byteLength = existing.DSSize;
                        }
                    }

                    // add the content stream
                    MIMETypedStream content = new MIMETypedStream(null, byteContent, null, byteLength);
                    newDS.putContentStream(content);

                    // checksum only needs recalc if we added a header
                    // note getChecksum() caters for checksum type set to disabled
                    if (addXMLHeader) {
                        logger.debug("Recalculating checksum.  Type={} Existing checksum: {}",
                                newDS.DSChecksumType, newDS.DSChecksum != null ? newDS.DSChecksum : "none");

                        // forces computation rather than return existing
                        newDS.DSChecksum = Datastream.CHECKSUM_NONE;
                        newDS.DSChecksum = newDS.getChecksum();

                        if (logger.isDebugEnabled()) {
                            logger.debug("New checksum: {}", newDS.DSChecksum);
                            logger.debug("Testing new checksum, response is {}", newDS.compareChecksum());
                        }
                    }

                    w.addDatastream(newDS, true);
                }

                Date nowUTC = Server.getCurrentDate(context);
                String logMessage = "Modified datastream control group for " + pid + " " + dsID + " from " + currentDS.DSControlGrp + " to " + controlGroup;
                addAuditRecord(context,
                               w,
                               "modifyDatastreamControlGroup",
                               dsID,
                               logMessage,
                               nowUTC);

                w.commit(logMessage);
                return versions;

            } else { // existing control group is not X
                if (currentDS.DSControlGrp.equals("M")) {
                    // nothing modified
                    return new Date[0];
                } else {
                    throw new GeneralException("Original control group must be X, it is " + currentDS.DSControlGrp);
                }
            }

        } finally {
            // Logger completion
            if (logger.isInfoEnabled()) {

                StringBuilder logMsg =
                        new StringBuilder("Completed modifyDatastreamControlGroup(");
                logMsg.append("pid: ").append(pid);
                logMsg.append(", datastream: ").append(dsID);
                logMsg.append(", new control group: ").append(controlGroup);
                logMsg.append(", add XML header: ").append(addXMLHeader);
                logMsg.append(", set MIMEType charset: ").append(setMIMETypeCharset);
                logMsg.append(")");
                logger.info(logMsg.toString());
            }
            finishModification(w, "modifyDatastreamControlGroup");
        }
    }
public Date [ ] modifyDatastreamControlGroup ( Context context , String pid , String dsID , String controlGroup , boolean addXMLHeader , boolean reformat , boolean setMIMETypeCharset ) throws ServerException { DOWriter w = null ; try { logger . debug ( "Entered modifyDatastreamControlGroup" ) ; m_authz . enforceReloadPolicies ( context ) ; if ( ! controlGroup . equals ( "M" ) ) throw new GeneralException ( "Invalid target controlGroup " + controlGroup + ".  Only \"M\" is currently supported" ) ; try { w = m_manager . getWriter ( false , context , pid ) ; } catch ( ObjectNotInLowlevelStorageException e ) { throw new ObjectNotFoundException ( "Object " + pid + " does not exist." ) ; } Datastream currentDS = w . GetDatastream ( dsID , null ) ; if ( currentDS == null ) { throw new DatastreamNotFoundException ( "Datastream " + dsID + " not found" ) ; } if ( currentDS . DSControlGrp . equals ( "X" ) ) { Date [ ] versions = w . getDatastreamVersions ( dsID ) ; Map < Date , Datastream > copyDS = new HashMap < Date , Datastream > ( versions . length ) ; for ( Date version : versions ) { Datastream d = w . GetDatastream ( dsID , version ) ; copyDS . put ( version , d . copy ( ) ) ; } w . removeDatastream ( dsID , null , null ) ; Arrays . sort ( versions ) ; for ( int i = versions . length - 1 ; i >= 0 ; i -- ) { DatastreamXMLMetadata existing = ( DatastreamXMLMetadata ) copyDS . get ( versions [ i ] ) ; DatastreamManagedContent newDS = new DatastreamManagedContent ( ) ; existing . copy ( newDS ) ; newDS . DSControlGrp = controlGroup ; newDS . DSLocation = null ; newDS . DSLocationType = null ; if ( setMIMETypeCharset ) { if ( newDS . DSMIME != null && ! newDS . DSMIME . isEmpty ( ) & ! newDS . DSMIME . contains ( "charset=" ) ) { newDS . DSMIME = newDS . DSMIME + "; charset=UTF-8" ; } else { newDS . DSMIME = "text/xml; charset=UTF-8" ; } } InputStream byteContent ; long byteLength ; if ( reformat ) { ReadableByteArrayOutputStream out = new ReadableByteArrayOutputStream ( 2048 ) ; this . getXML ( existing . getContentStream ( ) , out , addXMLHeader ) ; out . close ( ) ; byteContent = out . toInputStream ( ) ; byteLength = out . length ( ) ; } else { if ( addXMLHeader ) { byteContent = new SequenceInputStream ( new ByteArrayInputStream ( xmlHeader ) , existing . getContentStream ( ) ) ; byteLength = xmlHeader . length + existing . DSSize ; } else { byteContent = existing . getContentStream ( ) ; byteLength = existing . DSSize ; } } MIMETypedStream content = new MIMETypedStream ( null , byteContent , null , byteLength ) ; newDS . putContentStream ( content ) ; if ( addXMLHeader ) { logger . debug ( "Recalculating checksum.  Type={} Existing checksum: {}" , newDS . DSChecksumType , newDS . DSChecksum != null ? newDS . DSChecksum : "none" ) ; newDS . DSChecksum = Datastream . CHECKSUM_NONE ; newDS . DSChecksum = newDS . getChecksum ( ) ; if ( logger . isDebugEnabled ( ) ) { logger . debug ( "New checksum: {}" , newDS . DSChecksum ) ; logger . debug ( "Testing new checksum, response is {}" , newDS . compareChecksum ( ) ) ; } } w . addDatastream ( newDS , true ) ; } Date nowUTC = Server . getCurrentDate ( context ) ; String logMessage = "Modified datastream control group for " + pid + " " + dsID + " from " + currentDS . DSControlGrp + " to " + controlGroup ; addAuditRecord ( context , w , "modifyDatastreamControlGroup" , dsID , logMessage , nowUTC ) ; w . commit ( logMessage ) ; return versions ; } else { if ( currentDS . DSControlGrp . equals ( "M" ) ) { return new Date [ 0 ] ; } else { throw new GeneralException ( "Original control group must be X, it is " + currentDS . DSControlGrp ) ; } } } finally { if ( logger . isInfoEnabled ( ) ) { StringBuilder logMsg = new StringBuilder ( "Completed modifyDatastreamControlGroup(" ) ; logMsg . append ( "pid: " ) . append ( pid ) ; logMsg . append ( ", datastream: " ) . append ( dsID ) ; logMsg . append ( ", new control group: " ) . append ( controlGroup ) ; logMsg . append ( ", add XML header: " ) . append ( addXMLHeader ) ; logMsg . append ( ", set MIMEType charset: " ) . append ( setMIMETypeCharset ) ; logMsg . append ( ")" ) ; logger . info ( logMsg . toString ( ) ) ; } finishModification ( w , "modifyDatastreamControlGroup" ) ; } }
Migrate the datastream from one control group to another, returning list of versions migrated.
Only supports migration from X (inline) to M (managed content).  Returns an array of date/times of the
datastream versions migrated (empty if datastream already had the desired control group).  Throws
ObjectNotFoundException/DatastreamNotFoundException if object or datastream does not exist.

@param context
@param pid
@param dsID
@param controlGroup - new Control Group for datastream
@param addXMLHeader - add an XML header declaring UTF-8 character encoding to datastream content
@param reformat - reformat the XML (in the same format as used for inline XML)
@param setMIMETypeCharset - add charset declaration (UTF-8) to the MIMEType, and add text/xml MIMEType if no MIMEType is set
@return array of versions migrated
@throws ServerException