/**
  * @throws Exception
  * @see de.fhg.fokus.cm.service.ComplaintService#getComplaint(java.lang.String)
  */
 private Complaint getComplaint(Long complaintId, boolean withoutCRP) throws Exception {
   final EntityManager entityManager = createEntityManager();
   final Complaint complaint = entityManager.find(Complaint.class, complaintId);
   logger.info("complaint [" + complaint.getId() + "] selected"); // $NON-NLS-1$ //$NON-NLS-2$
   if (withoutCRP) return refactorComplaint(complaint);
   return complaint;
 }
 private void setAvgRating(Complaint c) {
   Float avgRating = 0.0f;
   for (Rating r : c.getRatings().getRatings()) {
     avgRating += r.getValue();
     c.setAverageRating(avgRating / c.getRatings().getRatings().size());
   }
 }
 @Override
 public Comment deleteComplaintComment(Long complaintId, Long objectId) throws Exception {
   final EntityManager em = createEntityManager();
   Complaint c;
   Comment o = null;
   try {
     c = em.find(Complaint.class, complaintId);
     o = em.find(Comment.class, objectId);
     c.getComments().getComments().remove(o);
     em.remove(o);
     return o;
   } finally {
     // //em.close();
   }
 }
 @Override
 public Photo deleteComplaintPhoto(Long complaintId, Long objectId) throws Exception {
   final EntityManager em = createEntityManager();
   em.getTransaction().begin();
   Complaint c;
   Photo o = null;
   try {
     c = em.find(Complaint.class, complaintId);
     o = em.find(Photo.class, objectId);
     c.getPhotos().getPhotos().remove(o);
     em.remove(o);
     em.getTransaction().commit();
     return o;
   } finally {
     // em.close();
   }
 }
  /**
   * @param complaintAbbr
   * @return
   * @throws Exception
   */
  private String getOrderByClause(final String complaintAbbr, String orderBy, Boolean orderDesc)
      throws Exception {
    String ASC = "DESC";
    if (orderDesc == null || orderDesc == false) ASC = "ASC";

    if (orderBy == null || orderBy == "") orderBy = "id";
    Complaint c = new Complaint();
    c.getAverageRating();
    if (orderBy.equals("id")
        || orderBy.equals("averageRating")
        || orderBy.equals("title")
        || orderBy.equals("description")
        || orderBy.equals("userId")
        || orderBy.equals("tags"))
      return " ORDER BY " + complaintAbbr + "." + orderBy + " " + ASC; // $NON-NLS-1$ //$NON-NLS-2$
    else throw new Exception("orderBy=" + orderBy + " is not allowed");
  }
  /**
   * @throws Exception
   * @see de.fhg.fokus.cm.service.ComplaintService#deleteComplaint(java.lang.String)
   * @return null
   */
  @Override
  public Complaint deleteComplaint(Long complaintId) throws Exception {
    EntityManager em = createEntityManager();
    Complaint complaint;
    try {
      EntityTransaction tx = em.getTransaction();
      tx.begin();
      // TODO try to cascade the delete to comments, photos and ratings
      complaint = em.find(Complaint.class, complaintId);
      complaint.getComments().getComments().clear();

      //
      // try {
      // List<Comment> list = complaint.getComments().getComments();
      // for (Comment object : list)
      // this.deleteComplaintComment(complaintId, object.getId());
      // } catch (Exception e) {
      // // no Comments, nothing to do
      // }
      // try {
      // List<Photo> list = complaint.getPhotos().getPhotos();
      // for (Photo object : list)
      // this.deleteComplaintPhoto(complaintId, object.getId());
      // } catch (Exception e) {
      // // no Photos, nothing to do
      // }
      // try {
      // List<Rating> list = complaint.getRatings().getRatings();
      // for (Rating object : list)
      // this.deleteComplaintRating(complaintId, object.getId());
      // } catch (Exception e) {
      // // no Ratings, nothing to do
      // }

      String deleteComplaint =
          "DELETE " + Complaint.class.getName() + " c WHERE c.id = :complaintId";
      em.createQuery(deleteComplaint).setParameter("complaintId", complaintId).executeUpdate();
      logger.info("complaint [" + complaintId + "] deleted"); // $NON-NLS-1$ //$NON-NLS-2$
      tx.commit();
    } finally {
      // em.close();
    }
    return null;
  }
  @Override
  public Rating deleteComplaintRating(Long complaintId, Long objectId) throws Exception {
    final EntityManager em = createEntityManager();
    em.getTransaction().begin();
    Complaint c;
    Rating o = null;
    try {
      c = em.find(Complaint.class, complaintId);
      o = em.find(Rating.class, objectId);
      c.getRatings().getRatings().remove(o);
      em.remove(o);
      setAvgRating(c);
      em.getTransaction().commit();

      return o;
    } finally {
      // em.close();
    }
  }
  @Override
  public Photo addPhoto(Long complaintId, Photo photo) throws Exception {
    final EntityManager em = createEntityManager();
    try {
      em.getTransaction().begin();
      Complaint c = em.find(Complaint.class, complaintId);
      photo.setId(0);
      if (c.getPhotos() == null) c.setPhotos(new Complaint.Photos());
      c.getPhotos().getPhotos().add(photo);
      em.getTransaction().commit();

    } catch (Exception e) {
      // TODO
      e.printStackTrace();
    } finally {
      // em.close();
    }
    return photo;
  }
  @Override
  public Rating addRating(Long complaintId, Rating rating) throws Exception {
    final EntityManager em = createEntityManager();
    try {
      em.getTransaction().begin();
      Complaint c = em.find(Complaint.class, complaintId);
      rating.setId(0);
      if (c.getRatings() == null) c.setRatings(new Complaint.Ratings());

      c.getRatings().getRatings().add(rating);
      setAvgRating(c);
      em.getTransaction().commit();
    } catch (Exception e) {
      // TODO
      e.printStackTrace();
    } finally {
      // em.close();
    }
    return rating;
  }
  @Override
  public Comment addComment(Long complaintId, Comment comment) throws Exception {
    final EntityManager em = createEntityManager();
    try {
      em.getTransaction().begin();
      Complaint c = em.find(Complaint.class, complaintId);
      comment.setId(0);
      if (c.getComments() == null) c.setComments(new Complaint.Comments());

      c.getComments().getComments().add(comment);
      em.getTransaction().commit();

    } catch (Exception e) {
      // TODO
      e.printStackTrace();
    } finally {
      // em.close();
    }
    return comment;
  }
 @Override
 public Complaint addComplaint(Complaint complaint) throws Exception {
   final EntityManager em = createEntityManager();
   try {
     em.getTransaction().begin();
     em.persist(complaint);
     em.getTransaction().commit();
     logger.debug("complaint [" + complaint.getId() + "] inserted"); // $NON-NLS-1$ //$NON-NLS-2$
   } finally {
     em.close();
   }
   return refactorComplaint(complaint);
 }
 @Override
 public Ratings getRatings(Long complaintId, Integer limit, Integer offset, String userId)
     throws Exception {
   offset = ServiceHelper.checkOffset(offset);
   Ratings ratings = new Ratings();
   Complaint complaint = getComplaint(complaintId);
   List<Rating> allRatings = complaint.getRatings().getRatings();
   List<Rating> rl = allRatings;
   if (userId != null) {
     rl = new ArrayList<Rating>();
     for (Rating rating : allRatings) {
       if (userId.equals(rating.getUserId())) {
         rl.add(rating);
       }
     }
   }
   Integer newLimit = ServiceHelper.calcLimit(offset, limit, rl.size());
   ratings.setRatings(rl.subList(offset, offset + newLimit));
   ratings.setOffset(offset);
   ratings.setResult(newLimit);
   ratings.setTotal(rl.size());
   return ratings;
 }
 @Override
 public Photos getPhotos(Long complaintId, Integer limit, Integer offset, String userId)
     throws Exception {
   offset = ServiceHelper.checkOffset(offset);
   Photos photos = new Photos();
   Complaint complaint = getComplaint(complaintId);
   List<Photo> allPhotos = complaint.getPhotos().getPhotos();
   List<Photo> rl = allPhotos;
   if (userId != null) {
     rl = new ArrayList<Photo>();
     for (Photo photo : allPhotos) {
       if (userId.equals(photo.getUserId())) {
         rl.add(photo);
       }
     }
   }
   Integer newLimit = ServiceHelper.calcLimit(offset, limit, rl.size());
   photos.setPhotos(rl.subList(offset, offset + newLimit));
   photos.setOffset(offset);
   photos.setResult(newLimit);
   photos.setTotal(rl.size());
   return photos;
 }
 @Override
 public Comments getComments(Long complaintId, Integer limit, Integer offset, String userId)
     throws Exception {
   offset = ServiceHelper.checkOffset(offset);
   Comments comments = new Comments();
   Complaint complaint = getComplaint(complaintId);
   List<Comment> allComments = complaint.getComments().getComments();
   List<Comment> rl = allComments;
   if (userId != null) {
     rl = new ArrayList<Comment>();
     for (Comment comment : allComments) {
       if (userId.equals(comment.getUserId())) {
         rl.add(comment);
       }
     }
   }
   Integer newLimit = ServiceHelper.calcLimit(offset, limit, rl.size());
   comments.setComments(rl.subList(offset, offset + newLimit));
   comments.setOffset(offset);
   comments.setResult(newLimit);
   comments.setTotal(rl.size());
   return comments;
 }
 private Photo findPhoto(Complaint c, Long objectId) throws Exception {
   String objectName = "object"; // $NON-NLS-1$
   for (Photo o : c.getPhotos().getPhotos()) {
     objectName = o.getClass().getSimpleName();
     if (o.getId() == objectId) {
       logger.debug(
           objectName
               + " ["
               + objectId //$NON-NLS-1$
               + "] is attached to complaint ["
               + c.getId()
               + "]"); //$NON-NLS-1$ //$NON-NLS-2$
       return o;
     }
   }
   throw new Exception(
       objectName
           + " ["
           + objectId //$NON-NLS-1$
           + "] is NOT attached to complaint ["
           + c.getId()
           + "]"); //$NON-NLS-1$ //$NON-NLS-2$
 }
  /**
   * exact calculation
   *
   * @param c the Complaint
   * @param radius radius of area
   * @param latitude latitude of center of area
   * @param longitude longitude of center of area
   * @return true if complaint is in area
   */
  @SuppressWarnings("unused")
  private Boolean isComplaintInArea(Complaint c, Double radius, Double latitude, Double longitude) {

    // http://www.kompf.de/gps/distcalc.html
    final double EARTH_DIAMETER = 6378.388;
    double lat1 = latitude.doubleValue();
    double lon1 = longitude.doubleValue();
    double lat2 = c.getGeolocation().getLatitude();
    double lon2 = c.getGeolocation().getLongitude();

    if (radius
        > EARTH_DIAMETER
            * Math.acos(
                Math.sin(lat1) * Math.sin(lat2)
                    + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1))) return true;
    return false;
  }
 @Override
 public Complaint updateComplaint(Complaint complaint) throws Exception {
   final EntityManager em = createEntityManager();
   Complaint updateComplaint;
   try {
     em.getTransaction().begin();
     updateComplaint = em.find(Complaint.class, complaint.getId());
     if (updateComplaint != null) {
       // updating
       updateComplaint.setAddress(complaint.getAddress());
       updateComplaint.setAverageRating(complaint.getAverageRating());
       updateComplaint.setCategory(complaint.getCategory());
       updateComplaint.setComments(complaint.getComments());
       updateComplaint.setCreationTime(complaint.getCreationTime());
       updateComplaint.setDescription(complaint.getDescription());
       updateComplaint.setGeolocation(complaint.getGeolocation());
       updateComplaint.setPhotos(complaint.getPhotos());
       updateComplaint.setRatings(complaint.getRatings());
       updateComplaint.setStatus(complaint.getStatus());
       updateComplaint.setTags(complaint.getTags());
       updateComplaint.setTitle(complaint.getTitle());
       updateComplaint.setUserId(complaint.getUserId());
       em.merge(updateComplaint);
       logger.debug("complaint [" + complaint.getId() + "] updated"); // $NON-NLS-1$ //$NON-NLS-2$
     } else {
       throw new Exception(
           "complaint ["
               + complaint.getId() // $NON-NLS-1$
               + "] not found"); //$NON-NLS-1$
     }
     em.getTransaction().commit();
   } finally {
     em.close();
   }
   return refactorComplaint(updateComplaint);
 }
 /**
  * sets properties comments, ratings and photos to null
  *
  * @param c the complete complaint
  * @return the complaint without comments, ratings and photos
  */
 private Complaint refactorComplaint(Complaint c) {
   c.setComments(null);
   c.setRatings(null);
   c.setPhotos(null);
   return c;
 }