Last active
April 9, 2020 13:23
-
-
Save turboBasic/c48e4f5adc4925a0f454b9f6acfc943d to your computer and use it in GitHub Desktop.
Represent Groovy class as Map #groovy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| interface Mappable { | |
| Map asMap() | |
| } | |
| abstract class AbstractMappableImpl implements Mappable { | |
| Set options | |
| Set getOptions() { | |
| options | |
| } | |
| void setOptions(Collection options) { | |
| this.options = options as Set | |
| } | |
| void setOptions(def options) { | |
| setOptions([options].flatten()) | |
| } | |
| @NonCPS | |
| final Map asMap() { | |
| fieldsProvider() | |
| .collectEntries { | |
| [(it.name): fieldTransformer(it)] | |
| } | |
| } | |
| @NonCPS | |
| List fieldsProvider() { | |
| ownFieldsProvider() | |
| } | |
| abstract def fieldTransformer(def field) | |
| @NonCPS | |
| final List ownFieldsProvider() { | |
| privateFields().toList() + | |
| allProperties().toList() | |
| } | |
| @NonCPS | |
| final protected List privateFields() { | |
| this.class | |
| .declaredFields | |
| .findAll { | |
| !it.synthetic && | |
| it.modifiers != java.lang.reflect.Modifier.PUBLIC | |
| } | |
| } | |
| @NonCPS | |
| final protected List allProperties() { | |
| this.metaClass | |
| .properties | |
| .findAll { 'class' != it.name } | |
| } | |
| } | |
| class MappableImpl extends AbstractMappableImpl { | |
| enum Options { | |
| OWN_PROPERTIES, | |
| INHERITED_PROPERTIES, | |
| RECURSE_INTO_CLASSES, | |
| PRIVATE_FIELDS | |
| } | |
| Set options = [ | |
| Options.OWN_PROPERTIES, | |
| Options.INHERITED_PROPERTIES, | |
| ] | |
| @NonCPS | |
| @Override | |
| Set<Options> getOptions() { | |
| options.intersect(Options.values().toList()) | |
| } | |
| void setOptions(Collection options) { | |
| Set result = [] as Set | |
| options.each { | |
| try { | |
| result << Options.valueOf( "${it}".trim().toUpperCase() ) | |
| } | |
| catch(e) {} | |
| } | |
| this.options = result | |
| } | |
| @NonCPS | |
| @Override | |
| List fieldsProvider() { | |
| super.fieldsProvider() | |
| .findAll { | |
| if (!options.contains(Options.INHERITED_PROPERTIES)) | |
| return it.type == this.class | |
| if (!options.contains(Options.OWN_PROPERTIES)) | |
| return it.type != this.class | |
| if (!options.contains(Options.PRIVATE_FIELDS)) { | |
| return it.type != this.class | |
| } | |
| } | |
| } | |
| @NonCPS | |
| @Override | |
| def fieldTransformer(def field) { | |
| def obj | |
| if (field instanceof java.lang.reflect.Field) { | |
| obj = field.getType() | |
| } else { | |
| obj = field | |
| } | |
| if (Options.RECURSE_INTO_CLASSES in options) { | |
| if (Mappable.isAssignableFrom(obj)) | |
| delegate."${obj.name}" ?. asMap() | |
| else | |
| delegate."${obj.name}" | |
| } else { | |
| this."${field.name}" | |
| } | |
| } | |
| @NonCPS | |
| Mappable withOptions(def options) { | |
| if (options instanceof Collection) | |
| setOptions(this.options + options) | |
| else | |
| setOptions(this.options + [options]) | |
| return this | |
| } | |
| } | |
| class Y extends MappableImpl { | |
| String yProp1 = '111' | |
| private String yField2 = 'private in Y' | |
| } | |
| class Z extends Y { | |
| Map zProp1 = [ | |
| a: 12, | |
| b: 'xxx' | |
| ] | |
| private String zField = 'private in Z' | |
| } | |
| String prettify(def obj) { | |
| groovy.json.JsonOutput.prettyPrint( | |
| groovy.json.JsonOutput.toJson(obj) | |
| ) | |
| } | |
| @NonCPS | |
| def getData() { | |
| Map y = new Y().asMap() | |
| Map z = new Z().withOptions(['INHERITED_PROPERTIES', 'PRIVATE_FIELDS','RECURSE_INTO_CLASSES']).asMap() | |
| return [ y, z ] | |
| } | |
| node() { | |
| println 'y: ' + prettify(getData()[0]) | |
| println 'z: ' + prettify(getData()[1]) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment