diff --git a/lib/linguist/languages.yml b/lib/linguist/languages.yml index b5eebfe281..b0dbc307b2 100644 --- a/lib/linguist/languages.yml +++ b/lib/linguist/languages.yml @@ -349,6 +349,7 @@ Apex: color: "#1797c0" extensions: - ".cls" + - ".apex" - ".trigger" tm_scope: source.apex ace_mode: java diff --git a/samples/Apex/SoqlUtils.apex b/samples/Apex/SoqlUtils.apex new file mode 100644 index 0000000000..580ec3a776 --- /dev/null +++ b/samples/Apex/SoqlUtils.apex @@ -0,0 +1,101 @@ +/* ============================================================ + * This code is part of the "apex-lang" open source project avaiable at: + * + * http://code.google.com/p/apex-lang/ + * + * This code is licensed under the Apache License, Version 2.0. You may obtain a + * copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * ============================================================ + */ +global class SoqlUtils { + + global static String toLiteral(final Object value){ + return toLiteral(value,null); + } + + global static String toLiteral(final Object value, SoqlOptions options){ + if(options == null){ + options = SoqlOptions.DEFAULT_OPTIONS; + } + String literal = ''; + if( value == null){ + literal += 'null'; + } else if( value instanceof Soqlable ){ + return ((Soqlable)value).toSoql(options); + } else if( value instanceof String || + value instanceOf ID){ + String manipulated = (String) value; + if(options.escapeSingleQuotes == true){ + manipulated = String.escapeSingleQuotes(manipulated); + } + literal += '\'' + manipulated + '\''; + } else if( value instanceOf Boolean || + value instanceOf Integer || + value instanceOf Long || + value instanceOf Double || + value instanceOf Decimal){ + literal += value; + } else if( value instanceOf Date){ + literal += Datetime.newInstance(((Date)value).year(), ((Date)value).month(), ((Date)value).day()).format('yyyy-MM-dd'); + } else if( value instanceOf Datetime){ + literal += ((Datetime) value).format('yyyy-MM-dd') + 'T' + ((Datetime) value).format('hh:mm:ss') + 'Z'; + } else { + throw new IllegalArgumentException('invalid value; value must be null, a primitive type ' + + '(String|ID|Boolean|Integer|Long|Double|Decimal|Date|Datetime), or implement Soqlable interface'); + } + return literal; + } + + global static List toLiteral(final List values){ + return toLiteral(values,SoqlOptions.DEFAULT_OPTIONS); + } + + global static List toLiteral(final List values, final SoqlOptions options){ + final List literals = new List(); + if(values != null && values.size() > 0){ + for(Object obj : values){ + literals.add(toLiteral(obj,options)); + } + } + return literals; + } + + global static void assertEquals(String expected, String actual){ + System.assert( + equals(expected,actual), + 'Assertion failed, the following two SOQLs are not equal. Expected: ' + expected + ', Actual: ' + actual); + } + + /** + * This equals is fairly simplistic. It will account for unordered columns, + * lower vs upper case (SELECT vs select) but it won't take into account anything else. Different + * order of where conditions for example. + */ + global static Boolean equals(String soql1, String soql2){ + if( soql1.contains('\n') != soql2.contains('\n') ){ + return false; + } + soql1 = StringUtils.replace(StringUtils.trim(StringUtils.lowerCase(soql1)), '\n', ''); + soql2 = StringUtils.replace(StringUtils.trim(StringUtils.lowerCase(soql2)), '\n', ''); + if(StringUtils.equals(soql1,soql2)){ + return true; + } + if(!StringUtils.startsWith(soql1, 'select') || !StringUtils.startsWith(soql2, 'select')){ + return false; + } + String afterSelect1 = StringUtils.trim(StringUtils.substringAfter(soql1,'select')); + String afterSelect2 = StringUtils.trim(StringUtils.substringAfter(soql2,'select')); + Set columns1 = StringUtils.trimAll(SetUtils.listToSet(StringUtils.split(StringUtils.trim(StringUtils.substringBeforeLast(afterSelect1,' from ')),','))); + Set columns2 = StringUtils.trimAll(SetUtils.listToSet(StringUtils.split(StringUtils.trim(StringUtils.substringBeforeLast(afterSelect2,' from ')),','))); + if(!SetUtils.equals(columns1,columns2)){ + return false; + } + String afterFrom1 = StringUtils.trim(StringUtils.substringAfterLast(soql1,' from ')); + String afterFrom2 = StringUtils.trim(StringUtils.substringAfterLast(soql2,' from ')); + return StringUtils.equals(afterFrom1,afterFrom2); + } + + +} \ No newline at end of file diff --git a/samples/Apex/UrlUtils.apex b/samples/Apex/UrlUtils.apex new file mode 100644 index 0000000000..3a0df9b006 --- /dev/null +++ b/samples/Apex/UrlUtils.apex @@ -0,0 +1,59 @@ +/* ============================================================ + * This code is part of the "apex-lang" open source project avaiable at: + * + * http://code.google.com/p/apex-lang/ + * + * This code is licensed under the Apache License, Version 2.0. You may obtain a + * copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * ============================================================ + */ +global class UrlUtils { + + global static String getBase(String url){ + String[] split = StringUtils.split(url, '?'); + if(split == null || split.size() == 0){ + return null; + } + return split[0]; + } + + global static Map getParams(String url){ + //url -> http://google.com?api=x&xyz=123 + Map returnMap = new Map(); + String[] split = StringUtils.split(url, '?'); + //split -> ['http://google.com','api=x&xyz=123'] + if(split == null || split.size() != 2 || split[1] == null){ + return returnMap; + } + split = StringUtils.split(split[1],'&'); + //split -> ['api=x','xyz=123'] + if(split != null && split.size() > 0){ + String[] split2 = null; + for(String keyValuePair : split){ + //keyValuePair -> 'api=x' + split2 = StringUtils.split(keyValuePair,'='); + String key = ''; + if(split2 != null && split2.size() > 0) key = split2[0]; + String value = ''; + if(split2 != null && split2.size() > 1) value = split2[1]; + returnMap.put(key,EncodingUtil.urlDecode(value, 'UTF-8')); + } + } + return returnMap; + } + + global static String ensureUrlBeginsWithHttp(String url){ + if(StringUtils.isNotEmpty(url)){ + final String lowerCaseUrl = StringUtils.lowerCase(url); + if( !StringUtils.startsWith(lowerCaseUrl, 'http://') + && !StringUtils.startsWith(lowerCaseUrl, 'https://')){ + if(StringUtils.contains(lowerCaseUrl, '//')) url = StringUtils.substringAfter(url, '//'); + url = 'http://'+ StringUtils.stripStart(url,'/:'); + } + } + return url; + } + +} \ No newline at end of file