AEM Query Builder: Implementing PredicateEvaluator for ordering only - aem

I'm trying to implement PredicateEvaluator for ordering purpose only - no filtering.
So I started with:
public class OrderByTagPredicate implements PredicateEvaluator {
private static final Logger log = Logger.getLogger(OrderByTagPredicate.class.getSimpleName());
public OrderByTagPredicate() {
super();
}
#Override
public Comparator<Row> getOrderByComparator(final Predicate predicate, final EvaluationContext context) {
return new Comparator<Row>() {
#Override
public int compare(Row o1, Row o2) {
// TODO Auto-generated method stub
return 0;
}
};
}
#Override
public boolean canFilter(Predicate arg0, EvaluationContext arg1) {
return true;
}
#Override
public boolean canXpath(Predicate arg0, EvaluationContext arg1) {
return true;
}
#Override
public FacetExtractor getFacetExtractor(Predicate arg0, EvaluationContext arg1) {
return null;
}
#Override
public String[] getOrderByProperties(Predicate arg0, EvaluationContext arg1) {
return null;
}
#Override
public String getXPathExpression(Predicate arg0, EvaluationContext arg1) {
return null;
}
#Override
public boolean includes(Predicate arg0, Row arg1, EvaluationContext arg2) {
return true;
}
#Override
public boolean isFiltering(Predicate arg0, EvaluationContext arg1) {
return false;
}
}
I registered the predicate with:
query.registerPredicateEvaluator("orderbytag", new OrderByTagPredicate());
And added it the map: map.put("orderbytag","xxx"); which is then used to create a PredicateGroup.
I've tried to debug by putting breakpoints in all the methods from the OrderByTagPredicate class, but it seems like the methods "getOrderByComparator(...)" never got called.
Any clue?

Resolved by adding the following into the map:
map.put("orderby","orderbytag");
The orderby clause was missing. Adding this clause makes AEM use the so-called PredicateEvalutor ordering method to be executed!

When you just want to sort by a particular property, the easiest way to do it is to include an ordering predicate in the PredicateGroup you use to build your query. That way, you don't even need to worry about custom evaluators, since the default one will handle it for you.
Assuming you've already created "predicateGroup", and you want to sort by 'indexName' ascending, you would do:
Predicate orderPredicate = new Predicate(Predicate.ORDER_BY);
orderPredicate.set(Predicate.ORDER_BY, "#" + indexName);
orderPredicate.set(Predicate.PARAM_SORT, Predicate.SORT_ASCENDING);
predicateGroup.add(orderPredicate);

Related

How to work with PGpoint for Geolocation using PostgreSQL?

I found a lot of answers that suggest to use spatial data with Hibernate spatial data geolocation but I want to know if that is the best because I found that PostgreSQL works with PGpoint for GeoLocation. I implemented but it doesn't work because doesn't save.
ERROR: column "location" is of type point but expression is of type character varying
I have the same question but nobody answered him. So let me add other question below if nobody knows about this question.
As suggestion I'd want to know what is the best way to use Geo data on Spring Boot Context
Thanks! have a good day.
There is no way to save/update/get/ PGpoint object directly,
Then you have to create your own user type for supporting PGpoint in order to convert it, before this is saved, UserType is a class of Hibernate which allows to create custom type in order to convert it before to save on database.
Here is code that you need to implement:
First: Need to create a class that implements of UserType:
public class PGPointType implements UserType {
#Override
public int[] sqlTypes() {
return new int[]
{
Types.VARCHAR
};
}
#SuppressWarnings("rawtypes")
#Override
public Class<PGpoint> returnedClass() {
return PGpoint.class;
}
#Override
public boolean equals(Object obj, Object obj1) {
return ObjectUtils.equals(obj, obj1);
}
#Override
public int hashCode(Object obj) {
return obj.hashCode();
}
#Override
public Object nullSafeGet(ResultSet resultSet, String[] names, SharedSessionContractImplementor sharedSessionContractImplementor, Object o) throws SQLException {
if (names.length == 1) {
if (resultSet.wasNull() || resultSet.getObject(names[0]) == null) {
return null;
} else {
return new PGpoint(resultSet.getObject(names[0]).toString());
}
}
return null;
}
#Override
public void nullSafeSet(PreparedStatement statement, Object value, int index, SharedSessionContractImplementor sharedSessionContractImplementor) throws SQLException {
if (value == null) {
statement.setNull(index, Types.OTHER);
} else {
statement.setObject(index, value, Types.OTHER);
}
}
#Override
public Object deepCopy(Object obj) {
return obj;
}
#Override
public boolean isMutable() {
return Boolean.FALSE;
}
#Override
public Serializable disassemble(Object obj) {
return (Serializable) obj;
}
#Override
public Object assemble(Serializable serializable, Object obj) {
return serializable;
}
#Override
public Object replace(Object obj, Object obj1, Object obj2) {
return obj;
}
}
Second: Need to add on entity header #TypeDef annotation, add a name and the PGPointType that you created it and on some field header of type PGpoint, add #Type annotation with the name that you created it:
#TypeDef(name = "type", typeClass = PGPointType.class)
#Entity
public class Entity {
#Type(type = "type")
private PGpoint pgPoint;
// Getters and setters
}
Kind regards.

