src/main/scala/radview/model/Cdr.scala
changeset 2 cf829ec742b3
child 7 6e3d323f9ec5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/radview/model/Cdr.scala	Sun Apr 03 15:55:02 2011 +0200
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2011 Tomas Zeman <tzeman@volny.cz>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package radview.model
+
+import java.util.Date
+import net.liftweb.common._
+import net.liftweb.mapper._
+import radview.snippet.SessionSnippet
+
+/*
+  Table: v_radacct
+ */
+object Cdr extends Cdr with LongKeyedMetaMapper[Cdr] with Loggable {
+  override def dbTableName = "v_radacct"
+  override def dbDefaultConnectionIdentifier = RadAcctConnectionIdentifier
+
+  def bySession(s: CdrSession) = findAll(By(sid, s.sid),
+    OrderBy(radacctid, Ascending))
+
+  def fieldsForList = List(sid, ts, inBytes, outBytes, statusType, acctuniqueid,
+    username, groupname, realm, nasipaddress, nasportid, nasporttype,
+    acctsessiontime, acctauthentic, serviceType, framedProto, framedIp,
+    statusType, cell)
+
+  import java.sql.{Date => SqlDate}
+  implicit def d2sqlD(d: Date): SqlDate = new SqlDate(d.getTime)
+
+  private def diff(col: MappedField[_, _]) = String.format(
+    "MAX(%1$s) - MIN(%1$s) AS %1$s", col.dbColumnName)
+  private def min(col: MappedField[_, _]) = String.format(
+    "MIN(%1$s) AS %1$s", col.dbColumnName)
+  private def max(col: MappedField[_, _]) = String.format(
+    "MAX(%1$s) AS %1$s", col.dbColumnName)
+
+  def sessions(from: Date, to: Date, field: MappedField[_, Cdr],
+    value: String) = findAllByPreparedStatement { sc =>
+      val selectS = List(sid.dbColumnName, diff(inBytes), diff(outBytes))
+      val sql = String.format(
+        "SELECT %s FROM %s WHERE %s = ? AND %s BETWEEN ? AND ? GROUP BY %s",
+        selectS mkString ",", dbTableName, field.dbColumnName,
+        ts.dbColumnName, sid.dbColumnName)
+      logger.debug(sql + "; params: " + from + ", " + to + ", " +
+        field.dbColumnName + "=" + value)
+      val stm = sc.connection.prepareStatement(sql)
+      stm.setString(1, value)
+      stm.setDate(2, from)
+      stm.setDate(3, to)
+      stm
+    }
+
+  def session(sessionId: String): Box[CdrSession] =
+    Box(sessions(List(sessionId)))
+
+  def sessions(sessionIds: List[String]): List[CdrSession] = sessionIds match {
+    case Nil => Nil
+    case xs =>
+      val cdr1 = findAllByPreparedStatement { sc =>
+        val selectS = List(sid.dbColumnName, diff(inBytes), diff(outBytes),
+          min(radacctid), max(ts))
+        val sql = String.format(
+          "SELECT %s FROM %s WHERE %s IN (%s) GROUP BY %s",
+          selectS.mkString(","), dbTableName, sid.dbColumnName,
+          sessionIds.map(r=>"?").mkString(","), sid.dbColumnName)
+        logger.debug(sql)
+        val stm = sc.connection.prepareStatement(sql)
+        sessionIds.zipWithIndex.map { r => stm.setString(r._2 + 1, r._1) }
+        stm
+      }
+      val cdr2 = Cdr.findAll(ByList(radacctid, cdr1 map { _.radacctid.is }))
+      val tsMap = Map[String, Cdr]() ++ (cdr2 map { c => (c.sid.is, c) })
+      for {
+        c1 <- cdr1
+        c2 <- tsMap.get(c1.sid.is)
+      } yield {
+        CdrSession(c1.sid, c2.ts, c1.ts, c1.inBytes, c1.outBytes, c2.cell)
+      }
+  }
+}
+
+class Cdr extends LongKeyedMapper[Cdr] with CellAware {
+  def getSingleton = Cdr
+  def primaryKeyField = radacctid
+
+  object radacctid extends MappedLongIndex(this) {
+    override def dbColumnName = "radacctid"
+  }
+
+  object sid extends MappedPoliteStringColName(this, 64, "acctsessionid",
+    "Session Id") {
+    override def asHtml =
+      <a href={SessionSnippet.url(is)}>{super.asHtml}</a>
+  }
+
+  object acctuniqueid extends MappedPoliteStringColName(this, 32,
+    "acctuniqueid", "Unique Id")
+
+  object username extends MappedPoliteStringColName(this, 64, "username",
+    "User")
+
+  object groupname extends MappedPoliteStringColName(this, 64, "groupname",
+    "Group")
+
+  object realm extends MappedPoliteStringColName(this, 64, "realm", "Realm")
+
+  object nasipaddress extends MappedPoliteStringColName(this, 15,
+    "nasipaddress", "NAS IP")
+
+  object nasportid extends MappedPoliteStringColName(this, 15, "nasportid",
+    "NAS Port Id")
+
+  object nasporttype extends MappedPoliteStringColName(this, 32,
+    "nasporttype", "NAS Port Type")
+
+  object acctsessiontime extends MappedIntColName(this, "acctsessiontime",
+    "Session Time")
+
+  object acctauthentic extends MappedPoliteStringColName(this, 32,
+    "acctauthentic", "Authenticator")
+
+  object inBytes extends MappedLongColName(this, "acctinputoctets",
+    "Input bytes")
+
+  object outBytes extends MappedLongColName(this, "acctoutputoctets",
+    "Output bytes")
+
+  object calledNo extends MappedPoliteStringColName(this, 50,
+    "calledstationid", "Called No.")
+
+  object callingNo extends MappedLongColName(this, "callingstationid",
+    "Calling No.")
+
+  object termCause extends MappedPoliteStringColName(this, 32,
+    "acctterminatecause", "Termination Cause")
+
+  object serviceType extends MappedPoliteStringColName(this, 32,
+    "servicetype", "Service Type")
+
+  object framedProto extends MappedPoliteStringColName(this, 32,
+    "framedprotocol", "Framed Protocol")
+
+  object framedIp extends MappedPoliteStringColName(this, 15,
+    "framedipaddress", "Framed IP")
+
+  object startDelay extends MappedIntColName(this, "acctstartdelay",
+    "Start Delay")
+
+  object stopDelay extends MappedIntColName(this, "acctstopdelay",
+    "Stop Delay")
+
+  object corrId extends MappedPoliteStringColName(this, 64,
+    "3GPP2_Correlation_Id", "3GPP2 Correlation Id")
+
+  object statusType extends MappedPoliteStringColName(this, 15,
+    "Acct_Status_Type", "Status Type")
+
+  object ts extends MappedDateTime(this) {
+    override def dbColumnName = "Event_Timestamp"
+    override def displayName = "Timestamp"
+  }
+
+  object releaseInd extends MappedIntColName(this, "3GPP2_Release_Indicator",
+    "3GPP2 Release Indicator")
+
+  object activeTime extends MappedIntColName(this, "3GPP2_Active_Time",
+    "3GPP2 Active Time")
+
+}
+
+case class CdrSession(sid: String, start: Date, end: Date, inBytes: Long,
+  outBytes: Long, cellId: String) {
+
+  def cell: Box[Cell] = Cell.findByKey(cellId)
+}
+
+// vim: set ts=2 sw=2 et: