How to remove all comments from docx file with docx4j? - docx4j

I'd like to remove all the comments from a docx file using docx4j.
I can remove the actual comments with a piece of code like is shown below, but I think I also need to remove the comment references from the main document part as well (otherwise the document is corrupted), but I can't figure out how to do that.
CommentsPart cmtsPart = wordMLPackage.getMainDocumentPart().getCommentsPart();
org.docx4j.wml.Comments cmts = cpart.getJaxbElement();
List<Comments.Comment> coms = cmts.getComment();
coms.clear();
Any guidance appreciated!
I also posted this question on the docx4j forum: http://www.docx4java.org/forums/docx-java-f6/how-to-remove-all-comments-from-docx-file-t1329.html.
Thanks.

You can use TraversalUtil to find the relevant objects (CommentRangeStart, CommentRangeEnd, R.CommentReference), and then remove them.
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import org.docx4j.TraversalUtil;
import org.docx4j.TraversalUtil.CallbackImpl;
import org.docx4j.XmlUtils;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.Body;
import org.docx4j.wml.CommentRangeEnd;
import org.docx4j.wml.CommentRangeStart;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.R.CommentReference;
import org.jvnet.jaxb2_commons.ppp.Child;
public class Foo {
public static void main(String[] args) throws Exception {
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage
.load(new java.io.File(System.getProperty("user.dir") + "/Foo.docx"));
MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
org.docx4j.wml.Document wmlDocumentEl = (org.docx4j.wml.Document) documentPart
.getJaxbElement();
Body body = wmlDocumentEl.getBody();
CommentFinder cf = new CommentFinder();
new TraversalUtil(body, cf);
for (Child commentElement : cf.commentElements) {
System.out.println(commentElement.getClass().getName());
Object parent = commentElement.getParent();
List<Object> theList = ((ContentAccessor)parent).getContent();
boolean removeResult = remove(theList, commentElement );
System.out.println(removeResult);
}
}
private static boolean remove(List<Object> theList, Object bm) {
// Can't just remove the object from the parent,
// since in the parent, it may be wrapped in a JAXBElement
for (Object ox : theList) {
if (XmlUtils.unwrap(ox).equals(bm)) {
return theList.remove(ox);
}
}
return false;
}
static class CommentFinder extends CallbackImpl {
List<Child> commentElements = new ArrayList<Child>();
#Override
public List<Object> apply(Object o) {
if (o instanceof javax.xml.bind.JAXBElement
&& (((JAXBElement)o).getName().getLocalPart().equals("commentReference")
|| ((JAXBElement)o).getName().getLocalPart().equals("commentRangeStart")
|| ((JAXBElement)o).getName().getLocalPart().equals("commentRangeEnd")
)) {
System.out.println(((JAXBElement)o).getName().getLocalPart());
commentElements.add( (Child)XmlUtils.unwrap(o) );
} else
if (o instanceof CommentReference ||
o instanceof CommentRangeStart ||
o instanceof CommentRangeEnd) {
System.out.println(o.getClass().getName());
commentElements.add((Child)o);
}
return null;
}
#Override // to setParent
public void walkJAXBElements(Object parent) {
List children = getChildren(parent);
if (children != null) {
for (Object o : children) {
if (o instanceof javax.xml.bind.JAXBElement
&& (((JAXBElement)o).getName().getLocalPart().equals("commentReference")
|| ((JAXBElement)o).getName().getLocalPart().equals("commentRangeStart")
|| ((JAXBElement)o).getName().getLocalPart().equals("commentRangeEnd")
)) {
((Child)((JAXBElement)o).getValue()).setParent(XmlUtils.unwrap(parent));
} else {
o = XmlUtils.unwrap(o);
if (o instanceof Child) {
((Child)o).setParent(XmlUtils.unwrap(parent));
}
}
this.apply(o);
if (this.shouldTraverse(o)) {
walkJAXBElements(o);
}
}
}
}
}
}

Related

Cleaning up unused images in PDF page resources

