cancel
Showing results for 
Search instead for 
Did you mean: 

Generate a new file pdf from one field of noderef

zlucy82
Confirmed Champ
Confirmed Champ

Hi all,

i need to create a Call-Web-Script DocLib action that execute a function based on java code.

The Java class get the input noderef, extract one its specific field  and generate a pdf with only the field's value.
My difficult is generate and return a new pdf with custom content, i thought to use the java itext library.

Can someone help me?

Thank you.

6 REPLIES 6

afaust
Legendary Innovator
Legendary Innovator

Where specificly do you need help? You only mentioned what your task is, but not where you have any issues...

zlucy82
Confirmed Champ
Confirmed Champ

I need to add a new DocLib action to the Document Library of Alfresco Community 5.1 and i created a maven repo-amp and share-amp.

I followed this tutorial: http://docs.alfresco.com/5.0/tasks/dev-extensions-share-tutorials-add-action-doclib.html

In short, i executed these steps

1. In the share-amp, i added a new Surf Extension Module file "printProtocol-share-extensions.xml" that defines, for the "DocLibActions" condition, an action with id "print-protocol", a function called "onViewPrintableProtocol", the success message and failure messages for the action and finally defines the position of the action in the actionGroups tag. The file defines also a dependency for "DocLibCustom" condition that includes a "custom-doclib-actions.js" file.

2. In the share-amp, i added an icon for the action.

3. The JS file "custom-doclib-actions.js" implements the custom JavaScript function that registers a new custom action "onViewPrintablePDF", This action calls a custom Repository Web Script through the "printprotocol?noderef={myNodeRef}" url and sends to the webscript the noderef of the current node. The custom webscript must returns the pdf that has as content only the value of one specific field of the node.

5. In the repo-amp, i added a webscript "printProtocol" that returns a JSON result with the reference of the noderef of the node

5. In the repo-amp, i edited the java bean configuration file "webscript-context.xml" that links the webscript to the class java "protocolloPdfBean.java"

6. In the repo-amp, i implemented a java class "protocolloPdfBean" that gets the node and generate and return a pdf that has as content only the value of one specific field of the node.

I hope, that all is clear, thank you very much.

jpotts
World-Class Innovator
World-Class Innovator

That looks like a good approach. Where are you stuck? Or, if you are seeing errors, what errors are you seeing?

zlucy82
Confirmed Champ
Confirmed Champ

My stuck was "in wich way write java code for generate a new pdf file", however i found a solution, this here is my code:

public NodeRef create(NodeRef currentNode, String protocolNumber){
     
          ChildAssociationRef childAssociationRef = nodeService.getPrimaryParent(currentNode);
          //get the parent of the current node
          NodeRef parent = childAssociationRef.getParentRef();
          
          //get the protocol field value
          QName QNAME_FIELD_PRTOCOLO =  QName.createQName("http://www.pyxisos.com/model/content/1.0", "protocollo_ap");
          String protocollo = (String)nodeService.getProperty(currentNode, QNAME_FIELD_PRTOCOLO);

          //create hashmap for nodeProtocol
          Map<QName, Serializable> propsNodeProtocolo = new HashMap<QName, Serializable>(1);
          //assign name prop_name
          propsNodeProtocolo.put(ContentModel.PROP_NAME, "pdfTmp.pdf");
          
          //create new node protocol
          NodeRef nodeProtocol = nodeService.createNode(
                parent,
                ContentModel.ASSOC_CONTAINS,
                QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "protocolloetichetta"),
                ContentModel.TYPE_CONTENT,
                propsNodeProtocolo
          ).getChildRef();
          
          //set node MimetypeMap to MIMETYPE_PDF
          ContentWriter writerNodeProtocol = this.contentService.getWriter(nodeProtocol, ContentModel.PROP_CONTENT, true);
          writerNodeProtocol.setMimetype(MimetypeMap.MIMETYPE_PDF);
          writerNodeProtocol.setEncoding("UTF-8");
          writerNodeProtocol.putContent("TEST");
          
          //create a pdf document
          Rectangle pageSize = new Rectangle(200, 100);
          Document document = new Document(pageSize);
          try {
               ContentWriter writer = contentService.getWriter(nodeProtocol, ContentModel.PROP_CONTENT, true);
               PdfWriter.getInstance(document, writer.getContentOutputStream());
               document.open();
               //add the value of field protocol
               document.add(new Paragraph(protocollo));
               document.close();
               } catch (Exception e) {
                    e.printStackTrace();
          }
          
          //return new pdf node
          return nodeProtocol;
     }


