/* * FinTP - Financial Transactions Processing Application * Copyright (C) 2013 Business Information Systems (Allevo) S.R.L. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> * or contact Allevo at : 031281 Bucuresti, 23C Calea Vitan, Romania, * phone +40212554577, office@allevo.ro <mailto:office@allevo.ro>, www.allevo.ro. */ package ro.allevo.fintpws.util; import java.io.FileNotFoundException; import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.Time; import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.Metamodel; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.PathSegment; import javax.ws.rs.core.UriInfo; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; /** * @author costi * @version $Revision: 1.0 $ */ public final class ResourcesUtils { /** * Field logger. */ private static Logger logger = LogManager.getLogger(ResourcesUtils.class .getName()); /** * Field ENTITYMETHODSET. (value is ""set"") */ static final String ENTITYMETHODSET = "set"; /** * Field ENTITYMETHODGET. (value is ""get"") */ static final String ENTITYMETHODGET = "get"; /** * Field logger. */ // private static Logger logger = LogManager.getLogger(ResourcesUtils.class // .getName()); /** * Field LINK_HREF. (value is ""href"") */ static final String LINK_HREF = "href"; /** * Field LINK_REL. (value is ""rel"") */ static final String LINK_REL = "rel"; /** * Field SORT_FIELD. (value is ""sort_field"") */ static final String SORT_FIELD = "sort_field"; /** * Field SORT_ORDER. (value is ""sort_order"") */ static final String SORT_ORDER = "sort_order"; /** * Field SORT_ORDER_TYPE. (value is ""descending"") */ static final String SORT_ORDER_TYPE = "descending"; /** * Field FILTER. (value is ""filter_"") */ static final String FILTER = "filter_"; /** * Field FILTER_TYPE_EXACT. (value is ""_exact"") */ static final String FILTER_TYPE_EXACT = "_exact"; /** * Field FILTER_TYPE_CONTAINS. (value is ""_contains"") */ static final String FILTER_TYPE_CONTAINS = "_contains"; /** * Field FILTER_TYPE_END. (value is ""_end"") */ static final String FILTER_TYPE_END = "_end"; /** * Field ERROR_REASON_REFLECTION_ERROR. (value is ""Something bad happened * when reflecting"") */ static final String ERROR_REASON_REFLECTION_ERROR = "Something bad happened when reflecting"; /** * Constructor for ResourcesUtils. */ private ResourcesUtils() { } /** * Method optTimestamp. Converts a string value to a timestamp if the string * is not empty. Returns null otherwise. * * @param stringTime * String * @return Timestamp Returns null if the input string is null or empty. * @throws ParseException */ public static Timestamp optTimestamp(String stringTime) throws ParseException { if ((null == stringTime) || (stringTime.isEmpty())) { return null; } return new Timestamp(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") .parse(stringTime).getTime()); } /** * Method optTime.Converts a string value to a time if the string is not * empty. Returns null otherwise. * * @param stringTime * String * @return Time * @throws ParseException */ public static Timestamp optTime(String stringTime) throws ParseException { if ((null == stringTime) || (stringTime.isEmpty())) { return null; } return new Timestamp(new SimpleDateFormat("hh:mm:ss").parse(stringTime) .getTime()); } /** * Method asTimestampMandatory. Converts a string value to a timestamp. * * @param stringTime * String * @return Timestamp Returns curent time if the input string is null or * empty. * @throws ParseException */ public static Timestamp getTimestamp(String stringTime) throws ParseException { Timestamp finalTimestamp = optTimestamp(stringTime); return (null == finalTimestamp) ? new Timestamp( System.currentTimeMillis()) : finalTimestamp; } public static String getIsoDateFromTimestamp(Timestamp timestamp){ if(null == timestamp) return null; return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") .format(timestamp); } /** * Method getTime. * * @param stringTime * String * @return Time * @throws ParseException */ public static String getISODate(Date date) throws ParseException { return new SimpleDateFormat("yyyy-MM-dd").format(date); } /** * Method getTime. * * @param stringTime * String * @return Time * @throws ParseException */ public static Timestamp getTime(String stringTime) throws ParseException { Timestamp finalTimestamp = optTime(stringTime); return (null == finalTimestamp) ? new Timestamp(System.currentTimeMillis()) : finalTimestamp; } /** * Method blankIfNull. * * @param object * Object * @return Object */ public static Object blankIfNull(Object object) { return (null == object) ? "" : object; } /** * Method getQueryParamValue. Returns the value of the query parameter named * queryParamName from URI uriInfo. * * @param uriInfo * UriInfo * @param queryParamName * String * * @return String Null if the parameter with name queryParamName can not be * found. */ public static String getQueryParamValue(UriInfo uriInfo, String queryParamName) { MultivaluedMap<String, String> parameters = uriInfo .getQueryParameters(); if (parameters.containsKey(queryParamName)) { return parameters.getFirst(queryParamName); } return null; } /** * Method createLink. * * @param baseObject * JSONObject * @param href * String * @param rel * String * @return JSONObject * @throws JSONException */ public static JSONObject createLink(JSONObject baseObject, String href, String rel) throws JSONException { return baseObject.put("link", new JSONObject().put(LINK_HREF, href) .put(LINK_REL, rel)); } /** * Method createParentLink. Create link to the parent resource * * @param baseObject * JSONObject * @param rel * String * @param uriInfo * UriInfo * @return JSONObject * @throws JSONException */ public static JSONObject createParentLink(JSONObject baseObject, String rel, UriInfo uriInfo) throws JSONException { // TODO : use URIBuilder for path composition // remove last segment and recreate the path String href = ""; List<PathSegment> listSegments = uriInfo.getPathSegments(); listSegments.remove(listSegments.size() - 1); for (PathSegment xp : listSegments) { href += xp.getPath() + "/"; } href = href.substring(0, href.length() - 1); // add the link return createLink(baseObject, href, rel); } /** * Method getClassDescription. * * @param c * Class<?> * @return String */ public static String getClassDescription(Class<?> c) { try { if (c.isAnnotationPresent(HtmlDoc.class)) { StringBuilder ret = new StringBuilder(); HtmlDoc doc = c.getAnnotation(HtmlDoc.class); ret.append(String.format("<h2>%s</h2>", doc.description())); if (!doc.post().isEmpty()) { ret.append(String.format("<b>POST</b><br/>%s", doc.post())); } if (!doc.get().isEmpty()) { ret.append(String.format("<b>GET</b><br/>%s", doc.get())); } if (!doc.put().isEmpty()) { ret.append(String.format("<b>PUT</b><br/>%s", doc.put())); } if (!doc.delete().isEmpty()) { ret.append(String.format("<b>DELETE</b><br/>%s", doc.delete())); } } } catch (Exception e) { logger.error(String.format( "Error retrieving description for class [%s]", c), e); } return String.format("no description for %s", c); } /** * Method getClassDescription. * * @param className * String * @return String */ public static String getClassDescription(String className) { try { return getClassDescription(Class.forName(className)); } catch (Exception e) { logger.error(String.format( "Error retrieving description for class [%s]", className), e); } return String.format("no description for %s", className); } /** * Method getTypedQuery. * * @param uriInfo * UriInfo * @param em * EntityManager * @param entity * Class<?> * @param filterName * String * @param filterValue * String * * @return TypedQuery<?> * @throws SecurityException * @throws NoSuchFieldException * @throws FileNotFoundException * @throws UnsupportedEncodingException */ public static TypedQuery<?> getTypedQuery(UriInfo uriInfo, EntityManager em, Class<?> entity, String filterName, String filterValue) { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<?> query = cb.createQuery(entity); Root<?> queryRoot = query.from(entity); MultivaluedMap<String, String> params = uriInfo.getQueryParameters(); if (params.containsKey(SORT_FIELD)) { try { // Check if there are field in entity queryRoot.get(params.getFirst(SORT_FIELD)); if (params.containsKey(SORT_ORDER) && params.getFirst(SORT_ORDER).equals("descending")) { query.orderBy(cb.desc(queryRoot.get(params .getFirst(SORT_FIELD)))); } else { query.orderBy(cb.asc(queryRoot.get(params .getFirst(SORT_FIELD)))); } } catch (IllegalArgumentException e) { // skip sort field } } String filterEntityName = ""; Predicate predicate = cb.conjunction(); for (String filterFiled : params.keySet()) { if (filterFiled.startsWith(FILTER)) { if (filterFiled.endsWith(FILTER_TYPE_EXACT) || filterFiled.endsWith(FILTER_TYPE_CONTAINS) || filterFiled.endsWith(FILTER_TYPE_END)) { filterEntityName = filterFiled.substring( filterFiled.indexOf("_") + 1, filterFiled.lastIndexOf("_")); } else { filterEntityName = filterFiled.substring(7); } try { // Check if there are field in entity queryRoot.get(filterEntityName); switch(filterFiled.substring(filterFiled.indexOf('_'))){ case FILTER_TYPE_EXACT: predicate = cb.and(predicate, cb.equal( queryRoot.get(filterEntityName), params.getFirst(filterFiled))); break; case FILTER_TYPE_CONTAINS: predicate = cb.and(predicate, cb.like( queryRoot.<String> get(filterEntityName), "%" + params.getFirst(filterFiled) + "%")); break; default: if (queryRoot.get(filterEntityName).getJavaType().toString() .contains("java.sql.Timestamp")) { if (filterFiled.endsWith(FILTER_TYPE_END)) { predicate = cb .and(predicate, cb.lessThanOrEqualTo( queryRoot .<Timestamp> get(filterEntityName), getTimestamp(params .getFirst(filterFiled)))); } else { predicate = cb .and(predicate, cb.greaterThanOrEqualTo( queryRoot .<Timestamp> get(filterEntityName), getTimestamp(params .getFirst(filterFiled)))); } } else { predicate = cb .and(predicate, cb.like(queryRoot .<String> get(filterEntityName), params.getFirst(filterFiled) + "%")); } break; } /* if (filterFiled.endsWith(FILTER_TYPE_EXACT)) { predicate = cb.and(predicate, cb.equal( queryRoot.get(filterEntityName), params.getFirst(filterFiled))); } else { if (filterFiled.endsWith(FILTER_TYPE_CONTAINS)) { predicate = cb.and(predicate, cb.like( queryRoot.<String> get(filterEntityName), "%" + params.getFirst(filterFiled) + "%")); } else { if (queryRoot.get(filterEntityName).getJavaType().toString() .contains("java.sql.Timestamp")) { if (filterFiled.endsWith(FILTER_TYPE_END)) { predicate = cb .and(predicate, cb.lessThanOrEqualTo( queryRoot .<Timestamp> get(filterEntityName), getTimestamp(params .getFirst(filterFiled)))); } else { predicate = cb .and(predicate, cb.greaterThanOrEqualTo( queryRoot .<Timestamp> get(filterEntityName), getTimestamp(params .getFirst(filterFiled)))); } } else { predicate = cb .and(predicate, cb.like(queryRoot .<String> get(filterEntityName), params.getFirst(filterFiled) + "%")); } } }*/ } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } if (null != filterName) { predicate = cb.and(predicate, cb.equal(queryRoot.get(filterName), filterValue)); } query.where(predicate); return em.createQuery(query); } /** * Method getCountTypedQuery. * * @param uriInfo * UriInfo * @param em * EntityManager * @param entity * Class<?> * @param filterName * String * @param filterValue * String * @return TypedQuery<?> * @throws SecurityException * @throws NoSuchFieldException */ public static TypedQuery<?> getCountTypedQuery(UriInfo uriInfo, EntityManager em, Class<?> entity, String filterName, String filterValue) { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Long> query = cb.createQuery(Long.class); Root<?> queryRoot = query.from(entity); query.select(cb.count(queryRoot)); Predicate predicate = cb.conjunction(); String filterEntityName = ""; MultivaluedMap<String, String> params = uriInfo.getQueryParameters(); for (String filterFiled : params.keySet()) { if (filterFiled.startsWith(FILTER)) { if (filterFiled.endsWith(FILTER_TYPE_EXACT) || filterFiled.endsWith(FILTER_TYPE_CONTAINS) || filterFiled.endsWith(FILTER_TYPE_END)) { filterEntityName = filterFiled.substring( filterFiled.indexOf("_") + 1, filterFiled.lastIndexOf("_")); } else { filterEntityName = filterFiled.substring(7); } try { // Check if there are field in entity queryRoot.get(filterEntityName); if (filterFiled.endsWith(FILTER_TYPE_EXACT)) { predicate = cb.and(predicate, cb.equal( queryRoot.get(filterEntityName), params.getFirst(filterFiled))); } else { if (filterFiled.endsWith(FILTER_TYPE_CONTAINS)) { predicate = cb.and(predicate, cb.like( queryRoot.<String> get(filterEntityName), "%" + params.getFirst(filterFiled) + "%")); } else { if (entity.getDeclaredField(filterEntityName) .getType().toString() .contains("java.sql.Timestamp")) { if (filterFiled.endsWith(FILTER_TYPE_END)) { predicate = cb .and(predicate, cb.lessThanOrEqualTo( queryRoot .<Timestamp> get(filterEntityName), getTimestamp(params .getFirst(filterFiled)))); } else { predicate = cb .and(predicate, cb.greaterThanOrEqualTo( queryRoot .<Timestamp> get(filterEntityName), getTimestamp(params .getFirst(filterFiled)))); } } else { if (entity.getDeclaredField(filterEntityName) .getType().isEnum()) { Method methodFromName = entity .getDeclaredField(filterEntityName) .getType() .getDeclaredMethod("fromName", String.class); @SuppressWarnings("unchecked") Enum enumVal = Enum .valueOf( (Class<Enum>) entity .getDeclaredField( filterEntityName) .getType(), methodFromName .invoke("fromName", params.getFirst(filterFiled)) .toString()); predicate = cb .and(predicate, cb.like(queryRoot .<String> get(filterEntityName), enumVal.ordinal() + "%")); } else { predicate = cb .and(predicate, cb.like(queryRoot .<String> get(filterEntityName), params.getFirst(filterFiled) + "%")); } } } } } catch (Exception e) { // skip filter field logger.error(ERROR_REASON_REFLECTION_ERROR, e); } } } if (null != filterName) { predicate = cb.and(predicate, cb.equal(queryRoot.get(filterName), filterValue)); } query.where(predicate); return em.createQuery(query); } /** * Method hasSortOrFilter. * * @param uriInfo * UriInfo * * @return boolean */ public static boolean hasSortOrFilter(UriInfo uriInfo) { MultivaluedMap<String, String> params = uriInfo.getQueryParameters(); if (params.containsKey(SORT_FIELD)) return true; for (String filterFiled : params.keySet()) { if (filterFiled.startsWith(FILTER)) return true; } return false; } }