The method getKids() is undefined for the type PDField - pdfbox

https://issues.apache.org/jira/browse/PDFBOX-2148
When there are multiple copies with the same field name, the getFullyQualifiedName for each kid in the list of PDField objects returns the name of the parent, followed by .null. So if the parent field is called Button2 and it has 4 instances the result of printing out all the names will be:
Button2.null
Button2.null
Button2.null
Button2.null

According to the comments to the question, the OP refers to PDFBox 2.0.x versions, in particular 2.0.6.
getKids()
The method getKids() is undefined for the type PDField
In PDFBox 2.0.6 there are two immediate sub-classes of PDField. Different variants of the former (1.8.x) getKids() method are implemented in there:
PDNonTerminalField - the method retrieving the kids in this class is getChildren() and returns a List<PDField>, a list of form fields.
PDTerminalField - the method retrieving the kids in this class is getWidgets and returns a List<PDAnnotationWidget>, a list of widget annotations.
name of the parent, followed by .null
When there are multiple copies with the same field name, the getFullyQualifiedName for each kid in the list of PDField objects returns the name of the parent, followed by .null
This is not the case in PDFBox 2.0.x.
In the sample document attached to the PDFBox issue PDFBOX-2148 PDFBox now correctly finds only a single field which appropriately is named "Button2". This field is a PDTerminalField and has 4 widget annotations. The class of the latter, PDAnnotationWidget, has no getFullyQualifiedName method, so there are no ".null" names.
Thus, this problem is gone.
FQN of duplicate fields
(from the OP's comment responding to "What exactly is your question?")
how to get Fully Qualified Name of duplicate fields in pdfbox
There are no duplicate fields in (valid) PDFs, for a given name there is at most a single field which may have multiple widgets. Widgets do not have individual FQNs.
Thus, what you call "duplicate fields" in your example document actually is a single field with multiple widgets; the name of that field is "Button2" and can be retrieved using getFullyQualifiedName().
which page which form field
(from the OP's comments to this answer)
but how to get current page no in pdfbox.. for example there are 3 page and in page 2 there is a form field so how can i get which page which form field ?
All PDAnnotation classes, among them PDAnnotationWidget, have a getPage() method returning a PDPage instance.
BUT: As specified in ISO 32000-1, annotations (in particular form field widgets) are not required to have a link to the page on which they are drawn (except for screen annotations associated with rendition actions).
Thus, the above mentioned method getPage() may return null (probably more often than not).
So to determine the respective pages of your widgets, you have to approach the problem the other way around: Iterate over all pages and look for the annotation widgets in the respective annotation array.
For PDFBox 1.8.x you can find example code in this stackoverflow answer. With the information given in the previous parts of this answer it should be easy to port the code to PDFBox 2.0.x.
checkbox and radio button
(also from the OP's comments to this answer)
one more issue if i am using checkbox and radio button both then field.getFieldType() output is Btn for both. how to identify it?
You can identify them by inspecting the field flags which you retrieve via fields.getFieldFlags():
If the Pushbutton flag is set (PDButton.FLAG_PUSHBUTTON), the field is a regular push button.
Otherwise, if the Radio flag is set (FLAG_RADIO), the field is a radio button.
Otherwise, the field is a check box.
Alternatively you can check the class of the field object which for Btn may be PDPushButton, PDRadioButton, or PDCheckBox.
Beware: If a check box field has multiple widgets with differently named on states, this check box field and its widgets act like a radio button group! And not only in theory, I've seen PDFs with such check box fields in the wild.
To really be sure concerning the behavior of the fields, you therefore also should compare the names of the on states of all the widgets of a given check box.

Related

Conditionally capturing pre-determined text in one field based on multiple choice selection in another field in REDCap

Problem: How can you capture a pre-determined or static text value based on what choice a user makes from a multiple choice menu on a survey?
Example: Suppose you have the following basic setup:
I have four text statements that correspond to options 1-4 (e.g., "Statement corresponding to Option 1", "Statement corresponding to Option 2", etc.). If the user chooses, say, Option 1 from the sample_options field, then I would like to capture the text value of the pre-prepared statement in the option_statement field. The user should not be able to alter the captured text statement (e.g., maybe hide the field using the #HIDDEN action tag).
Attempt: It seemed like this might be a problem that could be resolved with action tags, namely the #DEFAULT one, but I have been unable to do this. I also thought about trying to use a calculated field instead of a text field for option_statement, but calculated fields must return numeric values:
This seems like a problem that should be somewhat straightforward to tackle, but I have been baffled by just how hard it seems to be to simply capture static text in one field based on a user's selection in another field.
If I understand the question, you want to select a text string from a list of (in this case) 4 options, depending on the user selecting a choice from a radio/dropdown?
Probably the easiest method is to use #CALCTEXT (if you are on a sufficiently recent version), which allows you to conditionally populate a text field, i.e.:
#CALCTEXT(
if([sample_options] = 1, "This is the label for option 1",
if([sample_options] = 2, "This is the label for option 2",
if([sample_options] = 3, "This is the label for option 3",
if([sample_options] = 4, "This is the label for option 4", "This is an else value")
)
)
)
)
But if you do not have #CALCTEXT available to you, you can do this with a #DEFAULT, by constructing another radio field (#HIDDEN if you like) on a separate page or instrument (as #DEFAULT needs the value to exist in the database on page load, and so does not work dynamically on the page), with your four labels as the options with the same choice codes as your [sample_choices] field. For example:
1,This is the label for option 1
2,This is the label for option 2
3,This is the label for option 3
4,This is the label for option 4
And annotate it with:
#DEFAULT='[sample_choice]'
Thus if a user selects 3 for [sample_choice] and proceeds to the page or instrument that has the label field, the #DEFAULT tag will automatically select choice 3 from the label field, which can then be stored in the dataset and piped into an email, onto the page, or whatever.

iMacros Tag Line properties

I'm trying to create a macro to log in to a company owned web page. When I record putting the cursor into the User Name text box, the following command is recorded:
TAG POS=1 TYPE=INPUT:TEXT FORM=ACTION:/pdp/qnyfy/resumeSAML50/pdp/startSSO.ping
The problem is that the "qnyfy" part of the tag line changes. The next time I try to record this tag line, every thing is the same except that "qnyfy" changes to something else; which renders my VBA code useless for logging into this web page.
Is there a way to extract this information first, find out what that 5 characters should be and then re-build a string to use the correct tag line?
Windows 7
Excel 2016
iMacros 10.3
Thanks for the help........
OK, #OP opened some parallel Thread on the iMacros Forum (iMacros Tag Line Properties), which allows me to simplify a bit this Answer and to remove a few of the original IF-IF-IF...
(The parallel Thread contains a bit more (Background) Info and more precise Sols/Scripts applied to this specific Script, for those interested...)
First, FCI (Full Config Info) was originally not completely clear, now it is:
=> iMB v10.3, 'Scripting Interface' v10.3, Win7.
("iMacros v10.3" could have meant 'v10.3 for CR 'Free'/'PE'' also...)
(The 'TAG' Statement is truncated is this Thread, it is complete + complete Script in the parallel Thread...)
Several Solutions, I'll go from "simplest" to "more complex":
1- The 'FORM' Parameter can probably simply completely be removed. It is usually not needed, unless there are several Forms on the Page with similar HTML Elements, here the 'INPUT' Field.
2- Same like '1', but using for example the 'CLASS' Attribute or any Attr(s) that might identify this 'INPUT' Field uniquely if there are several Forms on the Page with similar (but not identical) 'INPUT' Fields. (Or by adjusting the 'POS=n' if they are identical...)
3- Same like '1' or '2', but combined with 'Relative Positioning', on some HTML Element that can be identified "easily" and uniquely to be used as the Anchor, either inside ('3a') the same 'FORM' or 'DIV' (=> this 'INPUT' probably has some 'Label' next to it like some "Login:" for example), or just outside ('3b') if that Form has some Name/Title for that "Section", usually in 'H2' or 'H3' Type.
4- Simply replace the dynamic part ("qnyfy") with a Wildcard:
TAG POS=1 TYPE=INPUT:TEXT FORM=ACTION:/pdp/*/resumeSAML50/pdp/startSSO.ping
Sols [1-4] probably provide a "Shortcut" to probably achieve the desired Result, but they actually don't really answer #OP's Qt which was "How to identify/extract/isolate this "qnyfy" 5 Letter String...?"
5- Using first one of [1-4] Methods, manage to tag some Element that will be inside that 'FORM', either the 'INPUT' Field itself or one Element that could be used as Anchor in '3a' (with Anchor Inside the Form), and then use 'Double Relative Positioning' (more Info on the iMacros Forum where I've several times already completely explained the Principle) to identify and tag and extract (=HTM) the complete 'Containing 'DIV'' (or could be 'SPAN', but there will very probably be some (outer) 'DIV' also) containing the 'FORM' to then isolate the "qnyfy" part using 'EVAL', stg like...:
SET !EXTRACT_TEST_POPUP NO
TAG POS=1 TYPE=INPUT:TEXT FORM=ACTION:/pdp/*/resumeSAML50/pdp/startSSO.ping ATTR=CLASS:* EXTRACT=TXT
TAG POS=R-1 TYPE=DIV ATTR=TXT:* EXTRACT=TXT
SET !EXTRACT NULL
TAG POS=R1 TYPE=DIV ATTR=TXT:*&&CLASS:* EXTRACT=HTM
SET Form_ID EVAL("var s='{{!EXTRACT}}'; var x,y,z; x=s.split('ACTION:/pdp/'); y=x[1].split('/'); z=y[0]; z;")
PROMPT EXTRACT:<BR><BR>{{!EXTRACT}}<BR><BR>Form_ID:<SP>_{{Form_ID}}_
6- This one actually comes between '4' and '5', it would be by using '3b' to first locate some Anchor outside the 'FORM' and its 'Containing 'DIV'', then only one Level of 'Relative Positioning' would be needed... (And the 'EVAL()' Statement remains the same...)
That's it...! It would help / add some "Reliability" if for example the Class of the Containing 'DIV' can be identified/added.
Not relevant for iMB v10.3 anymore:
And if "iMacros v10.3" meant "iMacros for CR v10.3 'Free'", you'll need to use ['!VAR1'-'!VAR3'] instead of 'Form_ID' as User Defined Vars are not supported in the 'Free' Version...
[All Solutions/Scripts not tested of course...! Hum, I had previously mentioned that I could directly think of 3 or 4 Solutions, here are already 6, ah-ah...!, and there are also different possible Variants on all 6 of them...]
7- In the parallel Thread on the iMacros Forum, I also mentioned and explained about a Sol_7 using the 'EVENT' Mode with or without ID, which wouldn't be of use for this User as the 'EVENT' Mode was not supported in iMB v10.3.
Rmk:
Sol_5 and Sol_6 can actually be used to deal with Dynamic ID's, same Principle...!
>
I might one day have to delete this Answer as I am currently (re)using each time my last 5/5 'Answer_Credit', I each time have to delete some previous Answer, to be able to post a 5th one, as most Users on the 'iMacros' Tag-Channel usually never follow up on their Threads and don't do "+1" or "Accept Solution"..., and all my previous Answers also usually all get downvoted anyway by some "angry" User(s), so I never manage to pass the Threshold for more than 5 Answers, ah-ah...!, tja...!
(No big deal probably as I actually never or very-very rarely answer Threads on SOF as I don't like the Rep-Pts System, I only answered this one because #OP is a "nice User" that I knew from the iMacros Forum, ah-ah...!)
(I still don't know what the 'community wiki' CB means below posting an Answer...?)

How to Identify Elements in Salesforce Lightning for Selenium

I am trying to automate Salesforce lightning using Selenium, but getting issues with identifying elements. Reason, its having dynamic IDs , and other attributes are either very long , or they are not unique.
For eg ,
<a id="170:1968;a" class="textUnderline outputLookupLink slds-truncate forceOutputLookup"
data-refid="recordId"
data-recordid="0059E000001aOCSQA2"
data-special-link="true"
href="#/sObject/0059E000001aOCSQA2/view"
target="_blank" rel="noreferrer"
title="" data-aura-rendered-by="170:1968;a" data-aura-class="forceOutputLookup"/>
In above code , ID is dynamic , Class is not unique, and all the Lookup elements are associated with it. Also the absolute path is not much trusted , and hence I am trying to find any concrete option to handle these elements. Any help will be highly appreciated.
Here, you could try using the contains method if at least a part of the id attribute value is static.
From your code, you could try
//a[contains(#id,"a")]/ //--extended xpath--
From the given html code, the 'a' in the id attribute of the a tag looks static, while the rest changes.
You can ask the developers to provide an id to the lightning component using aura:id
Then the dynamic id won't be generated.
You can try with field labels and fetch its parent node(s), and then fetching childs or brother nodes to locate related texts/text boxes etc.
Eg. You are in Account Edit/New page, and you want to fill in a value to the text box for Account Name field. So you can firstly try with //*[text()='Account Name']/parent::* to find an element that covers BOTH the field label and the text box.
And then you can check if the text box is a 'brother' or a 'child'. If it's a 'child' then try with //*[text()='Account Name']/parent::*(/parent::*)//*[attributes for the text box];
If it's 'brothers' then try with //*[text()='Account Name']/parent::*(/parent::*)/following-sibling::*[attributes for the text box]
You can use this logic to locate all type of fields in all standard lightning pages.

How can I have multiple instances of same dojo form element with same id in a page?

I have a page say profile.htm with dojo declarative form with id="myForm". I have another page say dashboard.htm having border layout with 3 content pane. I want to show the profile.htm in all these three contentPanes. But when I try this then it gives registration error because there will be three forms with same Id.
Is there any solution for this so that I can have same page (with same id) in many contentPanes?
You simply can't, it's because of the HTML spec:
The id global attribute defines a unique identifier (ID) which must be unique in the whole document.
See: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id
The same goes for dijit's, if there are many dijit's with the ID myDijit what would registry.byId('myDijit') return? Dijit has it's own method of assigning unique ID's just as long as you don't assign one.

Does mvc 4 application need another model to return aggregate data on an existing table and model

I have a table (and model) with the following properties in an asp.net MVC 4 application:
TV Table
height
width
depth
type
brand
cost
When the user answes a question about the space that they have for the TV I then do an ajax call to determine which types are possible to fit into the space they have specified. Which type of TV type they want is the following question, so some options may need to be disabled. The SQL for what types fit in the space is "select distinct type from TV where height < #height and width < #width and depth < #depth".
Should I:
1. create a new model that I call from the TV controller just to return the distinct types
2. add a method to the TV model that I call from the TV controller that just returns a list of string with the types that fit
Depends on what you want to display to the user based on her selection' e. g.
If you want to display TV name + its description then returning a list of TV model will make sense.
If you are just going to display a list of TV names in combo box, then returning a list of string will suffice.
Calling a new action make sense in both cases IMHO.
EDIT:
For 2 - I want to return a list of string - should I create a new data model for this, or add a method in the existing TV data model that returns a list of string?
To expand on above query, since its not clear (at least I do not visualize it) from your question i will assume few things.
Case 1: You are displaying a view say "TVSelection" to the user that does not contain list of TVModels. In this view you are expecting user to enter three values i.e. Width, Height, Depth. Now when user enter these values, she can submit the form or you can fetch the TV Brand name list on Lost Focus event as well. In any case, the question would be are you updating existing view by populating the combo box or you are displaying a new view. I am assuming you are updating existing "TVSelection" view by the means of making an AJAX call. In that case you can just call a method on your controller (which displayed the "TVSelection" view) that returns a list of TV Brand names.
Case 2: You are displaying "TVSelection" view that already has a list of TVModel objects and you update it dynamically on selection of required field (filtering). In this case you can add a method in the TVModel itself to filter names only that matches the user selection.
I found these links relevant 1 & 2.
Hope that make sense.
Please add more details to your question if this does not answer your question.