5

I'm trying to figure out how I can go about finding members of a list - but only ones that haven't past their expired date - which is one of the properties of the model.

Right now I have:

public static Result getAllNotifications() {
 List<Notification> notifications = Notification.getAllNotifications();

 for (Notification i: notifications) {
     List<Attachments> attachments = Attachments.findAllById(i.id);
     i.attached = attachments;
 }

    return ok(toJson(notifications));
}

Somewhere in there I need to check the expiration date of an individual notification and not return it if today is past that date.

Right now that model for a notificatin looks like this:

public class Notification extends Model {

/**
 * 
 */
private static final long serialVersionUID = 1L;

@Id
@NonEmpty
public Long id;

@Constraints.Required
public String title;

@Formats.DateTime(pattern = "dd/MM/yyyy")
public Date created = new Date();

@Constraints.Required
@Column(columnDefinition="TEXT")
public String text;

@Formats.DateTime(pattern = "dd/MM/yyyy")
public Date updated = new Date();

public Boolean status;

public Date expires;

public String author;

public List<Attachments> attached;

public Notification() {
}

public Notification(Long id, String title, String text) {
    this.created = new Date();
    this.title = title;
    this.text = text;
    this.id = id;
}

public static Model.Finder<String, Notification> find = new Model.Finder<String,     Notification>(String.class, Notification.class);

This is my first ever Stackoverflow post so go easy on me! And thank you, in advance, for the help!

tereško
  • 58,060
  • 25
  • 98
  • 150
pixelworlds
  • 818
  • 2
  • 11
  • 22

2 Answers2

5

Hm, you're looking for all rows which expires date is bigger than current one OR it's null (not set), right?

In such case you can just use simple DB comparission (iterating whole resultset is definitely WRONG idea!)

  • gt stands for Greater Than
  • lt for Lower Than

in your model add finders:

// If expires date is grater than current one, the Notification IS expired
public static List<Notification> findAllExpired() {
    return find.where().gt("expires", new Date()).findList();
}

// If expires date is lower than current one OR isn't set at all,
// the Notification is valid.
public static List<Notification> findAllNotExpired() {
    return find.where().or(
              Expr.lt("expires", new Date()),
              Expr.isNull("expires")
           ).findList();
}

So you'll get the list not expired (or not expired) notifications in your controller:

List<Notification> notExpiredList = Notification.findAllNotExpired();

// check in terminal
for (Notification notification : notExpiredList) {
    Logger.info("This Notification IS NOT expired: " + notification.title);
}

List<Notification> expiredList = Notification.findAllExpired();

// check in terminal
for (Notification notification : expiredList) {
    Logger.warn("This Notification IS expired: " + notification.title);
}
biesior
  • 55,576
  • 10
  • 125
  • 182
1

You could use an iterator and remove all notifications that are expired.

something like this:

    public static Result getAllNotifications() {
      List<Notification> notifications = Notification.getAllNotifications();

      Iterator<Notification> iterator = notifications.iterator();

      while (iterator.hasNext()) {
        Notification next = iterator.next();
        if (new Date().after(next.expires)) {
            iterator.remove();
        }
      }


      for (Notification i: notifications) {
        List<Attachments> attachments = Attachments.findAllById(i.id);
        i.attached = attachments;
      }

      return ok(toJson(notifications));
  }

if the List is immutable you could return a filtered copy of it.

Jonas Adler
  • 905
  • 5
  • 9
  • you may eventually encounter a OutOfMemoryException, since you load a lot of objects in the memory. – ndeverge Nov 14 '12 at 15:28
  • That worked absolutely perfectly Jonas!! Many, many thanks for your help my friend! – pixelworlds Nov 14 '12 at 19:43
  • 1
    Consider what will happen if you'll try to check 3 millions notifications that way... – biesior Nov 14 '12 at 22:36
  • 3
    @pixelworlds you should go with the solution `biesior` suggested. My solution is the quick and dirty version. The proper way of doing it is what `biesior` wrote. I didn't go into the details of the play framework way of accessing a SQL database. What you want to do is exactly what databases are made for, so you should use their features. Thanks for your answer (and comment) `biesior` – Jonas Adler Nov 14 '12 at 23:39