Unable to subscribe to topic in KURA

I am writing sample Kura application in Java. But i am not able to receive message on subscribing to the topic .
In Kura web-UI:
LWT.topic attribute is :
$EDC/#account-name/#client-id (Eg: acc-name = "acc" client-id="client1")
I am publishing from client using topic
$EDC/acc/client1
But i am not receiving the message from the topic i.e following methods will never called
onControlMessageArrived() onMessageArrived()
But only there is a message on Kura.log as message arrived on topic $EDC/acc/client1 but not entering into methods onControlMessageArrived() onMessageArrived()
Code snippet:
public class ConfigurableExample implements ConfigurableComponent, CloudClientListener {
private static final Logger s_logger = LoggerFactory.getLogger(ConfigurableExample.class);
private static final String APP_ID = "Sample";
private CloudService m_cloudService;
private CloudClient m_cloudClient;
public void setCloudService(CloudService cloudService) {
s_logger.info("============================setCloudService============================{}" , cloudService!=null);
m_cloudService = cloudService;
}
public void unsetCloudService(CloudService cloudService) {
m_cloudService = null;
}
protected void activate(ComponentContext componentContext) {
s_logger.info("======================activate()===========================");
try {
if(m_cloudService==null)
throw new KuraException(KuraErrorCode.CONFIGURATION_ATTRIBUTE_INVALID);
if(m_cloudClient==null) {
m_cloudClient = m_cloudService.newCloudClient(APP_ID);
m_cloudClient.addCloudClientListener(this);
s_logger.info("===================={}================",m_cloudService.isConnected());
}
}
catch (KuraException e) {
s_logger.info("============================Exception============================ {}" , e.getMessage());
}
}
protected void deactivate(ComponentContext componentContext) {
s_logger.info("Bundle " + APP_ID + " has stopped!");
}
#Override
public void onConnectionEstablished() {
}
#Override
public void onConnectionLost() {
}
#Override
public void onControlMessageArrived(String arg0, String arg1, KuraPayload arg2, int arg3, boolean arg4) {
s_logger.info("++++++++++++++++++++++onControlMessageArrived with Parameters {},{},{},{},{} ++++++++++++++++++++",arg0, arg1,new String(arg2.getBody()),arg3,arg4);
}
#Override
public void onMessageArrived(String arg0, String arg1, KuraPayload arg2, int arg3, boolean arg4) {
s_logger.info("++++++++++++++++++++++onMessageArrived with Parameters {},{},{},{},{} ++++++++++++++++++++",arg0, arg1,new String(arg2.getBody()),arg3,arg4);
}
#Override
public void onMessageConfirmed(int arg0, String arg1) {
// TODO Auto-generated method stub
}
#Override
public void onMessagePublished(int arg0, String arg1) {
// TODO Auto-generated method stub
}
}

Simplest way to migrate from older JPA to newer with version with Query.getResultList() returning List<Object[]> instead of List<Vector>

