com.sksamuel.avro4s.Records.scala Maven / Gradle / Ivy
//
// private[avro4s] def verifyNewSchema[T](schemaFor: SchemaFor[T]) = {
// val schemaType = schemaFor.schema.getType
// if (schemaType != Schema.Type.RECORD)
// throw new Avro4sConfigurationException(
// s"Schema type for record codecs must be RECORD, received ${schemaFor.schema}")
// }
//
// def encoder[T: WeakTypeTag](ctx: CaseClass[Encoder, T],
// env: DefinitionEnvironment[Encoder],
// update: SchemaUpdate,
// fieldMapper: FieldMapper): Encoder[T] = {
// val record = buildRecordSchema(ctx, update)
// val schemaFor = SchemaFor[T](record, fieldMapper)
// val encoder = new RecordEncoder[T](ctx, schemaFor)
// val nextEnv = env.updated(encoder)
// val fieldsAndEncoders = ctx.parameters.flatMap { param =>
// val annotations = new AnnotationExtractors(param.annotations)
// if (annotations.transient) None else Some(new FieldEncoder(param)(nextEnv, update, record, ctx, fieldMapper))
// }
// val encoders = fieldsAndEncoders.map(_._2)
// update match {
// case FullSchemaUpdate(_) =>
// encoder.fieldEncoding =
// record.getFields.asScala.map(f => encoders.find(e => e.fieldName == f.name).get).toVector
//
// case _ =>
// val fields = fieldsAndEncoders.map(_._1)
// record.setFields(fields.asJava)
// encoder.fieldEncoding = encoders.toVector
// }
// encoder
// }
//
// def decoder[T: WeakTypeTag](ctx: CaseClass[Decoder, T],
// env: DefinitionEnvironment[Decoder],
// update: SchemaUpdate,
// fieldMapper: FieldMapper): Decoder[T] = {
// val record = buildRecordSchema(ctx, update)
// val schemaFor = SchemaFor[T](record, fieldMapper)
// val decoder = new RecordDecoder[T](ctx, schemaFor)
// val nextEnv = env.updated(decoder)
// val fieldsAndDecoders = ctx.parameters.zipWithIndex.map {
// case (param, idx) =>
// new FieldDecoder[T](param)(idx, nextEnv, update, record, ctx, fieldMapper)
// }
// val decoders = fieldsAndDecoders.map(_._2)
// update match {
// case FullSchemaUpdate(_) =>
// decoder.fieldDecoding = decoders.toVector
//
// case _ =>
// val fields = fieldsAndDecoders.flatMap(_._1)
// record.setFields(fields.asJava)
// decoder.fieldDecoding = decoders.toVector
// }
// decoder
// }
//
// def schema[T: WeakTypeTag](ctx: CaseClass[SchemaFor, T],
// env: DefinitionEnvironment[SchemaFor],
// update: SchemaUpdate,
// fieldMapper: FieldMapper): SchemaFor[T] = {
// val record = buildRecordSchema(ctx, update)
// // early incomplete construction here for potentially recursive schema definitions
// val schemaFor = SchemaFor[T](record, fieldMapper)
// val nextEnv = env.updated(schemaFor)
// val fields = ctx.parameters.flatMap { param =>
// val annotations = new AnnotationExtractors(param.annotations)
// if (annotations.transient) None
// else {
// val doc = valueTypeDoc(ctx, param)
// val schema = param.typeclass.resolveSchemaFor(nextEnv, NoUpdate).schema
// Some(buildSchemaField(param, schema, annotations, record.getNamespace, fieldMapper, doc))
// }
// }.asJava
// record.setFields(fields)
// schemaFor
// }
//
// def buildRecordSchema[Typeclass[_]](ctx: CaseClass[Typeclass, _], update: SchemaUpdate): Schema = {
// def newSchema(namespaceUpdate: Option[String]) = {
// val annotations = new AnnotationExtractors(ctx.annotations)
//
// val nameExtractor = NameExtractor(ctx.typeName, ctx.annotations)
// val namespace = namespaceUpdate.getOrElse(nameExtractor.namespace)
// val name = nameExtractor.name
//
// val record =
// Schema.createRecord(name.replaceAll("[^a-zA-Z0-9_]", ""),
// annotations.doc.orNull,
// namespace.replaceAll("[^a-zA-Z0-9_.]", ""),
// false)
// annotations.aliases.foreach(record.addAlias)
// annotations.props.foreach { case (k, v) => record.addProp(k: String, v: AnyRef) }
// record
// }
//
// update match {
// case FullSchemaUpdate(sf) =>
// if (sf.schema.getType != Schema.Type.RECORD)
// throw new Avro4sConfigurationException(s"Schema for case classes must be of type Record, got ${sf.schema}")
// sf.schema
// case NamespaceUpdate(namespace) => newSchema(Some(namespace))
// case _ => newSchema(None)
// }
// }
//
// private[avro4s] def buildSchemaField[Typeclass[_], T](param: Param[Typeclass, T],
// baseSchema: Schema,
// extractor: AnnotationExtractors,
// containingNamespace: String,
// fieldMapper: FieldMapper,
// valueTypeDoc: Option[String]): Schema.Field = {
// val doc = extractor.doc.orElse(valueTypeDoc).orNull
// val default: Option[AnyRef] = if (extractor.nodefault) None else param.default.asInstanceOf[Option[AnyRef]]
// val aliases = extractor.aliases
// val props = extractor.props
//
// // the name could have been overriden with @AvroName, and then must be encoded with the field mapper
// val name = extractor.name.getOrElse(fieldMapper.to(param.label))
//
// // the default value may be none, in which case it was not defined, or Some(null), in which case it was defined
// // and set to null, or something else, in which case it's a non null value
// val encodedDefault: AnyRef = default match {
// case None => null
// case Some(None) => JsonProperties.NULL_VALUE
// case Some(null) => JsonProperties.NULL_VALUE
// case Some(other) => DefaultResolver(other, baseSchema)
// }
//
// // if we have annotated with @AvroFixed then we override the type and change it to a Fixed schema
// // if someone puts @AvroFixed on a complex type, it makes no sense, but that's their cross to bear
// val schema = extractor.fixed.fold(baseSchema) { size =>
// SchemaBuilder.fixed(name).doc(doc).namespace(extractor.namespace.getOrElse(containingNamespace)).size(size)
// }
//
// // if our default value is null, then we should change the type to be nullable even if we didn't use option
// val schemaWithPossibleNull = if (default.contains(null) && schema.getType != Schema.Type.UNION) {
// SchemaBuilder.unionOf().`type`(schema).and().`type`(Schema.create(Schema.Type.NULL)).endUnion()
// } else schema
//
// // for a union the type that has a default must be first (including null as an explicit default)
// // if there is no default then we'll move null to head (if present)
// // otherwise left as is
// val schemaWithOrderedUnion = (schemaWithPossibleNull.getType, encodedDefault) match {
// case (Schema.Type.UNION, null) => SchemaHelper.moveNullToHead(schemaWithPossibleNull)
// case (Schema.Type.UNION, JsonProperties.NULL_VALUE) => SchemaHelper.moveNullToHead(schemaWithPossibleNull)
// case (Schema.Type.UNION, defaultValue) => SchemaHelper.moveDefaultToHead(schemaWithPossibleNull, defaultValue)
// case _ => schemaWithPossibleNull
// }
//
// // the field can override the containingNamespace if the Namespace annotation is present on the field
// // we may have annotated our field with @AvroNamespace so this containingNamespace should be applied
// // to any schemas we have generated for this field
// val schemaWithResolvedNamespace = extractor.namespace
// .map(SchemaHelper.overrideNamespace(schemaWithOrderedUnion, _))
// .getOrElse(schemaWithOrderedUnion)
//
// val field = encodedDefault match {
// case null => new Schema.Field(name, schemaWithResolvedNamespace, doc)
// case CustomUnionDefault(_, m) =>
// new Schema.Field(name, schemaWithResolvedNamespace, doc, m)
// case CustomEnumDefault(m) =>
// new Schema.Field(name, schemaWithResolvedNamespace, doc, m)
// case CustomUnionWithEnumDefault(_, _, m) => new Schema.Field(name, schemaWithResolvedNamespace, doc, m)
// case _ => new Schema.Field(name, schemaWithResolvedNamespace, doc, encodedDefault)
// }
//
// props.foreach { case (k, v) => field.addProp(k, v: AnyRef) }
// aliases.foreach(field.addAlias)
// field
// }
//
// private[avro4s] def valueTypeDoc[Typeclass[_], _](ctx: CaseClass[Typeclass, _],
// param: Param[Typeclass, _]): Option[String] =
// try {
// // if the field is a value type then we may have annotated it with @AvroDoc, and that doc should be
// // placed onto the field, not onto the record type, because there won't be a record type for a value type!
// // magnolia won't give us the type of the parameter, so we must find it in the class type
// import scala.reflect.runtime.universe
// val mirror = universe.runtimeMirror(Thread.currentThread().getContextClassLoader)
// val sym = mirror.staticClass(ctx.typeName.full).primaryConstructor.asMethod.paramLists.head(param.index)
//
// val anyValSym = typeOf[AnyVal].typeSymbol
// val typeSym = sym.typeSignature.typeSymbol
// if (typeSym.isClass && typeSym.asClass.baseClasses.contains(anyValSym)) {
// typeSym.annotations.collectFirst {
// case a if a.tree.tpe =:= typeOf[AvroDoc] =>
// val annoValue = a.tree.children.tail.head.asInstanceOf[Literal].value.value
// annoValue.toString
// }
// } else {
// None
// }
//
// } catch {
// case NonFatal(_) => None
// }
//}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy