How to copy notes item using Java - java

I would like to copy note item from one note document to the other using Java below is the my lotus script version of what i want to achive in Java
Sub CopyItem(FromDoc As NotesDocument, ToDoc As NotesDocument, itemName As String)
Dim FromItem As NotesItem
Dim ToItem As NotesItem
If Not (FromDoc.Hasitem(itemName)) Then Exit Sub
Set FromItem = FromDoc.GetFirstItem(itemName)
If Not ToDoc.hasitem(itemName) Then Set ToItem = ToDoc.CreateItem(itemName)
ToItem.Values = FromDoc.Values
End Sub
I have tried the below:
public static void copyAnItem(Document FromDoc, Document ToDoc, String sItemName){
Vector<String> FromItem = new Vector<String>();
Vector<String> ToItem = new Vector<String>();
if(!FromDoc.hasItem((itemName))){
return;
}
FromItem = FromDoc.getItemValue(itemName);
if(!ToDoc.hasItem(sItemName)){
ToItem.add(itemName);
}
ToItem.addAll(FromDoc);
}

public static void copyAnItem(Document fromDoc, Document toDoc, String itemName){
try {
if(fromDoc.hasItem(itemName)) {
toDoc.copyItem(fromDoc.getFirstItem(itemName));
}
} catch (NotesException e) {
// your exception handling
}
}
You can get the whole item including all properties from fromDoc with getFirstItem and can copy it to toDoc with copyItem in just one line of code.

public static void copyAnItem(Document FromDoc, Document ToDoc, String sItemName){
if(FromDoc.hasItem(sItemName)){
ToDoc.replaceItemValue(sItemName, FromDoc.getItemValue(sItemName));
}
}
It won't work with Authors or Readers items. Better the Knut solution :)

Related

Create file structure from strings

I am trying to create a BitBucket plugin to get the repository structure and print it out in a structured format. The plugin creates a button on the repo page and when clicked it connects with a servlet to produce an output, however I cannot get my formatting code to work.
E.g
Instead of:
Folder 1
File 1
File 2
I want it to indent children:
Folder 1
File 1
File 2
I currently have a JS file which controls the button and makes an ajax call to a Java file, and also passes the servlet URL including the parameters for the repo (Project, Repo).
In my Java file I have a doGet which gets the repo from the parameters and uses a custom contentTreeCallback() to get the files within the repo in order to print them out, using callback.getFiles(). Within this same Java file, I have defined a node class which creates a linked hash map which takes each file, splits it into components, and with a recursive loop appends children to nested lists in order to create the file structure. This should work, however my custom contentTreeCallback() gets a string rather than the file array it needs to return. I cannot figure out what changes I need to make to get this to work. I'm guessing I either adjust the callback to get the files or I move the node class functionality into the callback class. I would prefer the second option since this class already splits the string, it seems a bit redundant to do it twice.
The servlet java class:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// Get values from the URL
projectName= req.getParameter("project");
repoName = req.getParameter("repository");
repo = repositoryService.getBySlug(projectName, repoName);
// ByteArrayOutputStream out = new ByteArrayOutputStream();
MyContentTreeCallback callback = new MyContentTreeCallback();
PageRequestImpl pr = new PageRequestImpl(0, 1000);
// Get information from the defined location, store in ByteArrayOutputStream
contentService.streamDirectory(repo, "Master", "", true, callback, pr);
resp.setContentType("text/html");
resp.getWriter().print("<html><body><p>Repository: " + repo.getName() + "</p>");
Node root = new Node(null);
for(int i = 0; i < callback.getFiles().size(); i++) {
root.add(callback.getFiles().get(i));
}
root.writeTo(resp.getWriter());
resp.getWriter().print("</body></html>");
}
static final class Node {
final String name;
final Map<String, Node> children = new LinkedHashMap<>();
Node(String name) {
this.name = name;
}
void add(File file) {
Node n = this;
for(String component: file.getPath().getComponents())
n = n.children.computeIfAbsent(component, Node::new);
}
void writeTo(Appendable w) throws IOException {
if(name != null) w.append("<li><a href='/'>").append(name).append("</a></li>\n");
if(!children.isEmpty()) {
w.append("<ul>\n");
for(Node ch: children.values()) ch.writeTo(w);
w.append("</ul>\n");
}
}
}
And the custom callback class:
public class MyContentTreeCallback extends AbstractContentTreeCallback {
ArrayList<File> files = new ArrayList<File>();
ContentTreeSummary fileSummary;
public MyContentTreeCallback() {
}
#Override
public void onEnd(#Nonnull ContentTreeSummary summary) {
fileSummary = summary;
}
#Override
public void onStart(#Nonnull ContentTreeContext context) {
System.out.print("On start");
}
#Override
public boolean onTreeNode(#Nonnull ContentTreeNode node) {
String filePath = "";
if (node.getPath().getComponents().length>1) {
for(int i=0;i<node.getPath().getComponents().length;i++) {
filePath+=node.getPath().getComponents()[i]+"/";
//filePath=filePath.substring(0,filePath.length() - 1)
}
}
else {
filePath+=node.getPath().getName();
}
String lastChar = String.valueOf(filePath.charAt(filePath.length() - 1));
if(lastChar.equals("/")){ filePath=filePath.substring(0,filePath.length() -
1); }
files.add(filePath);
return true;
}
public ArrayList<File> getFiles(){
return files;
}
}
files.add(filePath); Is where the issue is in the callback class.
I'm sure it's simpler than I am making it out to be... Thanks for any help you can give

