From e9002d303d5e0efac93b8cb2c0fe78e299e22058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20G=C3=BCrtler?= Date: Mon, 30 Jul 2018 16:15:20 +0200 Subject: [PATCH 1/8] Move closures for type and parameter name manipulation to extra class Eases reusing these closures for other template operations, e.g. createDelegateImpl.groovy! --- .../atlas/codegen/GeneratorBase.groovy | 33 ++- .../codegen/TypeStringManipulation.groovy | 272 ++++++++++++++++++ 2 files changed, 298 insertions(+), 7 deletions(-) create mode 100644 src/main/groovy/de/lisaplus/atlas/codegen/TypeStringManipulation.groovy diff --git a/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy b/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy index d4da7ba..6b94b1e 100644 --- a/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy +++ b/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy @@ -4,6 +4,7 @@ import de.lisaplus.atlas.DoCodeGen import de.lisaplus.atlas.codegen.helper.java.JavaTypeConvert import de.lisaplus.atlas.codegen.helper.java.JsonTypeConvert import de.lisaplus.atlas.codegen.helper.java.SwaggerTypeConvert +import de.lisaplus.atlas.codegen.meta.TypeStringManipulation import de.lisaplus.atlas.model.ComplexType import de.lisaplus.atlas.model.InnerType import de.lisaplus.atlas.model.Model @@ -137,13 +138,14 @@ abstract class GeneratorBase { } /** - * methon create a map object and initialize it with some basic stuff - * @param model + * methon create a map object and initialize it with some basic string manipulation stuff + * needed for working with the types and their properties in the templates. * @return */ - Map createTemplateDataMap(Model model) { + Map getClosures() { + return new TypeStringManipulation().getClosures() + /* return [ - model:model, DOLLAR:'$', toLowerCase: toLowerCase, toUpperCase: toUpperCase, @@ -159,7 +161,6 @@ abstract class GeneratorBase { typeToMeta: JsonTypeConvert.meta, typeFormatToSwagger: SwaggerTypeConvert.format, typeFormatToJson: JsonTypeConvert.format, - renderInnerTemplate: renderInnerTemplate, breakTxt: breakTxt, containsTag: containsTag, missingTag: missingTag, @@ -170,8 +171,22 @@ abstract class GeneratorBase { filterPropsPerform: filterPropsPerform, printLines: printLines ] + */ + } + + /** + * methon create a map object and initialize it with some basic stuff + * @param model + * @return + */ + Map createTemplateDataMap(Model model) { + Map map = getClosures() + map.model = model + map.renderInnerTemplate = renderInnerTemplate + return map } + /* Closure> filterProps = { Type type, Map params -> // def filterProps = { type, params -> List props = type.properties @@ -328,10 +343,14 @@ abstract class GeneratorBase { def toUpperCase = { str -> return str==null ? EMPTY : str.toUpperCase() } - +*/ def renderInnerTemplate = { templateResource,actObj,indent -> def test = actObj.toString() def innerTemplate = createTemplateFromResource(templateResource,TemplateType.GString) + def data = getClosures() + data.actObj = actObj + data.renderInnerTemplate = renderInnerTemplate + /* def data = [ actObj: actObj, indent: indent, @@ -356,7 +375,7 @@ abstract class GeneratorBase { filterPropsPerform: filterPropsPerform, printLines: printLines ] - + */ return innerTemplate.make(data) } diff --git a/src/main/groovy/de/lisaplus/atlas/codegen/TypeStringManipulation.groovy b/src/main/groovy/de/lisaplus/atlas/codegen/TypeStringManipulation.groovy new file mode 100644 index 0000000..4f33d91 --- /dev/null +++ b/src/main/groovy/de/lisaplus/atlas/codegen/TypeStringManipulation.groovy @@ -0,0 +1,272 @@ +package de.lisaplus.atlas.codegen.meta; + +import de.lisaplus.atlas.codegen.helper.java.JavaTypeConvert +import de.lisaplus.atlas.codegen.helper.java.JsonTypeConvert +import de.lisaplus.atlas.codegen.helper.java.SwaggerTypeConvert +import de.lisaplus.atlas.model.ComplexType +import de.lisaplus.atlas.model.InnerType +import de.lisaplus.atlas.model.Property +import de.lisaplus.atlas.model.RefType +import de.lisaplus.atlas.model.Type + +class TypeStringManipulation { + + /** + * method create a map object and initialize it with some basic string manipulation stuff + * needed for working with the types and their properties in the templates. + * @return + */ + Map getClosures() { + return [ + DOLLAR:'$', + printIndent: printIndent, + toLowerCase: toLowerCase, + toUpperCase: toUpperCase, + firstLowerCase: firstLowerCase, + firstUpperCase: firstUpperCase, + lowerCamelCase: firstLowerCamelCase, + upperCamelCase: firstUpperCamelCase, + isInnerType: isInnerType, + isPropComplexType: isPropComplexType, + typeToJava: JavaTypeConvert.convert, + typeToSwagger: SwaggerTypeConvert.convert, + typeToJson: JsonTypeConvert.convert, + typeToMeta: JsonTypeConvert.meta, + typeFormatToSwagger: SwaggerTypeConvert.format, + typeFormatToJson: JsonTypeConvert.format, + breakTxt: breakTxt, + containsTag: containsTag, + missingTag: missingTag, + containsPropName: containsPropName, + missingPropName: missingPropName, + propsContainsTag: propsContainsTag, + filterProps: filterProps, + filterPropsPerform: filterPropsPerform, + printLines: printLines + ] + } + + def isInnerType = { type -> + return type && (type instanceof InnerType ) + } + + def isPropComplexType = { prop -> + return prop && prop.type && (prop.type instanceof ComplexType || prop.type instanceof RefType) + } + + def containsTag = { obj, tag -> + if (! tag ) return false + if (! ((obj instanceof Type) || (obj instanceof Property))) { + return false + } + if (!obj.tags) { + return false + } + return obj.tags.contains(tag) + } + + def containsPropName = { type, propName -> + if (! type ) return false + if (! propName ) return false + if (! (type instanceof Type)) return false + return type.properties.findIndexOf{ + it.name==propName + } != -1 + } + + def missingPropName = { type, propName -> + if (! type ) return false + if (! propName ) return false + if (! (type instanceof Type)) return false + return type.properties.findIndexOf{ + it.name==propName + } == -1 + } + + def missingTag = { obj, tag -> + if (! tag ) return false + if (! ((obj instanceof Type) || (obj instanceof Property))) { + return false + } + if (!obj.tags) { + return false + } + return ! obj.tags.contains(tag) + } + + def propsContainsTag = { type, name -> + if (! type ) return false + if (! name ) return false + if (! (type instanceof Type)) { + return false + } + def result = type.properties.find { it.tags.contains(name) } + if (result) { + return true + } + else { + return false + } + } + + def breakTxt = { String txtToBreak,int charPerLine,String breakText='\n' -> + if (!txtToBreak) return EMPTY + StringBuilder sb = new StringBuilder() + int txtLen = txtToBreak.length() + int aktPos = 0 + while (aktPos < txtLen) { + if ((aktPos + charPerLine) >= txtLen) { + // The rest of the word is smaller than the desired char count per line + sb.append(txtToBreak.substring(aktPos)) + break; + } else { + sb.append(txtToBreak.substring(aktPos, aktPos + charPerLine)) + aktPos += charPerLine + if (txtToBreak.substring(aktPos, aktPos + 1) == ' ') { + sb.append(breakText) + aktPos++ + } else { + for (aktPos; aktPos < txtLen; aktPos++) { + String subStr = txtToBreak.substring(aktPos, aktPos + 1) + if (subStr == ' ') { + sb.append(breakText) + aktPos++ + break + } else { + sb.append(subStr) + } + } + } + } + } + return sb.toString() + } + + def printIndent = { indent -> + def ret = '' + for (def i=0;i + return str==null ? EMPTY : str.toLowerCase() + } + + def toUpperCase = { str -> + return str==null ? EMPTY : str.toUpperCase() + } + + def firstLowerCase = { str -> + if (!str) return EMPTY + def first = str.substring(0,1) + first = first.toLowerCase() + if (str.length()>1) { + def rest = str.substring(1) + return first + rest + } + else { + return first + } + } + + def firstUpperCase = { str -> + if (!str) return EMPTY + def first = str.substring(0,1) + first = first.toUpperCase() + if (str.length()>1) { + def rest = str.substring(1) + return first + rest + } + else { + return first + } + } + + def firstUpperCamelCase = { str -> + if (!str) return EMPTY + def firstUpper = firstUpperCase(str) + return convertAllUnderLinesToCamelCase(firstUpper) + } + + def firstLowerCamelCase = { str -> + if (!str) return EMPTY + def firstLower = firstLowerCase(str) + return convertAllUnderLinesToCamelCase(firstLower) + } + + def convertAllUnderLinesToCamelCase = { String str -> + if (!str) return EMPTY + def i_ = str.indexOf('_') + while (i_!=-1) { + def stopLen = str.length()-1 + if (i_> filterProps = { Type type, Map params -> + def filterProps = { type, params -> + List props = type.properties + if (params.filterCls!= null) props = props.findAll { params.get('filterCls') } + if (params.name != null) props = props.findAll { prop -> prop.name == params.name } + if (params.namePattern != null) props = props.findAll { prop -> prop.name =~ params.namePattern } + if (params.complex != null) props = props.findAll { prop -> prop.isComplexType() == params.complex } + if (params.refComplex != null) props = props.findAll { prop -> + // println "refComplex: param=${params.refComplex} propName=${prop.name} propValue=${prop.isRefTypeOrComplexType()}" + prop.isRefTypeOrComplexType() == params.refComplex } + if (params.array != null) props = props.findAll { prop -> prop.type.isArray == params.array } + if (params.join != null) props = props.findAll { prop -> + // def evaled = prop.hasTag('join') == params.join + // println "join: param=${params.join} propName=${prop.name} propValue=${prop.hasTag('join')} evaled=${evaled}" + prop.hasTag('join') == params.join } + if (params.aggregation != null) props = props.findAll { prop -> prop.isAggregation() == params.aggregation } + if (params.implRefIsRef != null) props = props.findAll { prop -> prop.implicitRefIsRefType() == params.implRefIsRef } + if (params.implRefIsComp != null) props = props.findAll { prop -> prop.implicitRefIsComplexType() == params.implRefIsComp } + if (params.typeName!= null) props = props.findAll { prop -> prop.type.NAME == params.typeName } + if (params.typeNameNot!= null) props = props.findAll { prop -> prop.type.NAME != params.typeNameNot } + // Alternative: use pattern, e.g. typeNamePattern:'^(?!DATE$)' to get all types with names other than 'DATE' + if (params.typeNamePattern!= null) props = props.findAll { prop -> prop.type.NAME =~ params.typeNamePattern } + if (params.hasTag != null) props = props.findAll { prop -> prop.hasTag(params.hasTag) } + if (params.withoutTag != null) props = props.findAll { prop -> !prop.hasTag(params.withoutTag) } + return props + } + + // Closure> filterPropsPerform = {Type type, Map params, Closure toLines -> + def filterPropsPerform = { type, params, toLines -> + def props = filterProps.call(type, params) + def lines = [] + if (props.size() > 0 && params.comment != null) { + lines += params.comment + } + // props.each { prop -> lines = lines + toLines.call(prop) } + props.each { prop -> lines += toLines.call(prop) } + if (props.size() > 0 && true == params.newLine) { + lines += '' + } + return lines + } + + // Vararg definition is mandatory, call example: printLines3.call( [level:2, by: '.-'], new StringWriter(), list, list2 ) + // Closure printLines3 = { Writer out, Map params, List... lists -> + def printLines = { out, params,List... lists -> + def level = params.level?:0 + def by = params.by?:' ' + def prefix = '' + level.times { prefix += by} + lists.flatten().each { out << "$prefix$it\n" } + } + + private final static String EMPTY='' +} From e175970fdd57e88933948ed45b48254670fa1c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20G=C3=BCrtler?= Date: Mon, 30 Jul 2018 16:17:45 +0200 Subject: [PATCH 2/8] Removed the code, which was moved to TypeStringManipulation --- .../atlas/codegen/GeneratorBase.groovy | 287 ------------------ 1 file changed, 287 deletions(-) diff --git a/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy b/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy index 6b94b1e..f603323 100644 --- a/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy +++ b/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy @@ -1,15 +1,8 @@ package de.lisaplus.atlas.codegen import de.lisaplus.atlas.DoCodeGen -import de.lisaplus.atlas.codegen.helper.java.JavaTypeConvert -import de.lisaplus.atlas.codegen.helper.java.JsonTypeConvert -import de.lisaplus.atlas.codegen.helper.java.SwaggerTypeConvert import de.lisaplus.atlas.codegen.meta.TypeStringManipulation -import de.lisaplus.atlas.model.ComplexType -import de.lisaplus.atlas.model.InnerType import de.lisaplus.atlas.model.Model -import de.lisaplus.atlas.model.Property -import de.lisaplus.atlas.model.RefType import de.lisaplus.atlas.model.Type import groovy.text.GStringTemplateEngine import groovy.text.Template @@ -144,34 +137,6 @@ abstract class GeneratorBase { */ Map getClosures() { return new TypeStringManipulation().getClosures() - /* - return [ - DOLLAR:'$', - toLowerCase: toLowerCase, - toUpperCase: toUpperCase, - firstLowerCase: firstLowerCase, - firstUpperCase: firstUpperCase, - lowerCamelCase: firstLowerCamelCase, - upperCamelCase: firstUpperCamelCase, - isInnerType: isInnerType, - isPropComplexType: isPropComplexType, - typeToJava: JavaTypeConvert.convert, - typeToSwagger: SwaggerTypeConvert.convert, - typeToJson: JsonTypeConvert.convert, - typeToMeta: JsonTypeConvert.meta, - typeFormatToSwagger: SwaggerTypeConvert.format, - typeFormatToJson: JsonTypeConvert.format, - breakTxt: breakTxt, - containsTag: containsTag, - missingTag: missingTag, - containsPropName: containsPropName, - missingPropName: missingPropName, - propsContainsTag: propsContainsTag, - filterProps: filterProps, - filterPropsPerform: filterPropsPerform, - printLines: printLines - ] - */ } /** @@ -186,267 +151,15 @@ abstract class GeneratorBase { return map } - /* - Closure> filterProps = { Type type, Map params -> - // def filterProps = { type, params -> - List props = type.properties - if (params.filterCls!= null) props = props.findAll { params.get('filterCls') } - if (params.name != null) props = props.findAll { prop -> prop.name == params.name } - if (params.namePattern != null) props = props.findAll { prop -> prop.name =~ params.namePattern } - if (params.complex != null) props = props.findAll { prop -> prop.isComplexType() == params.complex } - if (params.refComplex != null) props = props.findAll { prop -> - // println "refComplex: param=${params.refComplex} propName=${prop.name} propValue=${prop.isRefTypeOrComplexType()}" - prop.isRefTypeOrComplexType() == params.refComplex } - if (params.array != null) props = props.findAll { prop -> prop.type.isArray == params.array } - if (params.join != null) props = props.findAll { prop -> - // def evaled = prop.hasTag('join') == params.join - // println "join: param=${params.join} propName=${prop.name} propValue=${prop.hasTag('join')} evaled=${evaled}" - prop.hasTag('join') == params.join } - if (params.aggregation != null) props = props.findAll { prop -> prop.isAggregation() == params.aggregation } - if (params.implRefIsRef != null) props = props.findAll { prop -> prop.implicitRefIsRefType() == params.implRefIsRef } - if (params.implRefIsComp != null) props = props.findAll { prop -> prop.implicitRefIsComplexType() == params.implRefIsComp } - if (params.typeName!= null) props = props.findAll { prop -> prop.type.NAME == params.typeName } - if (params.typeNameNot!= null) props = props.findAll { prop -> prop.type.NAME != params.typeNameNot } - // Alternative: use pattern, e.g. typeNamePattern:'^(?!DATE$)' to get all types with names other than 'DATE' - if (params.typeNamePattern!= null) props = props.findAll { prop -> prop.type.NAME =~ params.typeNamePattern } - if (params.hasTag != null) props = props.findAll { prop -> prop.hasTag(params.hasTag) } - if (params.withoutTag != null) props = props.findAll { prop -> !prop.hasTag(params.withoutTag) } - return props - } - - // Closure> filterPropsPerform = {Type type, Map params, Closure toLines -> - def filterPropsPerform = { type, params, toLines -> - def props = filterProps.call(type, params) - def lines = [] - if (props.size() > 0 && params.comment != null) { - lines += params.comment - } - // props.each { prop -> lines = lines + toLines.call(prop) } - props.each { prop -> lines += toLines.call(prop) } - if (props.size() > 0 && true == params.newLine) { - lines += '' - } - return lines - } - - - // Closure printLines3 = { Writer out, Map params, List... lists -> - // Vararg definition is mandatory, call example: printLines3.call( [level:2, by: '.-'], new StringWriter(), list, list2 ) - def printLines = { out, params,List... lists -> - def level = params.level?:0 - def by = params.by?:' ' - def prefix = '' - level.times { prefix += by} - lists.flatten().each { out << "$prefix$it\n" } - } - - def isInnerType = { type -> - return type && (type instanceof InnerType ) - } - - def isPropComplexType = { prop -> - return prop && prop.type && (prop.type instanceof ComplexType || prop.type instanceof RefType) - } - - def containsTag = { obj, tag -> - if (! tag ) return false - if (! ((obj instanceof Type) || (obj instanceof Property))) { - return false - } - if (!obj.tags) { - return false - } - return obj.tags.contains(tag) - } - - def containsPropName = { type, propName -> - if (! type ) return false - if (! propName ) return false - if (! (type instanceof Type)) return false - return type.properties.findIndexOf{ - it.name==propName - } != -1 - } - - def missingPropName = { type, propName -> - if (! type ) return false - if (! propName ) return false - if (! (type instanceof Type)) return false - return type.properties.findIndexOf{ - it.name==propName - } == -1 - } - - def missingTag = { obj, tag -> - if (! tag ) return false - if (! ((obj instanceof Type) || (obj instanceof Property))) { - return false - } - if (!obj.tags) { - return false - } - return ! obj.tags.contains(tag) - } - - def propsContainsTag = { type, name -> - if (! type ) return false - if (! name ) return false - if (! (type instanceof Type)) { - return false - } - def result = type.properties.find { it.tags.contains(name) } - if (result) { - return true - } - else { - return false - } - } - - def breakTxt = { String txtToBreak,int charPerLine,String breakText='\n' -> - if (!txtToBreak) return EMPTY - StringBuilder sb = new StringBuilder() - int txtLen = txtToBreak.length() - int aktPos = 0 - while (aktPos < txtLen) { - if ((aktPos + charPerLine) >= txtLen) { - // The rest of the word is smaller than the desired char count per line - sb.append(txtToBreak.substring(aktPos)) - break; - } else { - sb.append(txtToBreak.substring(aktPos, aktPos + charPerLine)) - aktPos += charPerLine - if (txtToBreak.substring(aktPos, aktPos + 1) == ' ') { - sb.append(breakText) - aktPos++ - } else { - for (aktPos; aktPos < txtLen; aktPos++) { - String subStr = txtToBreak.substring(aktPos, aktPos + 1) - if (subStr == ' ') { - sb.append(breakText) - aktPos++ - break - } else { - sb.append(subStr) - } - } - } - } - } - return sb.toString() - } - - def toLowerCase = { str -> - return str==null ? EMPTY : str.toLowerCase() - } - - def toUpperCase = { str -> - return str==null ? EMPTY : str.toUpperCase() - } -*/ def renderInnerTemplate = { templateResource,actObj,indent -> def test = actObj.toString() def innerTemplate = createTemplateFromResource(templateResource,TemplateType.GString) def data = getClosures() data.actObj = actObj data.renderInnerTemplate = renderInnerTemplate - /* - def data = [ - actObj: actObj, - indent: indent, - printIndent: printIndent, - DOLLAR:'$', - toLowerCase: toLowerCase, - toUpperCase: toUpperCase, - firstLowerCase: firstLowerCase, - firstUpperCase: firstUpperCase, - lowerCamelCase: firstLowerCamelCase, - upperCamelCase: firstUpperCamelCase, - isInnerType: isInnerType, - typeToJava: JavaTypeConvert.convert, - typeToSwagger: SwaggerTypeConvert.convert, - typeToJson: JsonTypeConvert.convert, - typeToMeta: JsonTypeConvert.meta, - typeFormatToSwagger: SwaggerTypeConvert.format, - typeFormatToJson: JsonTypeConvert.format, - renderInnerTemplate: renderInnerTemplate, - breakTxt: breakTxt, - filterProps: filterProps, - filterPropsPerform: filterPropsPerform, - printLines: printLines - ] - */ return innerTemplate.make(data) } - def printIndent = { indent -> - def ret = '' - for (def i=0;i - if (!str) return EMPTY - def first = str.substring(0,1) - first = first.toLowerCase() - if (str.length()>1) { - def rest = str.substring(1) - return first + rest - } - else { - return first - } - } - - def firstUpperCase = { str -> - if (!str) return EMPTY - def first = str.substring(0,1) - first = first.toUpperCase() - if (str.length()>1) { - def rest = str.substring(1) - return first + rest - } - else { - return first - } - } - - def firstUpperCamelCase = { str -> - if (!str) return EMPTY - def firstUpper = firstUpperCase(str) - return convertAllUnderLinesToCamelCase(firstUpper) - } - - def firstLowerCamelCase = { str -> - if (!str) return EMPTY - def firstLower = firstLowerCase(str) - return convertAllUnderLinesToCamelCase(firstLower) - } - - def convertAllUnderLinesToCamelCase = { String str -> - if (!str) return EMPTY - def i_ = str.indexOf('_') - while (i_!=-1) { - def stopLen = str.length()-1 - if (i_ extraParameters,Type currentType=null) abstract String getDestDir(Model dataModel, String outputBasePath, Map extraParameters,Type currentType=null) From 86de6c6bb5e0003f250d14ef484d6659b54a973c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20G=C3=BCrtler?= Date: Mon, 30 Jul 2018 17:10:50 +0200 Subject: [PATCH 3/8] Fixed wrong package declaration --- .../de/lisaplus/atlas/codegen/TypeStringManipulation.groovy | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/groovy/de/lisaplus/atlas/codegen/TypeStringManipulation.groovy b/src/main/groovy/de/lisaplus/atlas/codegen/TypeStringManipulation.groovy index 4f33d91..06dff27 100644 --- a/src/main/groovy/de/lisaplus/atlas/codegen/TypeStringManipulation.groovy +++ b/src/main/groovy/de/lisaplus/atlas/codegen/TypeStringManipulation.groovy @@ -1,4 +1,4 @@ -package de.lisaplus.atlas.codegen.meta; +package de.lisaplus.atlas.codegen import de.lisaplus.atlas.codegen.helper.java.JavaTypeConvert import de.lisaplus.atlas.codegen.helper.java.JsonTypeConvert @@ -26,6 +26,8 @@ class TypeStringManipulation { firstUpperCase: firstUpperCase, lowerCamelCase: firstLowerCamelCase, upperCamelCase: firstUpperCamelCase, + firstUpperCamelCase: firstUpperCamelCase, + firstLowerCamelCase: firstLowerCamelCase, isInnerType: isInnerType, isPropComplexType: isPropComplexType, typeToJava: JavaTypeConvert.convert, @@ -118,7 +120,7 @@ class TypeStringManipulation { if ((aktPos + charPerLine) >= txtLen) { // The rest of the word is smaller than the desired char count per line sb.append(txtToBreak.substring(aktPos)) - break; + break } else { sb.append(txtToBreak.substring(aktPos, aktPos + charPerLine)) aktPos += charPerLine From 8f99e42585f87dea8d72efa344c2b7892f0a7da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20G=C3=BCrtler?= Date: Mon, 30 Jul 2018 17:15:16 +0200 Subject: [PATCH 4/8] GeneratorBase must extend TypeStringManipulation for closure visibility Otherwise the closures are not visible in the sub-types of GeneratorBase! --- .../de/lisaplus/atlas/codegen/GeneratorBase.groovy | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy b/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy index f603323..cb872bc 100644 --- a/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy +++ b/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy @@ -1,22 +1,19 @@ package de.lisaplus.atlas.codegen import de.lisaplus.atlas.DoCodeGen -import de.lisaplus.atlas.codegen.meta.TypeStringManipulation import de.lisaplus.atlas.model.Model import de.lisaplus.atlas.model.Type import groovy.text.GStringTemplateEngine import groovy.text.Template import groovy.text.TemplateEngine -import groovy.text.XmlTemplateEngine import groovy.text.markup.MarkupTemplateEngine -import org.codehaus.groovy.runtime.StringBufferWriter import org.slf4j.Logger /** * Created by eiko on 05.06.17. */ -abstract class GeneratorBase { +abstract class GeneratorBase extends TypeStringManipulation { Template template static void createDir(String dirName) { @@ -131,13 +128,15 @@ abstract class GeneratorBase { } /** - * methon create a map object and initialize it with some basic string manipulation stuff + * method create a map object and initialize it with some basic string manipulation stuff * needed for working with the types and their properties in the templates. * @return */ + /* Map getClosures() { return new TypeStringManipulation().getClosures() } + */ /** * methon create a map object and initialize it with some basic stuff From 58ce4fcb58de013f6a53a45a9a82ef8ec43c1c99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20G=C3=BCrtler?= Date: Thu, 2 Aug 2018 12:29:04 +0200 Subject: [PATCH 5/8] Minor cosmetic changes --- .../de/lisaplus/atlas/codegen/TypeStringManipulation.groovy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/groovy/de/lisaplus/atlas/codegen/TypeStringManipulation.groovy b/src/main/groovy/de/lisaplus/atlas/codegen/TypeStringManipulation.groovy index 06dff27..d2704b6 100644 --- a/src/main/groovy/de/lisaplus/atlas/codegen/TypeStringManipulation.groovy +++ b/src/main/groovy/de/lisaplus/atlas/codegen/TypeStringManipulation.groovy @@ -245,7 +245,7 @@ class TypeStringManipulation { return props } - // Closure> filterPropsPerform = {Type type, Map params, Closure toLines -> + // Closure> filterPropsPerform = {Type type, Map params, Closure> toLines -> def filterPropsPerform = { type, params, toLines -> def props = filterProps.call(type, params) def lines = [] @@ -261,13 +261,13 @@ class TypeStringManipulation { } // Vararg definition is mandatory, call example: printLines3.call( [level:2, by: '.-'], new StringWriter(), list, list2 ) - // Closure printLines3 = { Writer out, Map params, List... lists -> + // Closure printLines = { Writer out, Map params, List... lists -> def printLines = { out, params,List... lists -> def level = params.level?:0 def by = params.by?:' ' def prefix = '' level.times { prefix += by} - lists.flatten().each { out << "$prefix$it\n" } + lists.flatten().each { line -> out << "${prefix}${line}\n" } } private final static String EMPTY='' From e5e74cbf907a52b754b4b8a9ddc1507f70eeb7ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20G=C3=BCrtler?= Date: Thu, 2 Aug 2018 12:29:31 +0200 Subject: [PATCH 6/8] Added getDefaultValue() --- .../groovy/de/lisaplus/atlas/model/Property.groovy | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/groovy/de/lisaplus/atlas/model/Property.groovy b/src/main/groovy/de/lisaplus/atlas/model/Property.groovy index 71a219a..11daeab 100644 --- a/src/main/groovy/de/lisaplus/atlas/model/Property.groovy +++ b/src/main/groovy/de/lisaplus/atlas/model/Property.groovy @@ -62,4 +62,16 @@ class Property { boolean hasTag(String tag) { return tags && tags.contains(tag) } + + /** + * The default value defined in the tags, or null, if none was defined. + * The default value tag defaultTrue is returned as True! + */ + String getDefaultValue() { + def value = null + if (tags) { + value = tags.find {it =~ 'default.*'}?.drop(7) + } + return value + } } From 0cc672cbb8942f02f78337fb8ce7c94233ecc662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20G=C3=BCrtler?= Date: Tue, 14 Aug 2018 12:11:44 +0200 Subject: [PATCH 7/8] Bugfix: Do add indent to bindings --- src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy b/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy index cb872bc..26a5b1a 100644 --- a/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy +++ b/src/main/groovy/de/lisaplus/atlas/codegen/GeneratorBase.groovy @@ -139,7 +139,7 @@ abstract class GeneratorBase extends TypeStringManipulation { */ /** - * methon create a map object and initialize it with some basic stuff + * method create a map object and initialize it with some basic stuff * @param model * @return */ @@ -155,6 +155,7 @@ abstract class GeneratorBase extends TypeStringManipulation { def innerTemplate = createTemplateFromResource(templateResource,TemplateType.GString) def data = getClosures() data.actObj = actObj + data.indent = indent data.renderInnerTemplate = renderInnerTemplate return innerTemplate.make(data) } From e9be23fb635b27ae47cebc1fabf8a66a6d7351f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20G=C3=BCrtler?= Date: Tue, 14 Aug 2018 12:16:29 +0200 Subject: [PATCH 8/8] Dirty hack for enabling the usage of mongoDB Index2d If one type contains properties named lon and lat, reorder properties to have these two at the top. For performing filtering on geo coordinates in Documents of the mongoDB (e.g. operation geoWithin), the Json document containing the coordinates must have the longitude/X coordinate as first property and the latitude/Y coordinate as second property (property names are irrelevant!). But as JsonSlurper reorders the properties in alphabetic sequence, we can not force the necessary longitude / latitude sequence by defining it in the model json. Therefore this code tests for the existence of the properties lon and lat. If both are present, then the properties are reordered so that lon and lat come first! --- .../atlas/builder/JsonSchemaBuilder.groovy | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/groovy/de/lisaplus/atlas/builder/JsonSchemaBuilder.groovy b/src/main/groovy/de/lisaplus/atlas/builder/JsonSchemaBuilder.groovy index e2aebde..67cccd8 100644 --- a/src/main/groovy/de/lisaplus/atlas/builder/JsonSchemaBuilder.groovy +++ b/src/main/groovy/de/lisaplus/atlas/builder/JsonSchemaBuilder.groovy @@ -234,6 +234,22 @@ class JsonSchemaBuilder implements IModelBuilder { propertyParent.properties.each { propObj -> propList.add(creeateSimpleProperty(model, parentName,currentSchemaPath,propObj)) } + // Dirty hack for enabling the usage of mongoDB Index2d: + // For performing filtering on geo coordinates in Documents of the mongoDB (e.g. operation geoWithin), the Json + // document containing the coordinates must have the longitude/X coordinate as first property and the latitude/Y + // coordinate as second property (property names are irrelevant!). + // But as JsonSlurper reorders the properties in alphabetic sequence, we can not force the necessary + // longitude / latitude sequence by defining it in the model json. + // Therefore this code tests for the existence of the properties lon and lat. If both are present, + // then the properties are reordered so that lon and lat come first! + Property lonProp = propList.find {prop -> prop.name == 'lon'} + Property latProp = propList.find {prop -> prop.name == 'lat'} + if (lonProp && latProp) { + propList.remove(lonProp) + propList.remove(latProp) + propList.add(0, latProp) + propList.add(0, lonProp) + } return propList }