| // Copyright (C) 2018 GerritForge Ltd |
| // |
| // 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 com.gerritforge.analytics.gitcommits.engine.events |
| |
| import com.typesafe.scalalogging.LazyLogging |
| import scala.util.{Failure, Success, Try} |
| |
| // for documentation about this object model see https://gerrit-review.googlesource.com/Documentation/cmd-stream-events.html |
| |
| trait GerritJsonEventParser extends Serializable { |
| def fromJson(json: String): Try[GerritJsonEvent] |
| } |
| |
| object EventParser extends GerritJsonEventParser with LazyLogging { |
| val ChangeMergedEventType = "change-merged" |
| val RefUpdatedEventType = "ref-updated" |
| |
| override def fromJson(json: String): Try[GerritJsonEvent] = { |
| import org.json4s._ |
| import org.json4s.native.JsonMethods._ |
| |
| implicit val formats: DefaultFormats.type = DefaultFormats |
| |
| def tryParse[T](jvalue: JValue)(implicit formats: Formats, mf: scala.reflect.Manifest[T]): Try[T] = { |
| try { |
| Success(jvalue.extract[T]) |
| } catch { |
| case e: MappingException => |
| Failure(MappingException(s"Invalid event of type `${mf.runtimeClass.getName}`: ${e.getMessage}", e)) |
| } |
| } |
| |
| Try(parse(json)).flatMap { parsedJson => |
| parsedJson \ "type" match { |
| case JString(ChangeMergedEventType) => |
| tryParse[ChangeMergedEvent](parsedJson) |
| |
| case JString(RefUpdatedEventType) => |
| tryParse[RefUpdatedEvent](parsedJson) |
| |
| case JNothing => |
| Failure(new IllegalArgumentException("Invalid JSON object received, missing 'type' field")) |
| |
| case JString(unsupportedType) => |
| Failure(new IllegalArgumentException(s"Unsupported event type '$unsupportedType'")) |
| |
| case unexpectedJsonType => |
| Failure(new IllegalArgumentException(s"Invalid JSON format for field 'type' `${unexpectedJsonType.getClass.getName}`")) |
| } |
| } |
| } |
| } |
| |
| case class GerritAccount(name: String, email: String, username: String) |
| object GerritAccount { |
| val NoAccountInfo = GerritAccount("", "", "") |
| } |
| |
| case class GerritComment(reviewer: GerritAccount, message: String) |
| |
| case class GerritChange(project: String, |
| branch: String, |
| topic: Option[String], |
| id: String, |
| number: String, |
| subject: String, |
| commitMessage: String, |
| owner: GerritAccount, |
| url: String, |
| createdOn: Long, |
| lastUpdated: Option[Long], |
| comments: List[GerritComment]) |
| |
| case class GerritApproval( |
| `type`: String, |
| value: String, |
| updated: Boolean = false, |
| oldValue: String, |
| by: GerritAccount |
| ) |
| |
| case class GerritPatchSet( |
| number: String, |
| revision: String, |
| ref: String, |
| draft: Option[Boolean] , |
| kind: String, |
| uploader: GerritAccount, |
| author: GerritAccount, |
| approvals: List[GerritApproval], |
| parents: List[String], |
| createdOn: Long, |
| sizeInsertions: Int, |
| sizeDeletions: Int |
| ) { |
| def isDraft : Boolean = draft.getOrElse(false) |
| } |
| |
| sealed trait GerritJsonEvent { |
| def `type`: String |
| |
| def eventCreatedOn: Long |
| |
| def account: GerritAccount |
| } |
| |
| sealed trait GerritRepositoryModifiedEvent extends GerritJsonEvent { |
| def modifiedProject: String |
| |
| def modifiedRef: String |
| } |
| |
| sealed trait GerritRefHasNewRevisionEvent extends GerritRepositoryModifiedEvent { |
| def newRev: String |
| } |
| |
| sealed trait GerritChangeBasedEvent extends GerritRefHasNewRevisionEvent { |
| def change: GerritChange |
| |
| def patchSet: GerritPatchSet |
| |
| //def files: Set[String] |
| } |
| |
| case class GerritChangeKey(id: String, `type`: Option[String], eventCreatedOn: Option[Long]) |
| |
| //https://gerrit-review.googlesource.com/Documentation/cmd-stream-events.html#_change_merged |
| case class ChangeMergedEvent( |
| override val change: GerritChange, |
| override val patchSet: GerritPatchSet, |
| submitter: GerritAccount, |
| override val newRev: String, |
| override val eventCreatedOn: Long, |
| changeKey: GerritChangeKey |
| ) extends GerritChangeBasedEvent { |
| override val `type`: String = "change-merged" |
| |
| override def account: GerritAccount = submitter |
| |
| def modifiedProject: String = change.project |
| |
| def modifiedRef: String = patchSet.ref |
| } |
| |
| case class GerritRefUpdate(project: String, refName: String, oldRev: String, newRev: String) |
| |
| case class RefUpdatedEvent( |
| refUpdate: GerritRefUpdate, |
| submitter: Option[GerritAccount], |
| override val eventCreatedOn: Long |
| ) extends GerritRefHasNewRevisionEvent { |
| override val `type`: String = "ref-updated" |
| |
| override def account: GerritAccount = submitter.getOrElse(GerritAccount.NoAccountInfo) |
| |
| def modifiedProject: String = refUpdate.project |
| |
| def modifiedRef: String = refUpdate.refName |
| |
| def newRev: String = refUpdate.newRev |
| } |