But now i have another stuck.
The real goal is click the "Print Protocol" action link of the node and open the printable pdf file that contains only the value of the "protocol field" of the node in a new tab window of the browser (to allow to print it). My code generates the real file PDF and save it in the same folder, but i don't want the physical file in that folder, thus i thought to call (always in the custom-doclib-actions.js file) a new custom webscript that delete the pdf node.

Could it be a a good solution?
 

Thank you.

jpotts
World-Class Innovator
World-Class Innovator

Another idea would be to do this as a rendition. The PDF you are generating that shows only a single property value is really just an alternative rendition (another way to format) the original piece of content. Renditions get stored as children of the document so they are not visible or easily accessible from the UI by the end-user.

If you don't like the rendition idea you could just do what you are doing, but instead of storing the PDF in the same folder as the document, store it as a child of the document. This is basically what renditions do but you wouldn't have to formally configure it as an official rendition. It has the same benefit of not being easily accessible from the front-end by the end-user.

In both cases, it is nice that the PDF is a child of the document because if the document is ever deleted the child will also be deleted. This will prevent you from ending up with a bunch of PDFs hanging around after the original content has been deleted.

zlucy82
Confirmed Champ
Confirmed Champ

Ok, i like very much the rendition idea. In this way, i don't need to implement another web-service to delete the node pdf. I changed my code in this way.

Thank you very much.

public NodeRef create(NodeRef currentNode, String protocolNumber){
     
          //get the protocol field value
          QName QNAME_FIELD_PROTOCOLO =  QName.createQName("http://www.pyxisos.com/model/content/1.0", "protocollo_ap");
          String protocollo = (String)nodeService.getProperty(currentNode, QNAME_FIELD_PROTOCOLO);

          //RENDITION OF THE INPUT NODE
          //CREATE RENDITION DEFINITION
          QName renditionName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "myRendDefinition");
          String renderingEngineName = ReformatRenderingEngine.NAME;
          RenditionDefinition renditionDefinition = renditionService.createRenditionDefinition(renditionName, renderingEngineName);
          renditionDefinition.setParameterValue(AbstractRenderingEngine.PARAM_MIME_TYPE, MimetypeMap.MIMETYPE_PDF);
          
          //PERFORMING RENDITION
          ChildAssociationRef renditionAssoc = renditionService.render(currentNode, renditionDefinition);
          NodeRef nodeProtocol = renditionAssoc.getChildRef();
          
          //WRITER OF NODE PROTOCOL
          ContentWriter writerNodeProtocolo = this.contentService.getWriter(nodeProtocol, ContentModel.PROP_CONTENT, true);
          writerNodeProtocolo.putContent("TEST");
          
          //CREATE A PDF DOCUMENT FROM NODE PROTOCOL
          Rectangle pageSize = new Rectangle(200, 100);
          Document document = new Document(pageSize);
          try {
               ContentWriter writer = contentService.getWriter(nodeProtocol, ContentModel.PROP_CONTENT, true);
               PdfWriter.getInstance(document, writer.getContentOutputStream());
               document.open();
               Font paragraphFont = FontFactory.getFont(FontFactory.HELVETICA, 10, Font.NORMAL);
               //add the value of field protocol
               document.add(new Paragraph("N. Protocollo: " + protocollo, paragraphFont));
               document.setMargins(0, 0, 0, 0);
               document.close();
               } catch (Exception e) {
                    e.printStackTrace();
          }
          
          //RETURN NODE PROTOCOL(RENDITION PDF FORMAT OF INPUT NODE)
          return nodeProtocol;
     }