signature:
public class Generator { /** * Generate a product by assembling components .
 * @ param components The components to assemble
 * @ param product The output to write the assembled product to
 * @ return Metrics about the generation process
 * @ throws IOException When an I / O error occurs */
public Metrics generate ( Iterable < C > components , DataBuffer product ) throws IOException { } }

implementation: return generate ( components . iterator ( ) , product ) ;


signature:
public class Generator { /** * Generate a product by assembling components .
 * @ param components The components to assemble
 * @ param product Storage for the assembled product
 * @ return Metrics about the generation process
 * @ throws IOException When an I / O error occurs */
public Metrics generate ( Iterator < C > components , DataBuffer product ) throws IOException { } }

implementation: assembler . start ( product ) ; try { while ( components . hasNext ( ) ) { assembler . add ( components . next ( ) ) ; } } finally { assembler . end ( ) ; } return assembler . getMetrics ( ) ;


signature:
public class Generator { /** * Generate a product by assembling components .
 * @ param components The components to assemble
 * @ param product The output to write the assembled product to
 * @ return Metrics about the generation process
 * @ throws IOException When an I / O error occurs */
public Metrics generate ( Enumeration < C > components , DataBuffer product ) throws IOException { } }

implementation: return generate ( new EnumerationIterator < C > ( components ) , product ) ;


signature:
public class Generator { /** * Generate a product from a single piece .
 * @ param component The component to generate the product from
 * @ param product The output to write the assembled product to
 * @ return Metrics about the generation process
 * @ throws IOException When an I / O error occurs */
public Metrics generate ( C component , DataBuffer product ) throws IOException { } }

implementation: return generate ( Collections . singletonList ( component ) , product ) ;


signature:
public class InfoArchiveRestClient { /** * Fetch the content for the specified content id .
 * @ param contentId The id of the content to fetch .
 * @ return A ContentResult
 * @ throws IOException When an I / O error occurs
 * @ deprecated Will be removed without replacement in a future version */
@ Override @ Deprecated public ContentResult fetchContent ( String contentId ) throws IOException { } }

implementation: try { String contentResource = resourceCache . getCiResourceUri ( ) ; URIBuilder builder = new URIBuilder ( contentResource ) ; builder . setParameter ( "cid" , contentId ) ; URI uri = builder . build ( ) ; return restClient . get ( uri . toString ( ) , contentResultFactory ) ; } catch ( URISyntaxException e ) { throw new IllegalStateException ( "Failed to create content resource uri." , e ) ; }


signature:
public class InfoArchiveRestClient { /** * Fetch the content for the specified order item .
 * @ param orderItem The order item .
 * @ return A ContentResult
 * @ throws IOException When an I / O error occurs
 * @ deprecated Will be removed without replacement in a future version */
@ Override @ Deprecated public ContentResult fetchOrderContent ( OrderItem orderItem ) throws IOException { } }

implementation: String downloadUri = Objects . requireNonNull ( Objects . requireNonNull ( orderItem , "Missing order item" ) . getUri ( LINK_DOWNLOAD ) , "Missing download URI" ) ; String fetchUri = restClient . uri ( downloadUri ) . addParameter ( "downloadToken" , "" ) . build ( ) ; return restClient . get ( fetchUri , contentResultFactory ) ;


signature:
public class InfoArchiveRestClient { /** * Upload the transformation zip with the stylesheet into Archive .
 * @ param exportTransformation The export transformation .
 * @ param zip The input stream of zip with stylesheet .
 * @ throws IOException When an I / O error occurs
 * @ return The uploaded transformation
 * @ deprecated Use declarative configuration to define transformations */
@ Override @ Deprecated public LinkContainer uploadTransformation ( ExportTransformation exportTransformation , InputStream zip ) throws IOException { } }

implementation: String uri = exportTransformation . getUri ( LINK_EXPORT_TRANSFORMATION_ZIP ) ; return restClient . post ( uri , LinkContainer . class , new BinaryPart ( "file" , zip , "stylesheet.zip" ) ) ;


signature:
public class FileGenerator { /** * Generate a file by assembling components .
 * @ param components The components to assemble
 * @ return The generated file and metrics about the generation process
 * @ throws IOException When an I / O error occurs */
public FileGenerationMetrics generate ( Iterator < C > components ) throws IOException { } }

implementation: File result = fileSupplier . get ( ) ; return new FileGenerationMetrics ( result , generate ( components , new FileBuffer ( result ) ) ) ;


signature:
public class UniqueDirectory { /** * Create a new directory in the given parent directory .
 * @ param parentDir The parent directory in which to create a new directory
 * @ return The newly created directory */
public static File in ( File parentDir ) { } }

implementation: File result = new File ( parentDir , UUID . randomUUID ( ) . toString ( ) ) ; if ( ! result . mkdirs ( ) ) { throw new RuntimeIoException ( new IOException ( "Could not create directory: " + result ) ) ; } return result ;


signature:
public class BaseBuilder { /** * End this builder .
 * @ return The parent builder */
public P end ( ) { } }

implementation: parent . addChildObject ( English . plural ( object . getType ( ) ) , object ) ; return parent ;


signature:
public class StringTemplate { /** * Prepares a group by adding renderers , adaptors and sub templates . Override this if you want to add additional
 * renderers . By default adds :
 * < ul >
 * < li > an { @ linkplain XmlDateRenderer } which renders Date instances into the standard XML date and time format < / li >
 * < li > an { @ linkplain MapModelAdaptor } which allows { @ linkplain java . util . Map } to be used transparently as domain
 * objects . < / li >
 * < / ul >
 * @ param group The template group */
protected void prepareGroup ( STGroup group ) { } }

implementation: registerAdaptor ( group , Map . class , new MapModelAdaptor ( ) ) ; registerRenderer ( group , Date . class , new XmlDateRenderer ( ) ) ;


signature:
public class StringTemplate { /** * Registers a ModelAdaptor with the group . Override this method if you want to suppress one OOTB adaptor but not all .
 * @ param < S > The domain object type
 * @ param group The template group
 * @ param type The domain object class
 * @ param adaptor The adaptor that will be used to extract properties of objects of type S */
protected < S > void registerAdaptor ( STGroup group , Class < S > type , ModelAdaptor adaptor ) { } }

implementation: group . registerModelAdaptor ( type , adaptor ) ;


signature:
public class StringTemplate { /** * Registers a renderer with the group . Override this method if you want to suppress one OOTB renderer but not all .
 * @ param < S > The domain object type
 * @ param group The template group
 * @ param type The domain object class
 * @ param attributeRenderer The renderer that will be used to render objects of type S into a String */
protected < S > void registerRenderer ( STGroup group , Class < S > type , AttributeRenderer attributeRenderer ) { } }

implementation: group . registerRenderer ( type , attributeRenderer ) ;


signature:
public class StringTemplate { /** * Prepares the template by adding the variables .
 * @ param prototype The template prototype
 * @ param domainObject The domain object
 * @ param contentInfo The reference information and the encoded content hashes
 * @ return The prepared template instance */
protected ST prepareTemplate ( ST prototype , D domainObject , Map < String , ContentInfo > contentInfo ) { } }

implementation: ST template = new ST ( prototype ) ; template . add ( MODEL_VARIABLE , domainObject ) ; template . add ( CONTENT_VARIABLE , contentInfo ) ; return template ;


signature:
public class BatchSipAssembler { /** * Add a domain object to the batch of SIPs .
 * @ param domainObject The domain object to add
 * @ throws IOException When an I / O error occurs */
public synchronized void add ( D domainObject ) throws IOException { } }

implementation: if ( shouldStartNewSip ( domainObject ) ) { startSip ( ) ; } assembler . add ( domainObject ) ;


signature:
public class ConfigurationObject { /** * Set the value of a property .
 * @ param name The name of the property to set
 * @ param value The value to set the property to */
public void setProperty ( String name , Object value ) { } }

implementation: properties . put ( name , toJsonValue ( value ) ) ;


signature:
public class ConfigurationObject { /** * Add an object that is to be owned by this object .
 * @ param collection The collection to store the child object under
 * @ param childObject The child object to add */
public void addChildObject ( String collection , ConfigurationObject childObject ) { } }

implementation: childObjects . computeIfAbsent ( collection , ignored -> new ArrayList < > ( ) ) . add ( childObject ) ;


signature:
public class Dates { /** * Convert a date to < a href = " https : / / tools . ietf . org / html / rfc3339 # section - 5.6 " > ISO 8601 dateTime < / a > format .
 * @ param dateTime The datetime to convert
 * @ return The dateTime in ISO format */
@ Nullable public static String toIso ( Date dateTime ) { } }

implementation: if ( dateTime == null ) { return null ; } Calendar calendar = Calendar . getInstance ( ) ; calendar . setTime ( dateTime ) ; return DatatypeConverter . printDateTime ( calendar ) ;


signature:
public class Dates { /** * Convert an < a href = " https : / / tools . ietf . org / html / rfc3339 # section - 5.6 " > ISO 8601 dateTime < / a > string to a date .
 * @ param dateTime The ISO dateTime to convert
 * @ return The converted dateTime */
@ Nullable public static Date fromIso ( String dateTime ) { } }

implementation: if ( dateTime == null ) { return null ; } return DatatypeConverter . parseDateTime ( dateTime ) . getTime ( ) ;


signature:
public class FileSupplier { /** * Returns a supplier that creates sequentially named files in the given directory .
 * @ param dir The directory in which to create files
 * @ param prefix The prefix for the file names
 * @ param suffix The suffix for the file names
 * @ return A supplier that creates sequentially named files in the given directory */
public static Supplier < File > fromDirectory ( File dir , String prefix , String suffix ) { } }

implementation: return new Supplier < File > ( ) { private int count ; @ Override public File get ( ) { return new File ( ensureDir ( dir ) , String . format ( "%s%d%s" , prefix , ++ count , suffix ) ) ; } } ;


signature:
public class SipAssembler { /** * Assemble a SIP that contains only structured data and is the only SIP in its DSS .
 * @ param < D > The type of domain objects to assemble the SIP from
 * @ param prototype Prototype for the Packaging Information
 * @ param pdiAssembler Assembler that builds up the PDI
 * @ return The newly created SIP assembler */
public static < D > SipAssembler < D > forPdi ( PackagingInformation prototype , Assembler < HashedContents < D > > pdiAssembler ) { } }

implementation: return forPdiWithHashing ( prototype , pdiAssembler , new NoHashAssembler ( ) ) ;


signature:
public class SipAssembler { /** * Assemble a SIP that contains only structured data and is the only SIP in its DSS .
 * @ param < D > The type of domain objects to assemble the SIP from
 * @ param factory Factory for creating the Packaging Information
 * @ param pdiAssembler Assembler that builds up the PDI
 * @ return The newly created SIP assembler */
public static < D > SipAssembler < D > forPdi ( PackagingInformationFactory factory , Assembler < HashedContents < D > > pdiAssembler ) { } }

implementation: return forPdiWithHashing ( factory , pdiAssembler , new NoHashAssembler ( ) ) ;


signature:
public class SipAssembler { /** * Assemble a SIP that contains only structured data and is the only SIP in its DSS .
 * @ param < D > The type of domain objects to assemble the SIP from
 * @ param prototype Prototype for the Packaging Information
 * @ param pdiAssembler Assembler that builds up the PDI
 * @ param pdiHashAssembler Assembler that builds up an encoded hash for the PDI
 * @ return The newly created SIP assembler */
public static < D > SipAssembler < D > forPdiWithHashing ( PackagingInformation prototype , Assembler < HashedContents < D > > pdiAssembler , HashAssembler pdiHashAssembler ) { } }

implementation: return forPdiAndContentWithHashing ( prototype , pdiAssembler , pdiHashAssembler , ContentAssembler . ignoreContent ( ) ) ;


signature:
public class SipAssembler { /** * Assemble a SIP that contains only structured data and is the only SIP in its DSS .
 * @ param < D > The type of domain objects to assemble the SIP from
 * @ param factory Factory for creating the Packaging Information
 * @ param pdiAssembler Assembler that builds up the PDI
 * @ param pdiHashAssembler Assembler that builds up an encoded hash for the PDI
 * @ return The newly created SIP assembler */
public static < D > SipAssembler < D > forPdiWithHashing ( PackagingInformationFactory factory , Assembler < HashedContents < D > > pdiAssembler , HashAssembler pdiHashAssembler ) { } }

