1

Here is my code

scala> s res6: String = 2005-05-06 14:58:56 192 45.14.5.238 200 TCP_NC_MISS 1123 496 GET http c4.maxserving.com /gen.js ?site=5835&area=side_ros&group=sidebar&PageID=33364329499 - DIRECT c4.maxserving.com application/x-javascript "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" PROXIED Web%20Advertisements - 192.16.170.44 SG-HTTP-Service - none - scala> s.split("\\s") res7: Array[String] = Array(2005-05-06, 14:58:56, 192, 45.14.5.238, 200, TCP_NC_MISS, 1123, 496, GET, http, c4.maxserving.com, /gen.js, ?site=5835&area=side_ros&group=sidebar&PageID=33364329499, -, DIRECT, c4.maxserving.com, application/x-javascript, "Mozilla/4.0, (compatible;, MSIE, 6.0;, Windows, NT, 5.1;, SV1;, .NET, CLR, 1.1.4322)", PROXIED, Web%20Advertisements, -, 192.16.170.44, SG-HTTP-Service, -, none, -) scala> case class BlueCoatEvent(date: String, | time: String, | timeTaken: String, | cIp: String, | scStatus: String, | sAction: String, | scBytes: String, | csBytes: String, | csMethod: String, | csUriScheme: String, | csHost: String, | csUriPath: String, | csUriQuery: String, | csUsername: String, | sHierarchy: String, | sSupplierName: String, | rsContentType: String, | csUserAgent: String, | scFilterResult: String, | scFilterCategory: String, | xVirusId: String, | sIp: String, | sSiteName: String, | xVirusDetails: String, | xIcapErrorCode: String, | xIcapErrorDetails: String) defined class BlueCoatEvent scala> 

How do I create blueCoatEvent from s.split("\\s")?

3
  • 2
    Using meaningful types would make your life a lot better, I promise. Commented Oct 7, 2015 at 21:35
  • Thanks @TravisBrown, I second that, I will change them Commented Oct 7, 2015 at 22:18
  • From the name, it looks like several groups of these are related. Probably those should have their own case classf es and the blueCoatEvent is composed of one of each of them + whatever is leftover Commented Oct 8, 2015 at 6:34

3 Answers 3

2
  1. See answer in Instantiating a case class from a list of parameters

  2. Introduce meaningsful sub-types/case classes and compose BlueCoatEvent with them.

Sign up to request clarification or add additional context in comments.

Comments

1

The ugly horrible way is this:

scala> case class A(x: String, y: String, z: String) defined class A scala> def toTuple[A <: Object](as:List[A]):Product = { | val tupleClass = Class.forName("scala.Tuple" + as.size) | tupleClass.getConstructors.apply(0).newInstance(as:_*).asInstanceOf[Product] | } toTuple: [A <: Object](as: List[A])Product scala> val l = List("a", "b", "c") l: List[String] = List(a, b, c) scala> val t3 = toTuple(l).asInstanceOf[Tuple3[String, String, String]] t3: (String, String, String) = (a,b,c) scala> val f = A.tupled f: ((String, String, String)) => A = <function1> scala> f(t3) res0: A = A(a,b,c) 

You can use any way you want to convert from collection to TupleN:

I picked toTuple from there.

This is unsafe, ugly and does not save you much. You can resort to code generation, reflection or macros to get something more helpful.

Another option:

Based on this idea Applying an argument list to curried function using foldLeft in Scala we can use A.curried with HList to produce a cleaner solution:

object CaseClassFromList extends App { sealed trait HList final case class HCons[H, T <: HList](head : H, tail : T) extends HList { def ::[H1](h : H1) = HCons(h, this) override def toString = head+" :: "+tail.toString } trait HNil extends HList { def ::[H1](h : H1) = HCons(h, this) override def toString = "HNil" } case object HNil extends HNil type ::[H, T <: HList] = HCons[H, T] trait FoldCurry[L <: HList, F, Out] { def apply(l : L, f : F) : Out } // Base case for HLists of length one implicit def foldCurry1[H, Out] = new FoldCurry[H :: HNil, H => Out, Out] { def apply(l : H :: HNil, f : H => Out) = f(l.head) } // Case for HLists of length n+1 implicit def foldCurry2[H, T <: HList, FT, Out] (implicit fct : FoldCurry[T, FT, Out]) = new FoldCurry[H :: T, H => FT, Out] { def apply(l : H :: T, f : H => FT) = fct(l.tail, f(l.head)) } // Public interface ... implemented in terms of type class and instances above def foldCurry[L <: HList, F, Out](l : L, f : F) (implicit fc : FoldCurry[L, F, Out]) : Out = fc(l, f) case class A(x: String, y: String, z: String) //val l = List("a", "b", "c") val lh = "a" :: "b" :: "c" :: HNil val newA = foldCurry(lh, A.curried) println(newA) } 

The problem again is that you can't get away from spelling out the types whether those are Tuple or HList unless you go unsafe way or some sort of code generation.

Comments

0

A different approach by defining a Map[String,String] over the values of an event; let

case class EventMap( data: Map[String,String]) 

and

def fields(cc: Product) = cc.getClass.getDeclaredFields.map(_.getName) 

Then from

EventMap( fields(BlueCoatEvent) zip s.split("\\s") toMap ) 

we can fetch values properties for a given stringisized BlueCoatEvent.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.