package restservices.util; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.servlet.http.HttpServletRequest; import org.apache.commons.codec.digest.DigestUtils; import restservices.RestServices; import com.google.common.base.Preconditions; import com.mendix.core.Core; import com.mendix.systemwideinterfaces.core.IContext; import com.mendix.systemwideinterfaces.core.IDataType; import com.mendix.systemwideinterfaces.core.IMendixIdentifier; import com.mendix.systemwideinterfaces.core.IMendixObject; import com.mendix.systemwideinterfaces.core.UserAction; import com.mendix.systemwideinterfaces.core.meta.IMetaObject; import com.mendix.systemwideinterfaces.core.meta.IMetaPrimitive; import com.mendix.systemwideinterfaces.core.meta.IMetaPrimitive.PrimitiveType; public class Utils { public static String getShortMemberName(String memberName) { return memberName.replaceFirst("^.+\\.", ""); } public static String autoGenerateLink(String value) { if (isUrl(value)) return "<a href='"+ value+ "'>" + value+ "</a>"; return value; } public static boolean isUrl(String url) { //a bit naive maybe.... return url != null && (url.startsWith("http://") || url.startsWith("https://")); } public static String getKeyFromUrl(String url) { int i = url.lastIndexOf('/'); if (i == -1 || i == url.length() -1) throw new RuntimeException("Not a key containing url: " + url); String key = url.substring(i + 1); i = key.indexOf('?'); if (i > -1) key = key.substring(0, i); i = key.indexOf('#'); if (i > -1) key = key.substring(0, i); return key; } public static void copyAttributes(IContext context, IMendixObject source, IMendixObject target) { if (source == null) throw new IllegalStateException("source is null"); if (target == null) throw new IllegalStateException("target is null"); for(IMetaPrimitive e : target.getMetaObject().getMetaPrimitives()) { if (!source.hasMember(e.getName())) continue; if (e.isVirtual() || e.getType() == PrimitiveType.AutoNumber) continue; target.setValue(context, e.getName(), source.getValue(context, e.getName())); } } public static IDataType getFirstArgumentType(String microflow) { Map<String, IDataType> args = Core.getInputParameters(microflow); //if microflow does not exist, this returns empty map instead of null if (null == Core.getReturnType(microflow) || args == null) throw new RuntimeException("Unknown microflow: " + microflow); if (args.size() == 0) throw new RuntimeException("Microflow " + microflow + " should have at least one argument!"); return args.entrySet().iterator().next().getValue(); } public static String getMD5Hash(String jsonString) throws UnsupportedEncodingException { return DigestUtils.md5Hex(jsonString.getBytes(RestServices.UTF8)); } public static boolean isValidKey(String key) { return key != null && !key.trim().isEmpty() && key.length() > 0 && key.length() < 400; //MWE: warn: magic number! } public static boolean isEmpty(String value) { return value == null || value.trim().isEmpty(); } public static boolean isNotEmpty(String value) { return !isEmpty(value); } public static Map<String, String> getArgumentTypes(String mf) { if (!microflowExists(mf)) //known args is usually empty map for non existing microflow :S. throw new IllegalArgumentException("Unknown microflow: " + mf); Map<String, IDataType> knownArgs = Core.getInputParameters(mf);; Map<String, String> args = new HashMap<String, String>(); for(Entry<String, IDataType> e : knownArgs.entrySet()) { args.put(e.getKey(), e.getValue().isMendixObject() ? e.getValue().getObjectType() : e.getValue().isList() ? e.getValue().getObjectType() + "*" : e.getValue().getType().toString() ); } return args; } public static String urlEncode(String value) { if (value == null) { return ""; } try { //See: http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1 //See: http://docs.oracle.com/javase/7/docs/api/java/net/URLEncoder.html //See: http://tools.ietf.org/html/rfc3986#section-2.3 //URLEncoder.encode differts on 2 things, spaces are encoded with +, as described in form-encoding. //This is replaces by %20, since that is always save. //Besides that, URLEncoder 'forgets' to encode '*', which is a reserved character..... So also replace it. return URLEncoder.encode(value, RestServices.UTF8).replace("+", "%20").replace("*", "%2A"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } public static String urlDecode(String value) { try { return URLDecoder.decode(value, RestServices.UTF8); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } public static String appendParamToUrl(String url, String paramName, String paramValue) { return url + (url.contains("?") ? "&" : "?") + urlEncode(paramName) + "=" + urlEncode(paramValue); } public static String appendSlashToUrl(String url) { Preconditions.checkNotNull(url, "URL should not be null"); return url.endsWith("/") ? url : url + "/"; } public static String removeTrailingSlash(String relativeUrl) { return relativeUrl.replaceAll("\\/$", ""); } public static String removeLeadingSlash(String relativeUrl) { return relativeUrl.replaceAll("^\\/", ""); } public static String removeLeadingAndTrailingSlash(String relativeUrl) { return removeLeadingSlash(removeTrailingSlash(relativeUrl)); } public static String nullToEmpty(String statusText) { return statusText == null ? "" : statusText; } public static String getRequestUrl(HttpServletRequest request) { return request.getRequestURL().toString() + (Utils.isEmpty(request.getQueryString()) ? "" : "?" + request.getQueryString()); } public static boolean isSystemAttribute(String key) { if ("createdDate".equals(key) || "changedDate".equals(key) || "System.owner".equals(key) || "System.changedBy".equals(key)) { return true; } return false; } public static boolean microflowExists(String mf) { return Core.getMicroflowNames().contains(mf); } public static boolean hasDataAccess(IMetaObject meta, IContext context) { return meta.hasMetaDataAccess(context); } public static <T> T withSessionCache(IContext c, final Function<T> worker) throws Exception { try { return Core.executeSync(new UserAction<T>(c) { @Override public T executeAction() throws Exception { return worker.apply(); } }); } catch (Exception e) { //executeSync wraps all thrown exeption 2 times in a CoreRuntimeException, unwrap it... Throwable cause1 = e.getCause(); if (cause1 == null || cause1.getCause() == null) throw e; else if (cause1.getCause() instanceof Exception) throw (Exception) cause1.getCause(); else throw new RuntimeException(e); } } public static void sortIdList(List<IMendixIdentifier> ids) { Collections.sort(ids, new Comparator<IMendixIdentifier>() { @Override public int compare(IMendixIdentifier o1, IMendixIdentifier o2) { if (o2 == null && o1 == null) return 0; if (o2 == null) return -1; if (o1 == null) return 1; return Long.compare(o1.toLong(), o2.toLong()); } }); } }