implementation: return forPdiAndContentWithHashing ( factory , pdiAssembler , pdiHashAssembler , ContentAssembler . ignoreContent ( ) ) ;


signature:
public class SipAssembler { /** * Assemble a SIP that contains only structured data and is the only SIP in its DSS .
 * @ param < D > The type of domain objects to assemble the SIP from
 * @ param prototype Prototype for the Packaging Information
 * @ param pdiAssembler Assembler that builds up the PDI
 * @ param contentsExtraction Extraction of content from domain objects added to the SIP
 * @ return The newly created SIP assembler */
public static < D > SipAssembler < D > forPdiAndContent ( PackagingInformation prototype , Assembler < HashedContents < D > > pdiAssembler , DigitalObjectsExtraction < D > contentsExtraction ) { } }

implementation: HashAssembler noHashAssembler = new NoHashAssembler ( ) ; return forPdiAndContentWithHashing ( prototype , pdiAssembler , noHashAssembler , contentsExtraction , noHashAssembler ) ;


signature:
public class SipAssembler { /** * Assemble a SIP that contains only structured data and is the only SIP in its DSS .
 * @ param < D > The type of domain objects to assemble the SIP from
 * @ param prototype Prototype for the Packaging Information
 * @ param pdiAssembler Assembler that builds up the PDI
 * @ param contentAssembler ContentAssembler that adds the digital objects to the SIP
 * @ return The newly created SIP assembler */
public static < D > SipAssembler < D > forPdiAndContent ( PackagingInformation prototype , Assembler < HashedContents < D > > pdiAssembler , ContentAssembler < D > contentAssembler ) { } }

implementation: HashAssembler noHashAssembler = new NoHashAssembler ( ) ; return forPdiAndContentWithHashing ( prototype , pdiAssembler , noHashAssembler , contentAssembler ) ;


signature:
public class SipAssembler { /** * Assemble a SIP that contains only structured data and is the only SIP in its DSS .
 * @ param < D > The type of domain objects to assemble the SIP from
 * @ param factory Factory for creating the Packaging Information
 * @ param pdiAssembler Assembler that builds up the PDI
 * @ param contentAssembler ContentAssembler that adds the digital objects to the SIP
 * @ return The newly created SIP assembler */
public static < D > SipAssembler < D > forPdiAndContent ( PackagingInformationFactory factory , Assembler < HashedContents < D > > pdiAssembler , ContentAssembler < D > contentAssembler ) { } }

implementation: HashAssembler noHashAssembler = new NoHashAssembler ( ) ; return forPdiAndContentWithHashing ( factory , pdiAssembler , noHashAssembler , contentAssembler ) ;


signature:
public class SipAssembler { /** * Assemble a SIP that contains only structured data and is the only SIP in its DSS .
 * @ param < D > The type of domain objects to assemble the SIP from
 * @ param factory Factory for creating the Packaging Information
 * @ param pdiAssembler Assembler that builds up the PDI
 * @ param contentsExtraction Extraction of content from domain objects added to the SIP
 * @ return The newly created SIP assembler */
public static < D > SipAssembler < D > forPdiAndContent ( PackagingInformationFactory factory , Assembler < HashedContents < D > > pdiAssembler , DigitalObjectsExtraction < D > contentsExtraction ) { } }

implementation: HashAssembler noHashAssembler = new NoHashAssembler ( ) ; return forPdiAndContentWithHashing ( factory , pdiAssembler , noHashAssembler , ContentAssembler . noDedup ( contentsExtraction , noHashAssembler ) ) ;


signature:
public class SipAssembler { /** * Assemble a SIP that contains only structured data and is the only SIP in its DSS .
 * @ param < D > The type of domain objects to assemble the SIP from
 * @ param prototype Prototype for the Packaging Information
 * @ param pdiAssembler Assembler that builds up the PDI
 * @ param contentsExtraction Extraction of content from domain objects added to the SIP
 * @ param contentHashAssembler Assembler that builds up an encoded hash for the extracted content
 * @ return The newly created SIP assembler */
public static < D > SipAssembler < D > forPdiAndContentWithContentHashing ( PackagingInformation prototype , Assembler < HashedContents < D > > pdiAssembler , DigitalObjectsExtraction < D > contentsExtraction , HashAssembler contentHashAssembler ) { } }

implementation: return forPdiAndContentWithHashing ( prototype , pdiAssembler , new NoHashAssembler ( ) , contentsExtraction , contentHashAssembler ) ;


signature:
public class SipAssembler { /** * Assemble a SIP that contains only structured data and is the only SIP in its DSS .
 * @ param < D > The type of domain objects to assemble the SIP from
 * @ param factory Factory for creating the Packaging Information
 * @ param pdiAssembler Assembler that builds up the PDI
 * @ param contentsExtraction Extraction of content from domain objects added to the SIP
 * @ param contentHashAssembler Assembler that builds up an encoded hash for the extracted content
 * @ return The newly created SIP assembler */
public static < D > SipAssembler < D > forPdiAndContentWithContentHashing ( PackagingInformationFactory factory , Assembler < HashedContents < D > > pdiAssembler , DigitalObjectsExtraction < D > contentsExtraction , HashAssembler contentHashAssembler ) { } }

implementation: return forPdiAndContentWithHashing ( factory , pdiAssembler , new NoHashAssembler ( ) , new ContentAssemblerDefault < D > ( contentsExtraction , contentHashAssembler ) ) ;


signature:
public class SipAssembler { /** * Assemble a SIP that is the only SIP in its DSS .
 * @ param < D > The type of domain objects to assemble the SIP from
 * @ param prototype Prototype for the Packaging Information
 * @ param pdiAssembler Assembler that builds up the PDI
 * @ param pdiHashAssembler Assembler that builds up an encoded hash for the PDI
 * @ param contentsExtraction Extraction of content from domain objects added to the SIP
 * @ param contentHashAssembler Assembler that builds up an encoded hash for the extracted content
 * @ return The newly created SIP assembler */
public static < D > SipAssembler < D > forPdiAndContentWithHashing ( PackagingInformation prototype , Assembler < HashedContents < D > > pdiAssembler , HashAssembler pdiHashAssembler , DigitalObjectsExtraction < D > contentsExtraction , HashAssembler contentHashAssembler ) { } }

implementation: return new SipAssembler < > ( new DefaultPackagingInformationFactory ( prototype ) , pdiAssembler , pdiHashAssembler , new DataBufferSupplier < > ( MemoryBuffer . class ) , new ContentAssemblerDefault < D > ( contentsExtraction , contentHashAssembler ) ) ;


signature:
public class SipAssembler { /** * Assemble a SIP that is the only SIP in its DSS .
 * @ param < D > The type of domain objects to assemble the SIP from
 * @ param prototype Prototype for the Packaging Information
 * @ param pdiAssembler Assembler that builds up the PDI
 * @ param pdiHashAssembler Assembler that builds up an encoded hash for the PDI
 * @ param contentAssembler ContentAssembler that adds the digital objects to the SIP
 * @ return The newly created SIP assembler */
public static < D > SipAssembler < D > forPdiAndContentWithHashing ( PackagingInformation prototype , Assembler < HashedContents < D > > pdiAssembler , HashAssembler pdiHashAssembler , ContentAssembler < D > contentAssembler ) { } }

implementation: return new SipAssembler < > ( new DefaultPackagingInformationFactory ( prototype ) , pdiAssembler , pdiHashAssembler , new DataBufferSupplier < > ( MemoryBuffer . class ) , contentAssembler ) ;


signature:
public class SipAssembler { /** * Assemble a SIP that is the only SIP in its DSS .
 * @ param < D > The type of domain objects to assemble the SIP from
 * @ param factory Factory for creating the Packaging Information
 * @ param pdiAssembler Assembler that builds up the PDI
 * @ param pdiHashAssembler Assembler that builds up an encoded hash for the PDI
 * @ param contentAssembler ContentAssembler that adds the digital objects to the SIP
 * @ return The newly created SIP assembler */
public static < D > SipAssembler < D > forPdiAndContentWithHashing ( PackagingInformationFactory factory , Assembler < HashedContents < D > > pdiAssembler , HashAssembler pdiHashAssembler , ContentAssembler < D > contentAssembler ) { } }

implementation: return new SipAssembler < > ( factory , pdiAssembler , pdiHashAssembler , new DataBufferSupplier < > ( MemoryBuffer . class ) , contentAssembler ) ;


signature:
public class IOStreams { /** * Utility method to copy the bytes from an InputStream to an OutputStream while also assembling a hash value in the
 * process .
 * @ param in The source stream
 * @ param out The target stream
 * @ param bufferSize The size of the internal buffer
 * @ param hashAssembler The HashAssembler to use .
 * @ throws IOException if an error occurs when copying the streams */
public static void copy ( InputStream in , OutputStream out , int bufferSize , HashAssembler hashAssembler ) throws IOException { } }

implementation: byte [ ] buffer = new byte [ bufferSize ] ; int numRead = Objects . requireNonNull ( in , "Missing input" ) . read ( buffer ) ; if ( numRead == 0 ) { throw new IllegalArgumentException ( "Missing content" ) ; } Objects . requireNonNull ( out , "Missing output" ) ; while ( numRead > 0 ) { out . write ( buffer , 0 , numRead ) ; hashAssembler . add ( buffer , numRead ) ; numRead = in . read ( buffer ) ; }


signature:
public class XmlUtil { /** * Return a new factory for building XML documents that is configured to operate securely . The factory also supports
 * < a href = " http : / / www . w3 . org / TR / REC - xml - names / " > XML namespaces < / a > and validation .
 * @ return The newly created factory */
public static DocumentBuilderFactory newSecureDocumentBuilderFactory ( ) { } }

implementation: try { DocumentBuilderFactory result = DocumentBuilderFactory . newInstance ( ) ; result . setFeature ( "http://javax.xml.XMLConstants/feature/secure-processing" , true ) ; result . setFeature ( "http://xml.org/sax/features/external-general-entities" , false ) ; result . setFeature ( "http://xml.org/sax/features/external-parameter-entities" , false ) ; result . setNamespaceAware ( true ) ; result . setValidating ( true ) ; return result ; } catch ( ParserConfigurationException e ) { throw new IllegalStateException ( e ) ; }


signature:
public class XmlUtil { /** * Parse the content of a given file into an XML document .
 * @ param file The file to parse
 * @ return The parsed XML document */
public static Document parse ( File file ) { } }

implementation: if ( ! file . isFile ( ) ) { throw new IllegalArgumentException ( "Missing file: " + file . getAbsolutePath ( ) ) ; } try { try ( InputStream stream = Files . newInputStream ( file . toPath ( ) , StandardOpenOption . READ ) ) { return parse ( stream ) ; } } catch ( IOException e ) { throw new IllegalArgumentException ( "Failed to parse " + file . getAbsolutePath ( ) , e ) ; }


signature:
public class XmlUtil { /** * Parse the content of a given reader into an XML document .
 * @ param reader The reader to parse
 * @ return The parsed XML document */
public static Document parse ( Reader reader ) { } }

implementation: DocumentBuilder documentBuilder = getDocumentBuilder ( ) ; try { return documentBuilder . parse ( new InputSource ( reader ) ) ; } catch ( SAXException | IOException e ) { throw new IllegalArgumentException ( "Failed to parse XML document" , e ) ; } finally { documentBuilder . reset ( ) ; }


signature:
public class XmlUtil { /** * Return the elements under a given parent element .
 * @ param parent The parent of the elements to return
 * @ return The children of the parent element */
public static Stream < Element > elementsIn ( Element parent ) { } }

implementation: return nodesIn ( parent ) . filter ( n -> n . getNodeType ( ) == Node . ELEMENT_NODE ) . map ( n -> ( Element ) n ) ;


signature:
public class XmlUtil { /** * Return the nodes under a given parent element .
 * @ param parent The parent of the nodes to return
 * @ return The children of the parent element */
public static Stream < Node > nodesIn ( Element parent ) { } }

implementation: return StreamSupport . stream ( new ChildNodesSpliterator ( parent ) , false ) ;


signature:
public class XmlUtil { /** * Return the first child element of a given parent element whose tag matches any of the given names . When no child
 * names are given , the first child element is returned .
 * @ param parent The parent of the element to return
 * @ param childNames The acceptable names of the children
 * @ return The first child element that matches any of the names */
public static Element getFirstChildElement ( Element parent , String ... childNames ) { } }

implementation: return firstOf ( namedElementsIn ( parent , childNames ) ) ;


