I would like to re-resolve a config object.
for example if I define this config:
val conf = ConfigFactory.parseString(
"""
| foo = a
| bar = ${foo}1
| baz = ${foo}2
""".stripMargin).resolve()
I will get those values:
conf.getString("bar") //res0: String = a1
conf.getString("baz") //res1: String = a2
given the object conf, what I want is to be able to change the value of foo, and get updated values for bar and baz.
Something like :
val conf2 = conf
.withValue("foo", ConfigValueFactory.fromAnyRef("b"))
.resolve()
and get:
conf2.getString("bar") //res0: String = b1
conf2.getString("baz") //res1: String = b2
but running this code will result in:
conf2.getString("foo") //res0: String = b
conf2.getString("bar") //res1: String = a1
conf2.getString("baz") //res2: String = a2
is this even possible?
It's not possible once resolve is called. In the documentation for resolve, it says:
Returns a replacement config with all substitutions resolved... Resolving an already-resolved config is a harmless no-op.
In other words, once you call resolve, all the substitions occur, and there is no reference to the original HOCON substitution syntax.
Of course, you can keep the unresolved Config object as a variable, and then use withValue:
val rawConf = ConfigFactory.parseString(
"""
| foo = a
| bar = ${foo}1
| baz = ${foo}2
""".stripMargin)
val conf2 = rawConf.withValue("foo", ConfigValueFactory.fromAnyRef("b")).resolve
val conf = rawConf.resolve
conf.getString("bar") //a1
conf2.getString("bar") //b1, as desired
Related
I want to extract domain name from uri.
For example, input to the regular expression may be of one of the below types
test.net
https://www.test.net
https://test.net
http://www.test.net
http://test.net
in all the cases the input should return test.net
Below is the code in implemented for my purpose
val re = "([http[s]?://[w{3}\\.]?]+)(.*)".r
But I didn't get expected result
below is my output
val re(prefix, domain) = "https://www.test.net"
prefix: String = https://www.t
domain: String = est.net
what is problem with my regular expression and how can I fix it?
what is problem with my regular expression and how can I fix it?
You are using a character class
[http.?://(www.)?]
This means:
either an h
or a t
or a t
or a .
or a ?
or a :
or a /
or a /
or a (
or a w
or a w
or a w
or a .
or a )
or a ?
It does not include an s, so it will not match https://.
It is not clear to me why you are using a character class here, nor why you are using duplicate characters in the class.
Ideally, you shouldn't try to parse URIs yourself; someone else has already done the hard work. You could, for example, use the java.net.URI class:
import java.net.URI
val u1 = new URI("test.net")
u1.getHost
// res: String = null
val u2 = new URI("https://www.test.net")
u2.getHost
// res: String = www.test.net
val u3 = new URI("https://test.net")
u3.getHost
// res: String = test.net
val u4 = new URI("http://www.test.net")
u4.getHost
// res: String = www.test.net
val u5 = new URI("http://test.net")
u5.getHost
// res: String = test.net
Unfortunately, as you can see, what you want to achieve does not actually comply with the official URI syntax.
If you can fix that, then you can use java.net.URI. Otherwise, you will need to go back to your old solution and parse the URI yourself:
val re = "(?>https?://)?(?>www.)?([^/?#]*)".r
val re(domain1) = "test.net"
//=> domain1: String = test.net
val re(domain2) = "https://www.test.net"
//=> domain2: String = test.net
val re(domain3) = "https://test.net"
//=> domain3: String = test.net
val re(domain4) = "http://www.test.net"
//=> domain4: String = test.net
val re(domain5) = "http://test.net"
//=> domain5: String = test.net
I'm trying to use the FastParse library to create a parser for a very primitive templating system like this:
Hello, your name is {{name}} and today is {{date}}.
So far I have:
scala> import fastparse.all._
import fastparse.all._
scala> val FieldStart = "{{"
FieldStart: String = {{
scala> val FieldEnd = "}}"
FieldEnd: String = }}
scala> val Field = P(FieldStart ~ (!FieldEnd ~ AnyChar).rep.! ~ FieldEnd)
Field: fastparse.all.Parser[String] = Field
scala> val Static = P((!FieldStart ~ !FieldEnd ~ AnyChar).rep.!)
Static: fastparse.all.Parser[String] = Static
scala> val Template = P(Start ~ (Field | Static) ~ End)
Template: fastparse.all.Parser[String] = Template
scala> Template parse "{{foo}}"
res0: fastparse.core.Parsed[String,Char,String] = Success(foo,7)
scala> Template parse "foo"
res1: fastparse.core.Parsed[String,Char,String] = Success(foo,3)
scala> Template parse "{{foo"
res2: fastparse.core.Parsed[String,Char,String] = Failure(End:1:1 ..."{{foo")
But when I try what I think should be the correct final form:
scala> val Template = P(Start ~ (Field | Static).rep ~ End)
Template: fastparse.all.Parser[Seq[String]] = Template
I get:
scala> Template parse "{{foo}}"
java.lang.OutOfMemoryError: Java heap space
at scala.collection.mutable.ResizableArray$class.ensureSize(ResizableArray.scala:103)
at scala.collection.mutable.ArrayBuffer.ensureSize(ArrayBuffer.scala:48)
at scala.collection.mutable.ArrayBuffer.$plus$eq(ArrayBuffer.scala:84)
at scala.collection.mutable.ArrayBuffer.$plus$eq(ArrayBuffer.scala:48)
at fastparse.core.Implicits$LowPriRepeater$GenericRepeater.accumulate(Implicits.scala:47)
at fastparse.core.Implicits$LowPriRepeater$GenericRepeater.accumulate(Implicits.scala:44)
at fastparse.parsers.Combinators$Repeat.rec$3(Combinators.scala:462)
at fastparse.parsers.Combinators$Repeat.parseRec(Combinators.scala:489)
at fastparse.parsers.Combinators$Sequence$Flat.rec$1(Combinators.scala:297)
at fastparse.parsers.Combinators$Sequence$Flat.parseRec(Combinators.scala:319)
at fastparse.parsers.Combinators$Rule.parseRec(Combinators.scala:160)
at fastparse.core.Parser.parseInput(Parsing.scala:374)
at fastparse.core.Parser.parse(Parsing.scala:358)
... 19 elided
What am I doing wrong?
Try like this:
val Field = P(FieldStart ~ (!FieldEnd ~ AnyChar).rep(min=1).! ~ FieldEnd)
val Static = P((!(FieldStart | FieldEnd) ~ AnyChar).rep(min=1).!)
val Template = P(Start ~ (Field | Static) ~ End)
You should be careful with .rep, it literally means zero or more...
Also, in the Static parser, the negative lookahead should look like !(FieldStart | FieldEnd),
I think, because you don't want (open braces or closed braces).
Hope it helps! ;)
I can resolve substitutions when I parse config from string, but not when parsing from map or file.
import java.io.File
import com.typesafe.config.{Config, ConfigFactory}
import scala.collection.JavaConversions.mapAsJavaMap
val s: String = "a = test, b = another ${a}"
val m: Map[String, String] = Map("a" -> "test", "b" -> "another ${a}")
val f: File = new File("test.properties") // contains "a = test\nb = another ${a}"
val cs: Config = ConfigFactory.parseString(s).resolve
val cm: Config = ConfigFactory.parseMap(mapAsJavaMap(m)).resolve
val cf: Config = ConfigFactory.parseFile(f).resolve
println("b from string = " + cs.getString("b"))
println("b from map = " + cm.getString("b"))
println("b from file = " + cf.getString("b"))
> b from string = another test
> b from map = another ${a}
> b from file = another ${a}
When I do not resolve immediately it's visible that variable placeholders are not really treated the same way:
val cs: Config = ConfigFactory.parseString(s)
val cm: Config = ConfigFactory.parseMap(mapAsJavaMap(m))
val cf: Config = ConfigFactory.parseFile(f)
> cs: com.typesafe.config.Config = Config(SimpleConfigObject({"a":"test","b":"another "${a}}))
> cm: com.typesafe.config.Config = Config(SimpleConfigObject({"a":"test","b":"another ${a}"}))
> cf: com.typesafe.config.Config = Config(SimpleConfigObject({"a":"test","b":"another ${a}"}))
I could maybe just convert map/file to string, but is there a way to make the library handle it?
The ConfigFactory.parseMap method lead to fromAnyRef, the relevant part for us is:
if (object instanceof String)
return new ConfigString.Quoted(origin, (String) object);
It never parses the value as ConfigReference, so there is no way the resolve could work.
Their rationale could be that if you "control" the data structure then you can, somehow, leverage scala string interpolation.
For the parseFile the situation is easier. Java properties files does not support ${} substitutions, the type of the file is guessed by the (.properties) file extension.
You can just use, for instance, the HOCON format: you just have to rename the file (e.g. test.conf), ${} substitutions should then work out-of-the-box.
More information here: HOCON
I have a class similar to the following:
class Cat(
val whiskers: Vector[Whiskers],
val tail: hasTail,
val ears: hasEars)
I also have a function which initializes these values based on the contents of a file as so:
val whiskers = initWhiskers()
val cat = new Cat(whiskers = whiskers, tail = initTail(), ears = initEars())
My question is: in some cases, there exist cats with no tails or ears. How do I account for this case by allowing for some of my cat objects to be without ears, and others to be with them?
To clarify:
val cat = new Cat(whiskers = whiskers, tail = null, ears = null)
val cat = new Cat(whiskers = whiskers, tail = initTail(), ears = null)
val cat = new Cat(whiskers = whiskers, tail = initTail(), ears = initEars())
I want all three of the above possibilities to be options. It would all be dependent on whether the file which I'm parsing has ears, or tails, etc.
What I've tried:
Setting values to null (which was terribly unsuccessful).
Making all member variables options (which seemed like a long-winded way of getting null values again).
Any other Options?
Thanks!
In Scala, we use Option monad to wrap things which can be null.
class Cat(
val whiskers: Vector[Whiskers],
val tail: Option[hasTail],
val ears: Option[hasEars]
)
val cat1 = new Cat(whiskers = whiskers, tail = None, ears = None)
val cat2 = new Cat(whiskers = whiskers, tail = Option(initTail()), ears = Option(initEars() )
scala> object Foo extends Enumeration {
| val Bar = Value(23)
| val Moo = Value(57)
| }
defined module Foo
scala> Foo.values
res27: Foo.ValueSet = Foo.ValueSet(Bar, Moo)
So far as expected. But then (continuing from above):
scala> Foo.values
res28: Foo.ValueSet = Foo.ValueSet(Bar, Moo, Value)
What just happened?
This is a bug in Scala 2.8.1. See the issue on JIRA.