We're currently researching the best way to upgrade from Toplink 2.1-60f to EclipseLink 2.6. The project is somewhat large and most of the manual work would have to be done in parts of the code where we are using NativeQuery. Query.getResultList() result differs between the two JPA-implementations as TopLink returns a List<Vector> and EclipseLink on the other hand returns a List<Object[]>. The code is unfortunately therefore littered with List<Vector> references.
Part of the solution would be to convert the result from list array to a list of vectors. Instead of doing this in all the numerous places manually, I was thinking we could use AspectJ to intercept the getResultList() calls and convert the return values. Is this a viable solution? Has anyone implemented similar solutions? We're using Maven as our build tool.
Thanks in advance!
My suggestion is: Use a good IDE and refactor your code!
But because you asked for an AOP solution, here is a self-consistent AspectJ example. As I have never used JPA, I will just recreate your situation as a little abstraction.
Abstract Query base implementation with lots of dummy methods:
package de.scrum_master.persistence;
import java.util.*;
import javax.persistence.*;
public abstract class MyBaseQueryImpl implements Query {
#Override public int executeUpdate() { return 0; }
#Override public int getFirstResult() { return 0; }
#Override public FlushModeType getFlushMode() { return null; }
#Override public Map<String, Object> getHints() { return null; }
#Override public LockModeType getLockMode() { return null; }
#Override public int getMaxResults() { return 0; }
#Override public Parameter<?> getParameter(String arg0) { return null; }
#Override public Parameter<?> getParameter(int arg0) { return null; }
#Override public <T> Parameter<T> getParameter(String arg0, Class<T> arg1) { return null; }
#Override public <T> Parameter<T> getParameter(int arg0, Class<T> arg1) { return null; }
#Override public <T> T getParameterValue(Parameter<T> arg0) { return null; }
#Override public Object getParameterValue(String arg0) { return null; }
#Override public Object getParameterValue(int arg0) { return null; }
#Override public Set<Parameter<?>> getParameters() { return null; }
#Override public Object getSingleResult() { return null; }
#Override public boolean isBound(Parameter<?> arg0) { return false; }
#Override public Query setFirstResult(int arg0) { return null; }
#Override public Query setFlushMode(FlushModeType arg0) { return null; }
#Override public Query setHint(String arg0, Object arg1) { return null; }
#Override public Query setLockMode(LockModeType arg0) { return null; }
#Override public Query setMaxResults(int arg0) { return null; }
#Override public <T> Query setParameter(Parameter<T> arg0, T arg1) { return null; }
#Override public Query setParameter(String arg0, Object arg1) { return null; }
#Override public Query setParameter(int arg0, Object arg1) { return null; }
#Override public Query setParameter(Parameter<Calendar> arg0, Calendar arg1, TemporalType arg2) { return null; }
#Override public Query setParameter(Parameter<Date> arg0, Date arg1, TemporalType arg2) { return null; }
#Override public Query setParameter(String arg0, Calendar arg1, TemporalType arg2) { return null; }
#Override public Query setParameter(String arg0, Date arg1, TemporalType arg2) { return null; }
#Override public Query setParameter(int arg0, Calendar arg1, TemporalType arg2) { return null; }
#Override public Query setParameter(int arg0, Date arg1, TemporalType arg2) { return null; }
#Override public <T> T unwrap(Class<T> arg0) { return null; }
}
The only method missing is getResultList(), so now let us provide two different implementations for it, extending the abstract base implementation:
Concrete Query implementation returning List<Vector>:
This emulates your TopLink class.
package de.scrum_master.persistence;
import java.util.*;
public class VectorQuery extends MyBaseQueryImpl {
#Override
public List getResultList() {
List<Vector<String>> resultList = new ArrayList<>();
Vector<String> result = new Vector<>();
result.add("foo"); result.add("bar");
resultList.add(result);
result = new Vector<>();
result.add("one"); result.add("two");
resultList.add(result);
return resultList;
}
}
Concrete Query implementation returning List<Object[]>:
This emulates your EclipseLink class.
package de.scrum_master.persistence;
import java.util.*;
public class ArrayQuery extends MyBaseQueryImpl {
#Override
public List getResultList() {
List<Object[]> resultList = new ArrayList<>();
Object[] result = new Object[] { "foo", "bar" };
resultList.add(result);
result = new Object[] { "one", "two" };
resultList.add(result);
return resultList;
}
}
Driver application:
The application creates queries of both concrete subtypes, each time assuming that the list elements will be vectors.
package de.scrum_master.app;
import java.util.*;
import de.scrum_master.persistence.*;
public class Application {
public static void main(String[] args) {
List<Vector<?>> resultList;
resultList = new VectorQuery().getResultList();
for (Vector<?> result : resultList)
System.out.println(result);
resultList = new ArrayQuery().getResultList();
for (Vector<?> result : resultList)
System.out.println(result);
}
}
Console log without aspect:
[foo, bar]
[one, two]
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to java.util.Vector
at de.scrum_master.app.Application.main(Application.java:15)
Uh-oh! This is exactly your problem, right? Now what can we do about it if we absolutely refuse to refactor? We abuse AOP for patching up the legacy code. (Please don't do it, but you can if you absolutely want to.)
AspectJ query result adapter:
Disregarding usage of raw types and other ugly stuff, here is my proof of concept:
package de.scrum_master.aspect;
import java.util.*;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class QueryResultAdapter {
#Around("call(* javax.persistence.Query.getResultList())")
public List<Vector> transformQueryResult(ProceedingJoinPoint thisJoinPoint) throws Throwable {
System.out.println(thisJoinPoint);
List result = (List) thisJoinPoint.proceed();
if (result != null && result.size() > 0 && result.get(0) instanceof Vector)
return result;
System.out.println("Transforming arrays to vectors");
List<Vector> transformedResult = new ArrayList<Vector>();
for (Object[] arrayItem : (List<Object[]>) result)
transformedResult.add(new Vector(Arrays.asList(arrayItem)));
return transformedResult;
}
}
Console log with aspect:
call(List de.scrum_master.persistence.VectorQuery.getResultList())
[foo, bar]
[one, two]
call(List de.scrum_master.persistence.ArrayQuery.getResultList())
Transforming arrays to vectors
[foo, bar]
[one, two]
Et voilĂ  - you can do ugly stuff and other things it was not invented for with AOP. ;-)