signature:
public class XmlUtil { /** * Return the elements under a given parent element whose tag matches any of the given names . When no child
 * names are given , all child elements are returned .
 * @ param parent The parent of the elements to return
 * @ param childNames The acceptable names of the children
 * @ return The children of the parent element */
public static Stream < Element > namedElementsIn ( Element parent , String ... childNames ) { } }

implementation: return elementsIn ( parent ) . filter ( e -> isName ( e , childNames ) ) ;


signature:
public class XmlUtil { /** * Validate an XML document against an XML Schema document .
 * @ param xml The XML document to validate
 * @ param xmlSchema The XML Schema document to validate against
 * @ param humanFriendlyDocumentType A human - friendly name that describes the schema
 * @ throws IOException When an I / O error occurs */
public static void validate ( InputStream xml , InputStream xmlSchema , String humanFriendlyDocumentType ) throws IOException { } }

implementation: try { newXmlSchemaValidator ( xmlSchema ) . validate ( new StreamSource ( Objects . requireNonNull ( xml ) ) ) ; } catch ( SAXException e ) { throw new ValidationException ( "Invalid " + humanFriendlyDocumentType , e ) ; }


signature:
public class ArchiveClients { /** * Returns an { @ linkplain ArchiveClient } for an application that it first configures .
 * @ param configurer How to configure the InfoArchive application
 * @ param connection How to communicate with the InfoArchive server
 * @ return An ArchiveClient
 * @ throws IOException When an I / O error occurs */
public static ArchiveClient configuringApplicationUsing ( ApplicationConfigurer configurer , ArchiveConnection connection ) throws IOException { } }

implementation: configurer . configure ( connection ) ; return usingAlreadyConfiguredApplication ( configurer . getApplicationName ( ) , connection ) ;


signature:
public class ArchiveClients { /** * Returns an { @ linkplain ArchiveClient } for an already configured application .
 * @ param applicationName The name of the already configured application to use
 * @ param connection How to communicate with the InfoArchive server
 * @ return An ArchiveClient
 * @ throws IOException When an I / O error occurs */
public static ArchiveClient usingAlreadyConfiguredApplication ( String applicationName , ArchiveConnection connection ) throws IOException { } }

implementation: RestClient restClient = connection . getRestClient ( ) ; return new InfoArchiveRestClient ( restClient , appResourceCache ( applicationName , connection , restClient ) ) ;


signature:
public class YamlMap { /** * Parses the given YAML .
 * @ param yaml The YAML string to parse
 * @ return A < code > YamlMap < / code > corresponding to the provided YAML string */
public static YamlMap from ( String yaml ) { } }

implementation: assertNotNull ( yaml ) ; try ( InputStream input = streamOf ( yaml ) ) { return from ( input ) ; } catch ( IOException e ) { throw new IllegalArgumentException ( "Failed to parse YAML string" , e ) ; }


signature:
public class YamlMap { /** * Parses the given YAML .
 * @ param yaml The YAML file to parse
 * @ return A < code > YamlMap < / code > corresponding to the provided YAML file , or an empty < code > YamlMap < / code > if the
 * file does not exist
 * @ throws IOException When an I / O error occurs */
public static YamlMap from ( File yaml ) throws IOException { } }

implementation: assertNotNull ( yaml ) ; if ( ! yaml . isFile ( ) ) { return new YamlMap ( ) ; } try ( InputStream input = Files . newInputStream ( yaml . toPath ( ) ) ) { return from ( input ) ; }


signature:
public class FileArchiver { /** * Build a SIP archive from all files in a given directory tree .
 * @ param args The command line args : < ol >
 * < li > The path to the directory to be archived . The default value is the current directory . < / li >
 * < li > The path to the SIP archive to be built . The default value is < code > build / files . zip < / code > < / li >
 * < / ol > */
public static void main ( String [ ] args ) { } }

implementation: try { Arguments arguments = new Arguments ( args ) ; File root = new File ( arguments . next ( "content" ) ) ; if ( ! root . isDirectory ( ) ) { root = new File ( "." ) ; } String rootPath = root . getCanonicalPath ( ) ; String sip = arguments . next ( "build/files.zip" ) ; new FileArchiver ( ) . run ( rootPath , sip ) ; } catch ( IOException e ) { e . printStackTrace ( System . out ) ; System . exit ( 1 ) ; }


signature:
public class ContentBuilder { /** * Sets the content .
 * @ param content the content to add
 * @ return this builder */
public ContentBuilder < P > as ( InputStream content ) { } }

implementation: try { return as ( IOUtils . toString ( content , StandardCharsets . UTF_8 ) ) ; } catch ( IOException e ) { throw new IllegalArgumentException ( "Failed to read content" , e ) ; }


signature:
public class ContentBuilder { /** * Sets the content from a named resource .
 * @ param name the name of the content resource to add
 * @ return this builder */
public ContentBuilder < P > fromResource ( String name ) { } }

implementation: try ( InputStream content = ContentBuilder . class . getResourceAsStream ( name ) ) { return as ( content ) ; } catch ( IOException e ) { throw new IllegalArgumentException ( "Failed to read resource: " + name , e ) ; }


signature:
public class Unzip { /** * Process a named entry in the ZIP file .
 * @ param < T > The type of result returned by the processor
 * @ param entry The name of the entry to process
 * @ param processor The processor that handles the entry ' s content
 * @ return The result of processing the entry */
public < T > T andProcessEntry ( String entry , Function < InputStream , T > processor ) { } }

implementation: try ( ZipFile zipFile = new ZipFile ( zip ) ) { return processEntry ( zipFile , entry , processor ) ; } catch ( IOException e ) { throw new RuntimeIoException ( e ) ; }


signature:
public class QSStringUtil { /** * Chinese characters transform
 * @ param str unEncoded chars
 * @ return encoded chars
 * @ throws QSException UnsupportedEncodingException */
public static String asciiCharactersEncoding ( String str ) throws QSException { } }

implementation: if ( QSStringUtil . isEmpty ( str ) ) { return "" ; } try { String encoded = URLEncoder . encode ( str , QSConstant . ENCODING_UTF8 ) ; encoded = encoded . replace ( "%2F" , "/" ) ; encoded = encoded . replace ( "%3D" , "=" ) ; encoded = encoded . replace ( "+" , "%20" ) ; encoded = encoded . replace ( "%3A" , ":" ) ; return encoded ; } catch ( UnsupportedEncodingException e ) { throw new QSException ( "UnsupportedEncodingException:" , e ) ; }


signature:
public class QSSignatureUtil { /** * Generate signature for request against QingStor .
 * @ param accessKey : API access key ID
 * @ param secretKey : API secret access key ID
 * @ param method : HTTP method
 * @ param requestURI :
 * @ param params : HTTP request parameters
 * @ param headers : HTTP request headers
 * @ return a string which can be used as value of HTTP request header field " Authorization "
 * directly .
 * < p > See < a href = " https : / / docs . qingcloud . com / qingstor / api / common / signature . html " > https : / / docs . qingcloud . com / qingstor / api / common / signature . html < / a > for more details
 * about how to do signature of request against QingStor . */
public static String generateAuthorization ( String accessKey , String secretKey , String method , String requestURI , Map < String , String > params , Map < String , String > headers ) { } }

implementation: String signature = generateSignature ( secretKey , method , requestURI , params , headers ) ; return String . format ( "QS %s:%s" , accessKey , signature ) ;


signature:
public class QSSignatureUtil { /** * Generate signature for request against QingStor .
 * @ param accessKey : API access key ID
 * @ param secretKey : API secret access key ID
 * @ param strToSign : strToSign
 * @ return a string which can be used as value of HTTP request header field " Authorization "
 * directly .
 * < p > See < a href = " https : / / docs . qingcloud . com / qingstor / api / common / signature . html " > https : / / docs . qingcloud . com / qingstor / api / common / signature . html < / a > for more details
 * about how to do signature of request against QingStor . */
public static String generateAuthorization ( String accessKey , String secretKey , String strToSign ) { } }

implementation: String signature = generateSignature ( secretKey , strToSign ) ; return String . format ( "QS %s:%s" , accessKey , signature ) ;


signature:
public class QSSignatureUtil { /** * Generate signature for request against QingStor .
 * @ param secretKey : API secret access key ID
 * @ param method : HTTP method
 * @ param requestURI :
 * @ param params : HTTP request parameters
 * @ param headers : HTTP request headers
 * @ return a string which can be used as value of HTTP request header field " Authorization "
 * directly .
 * < p > See < a href = " https : / / docs . qingcloud . com / qingstor / api / common / signature . html " > https : / / docs . qingcloud . com / qingstor / api / common / signature . html < / a > for more details
 * about how to do signature of request against QingStor . */
public static String generateSignature ( String secretKey , String method , String requestURI , Map < String , String > params , Map < String , String > headers ) { } }

implementation: String signature = "" ; String strToSign = getStringToSignature ( method , requestURI , params , headers ) ; logger . log ( Level . INFO , "== String to sign ==\n" + strToSign + "\n" ) ; signature = generateSignature ( secretKey , strToSign ) ; return signature ;


signature:
public class QSServerSignatureUtil { /** * Generate signature for request against QingStor .
 * @ param accessKey : API access key ID
 * @ param secretKey : API secret access key ID
 * @ param strToSign : strToSign
 * @ return a string which can be used as value of HTTP request header field " Authorization "
 * directly .
 * < p > See https : / / docs . qingcloud . com / qingstor / api / common / signature . html for more details
 * about how to do signature of request against QingStor . */
public static String generateAuthorization ( String accessKey , String secretKey , String strToSign ) { } }

implementation: return QSSignatureUtil . generateAuthorization ( accessKey , secretKey , strToSign ) ;


signature:
public class QSServerSignatureUtil { /** * Generate signature for request against QingStor .
 * @ param secretKey API secret access key ID
 * @ param strToSign string to sign
 * @ return signature
 * < p > See https : / / docs . qingcloud . com / qingstor / api / common / signature . html for more details < / p > */
public static String generateSignature ( String secretKey , String strToSign ) { } }

implementation: return QSSignatureUtil . generateSignature ( secretKey , strToSign ) ;


signature:
public class RequestHandler { /** * < p > OkHttp will use " Accept - Encoding : gzip " as default header ,
 * which may not get Content - Length form server when download . < / p > */
private void checkDownloadRequest ( ) { } }

implementation: if ( outputClass == null ) return ; boolean isDownloadRequest = false ; Field [ ] declaredField = outputClass . getDeclaredFields ( ) ; for ( Field field : declaredField ) { String methodName = "get" + QSParamInvokeUtil . capitalize ( field . getName ( ) ) ; Method [ ] methods = outputClass . getDeclaredMethods ( ) ; for ( Method m : methods ) { if ( m . getName ( ) . equalsIgnoreCase ( methodName ) ) { ParamAnnotation annotation = m . getAnnotation ( ParamAnnotation . class ) ; if ( annotation == null ) continue ; if ( "BodyInputStream" . equals ( annotation . paramName ( ) ) ) { isDownloadRequest = true ; break ; } } } } if ( isDownloadRequest ) { getBuilder ( ) . setHeader ( "Accept-Encoding" , "identity" ) ; }


signature:
public class RequestHandler { /** * Set signature and server time .
 * @ param accessKey accessKey
 * @ param signature signature
 * @ param gmtTime time format with GMT
 * @ throws QSException exception */
public void setSignature ( String accessKey , String signature , String gmtTime ) throws QSException { } }

implementation: builder . setHeader ( QSConstant . HEADER_PARAM_KEY_DATE , gmtTime ) ; setSignature ( accessKey , signature ) ;


signature:
public class Base64 { /** * Encodes hex octects into Base64
 * @ param binaryData Array containing binaryData
 * @ return Encoded Base64 array */
public static String encode ( byte [ ] binaryData ) { } }

