Add interactive checkbox to PDF using itext 7 - java

I'm trying to add an AcroField checkbox to a PDF that's being generated by iText7 pdfHTML. This is not working by default, I saw someone suggest using a custom tag worker but as much as I tried I couldn't get it to work. Does anyone have any idea how to implement this? Or an example?

I've created a very simple example to show you how one can create a custom tag worker and add an acrofield to a document while html to pdf processing.
Look at the next snippet:
class CustomTagWorkerFactory extends DefaultTagWorkerFactory {
#Override
public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
if (tag.name().equals("input")) {
if (AttributeConstants.CHECKBOX.equals(tag.getAttribute(AttributeConstants.TYPE))) {
return new AcroInputTagWorker(tag, context);
}
}
return null;
}
Here I've introduced a custom tag worker factory which will create default tagworkers for all tags except for the one I've specified (<input type="checkbox">).
Now let's add an acrofield to the document on <input type="checkbox"> processing:
class AcroInputTagWorker extends InputTagWorker {
public AcroInputTagWorker(IElementNode element, ProcessorContext context) {
super(element, context);
PdfAcroForm.getAcroForm(context.getPdfDocument(), true)
.addField(PdfFormField.createCheckBox(context.getPdfDocument(), new Rectangle(100, 700, 30, 30), "checkbox", "Off"));
}
That's basically it. The resultant pdf for a very simple html file (basically, just one line: <input type="checkbox">) looks as this:
Now let's briefly discuss what can be improved:
1) you may want to check whether CHECKED attribute is set and consider it while setting the acrofield's value (in the example above I've just set it as "Off")
2) you need to create different acrofield's name values (I've just used "checkbox")
3) you may want to render the acrofield not at a certain position, predefined before html to pdf processing. You may want to let iText define its position dynamically depending on where the input tag is placed.
In that case the solution would be more difficult. You will need to create your own CheckBox element (probably extended from aParagraph) and a renderer for it (probably extended from a ParagraphRender). Then you will need to override its layout method (perhaps just call super.layout() to get the coordinates of the paragraph and only then add the acrofield to the document). That's not easy, but it's certainly worth a try! And if you're not successful, you can always ask another SO question :)

Related

XWiki extension : detect event space creation