Please forgive me if this has been asked but I have not found any matches yet.
I have some PDF files where images are duplicated on each page's resources but never used in its content stream. I think this is causing the PDFSplit command to create very bloated pages. Is there any utility code or examples to clean up unused resources like this? Maybe a starting point for me to get going?
I was able to clean up the resources for each page by gathering a list of the images used inside the page's content stream. With the list of images, I then check the resources for the page and remove any that weren't used. See the PageExtractor.stripUnusedImages below for implementation details.
The resource object was shared between pages so I also had to make sure each page had its own copy of the resource object before removing images. See PageExtractor.copyResources below for implementation details.
The page splitter:
package org.apache.pdfbox.examples;
import org.apache.pdfbox.contentstream.operator.Operator;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.interactive.action.PDAction;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionGoTo;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDDestination;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageDestination;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class PageExtractor {
private final Logger log = LoggerFactory.getLogger(this.getClass());
public PDDocument extractPage(PDDocument source, Integer pageNumber) throws IOException {
PDDocument targetPdf = new PDDocument();
targetPdf.getDocument().setVersion(source.getVersion());
targetPdf.setDocumentInformation(source.getDocumentInformation());
targetPdf.getDocumentCatalog().setViewerPreferences(source.getDocumentCatalog().getViewerPreferences());
PDPage sourcePage = source.getPage(pageNumber);
PDPage targetPage = targetPdf.importPage(sourcePage);
targetPage.setResources(sourcePage.getResources());
stripUnusedImages(targetPage);
stripPageLinks(targetPage);
return targetPdf;
}
/**
* Collect the images used from a custom PDFStreamEngine (BI and DO operators)
* Create an empty COSDictionary
* Loop through the page's XObjects that are images and add them to the new COSDictionary if they were found in the PDFStreamEngine
* Assign the newly filled COSDictionary to the page's resource as COSName.XOBJECT
*/
protected void stripUnusedImages(PDPage page) throws IOException {
PDResources resources = copyResources(page);
COSDictionary pageObjects = (COSDictionary) resources.getCOSObject().getDictionaryObject(COSName.XOBJECT);
COSDictionary newObjects = new COSDictionary();
Set<String> imageNames = findImageNames(page);
Iterable<COSName> xObjectNames = resources.getXObjectNames();
for (COSName xObjectName : xObjectNames) {
if (resources.isImageXObject(xObjectName)) {
Boolean used = imageNames.contains(xObjectName.getName());
if (used) {
newObjects.setItem(xObjectName, pageObjects.getItem(xObjectName));
} else {
log.info("Found unused image: name={}", xObjectName.getName());
}
} else {
newObjects.setItem(xObjectName, pageObjects.getItem(xObjectName));
}
}
resources.getCOSObject().setItem(COSName.XOBJECT, newObjects);
page.setResources(resources);
}
/**
* It is necessary to copy the page's resources since it can be shared with other pages. We must ensure changes
* to the resources are scoped to the current page.
*/
protected PDResources copyResources(PDPage page) {
return new PDResources(new COSDictionary(page.getResources().getCOSObject()));
}
protected Set<String> findImageNames(PDPage page) throws IOException {
Set<String> imageNames = new HashSet<>();
PdfImageStreamEngine engine = new PdfImageStreamEngine() {
#Override
void handleImage(Operator operator, List<COSBase> operands) {
COSName name = (COSName) operands.get(0);
imageNames.add(name.getName());
}
};
engine.processPage(page);
return imageNames;
}
/**
* Borrowed from PDFBox page splitter
*
* #see org.apache.pdfbox.multipdf.Splitter#processAnnotations(org.apache.pdfbox.pdmodel.PDPage)
*/
protected void stripPageLinks(PDPage imported) throws IOException {
List<PDAnnotation> annotations = imported.getAnnotations();
for (PDAnnotation annotation : annotations) {
if (annotation instanceof PDAnnotationLink) {
PDAnnotationLink link = (PDAnnotationLink) annotation;
PDDestination destination = link.getDestination();
if (destination == null && link.getAction() != null) {
PDAction action = link.getAction();
if (action instanceof PDActionGoTo) {
destination = ((PDActionGoTo) action).getDestination();
}
}
if (destination instanceof PDPageDestination) {
// TODO preserve links to pages within the splitted result
((PDPageDestination) destination).setPage(null);
}
}
// TODO preserve links to pages within the splitted result
annotation.setPage(null);
}
}
}
The stream reader used to analyze the page's images:
package org.apache.pdfbox.examples;
import org.apache.pdfbox.contentstream.PDFStreamEngine;
import org.apache.pdfbox.contentstream.operator.Operator;
import org.apache.pdfbox.contentstream.operator.OperatorProcessor;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
import org.apache.pdfbox.pdmodel.graphics.form.PDTransparencyGroup;
import java.io.IOException;
import java.util.List;
abstract public class PdfImageStreamEngine extends PDFStreamEngine {
PdfImageStreamEngine() {
addOperator(new DrawObjectCounter());
}
abstract void handleImage(Operator operator, List<COSBase> operands);
protected class DrawObjectCounter extends OperatorProcessor {
#Override
public void process(Operator operator, List<COSBase> operands) throws IOException {
if (operands != null && isImage(operands.get(0))) {
handleImage(operator, operands);
}
}
protected Boolean isImage(COSBase base) throws IOException {
if (!(base instanceof COSName)) {
return false;
}
COSName name = (COSName)base;
if (context.getResources().isImageXObject(name)) {
return true;
}
PDXObject xObject = context.getResources().getXObject(name);
if (xObject instanceof PDTransparencyGroup) {
context.showTransparencyGroup((PDTransparencyGroup)xObject);
} else if (xObject instanceof PDFormXObject) {
context.showForm((PDFormXObject)xObject);
}
return false;
}
#Override
public String getName() {
return "Do";
}
}
}