AEM HTL data-sly-list just prints array as a string

I have a Java file returning an ArrayList of Buttons with a button_text property
public void activate() throws Exception {
buttonsNode = getResource().adaptTo(Node.class).getNode("buttons");
buttons = new ArrayList<Button>();
try{
NodeIterator ni = buttonsNode.getNodes();
while (ni.hasNext()) {
Node n = (Node)ni.nextNode();
String button_text = n.getProperty("buttonText").getString();
Button bs = new Button(button_text);
buttons.add(bs);
}
}
catch(Exception e){
}
}
public ArrayList<Button> getButtonsListObject(){
return buttons;
}
public class Button {
String button_text;
public Button(String button_text) {
this.button_text = button_text;
}
public String getButtonText() {
return button_text;
}
}
If I put
<ul data-sly-list.button="${PillButtons.buttons}">
<li>${button}</li>
</ul>
in my HTL I just get a list with one item that is just the array in plain text: "[{ "buttonText": one},{ "buttonText": two},{ "buttonText": three}]"
And doing
<ul data-sly-list.button="${PillButtons.getButtonsListObject}">
<li>${button}</li>
</ul>
Returns a list with three items but they are all blank.
How do I properly access and print this ArrayList?
For the first attempt, I'm unsure where the ${PillButtons.buttons} is coming from, maybe you also have a String getButtons() that returns that JSON.
For the second one, you are using the right method in ${PillButtons.getButtonsListObject} (you could also use ${PillButtons.buttonsListObject} as HTL is smart enough to look for the getter) but you also need to print out <li>${button.buttonText}<li> to get the expected output.

How to display a Postgres aliased field in Vaadin field?

