Module: DataMetaDom::ScalaLexer
- Includes:
- DataMetaDom
- Defined in:
- lib/dataMetaDom/scala.rb
Overview
Definition for generating Scala artifacts such as case classes and everything related that depends on Scala distro only witout any other dependencies.
For command line details either check the new method’s source or the README.rdoc file, the usage section.
Constant Summary collapse
- SCALA_SUBPACKAGE =
Scala Data Meta export subpackage, to distinguish between other platforms. Can not make it just “.scala” because if someone imports all the data model classes with underscore, they may pick up the “scala” subpackage too.
In which case, they will have trouble importing anything from the Scala core by “scala.*”, that violates the principle of “Least Astonishment”, they may dink around till they find out that they will have to use the root package to access the Scala core’s “scala”, not the exported DataMeta “scala”.
'scadm'- TEXTUAL_TYPER =
Renderer for the String type.
lambda{|t| 'String'}
- SCALA_IMPORTS =
Maps DataMeta DOM datatypes to the matching Scala classes, for those that need to be imported. The Scala source generator will import these if they are used in the class.
{ DATETIME => 'java.time.ZonedDateTime', NUMERIC => 'scala.math.BigDecimal' }
- AGGR_CLASSES =
DataMeta DOM aggregated field type spec mapped to matching Scala Case class:
{ Field::SET => 'scala.collection.Seq', # for Case classes, if the identity is different that full set of fields, Set makes no sense # which is a majority of the cases. Wait for full implementation and switch to scala.collection.mutable.Set Field::LIST => 'scala.collection.immutable.List', Field::DEQUE => 'scala.collection.Seq', }
- SCALA_TYPES =
A map from DataMeta DOM standard types to the lambdas that render correspondent Scala types per Scala syntax.
We used to render the primitives for the required types but the Verifiable interface made it impractical.
{ DataMetaDom::INT => lambda{ |t| len = t.length case when len <= 4; 'Int' when len <=8; 'Long' else; raise "Invalid integer length #{len}" end }, STRING => TEXTUAL_TYPER, DATETIME => lambda{|t| 'ZonedDateTime'}, BOOL => lambda{|t| 'Boolean'}, # req ? 'boolean' : 'Boolean'}, CHAR => TEXTUAL_TYPER, FLOAT => lambda{|t| len = t.length case when len <= 4; 'Float' # req ? 'float' : 'Float' when len <=8; 'Double' #req ? 'double' : 'Double' else; raise "Invalid float length #{len}" end }, RAW => lambda{|t| 'Array[Byte]'}, URL => lambda{|t| URL_CLASS}, NUMERIC => lambda{|t| 'BigDecimal'} }
- MAX_MAPPING_SIZE =
Maximum size of a Mapping (Map), rather aribtrary choice, not backed by any big idea.
10000
Constants included from DataMetaDom
BITSET, BOOL, BOOL_CONV, CANNED_RX, CHAR, CONVS, DATAMETA_LIB, DATETIME, DIMMED_TYPES, DOC, DOC_TARGETS, DTTM_CONV, DTTM_TYPE, END_KW, ENUM, FLOAT, FLOAT4, FLOAT8, FRACT_CONV, FULL_COMPARE, IDENTITY, ID_ONLY_COMPARE, ID_START, INCLUDE, INDENT, INDEX, INT, INT1, INT2, INT4, INT8, INTEGRAL_CONV, JAVA_DOC_TARGET, L, MAPPING, MATCHES, MODEL_LEVEL_TOKENS, NAMESPACE, NO_NAMESPACE, NUMERIC, OPTIONAL_PFX, OPT_DIMMABLE, PACK_SEPARATOR, PLAIN_DOC_TARGET, RAW, RECORD, RECORD_LEVEL_TOKENS, REC_ATTR_KEYWORDS, REQUIRED_PFX, SAME_FULL_SFX, SAME_ID_SFX, SCALE_TYPES, SOURCE_INDENT, STANDARD_TYPES, STRING, TEXT_CONV, TYPE_START, UNIQUE, URL, URL_TYPE, VERSION, VER_KW, WIKI, WIKI_REF_HTML
Class Method Summary collapse
-
.aggrScalaType(f, scalaPackage) ⇒ Object
aggregated Scala type.
-
.aggrType(aggr, trg, rawType, scalaPackage) ⇒ Object
Figures out type adjusted for aggregates and maps.
- .condenseType(fullType, ref_namespace) ⇒ Object
-
.genCaseClasses(model, outRoot) ⇒ Object
Generates scala sources for the model, the POJOs.
-
.genEntity(model, out, record, scalaPackage) ⇒ Object
Generates Scala source code, the Scala class for a DataMeta DOM Record.
-
.genEnumWorded(out, enum) ⇒ Object
Generates Scala source code for the worded enum, DataMeta DOM keyword “
enum”. -
.scalaNs(ns) ⇒ Object
Distinguish JVM classes by the platform, unless it’s Java.
-
.unaggrScalaType(dt, scalaPackage) ⇒ Object
Unaggregated Scala type.
Instance Method Summary collapse
-
#assertNamespace(name) ⇒ Object
Extracts 3 pieces of information from the given full name: * The namespace if any, i.e.
-
#classScalaDoc(docs) ⇒ Object
Scala Class ScalaDoc text with the Wiki reference.
-
#enumScalaDoc(docs) ⇒ Object
Scala Enum class-level ScalaDoc text with the Wiki reference.
-
#getScalaType(dmDomType) ⇒ Object
For the given DataMeta DOM data type and the isRequired flag, builds and returns the matching Scala data type declaration.
-
#scalaDocs(docs) ⇒ Object
Given the property
docsof Documentable, return the SCALA_DOC_TARGET if it is present, PLAIN_DOC_TARGET otherwise.
Methods included from DataMetaDom
combineNsBase, fullTypeName, getParenDimInfo, getterName, help, helpAndVerFirstArg, helpMySqlDdl, #helpOracleDdl, helpPojoGen, helpScalaGen, #migrClass, nsAdjustment, #qualName, setterName, splitNameSpace, uniPath, validNs?
Class Method Details
.aggrScalaType(f, scalaPackage) ⇒ Object
aggregated Scala type
125 126 127 128 129 |
# File 'lib/dataMetaDom/scala.rb', line 125 def self.aggrScalaType(f, scalaPackage) rawType = self.unaggrScalaType(f.dataType, scalaPackage) aggr = f.aggr? ? DataMetaDom.splitNameSpace(AGGR_CLASSES[f.aggr])[1] : nil ScalaLexer.aggrType(aggr, f.trgType, rawType, scalaPackage) end |
.aggrType(aggr, trg, rawType, scalaPackage) ⇒ Object
Figures out type adjusted for aggregates and maps.
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/dataMetaDom/scala.rb', line 91 def aggrType(aggr, trg, rawType, scalaPackage) if aggr k = rawType.to_sym subType = rawType # PRIMS_TO_WRAP.has_key?(k) ? PRIMS_TO_WRAP[k] : "#{aggr}[#{subType}]" elsif trg k = rawType.to_sym srcType = rawType typeRenderer = SCALA_TYPES[trg.type] rawTrg = typeRenderer ? typeRenderer.call(trg) : self.condenseType(self.scalaNs(trg.type), scalaPackage) k = rawTrg.to_sym trgType = rawTrg "Map[#{srcType}, #{trgType}]" else rawType end end |
.condenseType(fullType, ref_namespace) ⇒ Object
111 112 113 114 115 116 |
# File 'lib/dataMetaDom/scala.rb', line 111 def self.condenseType(fullType, ref_namespace) ns, base = DataMetaDom.splitNameSpace(fullType) ns = self.scalaNs(ns) # noinspection RubyNestedTernaryOperatorsInspection DataMetaDom.validNs?(ns, base) ? ( ns == ref_namespace ? base : fullType) : fullType end |
.genCaseClasses(model, outRoot) ⇒ Object
Generates scala sources for the model, the POJOs.
-
Parameters
-
parser- instance of Model -
outRoot- output directory
-
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/dataMetaDom/scala.rb', line 241 def genCaseClasses(model, outRoot) firstRec = model.records.values.first raise ArgumentError, "No records defined in the model #{model.sources.masterPath}" unless firstRec scalaPackage, base, packagePath = assertNamespace(firstRec.name) scalaPackage = self.scalaNs(scalaPackage) destDir = File.join(outRoot, packagePath, SCALA_SUBPACKAGE) # keep this in sync with scalaNs FileUtils.mkdir_p destDir out = File.open(File.join(destDir, 'Model.scala'), 'wb') begin out.puts %<package #{scalaPackage} import java.time.ZonedDateTime import scala.math.BigDecimal import scala.collection.immutable.Set import scala.collection.immutable.List import scala.collection.Seq /** * This content is generated by DataMeta, do not edit manually! */ > (model.enums.values + model.records.values).each {|e| case when e.kind_of?(DataMetaDom::Record) self.genEntity model, out, e, scalaPackage when e.kind_of?(DataMetaDom::Mappings) raise ArgumentError, "For name #{e.name}: Mappings can not be generated to a case class" when e.kind_of?(DataMetaDom::Enum) self.genEnumWorded out, e when e.kind_of?(DataMetaDom::BitSet) raise ArgumentError, "For name #{e.name}: BitsSets can not be generated to a case class" else raise "Unsupported Entity: #{e.inspect}" end } ensure out.close end end |
.genEntity(model, out, record, scalaPackage) ⇒ Object
Generates Scala source code, the Scala class for a DataMeta DOM Record
Parameters:
-
model- the source model to export from -
out- open output file to write the result to. -
record- instance of DataMetaDom::Record to export -
scalaPackage- Scala package to export to -
baseName- the name of the class to generate.
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/dataMetaDom/scala.rb', line 184 def self.genEntity(model, out, record, scalaPackage) baseName = record.baseName fields = record.fields out.puts <<ENTITY_CLASS_HEADER #{record.docs.empty? ? '' : ScalaLexer.classScalaDoc(record.docs)}case class #{baseName} ( #{fields.keys.map { |k| f = fields[k] typeDef = self.aggrScalaType(f, scalaPackage) " `#{f.name}`: #{typeDef}#{model.enums.keys.member?(f.dataType.type) ? '.Value' : ''}" }.join(",\n ") } ) ENTITY_CLASS_HEADER end |
.genEnumWorded(out, enum) ⇒ Object
Generates Scala source code for the worded enum, DataMeta DOM keyword “enum”.
203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/dataMetaDom/scala.rb', line 203 def self.genEnumWorded(out, enum) values = enum.keys.map{|k| enum[k]} # sort by ordinals to preserve the order _, base, _ = assertNamespace(enum.name) out.puts %< #{enum.docs.empty? ? '' : enumScalaDoc(enum.docs)}object #{base} extends Enumeration { type #{base} = Value val #{values.map{|v| "`#{v}`"}.join(', ')} = Value } > end |
.scalaNs(ns) ⇒ Object
Distinguish JVM classes by the platform, unless it’s Java
216 217 218 |
# File 'lib/dataMetaDom/scala.rb', line 216 def self.scalaNs(ns) "#{ns}.#{SCALA_SUBPACKAGE}" end |
.unaggrScalaType(dt, scalaPackage) ⇒ Object
Unaggregated Scala type
119 120 121 122 |
# File 'lib/dataMetaDom/scala.rb', line 119 def self.unaggrScalaType(dt, scalaPackage) typeRenderer = SCALA_TYPES[dt.type] typeRenderer ? typeRenderer.call(dt) : self.condenseType(self.scalaNs(dt.type), scalaPackage) end |
Instance Method Details
#assertNamespace(name) ⇒ Object
Extracts 3 pieces of information from the given full name:
-
The namespace if any, i.e. Scala package, empty string if none
-
The base name for the type, without the namespace
-
Scala package’s relative path, the dots replaced by the file separator.
Returns an array of these pieces of info in this exact order as described here.
228 229 230 231 232 233 234 |
# File 'lib/dataMetaDom/scala.rb', line 228 def assertNamespace(name) ns, base = DataMetaDom.splitNameSpace(name) scalaPackage = DataMetaDom.validNs?(ns, base) ? ns : '' packagePath = scalaPackage.empty? ? '' : scalaPackage.gsub('.', File::SEPARATOR) [scalaPackage, base, packagePath] end |
#classScalaDoc(docs) ⇒ Object
Scala Class ScalaDoc text with the Wiki reference.
146 147 148 149 150 151 152 |
# File 'lib/dataMetaDom/scala.rb', line 146 def classScalaDoc(docs) return <<CLASS_SCALADOC /** #{ScalaLexer.scalaDocs(docs)} */ CLASS_SCALADOC end |
#enumScalaDoc(docs) ⇒ Object
Scala Enum class-level ScalaDoc text with the Wiki reference.
157 158 159 160 161 162 163 |
# File 'lib/dataMetaDom/scala.rb', line 157 def enumScalaDoc(docs) return <<ENUM_SCALADOC /** #{ScalaLexer.scalaDocs(docs)} */ ENUM_SCALADOC end |
#getScalaType(dmDomType) ⇒ Object
For the given DataMeta DOM data type and the isRequired flag, builds and returns the matching Scala data type declaration. For standard types, uses the SCALA_TYPES map
169 170 171 172 |
# File 'lib/dataMetaDom/scala.rb', line 169 def getScalaType(dmDomType) typeRenderer = SCALA_TYPES[dmDomType.type] typeRenderer ? typeRenderer.call(dmDomType) : dmDomType.type end |
#scalaDocs(docs) ⇒ Object
Given the property docs of Documentable, return the SCALA_DOC_TARGET if it is present, PLAIN_DOC_TARGET otherwise. Returns empty string if the argument is nil.
134 135 136 137 138 139 140 141 142 |
# File 'lib/dataMetaDom/scala.rb', line 134 def scalaDocs(docs) return '' unless docs case when docs[PLAIN_DOC_TARGET] docs[PLAIN_DOC_TARGET].text else '' end end |