implementation:
if ( binaryData == null ) { return null ; } int lengthDataBits = binaryData . length * EIGHTBIT ; if ( lengthDataBits == 0 ) { return "" ; } int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP ; int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP ; int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets ; char encodedData [ ] = null ; encodedData = new char [ numberQuartet * 4 ] ; byte k = 0 , l = 0 , b1 = 0 , b2 = 0 , b3 = 0 ; int encodedIndex = 0 ; int dataIndex = 0 ; for ( int i = 0 ; i < numberTriplets ; i ++ ) { b1 = binaryData [ dataIndex ++ ] ; b2 = binaryData [ dataIndex ++ ] ; b3 = binaryData [ dataIndex ++ ] ; l = ( byte ) ( b2 & 0x0f ) ; k = ( byte ) ( b1 & 0x03 ) ; byte val1 = ( ( b1 & SIGN ) == 0 ) ? ( byte ) ( b1 >> 2 ) : ( byte ) ( ( b1 ) >> 2 ^ 0xc0 ) ; byte val2 = ( ( b2 & SIGN ) == 0 ) ? ( byte ) ( b2 >> 4 ) : ( byte ) ( ( b2 ) >> 4 ^ 0xf0 ) ; byte val3 = ( ( b3 & SIGN ) == 0 ) ? ( byte ) ( b3 >> 6 ) : ( byte ) ( ( b3 ) >> 6 ^ 0xfc ) ; encodedData [ encodedIndex ++ ] = lookUpBase64Alphabet [ val1 ] ; encodedData [ encodedIndex ++ ] = lookUpBase64Alphabet [ val2 | ( k << 4 ) ] ; encodedData [ encodedIndex ++ ] = lookUpBase64Alphabet [ ( l << 2 ) | val3 ] ; encodedData [ encodedIndex ++ ] = lookUpBase64Alphabet [ b3 & 0x3f ] ; } // form integral number of 6 - bit groups
if ( fewerThan24bits == EIGHTBIT ) { b1 = binaryData [ dataIndex ] ; k = ( byte ) ( b1 & 0x03 ) ; byte val1 = ( ( b1 & SIGN ) == 0 ) ? ( byte ) ( b1 >> 2 ) : ( byte ) ( ( b1 ) >> 2 ^ 0xc0 ) ; encodedData [ encodedIndex ++ ] = lookUpBase64Alphabet [ val1 ] ; encodedData [ encodedIndex ++ ] = lookUpBase64Alphabet [ k << 4 ] ; encodedData [ encodedIndex ++ ] = PAD ; encodedData [ encodedIndex ++ ] = PAD ; } else if ( fewerThan24bits == SIXTEENBIT ) { b1 = binaryData [ dataIndex ] ; b2 = binaryData [ dataIndex + 1 ] ; l = ( byte ) ( b2 & 0x0f ) ; k = ( byte ) ( b1 & 0x03 ) ; byte val1 = ( ( b1 & SIGN ) == 0 ) ? ( byte ) ( b1 >> 2 ) : ( byte ) ( ( b1 ) >> 2 ^ 0xc0 ) ; byte val2 = ( ( b2 & SIGN ) == 0 ) ? ( byte ) ( b2 >> 4 ) : ( byte ) ( ( b2 ) >> 4 ^ 0xf0 ) ; encodedData [ encodedIndex ++ ] = lookUpBase64Alphabet [ val1 ] ; encodedData [ encodedIndex ++ ] = lookUpBase64Alphabet [ val2 | ( k << 4 ) ] ; encodedData [ encodedIndex ++ ] = lookUpBase64Alphabet [ l << 2 ] ; encodedData [ encodedIndex ++ ] = PAD ; } return new String ( encodedData ) ;


signature:
public class Base64 { /** * Decodes Base64 data into octects
 * @ param encoded string containing Base64 data
 * @ return Array containind decoded data . */
public static byte [ ] decode ( String encoded ) { } }

implementation:
if ( encoded == null ) { return null ; } char [ ] base64Data = encoded . toCharArray ( ) ; // remove white spaces
int len = removeWhiteSpace ( base64Data ) ; if ( len % FOURBYTE != 0 ) { return null ; // should be divisible by four
} int numberQuadruple = ( len / FOURBYTE ) ; if ( numberQuadruple == 0 ) { return new byte [ 0 ] ; } byte decodedData [ ] = null ; byte b1 = 0 , b2 = 0 , b3 = 0 , b4 = 0 ; char d1 = 0 , d2 = 0 , d3 = 0 , d4 = 0 ; int i = 0 ; int encodedIndex = 0 ; int dataIndex = 0 ; decodedData = new byte [ ( numberQuadruple ) * 3 ] ; for ( ; i < numberQuadruple - 1 ; i ++ ) { if ( ! isData ( ( d1 = base64Data [ dataIndex ++ ] ) ) || ! isData ( ( d2 = base64Data [ dataIndex ++ ] ) ) || ! isData ( ( d3 = base64Data [ dataIndex ++ ] ) ) || ! isData ( ( d4 = base64Data [ dataIndex ++ ] ) ) ) { return null ; } // if found " no data " just return null
b1 = base64Alphabet [ d1 ] ; b2 = base64Alphabet [ d2 ] ; b3 = base64Alphabet [ d3 ] ; b4 = base64Alphabet [ d4 ] ; decodedData [ encodedIndex ++ ] = ( byte ) ( b1 << 2 | b2 >> 4 ) ; decodedData [ encodedIndex ++ ] = ( byte ) ( ( ( b2 & 0xf ) << 4 ) | ( ( b3 >> 2 ) & 0xf ) ) ; decodedData [ encodedIndex ++ ] = ( byte ) ( b3 << 6 | b4 ) ; } if ( ! isData ( ( d1 = base64Data [ dataIndex ++ ] ) ) || ! isData ( ( d2 = base64Data [ dataIndex ++ ] ) ) ) { return null ; // if found " no data " just return null
} b1 = base64Alphabet [ d1 ] ; b2 = base64Alphabet [ d2 ] ; d3 = base64Data [ dataIndex ++ ] ; d4 = base64Data [ dataIndex ++ ] ; if ( ! isData ( ( d3 ) ) || ! isData ( ( d4 ) ) ) { // Check if they are PAD characters
if ( isPad ( d3 ) && isPad ( d4 ) ) { if ( ( b2 & 0xf ) != 0 ) // last 4 bits should be zero
{ return null ; } byte [ ] tmp = new byte [ i * 3 + 1 ] ; System . arraycopy ( decodedData , 0 , tmp , 0 , i * 3 ) ; tmp [ encodedIndex ] = ( byte ) ( b1 << 2 | b2 >> 4 ) ; return tmp ; } else if ( ! isPad ( d3 ) && isPad ( d4 ) ) { b3 = base64Alphabet [ d3 ] ; if ( ( b3 & 0x3 ) != 0 ) // last 2 bits should be zero
{ return null ; } byte [ ] tmp = new byte [ i * 3 + 2 ] ; System . arraycopy ( decodedData , 0 , tmp , 0 , i * 3 ) ; tmp [ encodedIndex ++ ] = ( byte ) ( b1 << 2 | b2 >> 4 ) ; tmp [ encodedIndex ] = ( byte ) ( ( ( b2 & 0xf ) << 4 ) | ( ( b3 >> 2 ) & 0xf ) ) ; return tmp ; } else { return null ; } } else { // No PAD e . g 3cQl
b3 = base64Alphabet [ d3 ] ; b4 = base64Alphabet [ d4 ] ; decodedData [ encodedIndex ++ ] = ( byte ) ( b1 << 2 | b2 >> 4 ) ; decodedData [ encodedIndex ++ ] = ( byte ) ( ( ( b2 & 0xf ) << 4 ) | ( ( b3 >> 2 ) & 0xf ) ) ; decodedData [ encodedIndex ++ ] = ( byte ) ( b3 << 6 | b4 ) ; } return decodedData ;


signature:
public class Base64 { /** * remove WhiteSpace from MIME containing encoded Base64 data .
 * @ param data the byte array of base64 data ( with WS )
 * @ return the new length */
private static int removeWhiteSpace ( char [ ] data ) { } }

implementation:
if ( data == null ) { return 0 ; } // count characters that ' s not whitespace
int newSize = 0 ; int len = data . length ; for ( int i = 0 ; i < len ; i ++ ) { if ( ! isWhiteSpace ( data [ i ] ) ) { data [ newSize ++ ] = data [ i ] ; } } return newSize ;


signature:
public class UploadManager { /** * Upload a file with a sync request .
 * @ param file file
 * @ throws QSException exception */
public void put ( File file ) throws QSException { } }

implementation: if ( ! file . exists ( ) || file . isDirectory ( ) ) throw new QSException ( "File does not exist or it is a directory." ) ; put ( file , file . getName ( ) , null , "" ) ;


signature:
public class UploadManager { /** * Upload a file with a sync request .
 * @ param file file
 * @ param objectKey key of the object in the bucket
 * @ param fileName file name of response ( content - disposition ) when downloaded
 * @ param eTag MD5 info
 * @ throws QSException exception */
public void put ( File file , String objectKey , String fileName , String eTag ) throws QSException { } }

implementation:
// Check the file does exist or not .
if ( ! file . exists ( ) || file . isDirectory ( ) ) throw new QSException ( "File does not exist or it is a directory." ) ; // Check file ' s length .
long length = file . length ( ) ; if ( length < 1 ) throw new QSException ( "The size of file cannot be smaller than 1 byte." ) ; if ( length <= partSize ) { partCounts = 1 ; putFile ( file , objectKey , fileName , length ) ; } else { // Do multi uploads .
// Calculate part counts .
if ( length / partSize > MAX_PART_COUNTS ) { partSize = length / MAX_PART_COUNTS ; partCounts = MAX_PART_COUNTS ; // Check every part ' s size ( max 5GB ) .
if ( partSize > 5 * 1024 * 1024 * 1024L ) throw new QSException ( "The size of file is too large." ) ; } else { partCounts = ( int ) ( length / partSize ) ; if ( length % partSize > 0 ) partCounts += 1 ; } putFileMulti ( file , objectKey , fileName , eTag , length ) ; }


signature:
public class UploadManager { /** * Upload a file with a multi upload as a sync request .
 * @ param file file
 * @ param objectKey key of the object in the bucket
 * @ param fileName file name of response ( content - disposition ) when downloaded
 * @ param eTag MD5 info
 * @ param length length of the file .
 * @ throws QSException exception */
public void putFileMulti ( File file , final String objectKey , String fileName , String eTag , final long length ) throws QSException { } }

implementation:
if ( partSize < 4 * 1024 * 1024 ) { throw new QSException ( "Every part of the file can not smaller than 4 MB." ) ; } if ( recorder == null || recorder . get ( objectKey ) == null ) { Bucket . InitiateMultipartUploadInput inputInit = new Bucket . InitiateMultipartUploadInput ( ) ; Bucket . InitiateMultipartUploadOutput initOutput = bucket . initiateMultipartUpload ( objectKey , inputInit ) ; int code = initOutput . getStatueCode ( ) ; // Initiate occurs an error .
if ( code < 200 || code >= 300 ) { if ( callBack != null ) { OutputModel outputModel = new OutputModel ( ) ; outputModel . setStatueCode ( code ) ; outputModel . setMessage ( initOutput . getMessage ( ) ) ; callBack . onAPIResponse ( objectKey , outputModel ) ; } return ; } uploadModel = new UploadModel ( ) ; uploadModel . setTotalSize ( length ) ; uploadModel . setUploadID ( initOutput . getUploadID ( ) ) ; } else { byte [ ] bytes = recorder . get ( objectKey ) ; String json = new String ( bytes ) ; uploadModel = new Gson ( ) . fromJson ( json , UploadModel . class ) ; // Check status of the task .
if ( uploadModel . isUploadComplete ( ) ) { if ( callBack != null ) { OutputModel outputModel = new OutputModel ( ) ; outputModel . setStatueCode ( 201 ) ; outputModel . setMessage ( "This task has been uploaded." ) ; callBack . onAPIResponse ( objectKey , outputModel ) ; } return ; } } uploadModel . setTotalSize ( length ) ; // Check if all parts have been completely uploaded .
if ( uploadModel . isFileComplete ( ) ) { completeMultiUpload ( objectKey , fileName , eTag , uploadModel . getUploadID ( ) , length ) ; } else { for ( int i = uploadModel . getCurrentPart ( ) ; i < partCounts ; i ++ ) { // Make records when a new part starts to upload .
uploadModel . setCurrentPart ( i ) ; uploadModel . setBytesWritten ( i * partSize ) ; setData ( objectKey , recorder ) ; // Request cancelled . Stop upload other parts .
if ( cancellationHandler != null && cancellationHandler . isCancelled ( ) ) { // Keep parts data into the upload .
setData ( objectKey , recorder ) ; break ; } long contentLength = Math . min ( partSize , ( file . length ( ) - uploadModel . getCurrentPart ( ) * partSize ) ) ; Bucket . UploadMultipartInput input = new Bucket . UploadMultipartInput ( ) ; input . setBodyInputFilePart ( file ) ; input . setFileOffset ( i * partSize ) ; input . setContentLength ( contentLength ) ; input . setPartNumber ( i ) ; input . setUploadID ( uploadModel . getUploadID ( ) ) ; // Create request to upload a part .
RequestHandler requestHandler = bucket . uploadMultipartRequest ( objectKey , input ) ; // Progress listener
if ( progressListener != null ) { requestHandler . setProgressListener ( new BodyProgressListener ( ) { @ Override public void onProgress ( long len , long size ) { long bytesWritten = uploadModel . getCurrentPart ( ) * partSize + len ; progressListener . onProgress ( objectKey , bytesWritten , length ) ; } } ) ; } // Cancellation handler .
requestHandler . setCancellationHandler ( cancellationHandler ) ; // Sign with server if needed .
sign ( requestHandler ) ; // Send the request .
OutputModel send = requestHandler . send ( ) ; // Check response .
if ( send . getStatueCode ( ) != 200 && send . getStatueCode ( ) != 201 ) { // Failed .
setData ( objectKey , recorder ) ; // On upload failed
if ( callBack != null ) callBack . onAPIResponse ( objectKey , send ) ; // Once failed , break the circle .
break ; } else if ( i == partCounts - 1 ) { // Success and it is the last part of th file .
// Make a record in the upload .
uploadModel . setBytesWritten ( length ) ; uploadModel . setFileComplete ( true ) ; setData ( objectKey , recorder ) ; } } // Finally check .
if ( uploadModel . isFileComplete ( ) ) { completeMultiUpload ( objectKey , fileName , eTag , uploadModel . getUploadID ( ) , length ) ; } }