This is a query I wrote:
public List<PrRevamps> fetchRevampHistory(String refNo) {
List<PrRevamps> list = dsl.select(
DSL.concat(
Tables.PR_REVAMPS.PR_REVAMP_CODE,DSL.val("-"),
Tables.PR_REVAMP_CODES.PR_DESCRIPTION
).as("DESCRIPTION"),
Tables.PR_REVAMPS.PR_REVAMP_DATE,
Tables.PR_REVAMPS.PR_KEY)
.from(Tables.PR_REVAMP_CODES,Tables.PR_REVAMPS)
.where(Tables.PR_REVAMPS.PR_REVAMP_CODE.equal(Tables.PR_REVAMP_CODES.PR_CODE))
.and(Tables.PR_REVAMPS.PR_PROP_REF_NO.equal(refNo))
.fetchInto(PrRevamps.class);
return list;
}
and I need to display revampCode and description in one row in vaadin grid.
i.e "A-Marshall"
This is the grid code below:
private void populateRevampGrid() {
Object ref = serv.getAttribute("ref");
String propRef = "";
if(ref != null) {
propRef = (String)ref;
List<PrRevamps> list = getService().fetchRevampHistory(propRef);
if(!list.isEmpty()) {
revampGrid.setContainerDataSource(new BeanItemContainer<>(list));
//revampGrid.addColumn("prRevampCode").setHeaderCaption("REVAMP DESCRIPTION");
revampGrid.removeColumn("prKey");
revampGrid.removeColumn("prLeaseType");
revampGrid.removeColumn("prPropRefNo");
revampGrid.getColumn("prRevampDate").setHeaderCaption("REVAMP DATE");
revampGrid.getColumn("prRevampCode").setHeaderCaption("REVAMP TYPE");
} else {
clearfields();
Notification.show("list is empty",Type.ERROR_MESSAGE.WARNING_MESSAGE);
}
}
}
As I understand, you have the description field, that has the desired value.
If not, you can add properties, generated from an object on the fly. But for this, you will need to use Container.
The full description can be found on Vaadin documentation https://vaadin.com/docs/v7/framework/datamodel/datamodel-container.html (see GeneratedPropertyContainer)

Concurrency for recursive webcrawler-algorithm in Java