Get Xtext element for hover

My Xtext grammar looks like this:
Model:
MsgDef
;
MsgDef:
(definitions+=definition)+
;
definition:
type=fieldType ' '+ name=ValidID (' '* '=' ' '* const=Value)?
;
I am trying to create a tooltip for the definition element that just contains the text that is spanned by the element.
(Xtend syntax) Documentation provider:
import dsl.dsl_msg.definition
import static extension org.eclipse.xtext.nodemodel.util.NodeModelUtils.*
class MsgDocumentationProvider implements IEObjectDocumentationProvider {
override getDocumentation(EObject o) {
val result = switch(o) {
definition : o.node?.tokenText
}
return result
}
}
My EOBjectHover implementation:
package dsl.ui.hover
import dsl.dsl_msg.definition
import com.google.inject.Inject
import org.eclipse.emf.ecore.EObject
import org.eclipse.jface.text.IRegion
import org.eclipse.jface.text.ITextViewer
import org.eclipse.jface.text.Region
import org.eclipse.xtext.nodemodel.util.NodeModelUtils
import org.eclipse.xtext.resource.EObjectAtOffsetHelper
import org.eclipse.xtext.resource.XtextResource
import org.eclipse.xtext.ui.editor.hover.DispatchingEObjectTextHover
import org.eclipse.xtext.ui.editor.hover.IEObjectHoverProvider
import org.eclipse.xtext.util.Pair
import org.eclipse.xtext.util.Tuples
class MsgHover extends DispatchingEObjectTextHover {
#Inject
private EObjectAtOffsetHelper eObjectAtOffsetHelper;
#Inject private IEObjectHoverProvider msgHoverProvider;
override protected Pair<EObject, IRegion> getXtextElementAt(XtextResource resource, int offset) {
// check for cross reference
val crossLinkedEObject = eObjectAtOffsetHelper.resolveCrossReferencedElementAt(resource, offset);
if(crossLinkedEObject != null) {
[...]
} else {
val parseResult = resource.getParseResult();
if(parseResult != null) {
var leaf = NodeModelUtils.findLeafNodeAtOffset(parseResult.getRootNode(), offset);
if(leaf != null && leaf.isHidden() && leaf.getOffset() == offset) {
leaf = NodeModelUtils.findLeafNodeAtOffset(parseResult.getRootNode(), offset - 1);
}
// this is the part I am having trouble with
if(leaf != null && leaf.getGrammarElement() instanceof definition) {
val keyword = leaf.getGrammarElement() as definition;
return Tuples.create(keyword, new Region(leaf.getOffset(), leaf.getLength()));
}
//-----------------
}
}
return null;
}
override public Object getHoverInfo(EObject first, ITextViewer textViewer, IRegion hoverRegion) {
this.lastCreatorProvider = msgHoverProvider.getHoverInfo(first, textViewer, hoverRegion);
return this.lastCreatorProvider?.getInfo();
}
}
Hoverprovider for completeness sake:
class MsgHoverProvider extends DefaultEObjectHoverProvider {
override protected boolean hasHover(EObject o){
return true;
}
}
I don't get the marked code to create regions for the definition grammar element. I have also tried getting the parent nodes until I encounter the definition node, but that didn't work because the parents were actually just RuleCall implementations, and I didn't know what to do with them.
How do I get the definition?