signature:
public class UploadManager { /** * When sending a request will call this method to sign with server .
 * @ param requestHandler handler of the request .
 * @ throws QSException exception */
private void sign ( RequestHandler requestHandler ) throws QSException { } }

implementation: if ( callBack != null ) { String signed = callBack . onSignature ( requestHandler . getStringToSignature ( ) ) ; if ( ! QSStringUtil . isEmpty ( signed ) ) requestHandler . setSignature ( callBack . onAccessKey ( ) , signed ) ; String correctTime = callBack . onCorrectTime ( requestHandler . getStringToSignature ( ) ) ; if ( correctTime != null && correctTime . trim ( ) . length ( ) > 0 ) requestHandler . getBuilder ( ) . setHeader ( QSConstant . HEADER_PARAM_KEY_DATE , correctTime ) ; }


signature:
public class UploadManager { /** * Set data in the upload with a recorder .
 * @ param objectKey key
 * @ param recorder recorder */
private void setData ( String objectKey , Recorder recorder ) { } }

implementation: if ( recorder == null ) return ; String upload = new Gson ( ) . toJson ( uploadModel ) ; recorder . set ( objectKey , upload . getBytes ( ) ) ;


signature:
public class UploadManager { /** * Complete the multi upload .
 * @ param objectKey key of the object in the bucket
 * @ param fileName file name of response ( content - disposition ) when downloaded
 * @ param eTag MD5 info
 * @ param uploadID multi upload id
 * @ param length length of the file
 * @ throws QSException exception */
private void completeMultiUpload ( String objectKey , String fileName , String eTag , String uploadID , long length ) throws QSException { } }

implementation:
CompleteMultipartUploadInput completeMultipartUploadInput = new CompleteMultipartUploadInput ( uploadID , partCounts , 0 ) ; completeMultipartUploadInput . setContentLength ( length ) ; // Set content disposition to the object .
if ( ! QSStringUtil . isEmpty ( fileName ) ) { try { String keyName = QSStringUtil . percentEncode ( fileName , "UTF-8" ) ; completeMultipartUploadInput . setContentDisposition ( String . format ( "attachment; filename=\"%s\"; filename*=utf-8''%s" , keyName , keyName ) ) ; } catch ( UnsupportedEncodingException e ) { e . printStackTrace ( ) ; } } // Set the Md5 info to the object .
if ( ! QSStringUtil . isEmpty ( eTag ) ) { completeMultipartUploadInput . setETag ( eTag ) ; } RequestHandler requestHandler = bucket . completeMultipartUploadRequest ( objectKey , completeMultipartUploadInput ) ; sign ( requestHandler ) ; Bucket . CompleteMultipartUploadOutput send = ( Bucket . CompleteMultipartUploadOutput ) requestHandler . send ( ) ; if ( send . getStatueCode ( ) == 200 || send . getStatueCode ( ) == 201 ) { uploadModel . setUploadComplete ( true ) ; setData ( objectKey , recorder ) ; } // Response callback .
if ( callBack != null ) callBack . onAPIResponse ( objectKey , send ) ;


signature:
public class UploadManager { /** * Upload a file with a simple put object upload as a sync request . < br >
 * If a file ' s size is less than { @ link UploadManager # partSize } , there will call this method .
 * @ param file file
 * @ param objectKey key of the object in the bucket
 * @ param fileName file name of response ( content - disposition ) when downloaded
 * @ param length length of the file
 * @ throws QSException exception */
public void putFile ( File file , final String objectKey , String fileName , long length ) throws QSException { } }

implementation:
PutObjectInput input = new PutObjectInput ( ) ; input . setContentLength ( length ) ; input . setBodyInputFile ( file ) ; // Set content disposition to the object .
if ( ! QSStringUtil . isEmpty ( fileName ) ) { try { String keyName = QSStringUtil . percentEncode ( fileName , "UTF-8" ) ; input . setContentDisposition ( String . format ( "attachment; filename=\"%s\"; filename*=utf-8''%s" , keyName , keyName ) ) ; } catch ( UnsupportedEncodingException e ) { e . printStackTrace ( ) ; } } RequestHandler requestHandler = bucket . putObjectRequest ( objectKey , input ) ; // Set progress listener .
if ( progressListener != null ) { requestHandler . setProgressListener ( new BodyProgressListener ( ) { @ Override public void onProgress ( long len , long size ) { progressListener . onProgress ( objectKey , len , size ) ; } } ) ; } // Cancellation handler .
requestHandler . setCancellationHandler ( cancellationHandler ) ; // Sign if needed .
sign ( requestHandler ) ; OutputModel outputModel = requestHandler . send ( ) ; if ( callBack != null ) callBack . onAPIResponse ( objectKey , outputModel ) ;


signature:
public class FavoriteAction { /** * Invoking a FavoriteAction toggles it . */
@ Override public void invoke ( final ActionRequest req , final ActionResponse res ) throws IOException { } }

implementation: final NotificationEntry entry = getTarget ( ) ; final String notificationId = entry . getId ( ) ; final Set < String > favoriteNotices = this . getFavoriteNotices ( req ) ; if ( favoriteNotices . contains ( notificationId ) ) { favoriteNotices . remove ( notificationId ) ; } else { favoriteNotices . add ( notificationId ) ; } setFavoriteNotices ( req , favoriteNotices ) ;


signature:
public class FavoriteAction { /** * / * package - private */
Set < String > getFavoriteNotices ( final PortletRequest req ) { } }

implementation: final HashSet < String > rslt = new HashSet < String > ( ) ; final PortletPreferences prefs = req . getPreferences ( ) ; final String [ ] ids = prefs . getValues ( FAVORITE_NOTIFICATION_IDS_PREFERENCE , new String [ 0 ] ) ; for ( int i = 0 ; i < ids . length ; i ++ ) { rslt . add ( ids [ i ] ) ; } return rslt ;


signature:
public class FavoriteAction { /** * / * package - private */
void setFavoriteNotices ( final PortletRequest req , final Set < String > favoriteNotices ) { } }

implementation: final String [ ] ids = favoriteNotices . toArray ( new String [ favoriteNotices . size ( ) ] ) ; final PortletPreferences prefs = req . getPreferences ( ) ; try { prefs . setValues ( FAVORITE_NOTIFICATION_IDS_PREFERENCE , ids ) ; prefs . store ( ) ; } catch ( Exception e ) { throw new RuntimeException ( e ) ; }


signature:
public class Sorting { /** * Implementation */
private static Comparator < NotificationEntry > chooseConfiguredComparator ( HttpServletRequest req ) { } }

implementation:
final String strategyName = req . getParameter ( SORT_STRATEGY_PARAMETER_NAME ) ; if ( strategyName == null ) { // No strategy means " natural " ordering ; we won ' t be sorting . . .
return null ; } // We WILL be sorting ; work out the details . . .
try { final SortStrategy strategy = SortStrategy . valueOf ( strategyName . toUpperCase ( ) ) ; // tolerant of case mismatch
final String orderName = req . getParameter ( SORT_ORDER_PARAMETER_NAME ) ; final SortOrder order = StringUtils . isNotBlank ( orderName ) ? SortOrder . valueOf ( orderName . toUpperCase ( ) ) // tolerant of case mismatch
: SortOrder . valueOf ( SORT_ORDER_DEFAULT ) ; return order . equals ( SortOrder . ASCENDING ) ? strategy . getComparator ( ) // Default / ascending order
: Collections . reverseOrder ( strategy . getComparator ( ) ) ; // Descending order
} catch ( IllegalArgumentException e ) { LOGGER . warn ( "Unable to sort based on parameters {}='{}' and {}='{}'" , SORT_STRATEGY_PARAMETER_NAME , strategyName , SORT_ORDER_PARAMETER_NAME , req . getParameter ( SORT_ORDER_PARAMETER_NAME ) ) ; } // We didn ' t succeed in selecting a strategy & order
return null ;


signature:
public class JpaNotificationService { /** * Caller must insure that the state being set has not already been added to the entry
 * to avoid multiple events with the same state . */
public void addEntryState ( PortletRequest req , String entryId , NotificationState state ) { } }

implementation:
if ( usernameFinder . isAuthenticated ( req ) ) { final String username = usernameFinder . findUsername ( req ) ; String idStr = entryId . replaceAll ( ID_PREFIX , "" ) ; // remove the prefix
JpaEntry jpaEntry = notificationDao . getEntry ( Long . parseLong ( idStr ) ) ; if ( jpaEntry != null ) { JpaEvent event = new JpaEvent ( ) ; event . setEntry ( jpaEntry ) ; event . setState ( state ) ; event . setTimestamp ( new Timestamp ( new Date ( ) . getTime ( ) ) ) ; event . setUsername ( username ) ; notificationDao . createOrUpdateEvent ( event ) ; } else { throw new IllegalArgumentException ( "JpaEntry not found" ) ; } }


signature:
public class JpaNotificationService { /** * Implementation */
private NotificationResponse prepareResponse ( Set < JpaEntry > entries , String username ) { } }

implementation:
Map < String , NotificationCategory > categories = new HashMap < > ( ) ; for ( JpaEntry entry : entries ) { // Choose a category title
final String categryTitle = ! StringUtils . isBlank ( entry . getCategory ( ) ) ? entry . getCategory ( ) : messages . getMessage ( UNCATEGORIZED_MESSAGE_CODE , null , UNCATEGORIZED_DEFAULT_MESSAGE , Locale . getDefault ( ) ) ; // Obtain the category object matching the title
NotificationCategory category = categories . get ( categryTitle ) ; if ( category == null ) { category = new NotificationCategory ( ) ; category . setTitle ( categryTitle ) ; categories . put ( categryTitle , category ) ; } // Prepare a NotificationEntry
NotificationEntry y = prepareEntry ( entry , username ) ; if ( y != null ) { category . addEntries ( Collections . singletonList ( y ) ) ; } } // Create & load the response
final List < NotificationCategory > cList = new ArrayList < > ( categories . values ( ) ) ; final List < NotificationError > eList = Collections . emptyList ( ) ; // Anything here ?
return new NotificationResponse ( cList , eList ) ;


signature:
public class JpaNotificationService { /** * Creates a { @ link NotificationEntry } from a { @ link JpaEntry } , but will
 * return null if that process cannot be performed in a valid way .
 * @ return A fully - constituted { @ link NotificationEntry } or null */
private NotificationEntry prepareEntry ( JpaEntry entry , String username ) { } }

implementation:
/* * Implementation Note : Most notification fields are optional . This
 * method impl avoids setting fields within the NotificationEntry when
 * those fields are ( essentially ) unspecified on the JpaEntry in order
 * not to run afoul of any logic ( present or future ) that may trigger
 * when a field is set ( e . g . validation , virtual members , change
 * tracking ) . */