Based on the documentation here we can see that in a xwiki java extension, we can intercept the event UserCreation like that :
https://extensions.xwiki.org/xwiki/bin/view/Extension/Observation%20Module%20Local#HWritinganEventListenerinVelocityinaWikipage
public void onEvent(Event event, Object source, Object data)
{
XWikiDocument document = (XWikiDocument) source;
String wikiName = document.getDocumentReference().getWikiReference().getName();
DocumentReference userClass = new DocumentReference(wikiName, "XWiki", "XWikiUsers");
if (document.getXObject(userClass) != null) {
}
I want the same thing, but I want to detect the event space creation ( so basically when you add a space( basically a space is the main root page of an article ) in your wiki. But I didn't found any class like XWikiUsers for the space or the page.
It don't want to do it with velocity or groovy but in pure java extension and I have no clue, the doc is very huge but it's hard to found what I' looking for.
Technically, a "space" gets created whenever a page is created under it (either terminal page or WebHome).
So you could either:
do a query each time a page is being created (DocumentCreatingEvent, so not yet DocumentCreatedEvent) and then do a query (see https://extensions.xwiki.org/xwiki/bin/view/Extension/Query%20Module) to see if the space (matching the new document's space reference) matches an existing one or a deeper nested one inside the database... or
check if the newly created document (DocumentCreatedEvent) has the name WebHome which would be much better in terms of performance, but it will not work if you are working with terminal documents (i.e. other documents than 'WebHome' ones, see https://www.xwiki.org/xwiki/bin/view/Documentation/UserGuide/Features/ContentOrganization/#HTerminology

How can I add UnsignedProperties?

I'm trying to sign a XML document using XADES-BES and the smart card.
I made some changes in the class SignerBES.java according to my needs and the signature creation is working well !
My question: How can I add UnsignedProperties to get something like this :
<SignerRole>
<ClaimedRoles>
<ClaimedRole>EST</ClaimedRole>
</ClaimedRoles>
</SignerRole>
</SignedSignatureProperties>
<SignedDataObjectProperties>
<DataObjectFormat ObjectReference="#sigId">
<Description>des</Description>
<MimeType>text/xml</MimeType>
<Encoding>base64</Encoding>
</DataObjectFormat>
<CommitmentTypeIndication>
<CommitmentTypeId>
<Identifier/>
</CommitmentTypeId>
<AllSignedDataObjects/>
<CommitmentTypeQualifiers>
<CommitmentTypeQualifier>commitment</CommitmentTypeQualifier>
</CommitmentTypeQualifiers>
</CommitmentTypeIndication>
</SignedDataObjectProperties>
</SignedProperties>
<UnsignedProperties>
<UnsignedSignatureProperties>
<SignatureTimeStamp>
<EncapsulatedTimeStamp>noTimStampToken</EncapsulatedTimeStamp>
</SignatureTimeStamp>
<CounterSignature/>
<CompleteCertificateRefs/>
<CompleteRevocationRefs/>
<SigAndRefsTimeStamp/>
<RefsOnlyTimeStamp/>
<CertificatesValues/>
<RevocationValues/>
<ArchiveTimeStamp/>
</UnsignedSignatureProperties>
</UnsignedProperties>
</QualifyingProperties>
</ds:Object>
this is a code snippet SignerBES.java:
Collection<SignedSignatureProperty> fsssp = new ArrayList<SignedSignatureProperty>(2);
Collection<UnsignedSignatureProperty> fsusp = new ArrayList<UnsignedSignatureProperty>(2);
getFormatSpecificSignatureProperties(fsssp, fsusp, signingCertificateChain);
// Gather all the signature and data objects properties.
QualifyingProperties qualifProps = qualifPropsProcessor.getQualifyingProperties(
signedDataObjects, fsssp, fsusp);
// LOG
System.out.println("fsusp"+fsusp.size());
I tried to add it at SignerBES.java and DefaultSignaturePropertiesProvider.java but I do not know how I can add it :
public class DefaultSignaturePropertiesProvider implements SignaturePropertiesProvider
{
#Override
public void provideProperties(SignaturePropertiesCollector signaturePropsCol)
{
signaturePropsCol.setSigningTime(new SigningTimeProperty());
signaturePropsCol.setSignerRole(new SignerRoleProperty("EST"));
// UnsignedProperty
// OtherUnsignedSignatureProperty otherUnsignedProp=null;
// signaturePropsCol.addOtherSignatureProperty(otherUnsignedProp);
}}
I don't think I understand completely what you're trying, since it seems you're messing around the lib source code. Anyway, check out this page on the project docs.
Many of the unsigned qualifying properties are added automatically by xades4j when you use one of the signing profiles (e.g. if you use XAdesCSigningProfile, CompleteCertificateRefs/CompleteRevocationRefs are added).
Other properties are part of advanced forms and can only be added during validation of an existing signature. Refer to this wiki page and [this javadocs page](http://luisgoncalves.github.io/xades4j/javadocs/1.4.0/reference/xades4j/verification/XadesVerifier.html#verify(org.w3c.dom.Element, xades4j.verification.SignatureSpecificVerificationOptions, xades4j.production.XadesSignatureFormatExtender, xades4j.verification.XAdESForm)) for additional info.
Finally, some properties (e.g. CounterSignature) are not tied to any specific form, and can be added to any signature using a custom SignaturePropertiesProvider, registered on the signing profile that you are using.

DOJO : Not able to initialize the js Using New Keyword

I have a link, if i click the link i need to call another Js using new keyword like below.
<a style="padding: 2px 15px" data-dojo-attach-event="click:display">Form</a>
display : function(){
new com.cn.clb.dr.mytasks.BrandForm({
formInfo: brandForm,
brand: brandName
}, formPlacer).initialize();
}
Here very first time(1st time page loading) above js called perfectly, After that, i was clicked the link the above js is not called.
In the JS i have included both postcreate() and initialize().
Please tell me how to call the js.
Based on the additional information that Dijit is telling you you're trying to register a widget with an ID that's already registered, you need to destroy the first widget you create before creating another one based on the same element.
Additionally, the second argument passed to widget constructors indicates srcNodeRef, which is a node that will be replaced with the widget's own DOM. I'm sort of guessing here since there's not much context, but you probably don't want to be passing the same node reference to it multiple times since it will probably be invalid after the first.
Here is an example of something I would expect to work better, which destroys the widget if it exists from a previous call using destroyRecursive, and uses placeAt to place the widget under a parent node rather than using the srcNodeRef argument to replace a node.
display : function(){
var parentNode;
if (this._displayWidget) {
parentNode = this._displayWidget.domNode.parentNode;
this._displayWidget.destroyRecursive();
}
else {
parentNode = formPlacer.parentNode;
}
this._displayWidget = new com.cn.clb.dr.mytasks.BrandForm({
formInfo: brandForm,
brand: brandName
}).placeAt(parentNode).initialize();
}
Note that this currently doesn't take into account position among siblings in the parent node; it should be possible to amend the placeAt call accordingly.
Finally i got the fix, we are using ID attribute in html file, so instead of using ID am using data-dojo-attach-point in the html. After this change its working fine now.
instead of using id am using data-dojo-attach-point.

sencha GXT css classes

i'm having problems with styling grid in gxt, the thing is that the elements in the grid get (i don't know how exactly) css class named ".GKA1XC4LIC" and this class overrides the settings, provided by my own css class (in my own css file). However some properties (like font-size) i'm able to change with my class (i mean my css file is being loaded).
i guess this .GKA1XC4LIC class is generated somewhere i don't know where. Why it is done this way? Am i doing this completely wrong?
i set class name like this:
codeColumnConfig.setColumnTextClassName("smk-grid-text");
thanks
I assume you are using GXT3. You said some properties are set by changing the css. That is because the GXT3 has not set them and so they work.
To do use the GXT3 Appearnces correctly, it may be best to see this section Styling a GXT 3 application in the migration guide. It's about the middle of the page.
It explains the two ways to modify the Appearance pattern that GXT3 uses.
via configuration (in the GWT module XML file)
via constructor arguments
There is another explanation in the Sencha docs for Appearances
That said, that is pretty involved depending on how much you need to change things.
To do it quickly, I sometimes use a cell to render it how I need:
For example to render a cell in a grid a particular way I would do
ColumnConfig<Users, String> userCol = new ColumnConfig<SelectUserDialog.Users, String>(selectUserProperties.userName(), 240);
AbstractCell<String> c2 = new AbstractCell<String>() {
#Override public void render(com.google.gwt.cell.client.Cell.Context context, String value, SafeHtmlBuilder sb) {
value = "<div style=\"font-size:2.5EM; line-height : 30px; height=40px\" >" + value + "</div>";
sb.appendHtmlConstant(value);
}
};
userCol.setCell(c2);
If you are not using ColumnConfig already, you may need to see ValueProvider and ProperyAccess

Eclipse custom texteditor - marker annotation presentation issue

I want to write an eclipse plugin for my computer science lecturer. It's a custom editor with an xml based file format.
I've implemented syntax highlighting and other stuff. But I stuck when it comes to the usage of annotations/marker to show invalid content.
This is how it looks like, if the content is valid:
image of valid conent http://image-upload.de/image/aPcsaa/6c799a671c.png
This is how it looks like, if the content is invalid:
image of invalid conent http://image-upload.de/image/4TdooQ/04d662f397.png
As you can see, invalid attributes will get marked, but the problem is, the whole formatting seems to be lost between these annotations.
I use org.eclipse.jface.text.reconciler.Reconciler for delayed parsing of the content to create the document model. The model is used to format the text and display annotations. All this happens in the void void process(DirtyRegion dirtyRegion) method of the Reconciler.
For text formatting I use <ITextViewer>.changeTextPresentation(textAttributes, false) and for annotation handling I use
IAnnotationModel annotationModel = <ISourceViewer>.getAnnotationModel();
IAnnotationModelExtension annotationModelExtension = (IAnnotationModelExtension) annotationModel;
annotationModelExtension.replaceAnnotations(oldAnnotations, newAnnotations);
Since the Reconciler does not use the swt thread I have to use this construct to avoid exceptions:
<ITextViewer>.getTextWidget().getDisplay().asyncExec(new Runnable() {
#Override
public void run() {
<ITextViewer>.changeTextPresentation(textAttributes, false);
updateAnnotations(nodes);
}
});
By the way ITextViewer and ISourceViewer are meant as the same viewer object.
As annotation type I've testet: org.eclipse.ui.workbench.texteditor.spelling and some others, also custom types, but all with the same result.
I'm not quite sure, what I do wrong, could it be because it is all in a single call?
I hope someone can help me with this problem.
Thank you in advance.

Categories

Resources