In ActiveJDBC how to update value of one of the Composite Key fields?

I am using ActiveJDBC. I have a table that is made up of a composite key (parentId, childId, effStartDate). I have a new requirement to allow the updating of the effStartDate field. When I tried to update the field and save, it errors out. Is there an appropriate way to update this using the ORM or a raw SQL approach in ActiveJDBC?
Current approach:
mymodel.setEffStartDate(newStartDate);
mymodel.saveIt();
Updated to provide more details. Here's the exact code:
try {
ri.setEffStartDate(ld);
boolean didItSave = ri.saveIt(user);
System.out.println("here - " + didItSave);
} catch(Exception e) {
System.out.println("Exception: " + e);
}
When the saveIt runs, it doesn't error out. However, it returns FALSE and nothing gets updated in the database. So I misused "errors" in my earlier statement. I should have said it just doesn't do anything.
We are using Oracle database.
The model class trying to update:
package com.brookdale.model;
import java.time.LocalDate;
import org.javalite.activejdbc.annotations.BelongsTo;
import org.javalite.activejdbc.annotations.BelongsToParents;
import org.javalite.activejdbc.annotations.CompositePK;
import org.javalite.activejdbc.annotations.Table;
import org.javalite.activejdbc.validation.ValidationException;
import com.brookdale.model.activejdbc.CecilModel;
#Table("MONET.CONTACTREL")
#CompositePK({ "parentContactID", "childContactID", "contactRelTypeID", "effStartDate" })
#BelongsToParents({
#BelongsTo(foreignKeyName="relationshipId",parent=Relationship.class),
#BelongsTo(foreignKeyName="contactRelTypeID",parent=ContactRelType.class),
// #BelongsTo(foreignKeyName="parentContactID",parent=Contact.class),
// #BelongsTo(foreignKeyName="childContactID",parent=Contact.class),
#BelongsTo(foreignKeyName="childContactID",parent=Contact.class),
#BelongsTo(foreignKeyName="childContactID",parent=ResidentContactDetail.class)
})
public class ContactRel extends CecilModel {
private ResidentContactDetail emergResidentContactDetail;
private ResidentContactDetail healthResidentContactDetail;
private ResidentContactDetail finResidentContactDetail;
private int emergresidentind = 0;
public Long getParentContactID() {
return getLong("parentContactID");
}
public void setParentContactID(Long parentContactID) {
set("parentContactID",parentContactID);
}
public Long getChildContactID() {
return getLong("childContactID");
}
public void setChildContactID(Long childContactID) {
set("childContactID",childContactID);
}
public LocalDate getEffStartDate() {
return getLocalDate("effStartDate");
}
public void setEffStartDate(LocalDate effStartDate) {
setLocalDate("effStartDate",effStartDate);
}
public LocalDate getEffEndDate() {
return getLocalDate("effEndDate");
}
public void setEffEndDate(LocalDate effEndDate) {
setLocalDate("effEndDate",effEndDate);
}
public Integer getContactRelTypeID() {
return getInteger("contactRelTypeID");
}
public void setContactRelTypeID(Integer contactRelTypeID) {
set("contactRelTypeID",contactRelTypeID);
}
public Integer getRelationshipId() {
return getInteger("relationshipId");
}
public void setRelationshipId(Integer relationshipId) {
set("relationshipId",relationshipId);
}
public Integer getParentIsPrimaryResidentInd() {
return getInteger("parentIsPrimaryResidentInd");
}
public void setParentIsPrimaryResidentInd(Integer parentIsPrimaryResidentInd) {
set("parentIsPrimaryResidentInd",parentIsPrimaryResidentInd);
}
public Integer getParentIsSecondPersonInd() {
return getInteger("parentIsSecondPersonInd");
}
public void setParentIsSecondPersonInd(Integer parentIsSecondPersonInd) {
set("parentIsSecondPersonInd",parentIsSecondPersonInd);
}
public int getCourtesyCopyInd() {
return getInteger("courtesyCopyInd");
}
public void setCourtesyCopyInd(Integer courtesyCopyInd) {
set("courtesyCopyInd",courtesyCopyInd);
}
/* Additional helper methods */
public Contact getParentContact() {
return Contact.findById(getParentContactID());
}
public Contact getChildContact() {
return Contact.findById(getChildContactID());
}
public int getEmergresidentind() {
return emergresidentind;
}
public void setEmergresidentind(int emergresidentind) {
this.emergresidentind = emergresidentind;
}
#Override
public void validate(){
super.validate();
validatePresenceOf("parentContactID", "Parent Contact is required.");
validatePresenceOf("childContactID", "Contact is required.");
validatePresenceOf("contactRelTypeID", "Resident relationship type is required.");
validatePresenceOf("effStartDate", "Effective Start Date is required.");
validatePresenceOf("relationshipid", "Relationship is required.");
if(this.getEffEndDate() != null) {
if(this.getEffEndDate().isBefore(this.getEffStartDate())) {
this.addError("effenddate", "End date must be on or after the start date.");
}
}
if(this.hasErrors()) {
throw new ValidationException(this);
}
}
}
Our CecilModel class we are extending the Model class.
package com.brookdale.model.activejdbc;
import java.io.IOException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.axis.utils.StringUtils;
import org.apache.log4j.Logger;
import org.javalite.activejdbc.Model;
import org.javalite.activejdbc.validation.ValidationBuilder;
import org.javalite.activejdbc.validation.ValidationException;
import org.javalite.activejdbc.validation.ValidatorAdapter;
import com.brookdale.core.CLArgs;
import com.brookdale.exception.CecilErrorsException;
import com.brookdale.message.CecilMessage;
import com.brookdale.model.Building;
import com.brookdale.security.bo.User;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import oracle.sql.DATE;
public abstract class CecilModel extends Model {
final static Logger logger = Logger.getLogger(CecilModel.class);
private static final transient TypeReference<HashMap<String, Object>> mapType = new TypeReference<HashMap<String, Object>>() {};
private static final transient TypeReference<ArrayList<HashMap<String, Object>>> listMapType = new TypeReference<ArrayList<HashMap<String, Object>>>() {};
//add -0600 to specify cental time zone
private static final transient SimpleDateFormat jsonDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
private transient Map<String, Collection<Map<String, Object>>> jsonInclude = new HashMap<>();
public Timestamp getUpdateDateTime() {
return getTimestamp("updateDateTime");
}
public void setUpdateDateTime(LocalDateTime updateDateTime) {
set("updateDateTime",updateDateTime == null ? null : Timestamp.valueOf(updateDateTime));
}
public Timestamp getCreateDateTime() {
return getTimestamp("createDateTime");
}
public void setCreateDateTime(LocalDateTime createDateTime) {
set("createDateTime",createDateTime == null ? null : Timestamp.valueOf(createDateTime));
}
public String getUpdateUsername() {
return getString("updateUsername");
}
public void setUpdateUsername(String updateUsername) {
set("updateUsername",updateUsername);
}
public String getCreateUsername() {
return getString("createUsername");
}
public void setCreateUsername(String createUsername) {
set("createUsername",createUsername);
}
public Long getUpdateTimeId() {
return getLong("updatetimeid");
}
public void setUpdateTimeId(Long updateTimeId) {
if (updateTimeId == null)
setLong("updatetimeid", 1);
else
setLong("updatetimeid",updateTimeId);
}
public void incrementUpdateTimeId() {
Long updatetimeid = this.getUpdateTimeId();
if (updatetimeid == null)
this.setUpdateTimeId(1L);
else
this.setUpdateTimeId(updatetimeid+1L);
}
public boolean save(User user) {
String userId = (CLArgs.args.isAuthenabled()) ? user.getUserid() : "TEST_MODE";
// insert
java.sql.Timestamp now = java.sql.Timestamp.valueOf(java.time.LocalDateTime.now());
if (this.getId() == null || this.getId().toString().equals("0")) {
this.setId(null);
this.set("createDateTime", now);
this.set("createUsername", userId);
this.set("updateDateTime", now);
this.set("updateUsername", userId);
this.set("updateTimeId", 1);
}
// update
else {
Long updatetimeid = this.getLong("updateTimeid");
this.set("updateDateTime", now);
this.set("updateUsername", userId);
this.set("updateTimeId", updatetimeid == null ? 1 : updatetimeid + 1);
}
return super.save();
}
public boolean saveIt(User user) {
String userId = (CLArgs.args.isAuthenabled()) ? user.getUserid() : "TEST_MODE";
// insert
java.sql.Timestamp now = java.sql.Timestamp.valueOf(java.time.LocalDateTime.now());
if (this.isNew()) {
this.setId(null);
this.set("createDateTime", now);
this.set("createUsername", userId);
this.set("updateDateTime", now);
this.set("updateUsername", userId);
this.set("updateTimeId", 1);
}
// update
else {
Long updatetimeid = this.getLong("updateTimeid");
this.set("updateDateTime", now);
this.set("updateUsername", userId);
this.set("updateTimeId", updatetimeid == null ? 1 : updatetimeid + 1);
}
return super.saveIt();
}
public boolean saveModel(User user, boolean insert) {
return saveModel(user.getUserid(), insert);
}
public boolean saveModel(String userId, boolean insert) {
userId = (CLArgs.args.isAuthenabled()) ? userId : "TEST_MODE";
if(insert){
return this.insertIt(userId);
}else{
return this.updateIt(userId);
}
}
public boolean insertIt(String user) {
user = (CLArgs.args.isAuthenabled()) ? user : "TEST_MODE";
// insert
java.sql.Timestamp now = java.sql.Timestamp.valueOf(java.time.LocalDateTime.now());
this.set("createDateTime", now);
this.set("createUsername", user);
this.set("updateDateTime", now);
this.set("updateUsername", user);
this.set("updateTimeId", 1);
this.validate();
if(this.hasErrors()){
throw new ValidationException(this);
}
boolean inserted = super.insert();
if (!inserted)
throw new CecilErrorsException(new CecilMessage().error("Failed to insert " + this.getClass().getSimpleName()));
return inserted;
}
public boolean updateIt(String user) {
user = (CLArgs.args.isAuthenabled()) ? user : "TEST_MODE";
// update
java.sql.Timestamp now = java.sql.Timestamp.valueOf(java.time.LocalDateTime.now());
this.set("updateDateTime", now);
this.set("updateUsername", user);
this.incrementUpdateTimeId();
this.validate();
if(this.hasErrors()){
throw new ValidationException(this);
}
boolean updated = super.save();
if (!updated)
throw new CecilErrorsException(new CecilMessage().error("Failed to update " + this.getClass().getSimpleName()));
return updated;
}
#Override
public <T extends Model> T set(String field, Object value) {
if (value instanceof LocalDate) {
return super.set(field, java.sql.Date.valueOf((LocalDate)value));
} else if (value instanceof LocalDateTime) {
return super.set(field, java.sql.Timestamp.valueOf((LocalDateTime)value));
} else {
return super.set(field, value);
}
}
public LocalDate getLocalDate(String field) {
if (field == null || "".equals(field))
return null;
else {
java.sql.Date d = getDate(field);
return d == null ? null : d.toLocalDate();
}
}
public void setLocalDate(String field, LocalDate value) {
if (value == null)
setDate(field, null);
else
setDate(field, java.sql.Date.valueOf(value));
}
public LocalDateTime getLocalDateTime(String field) {
java.sql.Timestamp d = getTimestamp(field);
return d == null ? null : d.toLocalDateTime();
}
public void setLocalDateTime(String field, LocalDateTime value) {
if (value == null)
setTimestamp(field, null);
else
setTimestamp(field, java.sql.Timestamp.valueOf(value));
}
}
The method Model.saveIt() will save the model attributes to a table if such a record (according to primary keys) already exists. If you are setting the primary keys to values not found in the database, this method will exit without doing much.
Additionally, there are a few issues in your code that are not idiomatic of JavaLite.
Update: based on your comment below, the framework will update the record if it is not "new", meaning if the PK or Composite Keys are not null, it will assume that you know what you are doing and will expect to find that record in the table by primary or composite keys, therefore if they key(s) are set and not null, it will always generate an UPDATE rather than insert. As a result, if you are setting primary keys to values not present in the table, the saveIt() or save() will do nothing. Please, see http://javalite.io/surrogate_primary_keys for more information.
Additionally, you can enable Logging to see what SQL it generates.