I wrote a program in Java to find all pages of a website, starting with the URL of the startpage (using Jsoup as webcrawler). It is ok for small websites but too slow for sites with 200 or more pages:
public class SiteInspector {
private ObservableSet<String> allUrlsOfDomain; // all URLS found for site
private Set<String> toVisit; // pages that were found but not visited yet
private Set<String> visited; // URLS that were visited
private List<String> invalid; // broken URLs
public SiteInspector() {...}
public void getAllWebPagesOfSite(String entry) //entry must be startpage of a site
{
toVisit.add(entry);
allUrlsOfDomain.add(entry);
while(!toVisit.isEmpty())
{
String next = popElement(toVisit);
getAllLinksOfPage(next); //expensive
toVisit.remove(next);
}
}
public void getAllLinksOfPage(String pageURL) {
try {
if (urlIsValid(pageURL)) {
visited.add(pageURL);
Document document = Jsoup.connect(pageURL).get(); //connect to pageURL (expensive network operation)
Elements links = document.select("a"); //get all links from page
for(Element link : links)
{
String nextUrl = link.attr("abs:href"); // "http://..."
if(nextUrl.contains(new URL(pageURL).getHost())) //ignore URLs to external hosts
{
if(!isForbiddenForCrawlers(nextUrl)) // URLS forbidden by robots.txt
{
if(!visited.contains(nextUrl))
{
toVisit.add(nextUrl);
}
}
allUrlsOfDomain.add(nextUrl);
}
}
}
else
{
invalid.add(pageURL); //URL-validation fails
}
}
catch (IOException e) {
e.printStackTrace();
}
}
private boolean isForbiddenForCrawlers(String url){...}
private boolean urlIsValid(String url) {...}
public String popElement(Set<String> set) {...}
I know I have to run the expensive network-operation in extra threads.
Document document = Jsoup.connect(pageURL).get(); //connect to pageURL
My problem is that I have no idea how to properly outsource this operation while keeping the sets consistent (how to synchronize?). If possible I want to use a ThreadPoolExecutor to control the amount of threads that is getting started during the process. Do you guys have an idea how to solve this? Thanks in advance.
To use threads and also keep the sets consistent, you just need to create a thread that receives the variable you want to add to the Set but created empty, so the thread fills it when done and then adds it to the Set.
A simple example of that could be:
Main.class
for (String link : links) {
String validUrl = null;
taskThread = new Thread( new WebDownloadThreadHanlder(link, validUrl, barrier));
taskThread.start();
if (validUrl != null) {
allUrlsOfDomain.add(validUrl);
}
}
barrier.acquireUninterruptibly(links.size());
WebDownloadThreadHandler.class
public class WebDownloadThreadHandler implements Runnable {
private String link;
private String validUrl;
private Semaphore barrier;
public ScopusThreadHandler(String link, String validUrl, Semaphore barrier) {
this.link = link;
this.validUrl = null;
this.barrier = barrier;
}
public void run () {
try {
Document document = Jsoup.connect(this.link).userAgent("Mozilla/5.0");
Elements elements = document.select(YOUR CSS QUERY);
/*
YOUR JSOUP CODE GOES HERE, AND STORE THE VALID URL IN: this.validUrl = THE VALUE YOU GET;
*/
} catch (IOException) {
e.printStackTrace();
}
this.barrier.release();
}
}
What you are doing here is creating a thread for every web you want to get all the links from, and storing them into variables, if you want to retrieve more than one lvalid link from every page, you can do it using a Set and adding it a to a global set (appending it). The thing is that to keep your code consistent you need to store the retrieved values in the variable you pass the thread as argument using THIS keyword.
Hope it helps! If you need anything else feel free to ask me!

How to translate a DTO in Struts 2

We are working for internationalizing an old application with some dirty code. For example, we have an object DTO InstrumentDto:
private String label;
private Quotation quotation;
private ExprQuote quoteExp;
public String getTypeCouponCouru() {
if (this.quoteExp.getCode().equals(Constants.INS_QUOTE_EXPR_PCT_NOMINAL_CPN_INCLUS)
|| this.quoteExp.getCode().equals(Constants.INS_QUOTE_EXPR_PCT_NOMINAL_INTERET)) {
return "Coupon attaché";
} else if(this.quoteExp.getCode().equals(Constants.INS_QUOTE_EXPR_PCT_NOMINAL_PIED_CPN)){
return "Coupon détaché";
} else {
return "";
}
}
public String getFormattedLabel() {
StringBuilder formattedLabel = new StringBuilder(this.label);
Quotation quote = this.quotation;
if (this.quotation != null) {
formattedLabel.append(" ");
formattedLabel.append(FormatUtil.formatDecimal(this.quotation.getCryQuote());
if (this.quoteExp.getType().equals("PERCENT")) {
formattedLabel.append(" %");
} else {
formattedLabel.append(" ");
formattedLabel.append(this.quotation.getCurrency().getCode());
}
formattedLabel.append(" le ");
formattedLabel.append(DateUtil.formatDate(this.quotation.getValoDate()));
}
return formattedLabel.toString();
}
Then, those methods are used on JSPs. For example for getFormattedLabel(), we have :
<s:select name = "orderUnitaryForm.fieldInstrument"
id = "fieldInstrument"
list = "orderUnitaryForm.instrumentList"
listKey = "id"
listValue = "formattedLabel" />
IMO, the first method doesn't have its place on the DTO. We are expecting the view to manage the label to print. And in this view (the JSP), no problem to translate those words.
Additionally, this method is just used in 2 JSP. Not a problem to "repeat" the conditional tests.
But it's more difficult for getFormattedLabel() : this method is used in a lot of JSP, and the building of the formatted label is "complicated". And it's not possible having the i18n service in the DTO.
So how to do that ?
Your code in getFormattedLabel() seems to be business logic.
A DTO is a simple object without any complex test/behavior (see wiki definition).
IMO, you should move this chunk of code to your Action and split your *.properties file like this:
Your *.properties:
message1= {0} % le {1}
message2= {0} {1} le {2}
Your Action:
public MyAction extends ActionSupport {
public String execute(){
//useful code here
InstrumentDto dto = new InstrumentDto();
StringBuilder formattedLabel = new StringBuilder(label);
if (this.quotation != null) {
String cryQuote = FormatUtil.formatDecimal(this.quotation.getCryQuote());
String date = DateUtil.formatDate(this.quotation.getValoDate());
if (this.quoteExp.getType().equals("PERCENT")) {
formattedLabel.append(getText("message1", new String[] { cryQuote, date }));
} else {
String cryCode = this.quotation.getCurrency().getCode();
formattedLabel.append(getText("message2", new String[] { cryQuote, cryCode, date }));
}
}
dto.setFormattedLabel(formattedLabel);
}
}
Hope this will help ;)

Categories

Resources