GXT 3 - The value of "Object" is null for a class which implements HasCell<C,T>

I am trying to implement HasCell(C,T) in GXT 3. But, the overridden functions which uses object of type C is null.
public class ImageCell implements HasCell<SensorTreeModel, ImageResource>{
private ClickableImageResourceCell imageCell = new ClickableImageResourceCell();
private TextButtonCell textCell = new TextButtonCell();
#Override
public Cell<ImageResource> getCell() {
// TODO Auto-generated method stub
return imageCell;
}
#Override
public FieldUpdater<SensorTreeModel, ImageResource> getFieldUpdater() {
// TODO Auto-generated method stub
return new FieldUpdater<SensorTreeModel, ImageResource>() {
#Override
public void update(int index, SensorTreeModel object, ImageResource value) {
object.getName();
Window.alert("image Clicked");
}
};
}
#Override
public ImageResource getValue(SensorTreeModel object) {
// TODO Auto-generated method stub
return com.sencha.project.client.Resources.INSTANCES.add();
}}
The value of object(SensorTreeModel) in getFieldUpdater as well as getValue are both null. Please do help. Thanks in advance! :)

Adding Hyperlink in GWT celltable

I am trying to add a hyperlink in celltable and on clicking on that link i want to call a method.
with the below code i am getting a hyperlink in my celltable correctly but I am not able to call a method by clicking on the link , when i click the link it takes me to the previous page.
Any Solution
Hyperlink link = new Hyperlink("Delete","");
Column<EmployerJobs, Hyperlink> linkColumn =
new Column<EmployerJobs, Hyperlink>(new HyperLinkCell()) {
#Override
public Hyperlink getValue(EmployerJobs list) {
link.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
deleteJobs(list);
}
});
return link;
}
});
Instead of a HyperlinkCell you can either use a ClickableTextCell, a ButtonCell or an ActionCell.
ClickableTextCell:
Column<EmployerJobs, String> linkColumn =
new Column<EmployerJobs, String>(new ClickableTextCell()) {
#Override
public String getValue(EmployerJobs object) {
return TEXT_TO_DISPLAY;
}
},'linkheadertext');
linkColumn.setFieldUpdater(new FieldUpdater<EmployerJobs, String>() {
#Override
public void update(int index, EmployerJobs object, String value) {
deleteJobs(object);
}
});
ButtonCell:
Column<EmployerJobs, String> buttonColumn =
new Column<EmployerJobs, String>(new ButtonCell()) {
#Override
public String getValue(EmployerJobs object) {
return TEXT_TO_DISPLAY;
}
},'linkheadertext');
buttonColumn.setFieldUpdater(new FieldUpdater<EmployerJobs, String>() {
#Override
public void update(int index, EmployerJobs object, String value) {
deleteJobs(object);
}
});
ActionCell:
Column<EmployerJobs, EmployerJobs> actionColumn =
new Column<EmployerJobs, EmployerJobs>(new ActionCell<EmployerJobs>("Click Me",
new ActionCell.Delegate<EmployerJobs>() {
#Override
public void execute(EmployerJobs jobs) {
deleteJobs(jobs);
}
})
{
#Override
public EmployerJobs getValue(EmployerJobs object) {
return object;
}
},'linkheadertext');
Check out the CellSample showcase for more infos.
I have post my answer on the similar thread:
How can I render a ClickableTextCell as an anchor in a GWT CellTable?
but for those who bookmarked this thread:
This is what you need
public class ClickableSafeHtmlCell extends AbstractCell<SafeHtml> {
/**
* Construct a new ClickableSafeHtmlCell.
*/
public ClickableSafeHtmlCell() {
super("click", "keydown");
}
#Override
public void onBrowserEvent(Context context, Element parent, SafeHtml value, NativeEvent event,
ValueUpdater<SafeHtml> valueUpdater) {
super.onBrowserEvent(context, parent, value, event, valueUpdater);
if ("click".equals(event.getType())) {
onEnterKeyDown(context, parent, value, event, valueUpdater);
}
}
#Override
protected void onEnterKeyDown(Context context, Element parent, SafeHtml value,
NativeEvent event, ValueUpdater<SafeHtml> valueUpdater) {
if (valueUpdater != null) {
valueUpdater.update(value);
}
}
#Override
public void render(Context context, SafeHtml value, SafeHtmlBuilder sb) {
if (value != null) {
sb.append(value);
}
}
And then usage:
Column<YourProxy, SafeHtml> nameColumn = new Column<YourProxy, SafeHtml>(
new ClickableSafeHtmlCell()) {
#Override
public SafeHtml getValue(YourProxy object) {
SafeHtmlBuilder sb = new SafeHtmlBuilder();
sb.appendHtmlConstant("<a>");
sb.appendEscaped(object.getName());
sb.appendHtmlConstant("</a>");
return sb.toSafeHtml();
}
};
nameColumn.setFieldUpdater(new FieldUpdater<YourProxy, SafeHtml>() {
#Override
public void update(int index, YourProxy object, SafeHtml value) {
Window.alert("You have clicked: " + object.getName());
}
});
As suggested in above answer you can use updater when you want inplace editing. But if you want to capture a click to perform some action, you can do it using ClickableTextCell.
ClickableTextCell employerJobsCell = new ClickableTextCell();
Column<EmployerJobs, String> employerJobsColumn = new Column<EmployerJobs, String>(employerJobsCell) {
#Override
public String getValue(EmployerJobs object) {
return object.getWhichStringToDisplay();
}
#Override
public void render(Context context, EmployerJobs object, SafeHtmlBuilder sb) {
//this method is optional, can be used if the display needs to be customized
}
#Override
public void onBrowserEvent(Context context, Element elem, EmployerJobs object, NativeEvent event) {
super.onBrowserEvent(context, elem, object, event);
Event evt = Event.as(event);
int eventType = evt.getTypeInt();
if (eventType == Event.ONCLICK) {
//call delete job when cell is clicked
deleteJobs(object);
}
}
};
dataGrid.addColumn(employerJobsColumn, "The header goes here");