Why is my Udp.send using Akka.io always getting timeout?

Executing this code always results in timeout error and never sending UDP packet.
Why?
I need to write somthing more because stackoverflow won't let me to send the question... ;-), but I think the question is very simple and the code is all needed.
package controllers;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.UntypedActor;
import akka.dispatch.Recover;
import akka.io.Tcp;
import akka.io.Udp;
import akka.io.UdpMessage;
import akka.japi.Procedure;
import akka.util.ByteString;
import java.net.InetSocketAddress;
import static akka.pattern.Patterns.ask;
import play.libs.Akka;
import play.mvc.Result;
import play.libs.F.Function;
import play.libs.F.Promise;
import play.mvc.*;
public class Application extends Controller {
static ActorRef myActor = Akka.system().actorOf(Props.create(Listener.class));
public static Result index() {
return async(
Akka.asPromise(
//Promise.wrap(
ask(
myActor,
UdpMessage.send(ByteString.fromString("esto es una prueba"), new InetSocketAddress("172.80.1.81", 21001)),
1000
)
// .recover(
// new Recover<Object>() {
// #Override
// public Object recover(Throwable t) throws Throwable {
// if( t instanceof AskTimeoutException ) {
// Logger.error("Got exception: ", t);
// return internalServerError("Timeout");
// }
// else {
// Logger.error("Got exception: ", t);
// return internalServerError("Got Exception: " + t.getMessage());
// }
// }
// })
).map(
new Function<Object,Result>() {
public Result apply(Object response) {
return ok(response.toString());
}
}
)
);
}
//http://doc.akka.io/docs/akka/2.2-M2/java/io.html
//https://gist.github.com/kafecho/5353393
//how to terminate actor on shutdown http://stackoverflow.com/questions/10875101/how-to-stop-an-akka-thread-on-shutdown
public static class Listener extends UntypedActor {
final ActorRef nextActor;
public Listener() {
this(null);
}
public Listener(ActorRef nextActor) {
this.nextActor = nextActor;
// request creation of a bound listen socket
final ActorRef mgr = Udp.get(getContext().system()).getManager();
mgr.tell(UdpMessage.bind(getSelf(), new InetSocketAddress("localhost",
31001)), getSelf());
}
#Override
public void onReceive(Object msg) {
if (msg instanceof Udp.Bound) {
final Udp.Bound b = (Udp.Bound) msg;
getContext().become(ready(getSender()));
} else
unhandled(msg);
}
private Procedure<Object> ready(final ActorRef socket) {
return new Procedure<Object>() {
#Override
public void apply(Object msg) throws Exception {
if (msg instanceof Udp.Received) {
final Udp.Received r = (Udp.Received) msg;
// echo server example: send back the data
socket.tell(UdpMessage.send(r.data(), r.sender()),
getSelf());
// or do some processing and forward it on
final Object processed = new Object();//TODO parse data etc., e.g. using PipelineStage
if(nextActor!=null){
nextActor.tell(processed, getSelf());
}
} else if (msg.equals(UdpMessage.unbind())) {
socket.tell(msg, getSelf());
} else if (msg instanceof Udp.Unbound) {
getContext().stop(getSelf());
} else if (msg instanceof Udp.Send){
socket.tell(msg, getSelf());
} else
unhandled(msg);
}
};
}
}
}

How to build a custom draw2d layoutmanager?

I would like to have a layout manager that can arrange two elements as follows:
one main element ABCDEF centered
one "postscript" element XYZ, positioned on the top right corner of the encapsulating figure
For example:
***********XYZ*
* ABCDEF *
***************
Can I use an existing layoutmanager for this? How do I build a custom layout manager that supports it?
Many thanks for your advice.
You can do that by using XYLayout.
There is a sample you can build on:
import org.eclipse.draw2d.AbstractLayout;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LayoutManager;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.Panel;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.PrecisionRectangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class HHH {
public static void main(String[] args) {
Display d = new Display();
Shell s = new Shell();
s.setLayout(new FillLayout());
FigureCanvas canvas = new FigureCanvas(s);
Figure content = new Figure();
content.setLayoutManager(new XYLayout());
PostScriptedFigure figure = new PostScriptedFigure();
content.add(figure, new Rectangle(100, 100, -1, -1));
figure.setMainFigure(new Label("The Main figure"));
figure.setPostScriptFigure(new Label("ps"));
figure.setBorder(new LineBorder());
canvas.setContents(content);
s.setSize(600, 500);
s.open();
while (!s.isDisposed()) {
if (!d.readAndDispatch()) {
d.sleep();
}
}
}
}
class PostScriptedFigure extends Panel {
private IFigure mainFigure, postScriptFigure;
private class PostScriptedLayoutManager extends AbstractLayout {
#Override
public void layout(IFigure container) {
final Rectangle clientArea = container.getClientArea();
final IFigure mainFigure = getMainFigure();
final IFigure postScriptFigure = getPostScriptFigure();
if (mainFigure != null) {
final Rectangle bounds = new PrecisionRectangle();
bounds.setSize(mainFigure.getPreferredSize(SWT.DEFAULT, SWT.DEFAULT));
final Rectangle mainClientArea = clientArea.getCopy();
if (postScriptFigure != null) {
mainClientArea.shrink(new Insets(postScriptFigure.getPreferredSize().height(), 0, 0, 0));
}
bounds.translate(mainClientArea.getCenter().getTranslated(bounds.getSize().getScaled(0.5f).getNegated()));
mainFigure.setBounds(bounds);
}
if (postScriptFigure != null) {
final Rectangle bounds = new PrecisionRectangle();
bounds.setSize(postScriptFigure.getPreferredSize(SWT.DEFAULT, SWT.DEFAULT));
bounds.translate(clientArea.getTopRight().getTranslated(bounds.getSize().getNegated().width(), 0));
postScriptFigure.setBounds(bounds);
}
// note that other potentionally added figures are ignored
}
#Override
protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) {
final Rectangle rect = new PrecisionRectangle();
final IFigure mainFigure = getMainFigure();
if (mainFigure != null) {
rect.setSize(mainFigure.getPreferredSize());
}
final IFigure postScriptFigure = getPostScriptFigure();
if (postScriptFigure != null) {
rect.resize(mainFigure != null ? 0 : postScriptFigure.getPreferredSize().width() , postScriptFigure.getPreferredSize().height());
}
// note that other potentionally added figures are ignored
final Dimension d = rect.getSize();
final Insets insets = container.getInsets();
return new Dimension(d.width + insets.getWidth(), d.height + insets.getHeight()).union(getBorderPreferredSize(container));
}
}
public PostScriptedFigure() {
super.setLayoutManager(new PostScriptedLayoutManager());
}
#Override
public void setLayoutManager(LayoutManager manager) {
// prevent from setting wrong layout manager
}
public IFigure getMainFigure() {
return mainFigure;
}
public void setMainFigure(IFigure mainFigure) {
if (getMainFigure() != null) {
remove(getMainFigure());
}
this.mainFigure = mainFigure;
add(mainFigure);
}
public IFigure getPostScriptFigure() {
return postScriptFigure;
}
public void setPostScriptFigure(IFigure postScriptFigure) {
if (getPostScriptFigure() != null) {
remove(getPostScriptFigure());
}
this.postScriptFigure = postScriptFigure;
add(postScriptFigure);
}
}