NotificationEntry rslt = new NotificationEntry ( ) ; // Id & title will always be present
rslt . setId ( ID_PREFIX + entry . getId ( ) ) ; final String title = entry . getTitle ( ) ; if ( StringUtils . isBlank ( title ) ) { log . warn ( "User '" + username + "' had a notification with an empty title:  " + entry . toString ( ) ) ; return null ; } rslt . setTitle ( title ) ; // But these fields are optional
if ( ! StringUtils . isBlank ( entry . getBody ( ) ) ) { // Body
rslt . setBody ( entry . getBody ( ) ) ; } if ( entry . getDueDate ( ) != null ) { // Due date
rslt . setDueDate ( entry . getDueDate ( ) ) ; } if ( ! StringUtils . isBlank ( entry . getImage ( ) ) ) { // Image
rslt . setImage ( entry . getImage ( ) ) ; } if ( ! StringUtils . isBlank ( entry . getLinkText ( ) ) ) { // Link text
rslt . setLinkText ( entry . getLinkText ( ) ) ; } if ( entry . getPriority ( ) != 0 ) { // Priority
rslt . setPriority ( entry . getPriority ( ) ) ; } if ( ! StringUtils . isBlank ( entry . getSource ( ) ) ) { // Source
rslt . setSource ( entry . getSource ( ) ) ; } if ( ! StringUtils . isBlank ( entry . getUrl ( ) ) ) { // Url
rslt . setUrl ( entry . getUrl ( ) ) ; } // States ( transaction log )
Map < NotificationState , Date > states = prepareStates ( entry , username ) ; rslt . setStates ( states ) ; // Collections of items . . .
if ( ! entry . getAttributes ( ) . isEmpty ( ) ) { // Attributes
List < NotificationAttribute > attributes = prepareAttributes ( entry . getAttributes ( ) ) ; rslt . setAttributes ( attributes ) ; } if ( ! entry . getActions ( ) . isEmpty ( ) ) { // Actions
List < NotificationAction > actions = prepareActions ( entry . getActions ( ) , username ) ; rslt . setAvailableActions ( actions ) ; } return rslt ;


signature:
public class SSPToken { /** * Helper method to determine if an SSPToken has expired . */
public boolean hasExpired ( ) { } }

implementation: long now = System . currentTimeMillis ( ) ; if ( created + ( expiresIn * 1000 ) + TIMEOUT_BUFFER > now ) { return false ; } return true ;


signature:
public class JpaServices { /** * Is the { @ link NotificationEntry } object owned by the JPA service ? */
public boolean contains ( NotificationEntry entry ) { } }

implementation: return StringUtils . isNotBlank ( entry . getId ( ) ) && entry . getId ( ) . startsWith ( JpaNotificationService . ID_PREFIX ) ;


signature:
public class JpaServices { /** * Provides the known history of status changes for the specified user and
 * notification < strong > in chronological order < / strong > . */
@ Override public List < EventDTO > getHistory ( NotificationEntry entry , String username ) { } }

implementation:
List < EventDTO > rslt = Collections . emptyList ( ) ; // default
/* * The JPA system owns status tracking , but it only tracks status for
 * entries that it owns . If the entry is not already a JPA - backed
 * entry , we would use a JPA - side " proxy . " */
final EntryDTO entryDto = contains ( entry ) ? jpaNotificationRestService . getNotification ( entry , false ) : fetchJpaProxyIfAvailable ( entry ) ; // There can ' t be history if there isn ' t ( yet ) a proxy
if ( entryDto != null ) { rslt = jpaNotificationRestService . getEventsByNotificationAndUser ( entryDto . getId ( ) , username ) ; } return rslt ;


signature:
public class JpaServices { /** * Implementation */
private EntryDTO fetchJpaProxyIfAvailable ( NotificationEntry entry ) { } }

implementation:
EntryDTO rslt = null ; // default
final List < EntryDTO > list = jpaNotificationRestService . getNotificationsBySourceAndCustomAttribute ( PROXY_SOURCE_NAME , PROXY_ID_ATTRIBUTE , entry . getId ( ) ) ; logger . debug ( "Search for JPA-backed entry with id='{}' returned the following:  {}" , entry . getId ( ) , list ) ; switch ( list . size ( ) ) { case 1 : // Cool ; we have one . . .
rslt = list . get ( 0 ) ; break ; case 0 : // Also cool ; we don ' t have one . . .
break ; default : // Not cool . . .
throw new IllegalStateException ( "More than one JPA-back entry exists for id=" + entry . getId ( ) ) ; } return rslt ;


signature:
public class NotificationResponseFlattener { /** * Add all entries from the notification category to the < code > allEntries < / code > list after adding an attribute ' category ' that contains
 * the category . That allows UIs that want the convenience of an uncategorized list , such as dataTables , to obtain the data in a simple
 * format that requires no additional processing but maintains the knowledge of the category of the entries .
 * @ param allEntries List of all entries
 * @ param notificationCategory < code > NotificationCategory < / code > to add its entries to the < code > allEntries < / code > list */
private void addAndCategorizeEntries ( List < NotificationEntry > allEntries , NotificationCategory notificationCategory ) { } }

implementation: for ( NotificationEntry entry : notificationCategory . getEntries ( ) ) { List < NotificationAttribute > attrs = new ArrayList < > ( entry . getAttributes ( ) ) ; attrs . add ( new NotificationAttribute ( "category" , notificationCategory . getTitle ( ) ) ) ; entry . setAttributes ( attrs ) ; allEntries . add ( entry ) ; }


signature:
public class JPANotificationRESTController { /** * Get the list of notifications . Supports optional ( and recommended ! ) paging
 * @ param page The 0 based page number
 * @ param pageSize the page size
 * @ return the list of matching notifications . */
@ RequestMapping ( method = RequestMethod . GET ) @ ResponseBody public List < EntryDTO > getNotifications ( @ RequestParam ( value = "page" , required = false ) Integer page , @ RequestParam ( value = "pageSize" , required = false ) Integer pageSize ) { } }

implementation: return restService . getNotifications ( page , pageSize ) ;


signature:
public class JPANotificationRESTController { /** * Create a notification .
 * @ param req the Http request
 * @ param response the Http response
 * @ param entry The Entry
 * @ return The persisted entry */
@ RequestMapping ( method = RequestMethod . POST ) @ ResponseStatus ( HttpStatus . CREATED ) @ ResponseBody public EntryDTO createNotification ( HttpServletRequest req , HttpServletResponse response , @ RequestBody EntryDTO entry ) { } }

implementation: EntryDTO persisted = restService . createNotification ( entry ) ; String url = getSingleNotificationRESTUrl ( req , persisted . getId ( ) ) ; response . addHeader ( "Location" , url ) ; return persisted ;


signature:
public class JPANotificationRESTController { /** * Get 1 notification by id .
 * @ param response the Http response
 * @ param id the id of the notification
 * @ param full optionally fetch addressee info . If false , addressee info will be omitted .
 * @ return the notification */
@ RequestMapping ( value = "/{notificationId}" , method = RequestMethod . GET ) @ ResponseBody public EntryDTO getNotification ( HttpServletResponse response , @ PathVariable ( "notificationId" ) long id , @ RequestParam ( value = "full" , required = false , defaultValue = "false" ) boolean full ) { } }

implementation: EntryDTO notification = restService . getNotification ( id , full ) ; if ( notification == null ) { response . setStatus ( HttpStatus . NOT_FOUND . value ( ) ) ; return null ; } return notification ;


signature:
public class JPANotificationRESTController { /** * Get the set of addressees for a notification .
 * @ param id the notification id
 * @ return the set of addressees */
@ RequestMapping ( value = "/{notificationId}/addressees" , method = RequestMethod . GET ) @ ResponseBody public Set < AddresseeDTO > getAddressees ( @ PathVariable ( "notificationId" ) long id ) { } }

implementation: return restService . getAddressees ( id ) ;


signature:
public class JPANotificationRESTController { /** * Create a new addressee for a notification .
 * @ param req the Http request
 * @ param resp the Http response
 * @ param id the notification id
 * @ param addressee the list of addressees
 * @ return the persisted addressee */
@ RequestMapping ( value = "/{notificationId}/addressees" , method = RequestMethod . POST ) @ ResponseBody @ ResponseStatus ( HttpStatus . CREATED ) public AddresseeDTO addAddressee ( HttpServletRequest req , HttpServletResponse resp , @ PathVariable ( "notificationId" ) long id , @ RequestBody AddresseeDTO addressee ) { } }

implementation: AddresseeDTO dto = restService . createAddressee ( id , addressee ) ; if ( dto == null ) { resp . setStatus ( HttpStatus . NOT_FOUND . value ( ) ) ; return null ; } String url = getSingleNotificationRESTUrl ( req , id ) + "/addressee/" + dto . getId ( ) ; resp . addHeader ( "Location" , url ) ; return dto ;


signature:
public class JPANotificationRESTController { /** * Get a specific addressee
 * @ param resp the Http Response
 * @ param notificationId the notification id
 * @ param addresseeId the addressee id
 * @ return the matching addressee if available */
@ RequestMapping ( value = "/{notificationId}/addressees/{addresseeId}" , method = RequestMethod . GET ) @ ResponseBody public AddresseeDTO getAddressee ( HttpServletResponse resp , @ PathVariable ( "notificationId" ) long notificationId , @ PathVariable ( "addresseeId" ) long addresseeId ) { } }

implementation: AddresseeDTO dto = restService . getAddressee ( addresseeId ) ; if ( dto == null ) { resp . setStatus ( HttpStatus . NOT_FOUND . value ( ) ) ; return null ; } return dto ;


signature:
public class JPANotificationRESTController { /** * Get the list of events for a notification .
 * @ param id the notification id
 * @ return the list of events */
@ RequestMapping ( value = "/{notificationId}/events" , method = RequestMethod . GET ) @ ResponseBody public List < EventDTO > getEventsByNotification ( @ PathVariable ( "notificationId" ) long id ) { } }

implementation: return restService . getEventsByNotification ( id ) ;


signature:
public class JPANotificationRESTController { /** * Get a specific event .
 * @ param response The Http response
 * @ param notificationId the notification id
 * @ param eventId the event id
 * @ return the matching event , if found */
@ RequestMapping ( value = "/{notificationId}/events/{eventId}" , method = RequestMethod . GET ) @ ResponseBody public EventDTO getEvent ( HttpServletResponse response , @ PathVariable ( "notificationId" ) long notificationId , @ PathVariable ( "eventId" ) long eventId ) { } }

implementation: EventDTO event = restService . getEvent ( eventId ) ; if ( event == null ) { response . setStatus ( HttpStatus . NOT_FOUND . value ( ) ) ; return null ; } return event ;


signature:
public class JPANotificationRESTController { /** * Create a new event .
 * @ param req the Http request
 * @ param resp the Http response
 * @ param notificationId the notification id
 * @ param event the event id
 * @ return The newly persisted object */
@ RequestMapping ( value = "/{notificationId}/events" , method = RequestMethod . POST ) @ ResponseStatus ( HttpStatus . CREATED ) @ ResponseBody public EventDTO createEvent ( HttpServletRequest req , HttpServletResponse resp , @ PathVariable ( "notificationId" ) long notificationId , @ RequestBody EventDTO event ) { } }

implementation: EventDTO dto = restService . createEvent ( notificationId , event ) ; if ( dto == null ) { resp . setStatus ( HttpStatus . NOT_FOUND . value ( ) ) ; return null ; } String url = getSingleNotificationRESTUrl ( req , notificationId ) + "/state/" + dto . getId ( ) ; resp . addHeader ( "Location" , url ) ; return dto ;


signature:
public class JPANotificationRESTController { /** * Build the URL for a specific notification .
 * @ param request the Http request
 * @ param id the notification id
 * @ return the URL to hit that specific id */
private String getSingleNotificationRESTUrl ( HttpServletRequest request , long id ) { } }

implementation:
String path = request . getContextPath ( ) + REQUEST_ROOT + id ; try { URL url = new URL ( request . getScheme ( ) , request . getServerName ( ) , request . getServerPort ( ) , path ) ; return url . toExternalForm ( ) ; } catch ( MalformedURLException e ) { // if it fails , just return a relative path . Not ideal , but better than nothing . . .
log . warn ( "Error building Location header" , e ) ; return path ; }


signature:
public class JpaNotificationRESTService { /** * Provides a complete transaction log for a notification and a single
 * recipient < strong > in chronological order < / strong > . */
@ Override @ Transactional ( readOnly = true ) public List < EventDTO > getEventsByNotificationAndUser ( long notificationId , String username ) { } }

