1 /***********************************************************************
2  * Copyright (c) 2013-2024 Commonwealth Computer Research, Inc.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Apache License, Version 2.0
5  * which accompanies this distribution and is available at
6  * http://www.opensource.org/licenses/apache2.0.php.
7  ***********************************************************************/
8 
9 package org.locationtech.geomesa.fs.storage.common.utils
10 
11 import org.apache.commons.io.IOUtils
12 import org.geotools.api.feature.simple.SimpleFeatureType
13 import org.locationtech.geomesa.fs.storage.api.{NamedOptions, PartitionSchemeFactory}
14 import org.locationtech.geomesa.fs.storage.common.StorageSerialization
15 import org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs
16 import org.locationtech.geomesa.utils.conf.ArgResolver
17 import org.locationtech.geomesa.utils.io.{PathUtils, WithClose}
18 
19 import java.nio.charset.StandardCharsets
20 import scala.util.control.NonFatal
21 
22 object PartitionSchemeArgResolver {
23 
24   private val instance = new PartitionSchemeArgResolver
25 
26   case class SchemeArgs(sft: SimpleFeatureType, scheme: String)
27 
28   def resolve(sft: SimpleFeatureType, scheme: String): Either[Throwable, NamedOptions] =
29     instance.getArg(SchemeArgs(sft, scheme))
30 }
31 
32 class PartitionSchemeArgResolver extends ArgResolver[NamedOptions, SchemeArgs] {
33 
34   import org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes._
35 
36   private val fileNameReg = """([^.]*)\.([^.]*)""" // e.g. "foo.bar"
37   private val confStrings = Seq("{")
38 
39   override protected def argType(args: SchemeArgs): ArgTypes = {
40     // guess the type we are trying to parse, to determine which error we show for failures
41     // order is important here
42     if (confStrings.exists(args.scheme.contains)) {
43       CONFSTR
44     } else if (args.scheme.matches(fileNameReg) || args.scheme.contains("/")) {
45       PATH
46     } else {
47       NAME
48     }
49   }
50 
51   override val parseMethodList: Seq[SchemeArgs => ResEither] = List[SchemeArgs => ResEither](
52     getNamedScheme,
53     parseFile,
54     parseString
55   )
56 
57   private [PartitionSchemeArgResolver] def getNamedScheme(args: SchemeArgs): ResEither = {
58     try {
59       val options = NamedOptions(args.scheme)
60       PartitionSchemeFactory.load(args.sft, options)
61       Right(options)
62     } catch {
63       case NonFatal(e) => Left((s"Unable to load named scheme ${args.scheme}", e, NAME))
64     }
65   }
66 
67   private [PartitionSchemeArgResolver] def parseString(args: SchemeArgs): ResEither = {
68     try {
69       val options = StorageSerialization.deserialize(args.scheme)
70       PartitionSchemeFactory.load(args.sft, options)
71       Right(options)
72     } catch {
73       case NonFatal(e) => Left((s"Unable to load scheme from arg ${args.scheme}", e, CONFSTR))
74     }
75   }
76 
77   private [PartitionSchemeArgResolver] def parseFile(args: SchemeArgs): ResEither = {
78     try {
79       val handle = PathUtils.interpretPath(args.scheme).headOption.getOrElse {
80         throw new RuntimeException(s"Could not read file at ${args.scheme}")
81       }
82       WithClose(handle.open) { is =>
83         if (is.hasNext) {
84           val config = IOUtils.toString(is.next._2, StandardCharsets.UTF_8)
85           val options = StorageSerialization.deserialize(config)
86           PartitionSchemeFactory.load(args.sft, options)
87           Right(options)
88         } else {
89           throw new RuntimeException(s"Could not read file at ${args.scheme}")
90         }
91       }
92     } catch {
93       case NonFatal(e) => Left((s"Unable to load scheme from file ${args.scheme}", e, PATH))
94     }
95   }
96 }
Line Stmt Id Pos Tree Symbol Tests Code
24 63567 1127 - 1157 Apply org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.<init> new PartitionSchemeArgResolver()
29 63568 1333 - 1356 Apply org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs.apply PartitionSchemeArgResolver.this.SchemeArgs.apply(sft, scheme)
29 63569 1317 - 1357 Apply org.locationtech.geomesa.utils.conf.ArgResolver.getArg PartitionSchemeArgResolver.this.instance.getArg(PartitionSchemeArgResolver.this.SchemeArgs.apply(sft, scheme))
36 63570 1540 - 1562 Literal <nosymbol> "([^.]*)\\.([^.]*)"
37 63571 1609 - 1617 Apply scala.collection.generic.GenericCompanion.apply scala.collection.Seq.apply[String]("{")
42 63572 1834 - 1854 Apply java.lang.String.contains args.scheme.contains(x$1)
42 63573 1815 - 1855 Apply scala.collection.IterableLike.exists PartitionSchemeArgResolver.this.confStrings.exists({ ((x$1: CharSequence) => args.scheme.contains(x$1)) })
43 63574 1865 - 1872 Select org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.CONFSTR org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.CONFSTR
43 63575 1865 - 1872 Block org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.CONFSTR org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.CONFSTR
44 63576 1908 - 1919 Select org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.fileNameReg PartitionSchemeArgResolver.this.fileNameReg
44 63577 1924 - 1949 Apply java.lang.String.contains args.scheme.contains("/")
44 63578 1888 - 1949 Apply scala.Boolean.|| args.scheme.matches(PartitionSchemeArgResolver.this.fileNameReg).||(args.scheme.contains("/"))
44 63583 1884 - 1993 If <nosymbol> if (args.scheme.matches(PartitionSchemeArgResolver.this.fileNameReg).||(args.scheme.contains("/"))) org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.PATH else org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.NAME
45 63579 1959 - 1963 Select org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.PATH org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.PATH
45 63580 1959 - 1963 Block org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.PATH org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.PATH
47 63581 1983 - 1987 Select org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.NAME org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.NAME
47 63582 1983 - 1987 Block org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.NAME org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.NAME
51 63587 2062 - 2147 Apply scala.collection.immutable.List.apply scala.collection.immutable.List.apply[org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs => PartitionSchemeArgResolver.this.ResEither]({ ((args: org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs) => PartitionSchemeArgResolver.this.getNamedScheme(args)) }, { ((args: org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs) => PartitionSchemeArgResolver.this.parseFile(args)) }, { ((args: org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs) => PartitionSchemeArgResolver.this.parseString(args)) })
52 63584 2097 - 2111 Apply org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.getNamedScheme PartitionSchemeArgResolver.this.getNamedScheme(args)
53 63585 2117 - 2126 Apply org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.parseFile PartitionSchemeArgResolver.this.parseFile(args)
54 63586 2132 - 2143 Apply org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.parseString PartitionSchemeArgResolver.this.parseString(args)
58 63593 2256 - 2369 Block <nosymbol> { val options: org.locationtech.geomesa.fs.storage.api.NamedOptions = org.locationtech.geomesa.fs.storage.api.`package`.NamedOptions.apply(args.scheme, org.locationtech.geomesa.fs.storage.api.`package`.NamedOptions.apply$default$2); org.locationtech.geomesa.fs.storage.api.PartitionSchemeFactory.load(args.sft, options); scala.`package`.Right.apply[Nothing, org.locationtech.geomesa.fs.storage.api.NamedOptions](options) }
59 63588 2283 - 2294 Select org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs.scheme args.scheme
59 63589 2270 - 2295 Apply org.locationtech.geomesa.fs.storage.api.NamedOptions.apply org.locationtech.geomesa.fs.storage.api.`package`.NamedOptions.apply(args.scheme, org.locationtech.geomesa.fs.storage.api.`package`.NamedOptions.apply$default$2)
60 63590 2330 - 2338 Select org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs.sft args.sft
60 63591 2302 - 2348 Apply org.locationtech.geomesa.fs.storage.api.PartitionSchemeFactory.load org.locationtech.geomesa.fs.storage.api.PartitionSchemeFactory.load(args.sft, options)
61 63592 2355 - 2369 Apply scala.util.Right.apply scala.`package`.Right.apply[Nothing, org.locationtech.geomesa.fs.storage.api.NamedOptions](options)
63 63594 2418 - 2447 Literal <nosymbol> "Unable to load named scheme "
63 63595 2460 - 2461 Literal <nosymbol> ""
63 63596 2448 - 2459 Select org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs.scheme args.scheme
63 63597 2416 - 2461 Apply scala.StringContext.s scala.StringContext.apply("Unable to load named scheme ", "").s(args.scheme)
63 63598 2466 - 2470 Select org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.NAME org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.NAME
63 63599 2415 - 2471 Apply scala.Tuple3.apply scala.Tuple3.apply[String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value](scala.StringContext.apply("Unable to load named scheme ", "").s(args.scheme), e, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.NAME)
63 63600 2410 - 2472 Apply scala.util.Left.apply scala.`package`.Left.apply[(String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value), Nothing](scala.Tuple3.apply[String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value](scala.StringContext.apply("Unable to load named scheme ", "").s(args.scheme), e, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.NAME))
63 63601 2410 - 2472 Block scala.util.Left.apply scala.`package`.Left.apply[(String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value), Nothing](scala.Tuple3.apply[String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value](scala.StringContext.apply("Unable to load named scheme ", "").s(args.scheme), e, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.NAME))
68 63607 2588 - 2721 Block <nosymbol> { val options: org.locationtech.geomesa.fs.storage.api.NamedOptions = org.locationtech.geomesa.fs.storage.common.`package`.StorageSerialization.deserialize(args.scheme); org.locationtech.geomesa.fs.storage.api.PartitionSchemeFactory.load(args.sft, options); scala.`package`.Right.apply[Nothing, org.locationtech.geomesa.fs.storage.api.NamedOptions](options) }
69 63602 2635 - 2646 Select org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs.scheme args.scheme
69 63603 2602 - 2647 Apply org.locationtech.geomesa.fs.storage.common.StorageSerialization.deserialize org.locationtech.geomesa.fs.storage.common.`package`.StorageSerialization.deserialize(args.scheme)
70 63604 2682 - 2690 Select org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs.sft args.sft
70 63605 2654 - 2700 Apply org.locationtech.geomesa.fs.storage.api.PartitionSchemeFactory.load org.locationtech.geomesa.fs.storage.api.PartitionSchemeFactory.load(args.sft, options)
71 63606 2707 - 2721 Apply scala.util.Right.apply scala.`package`.Right.apply[Nothing, org.locationtech.geomesa.fs.storage.api.NamedOptions](options)
73 63608 2770 - 2802 Literal <nosymbol> "Unable to load scheme from arg "
73 63609 2815 - 2816 Literal <nosymbol> ""
73 63610 2803 - 2814 Select org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs.scheme args.scheme
73 63611 2768 - 2816 Apply scala.StringContext.s scala.StringContext.apply("Unable to load scheme from arg ", "").s(args.scheme)
73 63612 2821 - 2828 Select org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.CONFSTR org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.CONFSTR
73 63613 2767 - 2829 Apply scala.Tuple3.apply scala.Tuple3.apply[String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value](scala.StringContext.apply("Unable to load scheme from arg ", "").s(args.scheme), e, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.CONFSTR)
73 63614 2762 - 2830 Apply scala.util.Left.apply scala.`package`.Left.apply[(String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value), Nothing](scala.Tuple3.apply[String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value](scala.StringContext.apply("Unable to load scheme from arg ", "").s(args.scheme), e, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.CONFSTR))
73 63615 2762 - 2830 Block scala.util.Left.apply scala.`package`.Left.apply[(String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value), Nothing](scala.Tuple3.apply[String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value](scala.StringContext.apply("Unable to load scheme from arg ", "").s(args.scheme), e, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.CONFSTR))
78 63633 2944 - 3501 Block <nosymbol> { val handle: org.locationtech.geomesa.utils.io.fs.FileSystemDelegate.FileHandle = org.locationtech.geomesa.utils.io.PathUtils.interpretPath(args.scheme).headOption.getOrElse[org.locationtech.geomesa.utils.io.fs.FileSystemDelegate.FileHandle](throw new scala.`package`.RuntimeException(scala.StringContext.apply("Could not read file at ", "").s(args.scheme))); org.locationtech.geomesa.utils.io.`package`.WithClose.apply[org.locationtech.geomesa.utils.collection.CloseableIterator[(Option[String], java.io.InputStream)], PartitionSchemeArgResolver.this.ResEither](handle.open)(((is: org.locationtech.geomesa.utils.collection.CloseableIterator[(Option[String], java.io.InputStream)]) => if (is.hasNext) { val config: String = org.apache.commons.io.IOUtils.toString(is.next()._2, java.nio.charset.StandardCharsets.UTF_8); val options: org.locationtech.geomesa.fs.storage.api.NamedOptions = org.locationtech.geomesa.fs.storage.common.`package`.StorageSerialization.deserialize(config); org.locationtech.geomesa.fs.storage.api.PartitionSchemeFactory.load(args.sft, options); scala.`package`.Right.apply[Nothing, org.locationtech.geomesa.fs.storage.api.NamedOptions](options) } else throw new scala.`package`.RuntimeException(scala.StringContext.apply("Could not read file at ", "").s(args.scheme))))(io.this.IsCloseable.closeableIsCloseable) }
79 63616 2981 - 2992 Select org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs.scheme args.scheme
79 63618 2957 - 3101 Apply scala.Option.getOrElse org.locationtech.geomesa.utils.io.PathUtils.interpretPath(args.scheme).headOption.getOrElse[org.locationtech.geomesa.utils.io.fs.FileSystemDelegate.FileHandle](throw new scala.`package`.RuntimeException(scala.StringContext.apply("Could not read file at ", "").s(args.scheme)))
80 63617 3025 - 3093 Throw <nosymbol> throw new scala.`package`.RuntimeException(scala.StringContext.apply("Could not read file at ", "").s(args.scheme))
82 63619 3118 - 3129 Select org.locationtech.geomesa.utils.io.fs.FileSystemDelegate.FileHandle.open handle.open
82 63631 3131 - 3131 Select org.locationtech.geomesa.utils.io.IsCloseableImplicits.closeableIsCloseable io.this.IsCloseable.closeableIsCloseable
82 63632 3108 - 3501 ApplyToImplicitArgs org.locationtech.geomesa.utils.io.WithClose.apply org.locationtech.geomesa.utils.io.`package`.WithClose.apply[org.locationtech.geomesa.utils.collection.CloseableIterator[(Option[String], java.io.InputStream)], PartitionSchemeArgResolver.this.ResEither](handle.open)(((is: org.locationtech.geomesa.utils.collection.CloseableIterator[(Option[String], java.io.InputStream)]) => if (is.hasNext) { val config: String = org.apache.commons.io.IOUtils.toString(is.next()._2, java.nio.charset.StandardCharsets.UTF_8); val options: org.locationtech.geomesa.fs.storage.api.NamedOptions = org.locationtech.geomesa.fs.storage.common.`package`.StorageSerialization.deserialize(config); org.locationtech.geomesa.fs.storage.api.PartitionSchemeFactory.load(args.sft, options); scala.`package`.Right.apply[Nothing, org.locationtech.geomesa.fs.storage.api.NamedOptions](options) } else throw new scala.`package`.RuntimeException(scala.StringContext.apply("Could not read file at ", "").s(args.scheme))))(io.this.IsCloseable.closeableIsCloseable)
83 63620 3151 - 3161 Select scala.collection.Iterator.hasNext is.hasNext
83 63628 3163 - 3397 Block <nosymbol> { val config: String = org.apache.commons.io.IOUtils.toString(is.next()._2, java.nio.charset.StandardCharsets.UTF_8); val options: org.locationtech.geomesa.fs.storage.api.NamedOptions = org.locationtech.geomesa.fs.storage.common.`package`.StorageSerialization.deserialize(config); org.locationtech.geomesa.fs.storage.api.PartitionSchemeFactory.load(args.sft, options); scala.`package`.Right.apply[Nothing, org.locationtech.geomesa.fs.storage.api.NamedOptions](options) }
84 63621 3205 - 3215 Select scala.Tuple2._2 is.next()._2
84 63622 3217 - 3239 Select java.nio.charset.StandardCharsets.UTF_8 java.nio.charset.StandardCharsets.UTF_8
84 63623 3188 - 3240 Apply org.apache.commons.io.IOUtils.toString org.apache.commons.io.IOUtils.toString(is.next()._2, java.nio.charset.StandardCharsets.UTF_8)
85 63624 3265 - 3305 Apply org.locationtech.geomesa.fs.storage.common.StorageSerialization.deserialize org.locationtech.geomesa.fs.storage.common.`package`.StorageSerialization.deserialize(config)
86 63625 3344 - 3352 Select org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs.sft args.sft
86 63626 3316 - 3362 Apply org.locationtech.geomesa.fs.storage.api.PartitionSchemeFactory.load org.locationtech.geomesa.fs.storage.api.PartitionSchemeFactory.load(args.sft, options)
87 63627 3373 - 3387 Apply scala.util.Right.apply scala.`package`.Right.apply[Nothing, org.locationtech.geomesa.fs.storage.api.NamedOptions](options)
89 63629 3415 - 3483 Throw <nosymbol> throw new scala.`package`.RuntimeException(scala.StringContext.apply("Could not read file at ", "").s(args.scheme))
89 63630 3415 - 3483 Block <nosymbol> throw new scala.`package`.RuntimeException(scala.StringContext.apply("Could not read file at ", "").s(args.scheme))
93 63634 3550 - 3583 Literal <nosymbol> "Unable to load scheme from file "
93 63635 3596 - 3597 Literal <nosymbol> ""
93 63636 3584 - 3595 Select org.locationtech.geomesa.fs.storage.common.utils.PartitionSchemeArgResolver.SchemeArgs.scheme args.scheme
93 63637 3548 - 3597 Apply scala.StringContext.s scala.StringContext.apply("Unable to load scheme from file ", "").s(args.scheme)
93 63638 3602 - 3606 Select org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.PATH org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.PATH
93 63639 3547 - 3607 Apply scala.Tuple3.apply scala.Tuple3.apply[String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value](scala.StringContext.apply("Unable to load scheme from file ", "").s(args.scheme), e, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.PATH)
93 63640 3542 - 3608 Apply scala.util.Left.apply scala.`package`.Left.apply[(String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value), Nothing](scala.Tuple3.apply[String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value](scala.StringContext.apply("Unable to load scheme from file ", "").s(args.scheme), e, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.PATH))
93 63641 3542 - 3608 Block scala.util.Left.apply scala.`package`.Left.apply[(String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value), Nothing](scala.Tuple3.apply[String, Throwable, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.Value](scala.StringContext.apply("Unable to load scheme from file ", "").s(args.scheme), e, org.locationtech.geomesa.utils.conf.ArgResolver.ArgTypes.PATH))