Skip to content

Commit

Permalink
Modernize scala syntax (#87)
Browse files Browse the repository at this point in the history
* Do not brackets for function without args

* Do not use postfix notation

* Do not use procedural syntax

* Use case class to get hashCode and equals

The `ValueSource` requires overriding `equals` and `hashCode()`. These two are
automatically derived for case classes.

* Collection is removed from recent scala be more explicit

* Refactor request parsing to validate the types of nested structures

* Use unchecked for inner types we cannot match on

* Use `case e: Throwable => ...` idiom to catch all possible exceptions.

The previous implementation `case e => ...` produces following warning on
modern scala

```
warning: This catches all Throwables. If this is really intended, use
         `case e : Throwable` to clear this warning.
    case e =>
         ^
```

* Add return type where asked by compiler
  • Loading branch information
iilyak authored Jan 29, 2024
1 parent 99b293c commit 1d84432
Show file tree
Hide file tree
Showing 14 changed files with 718 additions and 190 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class ClouseauQueryParser(version: Version,
fpRegex.matcher(str).matches()
}

private def setLowercaseExpandedTerms(field: String) {
private def setLowercaseExpandedTerms(field: String): Unit = {
getAnalyzer match {
case a: PerFieldAnalyzer =>
setLowercaseExpandedTerms(a.getWrappedAnalyzer(field))
Expand All @@ -116,7 +116,7 @@ class ClouseauQueryParser(version: Version,
}
}

private def setLowercaseExpandedTerms(analyzer: Analyzer) {
private def setLowercaseExpandedTerms(analyzer: Analyzer): Unit = {
setLowercaseExpandedTerms(!analyzer.isInstanceOf[KeywordAnalyzer])
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ClouseauSupervisor(ctx: ServiceContext[ConfigurationArgs]) extends Service
var cleanup = spawnAndMonitorService[IndexCleanupService, ConfigurationArgs]('cleanup, ctx.args)
var analyzer = spawnAndMonitorService[AnalyzerService, ConfigurationArgs]('analyzer, ctx.args)

override def trapMonitorExit(monitored: Any, ref: Reference, reason: Any) {
override def trapMonitorExit(monitored: Any, ref: Reference, reason: Any) = {
if (monitored == manager) {
logger.warn("manager crashed")
manager = spawnAndMonitorService[IndexManagerService, ConfigurationArgs]('main, ctx.args)
Expand Down
94 changes: 48 additions & 46 deletions src/main/scala/com/cloudant/clouseau/ClouseauTypeFactory.scala
Original file line number Diff line number Diff line change
Expand Up @@ -120,49 +120,51 @@ object ClouseauTypeFactory extends TypeFactory {
result
}

private def addFields(doc: Document, field0: Any): Unit = field0 match {
case (name: String, value: String, options: List[(String, Any)]) =>
val map = options.toMap
constructField(name, value, toStore(map), toIndex(map), toTermVector(map)) match {
case Some(field) =>
map.get("boost") match {
case Some(boost: Number) =>
field.setBoost(toFloat(boost))
case None =>
'ok
}
doc.add(field)
if (isFacet(map) && value.nonEmpty) {
val fp = FacetIndexingParams.DEFAULT
val delim = fp.getFacetDelimChar
if (!name.contains(delim) && !value.contains(delim)) {
val facets = new SortedSetDocValuesFacetFields(fp)
facets.addFields(doc, List(new CategoryPath(name, value)).asJava)
private def addFields(doc: Document, field0: Any): Unit = {
field0 match {
case (name: String, value: String, options: List[(String, Any) @unchecked]) =>
val map = options.collect { case t @ (_: String, _: Any) => t }.asInstanceOf[List[(String, Any)]].toMap
constructField(name, value, toStore(map), toIndex(map), toTermVector(map)) match {
case Some(field) =>
map.get("boost") match {
case Some(boost: Number) =>
field.setBoost(toFloat(boost))
case None =>
'ok
}
}
case None =>
'ok
}
case (name: String, value: Boolean, options: List[(String, Any)]) =>
val map = options.toMap
constructField(name, value.toString, toStore(map), Index.NOT_ANALYZED, toTermVector(map)) match {
case Some(field) =>
doc.add(field)
case None =>
'ok
}
case (name: String, value: Any, options: List[(String, Any)]) =>
val map = options.toMap
toDouble(value) match {
case Some(doubleValue) =>
doc.add(new DoubleField(name, doubleValue, toStore(map)))
if (isFacet(map)) {
doc.add(new DoubleDocValuesField(name, doubleValue))
}
case None =>
logger.warn("Unrecognized value: %s".format(value))
'ok
}
doc.add(field)
if (isFacet(map) && value.nonEmpty) {
val fp = FacetIndexingParams.DEFAULT
val delim = fp.getFacetDelimChar
if (!name.contains(delim) && !value.contains(delim)) {
val facets = new SortedSetDocValuesFacetFields(fp)
facets.addFields(doc, List(new CategoryPath(name, value)).asJava)
}
}
case None =>
'ok
}
case (name: String, value: Boolean, options: List[(String, Any) @unchecked]) =>
val map = options.collect { case t @ (_: String, _: Any) => t }.asInstanceOf[List[(String, Any)]].toMap
constructField(name, value.toString, toStore(map), Index.NOT_ANALYZED, toTermVector(map)) match {
case Some(field) =>
doc.add(field)
case None =>
'ok
}
case (name: String, value: Any, options: List[(String, Any) @unchecked]) =>
val map = options.collect { case t @ (_: String, _: Any) => t }.asInstanceOf[List[(String, Any)]].toMap
toDouble(value) match {
case Some(doubleValue) =>
doc.add(new DoubleField(name, doubleValue, toStore(map)))
if (isFacet(map)) {
doc.add(new DoubleDocValuesField(name, doubleValue))
}
case None =>
logger.warn("Unrecognized value: %s".format(value))
'ok
}
}
}

private def constructField(name: String, value: String, store: Store, index: Index, tv: TermVector): Option[Field] = {
Expand Down Expand Up @@ -192,7 +194,7 @@ object ClouseauTypeFactory extends TypeFactory {
case v: java.lang.Float => Some(v.doubleValue)
case v: java.lang.Integer => Some(v.doubleValue)
case v: java.lang.Long => Some(v.doubleValue)
case v: scala.math.BigInt => Some(v.doubleValue())
case v: scala.math.BigInt => Some(v.doubleValue)
case _ => None
}

Expand All @@ -212,7 +214,7 @@ object ClouseauTypeFactory extends TypeFactory {
case false => Store.NO
case str: String =>
try {
Store.valueOf(str toUpperCase)
Store.valueOf(str.toUpperCase)
} catch {
case _: IllegalArgumentException =>
Store.NO
Expand All @@ -228,7 +230,7 @@ object ClouseauTypeFactory extends TypeFactory {
case false => Index.NO
case str: String =>
try {
Index.valueOf(str toUpperCase)
Index.valueOf(str.toUpperCase)
} catch {
case _: IllegalArgumentException =>
Index.ANALYZED
Expand All @@ -240,7 +242,7 @@ object ClouseauTypeFactory extends TypeFactory {

def toTermVector(options: Map[String, Any]): TermVector = {
val termVector = options.getOrElse("termvector", "no").asInstanceOf[String]
TermVector.valueOf(termVector toUpperCase)
TermVector.valueOf(termVector.toUpperCase)
}

def isFacet(options: Map[String, Any]) = {
Expand Down
62 changes: 62 additions & 0 deletions src/main/scala/com/cloudant/clouseau/Converters.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// 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.cloudant.clouseau

object conversions {
/**
* Scala 2.9.1 doesn't have extractors on PartialFunction. These were introduced in
*
* [scala/scala#7111](https://github.com/scala/scala/pull/7111) and released in 2.13.0
*
* See also [SIP-38](https://docs.scala-lang.org/sips/converters-among-optional-functions-partialfunctions-and-extractor-objects.html)
*
* with extractors you can do something like
*
* ```scala
* val asString: PartialFunction[Any, String] =
* { case string: String => string }
*
* def test(value: Any): Option[String] = {
* value match {
* case asString(s) => Some(s)
* case _ => None
* }
* }
* ```
*
* This implicit conversion adds a middle ground solution. It can be used as follows:
*
* ```scala
* import conversions._ /// Here we bring implicit convertors in scope
*
* val asString: PartialFunction[Any, String] =
* { case string: String => string }
*
* def test(value: Any): Option[String] = {
* val asStringExtractor = asString.Extractor /// This is the extra line we need to add
* value match {
* case asStringExtractor(s) => Some(s) /// Use Extractor to get the matching content
* case _ => None
* }
* }
* ```
*
* @param pf
*/
class ExtendedPF[A, B](val pf: PartialFunction[A, B]) {
object Extractor {
def unapply(a: A): Option[B] = pf.lift(a)
}
}
implicit def extendPartialFunction[A, B](pf: PartialFunction[A, B]): ExtendedPF[A, B] = new ExtendedPF(pf)
}
10 changes: 5 additions & 5 deletions src/main/scala/com/cloudant/clouseau/DistanceValueSource.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ import java.util.Map
This is lucene spatial's DistanceValueSource but with configurable
x and y field names to better suit our existing API.
*/
class DistanceValueSource(ctx: SpatialContext,
lon: String,
lat: String,
multiplier: Double,
from: Point)
case class DistanceValueSource(ctx: SpatialContext,
lon: String,
lat: String,
multiplier: Double,
from: Point)
extends ValueSource {

def description() = "DistanceValueSource(%s)".format(from)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class ExternalSnapshotDeletionPolicy(dir: FSDirectory) extends IndexDeletionPoli

object ExternalSnapshotDeletionPolicy {

def snapshot(originDir: File, snapshotDir: File, files: Collection[String]) {
def snapshot(originDir: File, snapshotDir: File, files: Collection[String]) = {
if (!originDir.isAbsolute) {
throw new IOException(originDir + " is not an absolute path")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class IndexCleanupService(ctx: ServiceContext[ConfigurationArgs]) extends Servic
cleanup(rootDir, pattern, activeSigs)
}

private def cleanup(fileOrDir: File, includePattern: Pattern, activeSigs: List[String]) {
private def cleanup(fileOrDir: File, includePattern: Pattern, activeSigs: List[String]): Unit = {
if (!fileOrDir.isDirectory) {
return
}
Expand All @@ -71,7 +71,7 @@ class IndexCleanupService(ctx: ServiceContext[ConfigurationArgs]) extends Servic
}
}

private def recursivelyDelete(fileOrDir: File, deleteDir: Boolean) {
private def recursivelyDelete(fileOrDir: File, deleteDir: Boolean): Unit = {
if (fileOrDir.isDirectory) {
for (file <- fileOrDir.listFiles)
recursivelyDelete(file, deleteDir)
Expand All @@ -82,7 +82,7 @@ class IndexCleanupService(ctx: ServiceContext[ConfigurationArgs]) extends Servic
fileOrDir.delete
}

private def rename(srcDir: File, destDir: File) {
private def rename(srcDir: File, destDir: File): Unit = {
if (!srcDir.isDirectory) {
return
}
Expand Down
12 changes: 6 additions & 6 deletions src/main/scala/com/cloudant/clouseau/IndexManagerService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ class IndexManagerService(ctx: ServiceContext[ConfigurationArgs]) extends Servic
pid
}

def put(path: String, pid: Pid) {
def put(path: String, pid: Pid) = {
val prev = pathToPid.put(path, pid)
pidToPath.remove(prev)
pidToPath.put(pid, path)
}

def remove(pid: Pid) {
def remove(pid: Pid) = {
val path = pidToPath.remove(pid)
pathToPid.remove(path)
if (Option(path).isDefined) {
Expand All @@ -73,13 +73,13 @@ class IndexManagerService(ctx: ServiceContext[ConfigurationArgs]) extends Servic
pidToPath.isEmpty
}

def close() {
def close() = {
pidToPath.asScala foreach {
kv => kv._1 ! ('close, 'closing)
}
}

def closeByPath(path: String) {
def closeByPath(path: String) = {
pidToPath.asScala foreach {
kv =>
if (kv._2.startsWith(path)) {
Expand All @@ -104,7 +104,7 @@ class IndexManagerService(ctx: ServiceContext[ConfigurationArgs]) extends Servic
metrics.gauge("NativeFSLock.count")(getNativeFSLockHeldSize(LOCK_HELD.asScala))
}

def getNativeFSLockHeldSize(lockHeld: Collection[String]) = lockHeld.synchronized {
def getNativeFSLockHeldSize(lockHeld: scala.collection.mutable.Set[String]) = lockHeld.synchronized {
lockHeld.size
}

Expand Down Expand Up @@ -211,7 +211,7 @@ class IndexManagerService(ctx: ServiceContext[ConfigurationArgs]) extends Servic
}
}

private def replyAll(path: String, msg: Any) {
private def replyAll(path: String, msg: Any) = {
waiters.remove(path) match {
case Some(list) =>
for ((pid, ref) <- list) {
Expand Down
Loading

0 comments on commit 1d84432

Please sign in to comment.