implementation: final List < JpaEvent > events = notificationDao . getEvents ( notificationId , username ) ; return notificationMapper . toEventList ( events ) ;


signature:
public class RomeNotificationService { /** * Implementation */
private NotificationResponse doFetch ( List < String > feedUrls , String username ) { } }

implementation:
final List < NotificationCategory > categories = new ArrayList < > ( ) ; final List < NotificationError > errors = new ArrayList < > ( ) ; for ( String item : feedUrls ) { // It ' s okay to pull a response from cache , if we have one , since refresh happens in invoke ( )
final Element m = cache . get ( item ) ; if ( m != null ) { // # # CACHE HIT # #
if ( logger . isDebugEnabled ( ) ) { logger . debug ( "Feed cache HIT for url:  " + item ) ; } final NotificationCategory category = ( NotificationCategory ) m . getObjectValue ( ) ; categories . add ( category ) ; } else { // # # CACHE MISS # #
if ( logger . isDebugEnabled ( ) ) { logger . debug ( "Feed cache MISS for url:  " + item ) ; logger . debug ( "Checking the following feed URL for notifications for user '" + username + "' -- " + item ) ; } final NotificationCategory category = fetchFromSourceUrl ( item ) ; if ( category != null ) { cache . put ( new Element ( item , category ) ) ; categories . add ( category ) ; } else { final NotificationError error = new NotificationError ( ) ; error . setError ( "Service Unavailable" ) ; error . setSource ( getName ( ) ) ; errors . add ( error ) ; } } } final NotificationResponse rslt = new NotificationResponse ( ) ; rslt . setCategories ( categories ) ; rslt . setErrors ( errors ) ; return rslt ;


signature:
public class JpaNotificationDao { /** * Search for a JpaEntry with the specified Id . If the entry exists in the
 * persistence context , it is returned ; otherwise , null is returned . */
@ Override @ Transactional ( readOnly = true ) public JpaEntry getEntry ( long entryId ) { } }

implementation: Validate . isTrue ( entryId > 0 , "Invalid entryId:  " + entryId ) ; JpaEntry rslt = entityManager . find ( JpaEntry . class , entryId ) ; return rslt ;


signature:
public class UserAttributeParameterEvaluator { /** * Obtains information about the user from the Authorization header in the form of an OIDC Id
 * token . In the future , it would be better to provide a standard tool ( bean ) for this job in
 * the < code > uPortal - soffit - renderer < / code > component . */
private Jws < Claims > parseOidcToken ( HttpServletRequest req ) { } }

implementation:
final String authHeader = req . getHeader ( HttpHeaders . AUTHORIZATION ) ; if ( StringUtils . isBlank ( authHeader ) || ! authHeader . startsWith ( Headers . BEARER_TOKEN_PREFIX ) ) { /* * No OIDC token available */
return null ; } final String bearerToken = authHeader . substring ( Headers . BEARER_TOKEN_PREFIX . length ( ) ) ; try { // Validate & parse the JWT
final Jws < Claims > rslt = Jwts . parser ( ) . setSigningKey ( signatureKey ) . parseClaimsJws ( bearerToken ) ; logger . debug ( "Found the following OIDC Id token:  {}" , rslt . toString ( ) ) ; return rslt ; } catch ( Exception e ) { logger . info ( "The following Bearer token is unusable:  '{}'" , bearerToken ) ; logger . debug ( "Failed to validate and/or parse the specified Bearer token" , e ) ; } return null ;


signature:
public class AnyRowResourceContentJdbcNotificationService { /** * Subclasses < em > must < / em > call < code > super . init ( ) < / code > . */
@ PostConstruct public void init ( ) { } }

implementation:
super . init ( ) ; // Very important !
try { nonEmptyResponse = objectMapper . readValue ( jsonResource . getURL ( ) , NotificationResponse . class ) ; } catch ( IOException ioe ) { final String msg = "Failed to load JSON from resource:  " + jsonResource ; throw new RuntimeException ( msg , ioe ) ; }


signature:
public class SSPApi { /** * Set the SSP API Context . Note : this method will ensure that that the API context
 * starts with ' / ' and ensures that it does not end with a ' / ' .
 * @ param sspContext the API context */
@ Value ( "${studentSuccessPlanService.sspContext:/ssp}" ) public void setSspContext ( String sspContext ) { } }

implementation:
// ensure leading ' / '
if ( ! sspContext . startsWith ( "/" ) ) { sspContext = "/" + sspContext ; } // remove any trailing ' / '
if ( sspContext . endsWith ( "/" ) ) { sspContext = sspContext . replaceAll ( "/*$" , "" ) ; } this . sspContext = sspContext ;


signature:
public class SSPApi { /** * { @ inheritDoc } */
@ Override public < T > ResponseEntity < T > doRequest ( SSPApiRequest < T > request ) throws MalformedURLException , RestClientException { } }

implementation:
SSPToken token = getAuthenticationToken ( false ) ; request . setHeader ( AUTHORIZATION , token . getTokenType ( ) + " " + token . getAccessToken ( ) ) ; URL url = getSSPUrl ( request . getUrlFragment ( ) , true ) ; ResponseEntity < T > response = restTemplate . exchange ( url . toExternalForm ( ) , request . getMethod ( ) , request . getRequestEntity ( ) , request . getResponseClass ( ) , request . getUriParameters ( ) ) ; // if we get a 401 , the token may have unexpectedly expired ( eg . ssp server restart ) .
// Clear it , get a new token and replay the request one time .
if ( response . getStatusCode ( ) == HttpStatus . UNAUTHORIZED ) { token = getAuthenticationToken ( true ) ; request . setHeader ( AUTHORIZATION , token . getTokenType ( ) + " " + token . getAccessToken ( ) ) ; return restTemplate . exchange ( url . toExternalForm ( ) , request . getMethod ( ) , request . getRequestEntity ( ) , request . getResponseClass ( ) , request . getUriParameters ( ) ) ; } return response ;


signature:
public class SSPApi { /** * { @ inheritDoc } */
public URL getSSPUrl ( String urlFragment , boolean useContext ) throws MalformedURLException { } }

implementation: String path = ( useContext ) ? sspContext + urlFragment : urlFragment ; return new URL ( sspProtocol , sspHost , sspPort , path ) ;


signature:
public class SSPApi { /** * Get the authentication token to use .
 * @ param forceUpdate if true , get a new auth token even if a cached instance exists .
 * @ return The authentication token
 * @ throws MalformedURLException if the authentication URL is invalid
 * @ throws RestClientException if an error occurs when talking to SSP */
private synchronized SSPToken getAuthenticationToken ( boolean forceUpdate ) throws MalformedURLException , RestClientException { } }

implementation:
if ( authenticationToken != null && ! authenticationToken . hasExpired ( ) && ! forceUpdate ) { return authenticationToken ; } String authString = getClientId ( ) + ":" + getClientSecret ( ) ; String authentication = new Base64 ( ) . encodeToString ( authString . getBytes ( ) ) ; HttpHeaders headers = new HttpHeaders ( ) ; headers . add ( AUTHORIZATION , BASIC + " " + authentication ) ; // form encode the grant _ type . . .
MultiValueMap < String , String > form = new LinkedMultiValueMap < > ( ) ; form . add ( GRANT_TYPE , CLIENT_CREDENTIALS ) ; HttpEntity < MultiValueMap < String , String > > request = new HttpEntity < > ( form , headers ) ; URL authURL = getAuthenticationURL ( ) ; authenticationToken = restTemplate . postForObject ( authURL . toExternalForm ( ) , request , SSPToken . class ) ; return authenticationToken ;


signature:
public class NotificationResponse { /** * Returns the { @ link NotificationEntry } with the specified id , or null if
 * not present . */
public NotificationEntry findNotificationEntryById ( final String notificationId ) { } }

implementation:
// Assertions
if ( notificationId == null ) { String msg = "Argument 'notificationId' cannot be null" ; throw new IllegalArgumentException ( msg ) ; } // Providing a brute - force implementation for
// now ; we can improve it if it becomes important .
NotificationEntry rslt = null ; // default - - means not present
for ( NotificationCategory category : categories ) { for ( NotificationEntry entry : category . getEntries ( ) ) { if ( notificationId . equals ( entry . getId ( ) ) ) { rslt = entry ; break ; } } if ( rslt != null ) { break ; } } return rslt ;


signature:
public class NotificationResponse { /** * Combine the contents of this response with the provided response and
 * return a < b > new instance < / b > of { @ link NotificationResponse } . The
 * original instances are unchanged .
 * @ param response A new { @ link NotificationResponse } that contains data from both originals */
public NotificationResponse combine ( NotificationResponse response ) { } }

implementation: NotificationResponse rslt = new NotificationResponse ( this ) ; rslt . addCategories ( response . getCategories ( ) ) ; rslt . addErrors ( response . getErrors ( ) ) ; return rslt ;


signature:
public class NotificationResponse { /** * Return a < b > new instance < / b > of { @ link NotificationResponse } from which
 * the specified errors have been removed . The original instances are
 * unchanged .
 * @ param hiddenErrorKeys set of error keys to exclude from result */
public NotificationResponse filterErrors ( Set < Integer > hiddenErrorKeys ) { } }

implementation:
NotificationResponse rslt = new NotificationResponse ( this ) ; List < NotificationError > filteredErrors = new ArrayList < > ( ) ; for ( NotificationError r : errors ) { if ( ! hiddenErrorKeys . contains ( r . getKey ( ) ) ) { filteredErrors . add ( r ) ; } } rslt . setErrors ( filteredErrors ) ; // deep copy
return rslt ;


signature:
public class NotificationResponse { /** * Return a < b > new instance < / b > of { @ link NotificationResponse } containing only
 * { @ link NotificationEntry } objects within this response that match the specified
 * < code > Predicate < / code > . The category structure is preserved . Empty categories are removed . */
public NotificationResponse filter ( Predicate < NotificationEntry > predicate ) { } }

implementation: final List < NotificationCategory > filteredCategories = categories . stream ( ) . map ( category -> { final List < NotificationEntry > filteredEntries = category . getEntries ( ) . stream ( ) . filter ( predicate ) . collect ( Collectors . toList ( ) ) ; return filteredEntries . size ( ) > 0 ? new NotificationCategory ( category . getTitle ( ) , filteredEntries ) : null ; } ) . filter ( value -> value != null ) . collect ( Collectors . toList ( ) ) ; return new NotificationResponse ( filteredCategories , getErrors ( ) ) ; // deep copy


signature:
public class NotificationResponse { /** * Provides the total number of notifications contained in the response . */
@ JsonIgnore @ XmlTransient public int size ( ) { } }

implementation: return categories . stream ( ) . map ( NotificationCategory :: getEntries ) . mapToInt ( List :: size ) . sum ( ) ;


signature:
public class NotificationResponse { /** * Insert the given categories and their entries into the any existing
 * categories of the same title . If a category doesn ' t match an existing
 * one , add it to the list .
 * @ param newCategories collection of new categories and their entries . */
private void addCategories ( List < NotificationCategory > newCategories ) { } }

implementation:
if ( newCategories == null ) { return ; } // Start with a deep copy of the method parameter to simplify remaining logic
newCategories = newCategories . parallelStream ( ) . map ( NotificationCategory :: cloneNoExceptions ) . collect ( Collectors . toList ( ) ) ; // Create a map of current categories by title for processing
Map < String , NotificationCategory > catsByName = this . categories . parallelStream ( ) . collect ( toMap ( c -> c . getTitle ( ) . toLowerCase ( ) , c -> c ) ) ; // Split new categories between those that match an existing category and those that are completely new
Map < Boolean , List < NotificationCategory > > matchingNewCats = newCategories . stream ( ) . collect ( partitioningBy ( c -> catsByName . containsKey ( c . getTitle ( ) . toLowerCase ( ) ) ) ) ; // Add new entries to existing categories
matchingNewCats . get ( Boolean . TRUE ) . stream ( ) . forEachOrdered ( c -> catsByName . get ( c . getTitle ( ) . toLowerCase ( ) ) . addEntries ( c . getEntries ( ) ) ) ; // Add new categories
this . categories . addAll ( matchingNewCats . get ( Boolean . FALSE ) ) ;


signature:
public class NotificationResponse { /** * Best guess as to the reason this method exists : beans that produce fresh
 * { @ link NotificationResponse } objects ( without cloning them ) may safely cache them . They need
 * not fear that another bean will transform their copy . Beans that do clone them , however , can
 * safely operate on a clone . */
public NotificationResponse cloneIfNotCloned ( ) { } }

implementation: try { return isCloned ( ) ? this : ( NotificationResponse ) this . clone ( ) ; } catch ( CloneNotSupportedException e ) { log . error ( "Failed to clone() the sourceResponse" , e ) ; } return this ;


signature:
public class AbstractNotificationService { /** * Returns an empty collection and logs the event . All concrete implementations of
 * { @ link INotificationService } should override this method . The log entries this method
 * produces are an indication that the service subclass is not ready for the post - Portlet API
 * world . */
@ Override public NotificationResponse fetch ( HttpServletRequest request ) { } }

implementation: logger . warn ( "Notification service '{}' was invoked by the portlet-agnostic API, but it " + "doesn't override fetch(HttpServletRequest)" , getName ( ) ) ; return NotificationResponse . EMPTY_RESPONSE ;


signature:
public class SSPTaskNotificationService { /** * Fetch the set of SSP tasks for the uPortal user .
 * @ param req The < code > PortletRequest < / code >
 * @ return The set of notifications for this data source . */
@ Override public NotificationResponse fetch ( PortletRequest req ) { } }

implementation:
PortletPreferences preferences = req . getPreferences ( ) ; String enabled = preferences . getValue ( SSP_NOTIFICATIONS_ENABLED , "false" ) ; if ( ! "true" . equalsIgnoreCase ( enabled ) ) { return new NotificationResponse ( ) ; } String personId = getPersonId ( req ) ; if ( personId == null ) { // Not all students will have active SSP records ,
// so if no entry is found in SSP , just return an
// empty response set .
return new NotificationResponse ( ) ; } String urlFragment = getActiveTaskUrl ( ) ; SSPApiRequest < String > request = new SSPApiRequest < > ( urlFragment , String . class ) . addUriParameter ( "personId" , personId ) ; ResponseEntity < String > response ; try { response = sspApi . doRequest ( request ) ; } catch ( Exception e ) { log . error ( "Error reading SSP Notifications: " + e . getMessage ( ) ) ; return notificationError ( e . getMessage ( ) ) ; } if ( response . getStatusCode ( ) . series ( ) != HttpStatus . Series . SUCCESSFUL ) { log . error ( "Error reading SSP Notifications: " + response ) ; return notificationError ( response . getBody ( ) ) ; } NotificationResponse notification = mapToNotificationResponse ( req , response ) ; return notification ;


signature:
public class SSPTaskNotificationService { /** * Error handler .
 * @ param errorMsg The error message
 * @ return a notification response with the error message */
private NotificationResponse notificationError ( String errorMsg ) { } }

implementation: NotificationError error = new NotificationError ( ) ; error . setError ( errorMsg ) ; error . setSource ( getClass ( ) . getSimpleName ( ) ) ; NotificationResponse notification = new NotificationResponse ( ) ; notification . setErrors ( Arrays . asList ( error ) ) ; return notification ;


signature:
public class SSPTaskNotificationService { /** * Map and SSP Response to a NotificationResponse .
 * @ param request the portlet request
 * @ param response the response from the REST call to SSP
 * @ return the mapped notification response */
private NotificationResponse mapToNotificationResponse ( PortletRequest request , ResponseEntity < String > response ) { } }

implementation:
Configuration config = Configuration . builder ( ) . options ( Option . DEFAULT_PATH_LEAF_TO_NULL ) . build ( ) ; ReadContext readContext = JsonPath . using ( config ) . parse ( response . getBody ( ) ) ; // check the status embedded in the response too . . .
String success = readContext . read ( SUCCESS_QUERY ) ; // grr . SSP returns this as a string . . .
if ( ! "true" . equalsIgnoreCase ( success ) ) { String error = readContext . read ( MESSAGE_QUERY ) ; return notificationError ( error ) ; } // read the actual tasks . . .
Object rows = readContext . read ( ROWS_QUERY ) ; if ( ! ( rows instanceof JSONArray ) ) { throw new RuntimeException ( "Expected 'rows' to be an array of tasks" ) ; } String source = getNotificationSource ( request ) ; List < NotificationEntry > list = new ArrayList < > ( ) ; for ( int i = 0 ; i < ( ( JSONArray ) rows ) . size ( ) ; i ++ ) { NotificationEntry entry = mapNotificationEntry ( readContext , i , source ) ; if ( entry != null ) { attachActions ( request , entry ) ; list . add ( entry ) ; } } // build the notification response . . .
NotificationResponse notification = new NotificationResponse ( ) ; if ( ! list . isEmpty ( ) ) { NotificationCategory category = getNotificationCategory ( request ) ; category . addEntries ( list ) ; notification . setCategories ( Arrays . asList ( category ) ) ; } return notification ;


signature:
public class SSPTaskNotificationService { /** * Map a single notification entry .
 * @ param readContext the parsed JSON from SSP
 * @ param index the index of the current entry to read
 * @ param source the source value to use for the entry
 * @ return a new Notification Entry . May return null if the entry is invalid or complete */
private NotificationEntry mapNotificationEntry ( ReadContext readContext , int index , String source ) { } }

implementation:
boolean completed = readContext . read ( format ( ROW_COMPLETED_QUERY_FMT , index ) , Boolean . class ) ; if ( completed ) { return null ; } NotificationEntry entry = new NotificationEntry ( ) ; entry . setSource ( source ) ; String id = readContext . read ( format ( ROW_ID_QUERY_FMT , index ) ) ; entry . setId ( id ) ; String title = readContext . read ( format ( ROW_NAME_QUERY_FMT , index ) ) ; entry . setTitle ( title ) ; String desc = readContext . read ( format ( ROW_DESCRIPTION_QUERY_FMT , index ) ) ; entry . setBody ( desc ) ; String link = readContext . read ( format ( ROW_LINK_QUERY_FMT , index ) ) ; URL fixedLink = normalizeLink ( link ) ; if ( fixedLink != null ) { entry . setUrl ( fixedLink . toExternalForm ( ) ) ; } Date createDate = readContext . read ( format ( "$.rows[%d].createdDate" , index ) , Date . class ) ; Map < NotificationState , Date > states = new HashMap < > ( ) ; states . put ( NotificationState . ISSUED , createDate ) ; try { // the date is in an odd format , need to parse by hand . . .
String dateStr = readContext . read ( format ( ROW_DUE_DATE_QUERY_FMT , index ) ) ; if ( ! StringUtils . isBlank ( dateStr ) ) { synchronized ( dateFormat ) { Date dueDate = dateFormat . parse ( dateStr ) ; entry . setDueDate ( dueDate ) ; } } } catch ( Exception e ) { log . warn ( "Error parsing due date.  Ignoring" , e ) ; } return entry ;


signature:
public class SSPTaskNotificationService { /** * Attach any SSP specific actions to this entry , if enabled .
 * @ param request the portlet request
 * @ param entry the entry */
private void attachActions ( PortletRequest request , NotificationEntry entry ) { } }

implementation: PortletPreferences prefs = request . getPreferences ( ) ; String stringVal = prefs . getValue ( SSP_NOTIFICATIONS_ENABLE_MARK_COMPLETED , "false" ) ; boolean enableMarkCompleted = ( "true" . equalsIgnoreCase ( stringVal ) ) ; List < NotificationAction > actions = new ArrayList < > ( ) ; if ( enableMarkCompleted ) { MarkTaskCompletedAction action = new MarkTaskCompletedAction ( entry . getId ( ) ) ; actions . add ( action ) ; } entry . setAvailableActions ( actions ) ;


signature:
public class SSPTaskNotificationService { /** * Some of the links I have seen from SSP are not well formed . Try to convert any URLs
 * to a usable form .
 * @ param link The link value from SSP
 * @ return A full URL
 * @ throws java . net . MalformedURLException if the link value can not be converted
 * to a URL . */
private URL normalizeLink ( String link ) { } }

implementation:
try { if ( StringUtils . isEmpty ( link ) ) { return null ; } if ( link . startsWith ( "/" ) ) { return sspApi . getSSPUrl ( link , true ) ; } if ( link . startsWith ( "http://" ) || link . startsWith ( "https://" ) ) { return new URL ( link ) ; } // if all else fails , just tack on http : / / and see if the URL parser can handle
// it . Perhaps , not ideal . . .
return new URL ( "http://" + link ) ; } catch ( MalformedURLException e ) { log . warn ( "Bad URL from SSP Entry: " + link , e ) ; return null ; }


signature:
public class SSPTaskNotificationService { /** * Get the category name to use for SSP notifications .
 * @ param request the portlet request
 * @ return The notification category to use */
private NotificationCategory getNotificationCategory ( PortletRequest request ) { } }

implementation: PortletPreferences preferences = request . getPreferences ( ) ; String title = preferences . getValue ( NOTIFICATION_CATEGORY_PREF , DEFAULT_CATEGORY ) ; NotificationCategory category = new NotificationCategory ( ) ; category . setTitle ( title ) ; return category ;


signature:
public class SSPTaskNotificationService { /** * Get the source value to use for a Notification entry .
 * @ param req the portlet request
 * @ return the source value to use . */
private String getNotificationSource ( PortletRequest req ) { } }

implementation: PortletPreferences preferences = req . getPreferences ( ) ; String source = preferences . getValue ( NOTIFICATION_SOURCE_PREF , DEFAULT_NOTIFICATION_SOURCE ) ; return source ;


signature:
public class NotificationLifecycleController { /** * Implementation */
private String evaluateRedirectUri ( ActionRequest req ) { } }

implementation:
// Default response - - specify a relative URI , allowing the protocol to be inferred
String rslt = req . getContextPath ( ) + SUCCESS_PATH ; final PortletPreferences prefs = req . getPreferences ( ) ; final String protocol = prefs . getValue ( INVOKE_REDIRECT_PROTOCOL_PREFERENCE , null ) ; if ( protocol != null ) { // Specify an absolute URI . Apparently we need to insist on a protoco ( usually HTTPS )
String portPart = "" ; // default
final String port = prefs . getValue ( INVOKE_REDIRECT_PORT_PREFERENCE , null ) ; if ( port != null ) { portPart = ":" + port ; } rslt = protocol . toLowerCase ( ) + "://" + req . getServerName ( ) // Server hostname
+ portPart // Server port ( blank , with any luck )
+ rslt ; // Remainder of the URI ( as above )
} return rslt ;


signature:
public class ReadAction { /** * Invoking a ReadAction toggles it . */
@ Override public void invoke ( final ActionRequest req , final ActionResponse res ) throws IOException { } }

implementation: final NotificationEntry entry = getTarget ( ) ; final String notificationId = entry . getId ( ) ; final Set < String > readNotices = this . getReadNotices ( req ) ; if ( readNotices . contains ( notificationId ) ) { readNotices . remove ( notificationId ) ; } else { readNotices . add ( notificationId ) ; } setReadNotices ( req , readNotices ) ;


signature:
public class ReadAction { /** * / * package - private */
Set < String > getReadNotices ( final PortletRequest req ) { } }

implementation: final HashSet < String > rslt = new HashSet < > ( ) ; final PortletPreferences prefs = req . getPreferences ( ) ; final String [ ] ids = prefs . getValues ( READ_NOTIFICATION_IDS_PREFERENCE , new String [ 0 ] ) ; for ( int i = 0 ; i < ids . length ; i ++ ) { rslt . add ( ids [ i ] ) ; } return rslt ;


signature:
public class CompleteOnRedirectAction { /** * When invoke is called , a configured notification state is set for the entry if it has not already been set .
 * { @ link JpaNotificationService } and { @ link CacheNotificationService } are used here to add the entry state and clear
 * the cache for the user . This class is not managed by Spring , so these objects must be obtained using the
 * Spring context that { @ code SpringContext } provides .
 * @ param req
 * @ param res
 * @ throws IOException */
@ Override public void invoke ( final ActionRequest req , final ActionResponse res ) throws IOException { } }

implementation: JpaNotificationService jpaService = ( JpaNotificationService ) SpringContext . getApplicationContext ( ) . getBean ( "jpaNotificationService" ) ; final NotificationEntry entry = getTarget ( ) ; Map < NotificationState , Date > stateMap = entry . getStates ( ) ; if ( stateMap != null && ! stateMap . containsKey ( NotificationState . COMPLETED ) ) { jpaService . addEntryState ( req , entry . getId ( ) , NotificationState . COMPLETED ) ; } res . sendRedirect ( entry . getUrl ( ) ) ;