Sorry in advance about the title, I'm not sure if I'm using the correct terms.
/**
* #return {Object.<string, number>}
*/
function foo() {}
The tooltip in VSCode for the above looks like this:
function foo(): {
[x: string]: number;
}
How can I choose a different label than x, like baz? So that it looks like:
function foo(): {
[baz: string]: number;
}
/**
* #typedef {{ [baz: string]: number }} Thing
* #return {Thing}
*/
function foo() {}
Related
I have a trait that overrides toString to print the values of all fields:
/**
* Interface for classes that provide application configuration.
*/
trait Configuration {
/** abstract fields defined here. e.g., **/
def dbUrl: String
/**
* Returns a list of fields to be excluded by [[toString]]
*/
protected def toStringExclude: Seq[String]
/**
* Returns a String representation of this object that prints the values for all configuration fields.
*/
override def toString: String = {
val builder = new StringBuilder
val fields = this.getClass.getDeclaredFields
for (f <- fields) {
if (!toStringExclude.contains(f.getName)) {
f.setAccessible(true)
builder.append(s"${f.getName}: ${f.get(this)}\n")
}
}
builder.toString.stripSuffix("\n")
}
}
A concrete class currently looks like this:
class BasicConfiguration extends Configuration {
private val config = ConfigFactory.load
override val dbUrl: String = config.getString("app.dbUrl")
/**
* #inheritdoc
*/
override protected def toStringExclude: Seq[String] = Seq("config")
}
The problem is, if config were renamed at some point, the IDE would miss "config" in toStringExclude as it's just a string. So I'm trying to find a way to get the name of a field as a string, like getFieldName(config).
Using https://github.com/dwickern/scala-nameof,
import com.github.dwickern.macros.NameOf._
class BasicConfiguration extends Configuration {
private val config = ConfigFactory.load
override val dbUrl: String = config.getString("app.dbUrl")
/**
* #inheritdoc
*/
override protected def toStringExclude: Seq[String] = Seq(nameOf(config))
}
I don't like this and I wouldn't do this but here's this:
class BasicConfiguration extends Configuration {
private val config = ConfigFactory.load
override val dbUrl: String = config.getString("app.dbUrl")
private val excludeFields: Set[Any] = Set(config)
override protected val toStringExclude: Seq[String] = {
this.getClass
.getDeclaredFields
.filter(field => Try(field.get(this)).fold(_ => false, a => excludeFields.contains(a)))
.map(_.getName)
.toList
}
}
I'm using the play-slick plugin 3.0.1 with Play! 2.6.6 and seem to have run into a problem.
What I'm trying to do is to implement "grant" based permission system from a DB table containing several columns. Since this table can be broad, I wanted to find a way to programmatically generate column names and read bits from each column, and evaluate to the presence or absence of a grant.
For example, the table might look like:
granted_for grantee read write
id1 id2 1 0
Next I set things up like so:
import centralapp.api.string.CamelToUnderscore
import models.permissions.grants.Grant
import slick.ast.{BaseTypedType, TypedType}
import slick.jdbc
import slick.jdbc.JdbcType
import slick.jdbc.MySQLProfile.api._
import slick.lifted.ProvenShape
trait HasName {
/**
* #note "HasName"
*/
def simpleName: String = getClass.getSimpleName.replaceAll("[^a-zA-Z0-9_]", "")
/**
* #note "has_name"
*/
def classNameLower: String = simpleName.toUnderscoreLower
/**
* #note "HAS_NAME"
*/
def classNameUpper: String = simpleName.toUnderscoreUpper
}
And then a trait that defines a DB column abstraction:
trait DBColumn[C, T <: Table[_]] extends HasName {
/**
* the name of the column
*/
def columnName: String = classNameLower
/**
* get the column representation
*
* #param c the TypedType representation of this column's type
* #param table the table for which the column is being generated
* #return a Rep[C] (representation of type C)
*/
def col(implicit c: TypedType[C], table: T): Rep[C] = table.column[C](columnName)
}
And then use that to generate "Grant" column mappings:
package object db {
/**
* creates a grant column mapping from a boolean column for a given grant
*
* #param g the grant to obtain if the column is set to "true"
* #tparam G the subtype of the grant
* #return the JDBC type for the desired value
*/
def optGrantFromBoolCol[G <: Grant](g: G): JdbcType[Option[G]] with BaseTypedType[Option[G]] = MappedColumnType.base[Option[G], Boolean](
_.isDefined,
{
case true => Some(g)
case false => None
}
)
abstract class GrantCol[G <: Grant, T <: Table[_]](grant: G) extends DBColumn[Option[G], T] {
// class Grant also extends HasName; here I want to ensure the column name is exactly the same as the string representation of the grant.
override def columnName: String = grant.classNameLower
/**
* get the column representation
*
* #param table the table for which the column is being generated
* #return a Rep[C] (representation of type C)
*/
def grantCol(implicit table: T): jdbc.MySQLProfile.api.Rep[Option[G]] = col(optGrantFromBoolCol(grant), table)
}
}
And then I tried to use this like so:
object Columns {
case object GrantedFor extends DBColumn[String, MyTable]
case object Grantee extends DBColumn[String, MyTable]
case object Read extends GrantCol[UserGrant, MyTable](usergrants.Read)
}
// and then used it in a table:
class MyTable(tag: Tag) extends Table[SomeClass](tag, "my_table") {
implicit def table = this
val grantedFor = Columns.GrantedFor.col
val grantee = Columns.Grantee.col
val read = Columns.Read.grantCol
def * : ProvenShape[SomeClass] =
(grantedFor, grantee, read) <> // <- this is the problem: Cannot resolve symbol "<>"
(
???, // valid constructor from tuple
??? // valid unapply
)
def other : ProvenShape[OtherClass] =
(grantedFor, grantee) <> (
???,
???
)
}
As described in the comments, I see that the moment there's a "Grant" column in the tuple, the resolution for the <> symbol starts failing. I cannot seem to see what the problem here could be.
Any pointers?
I am studying about the Factory Design Pattern in Scala.One of the benefits of this method is Loose Coupling between Object Creation logic and Client (from http://www.journaldev.com/10350/factory-design-pattern-in-scala). How can we achieve this and why we need loose coupling at all? Can someone give some examples and explain this?
As I understood you are looking for an example on Factory Pattern in Scala, you can find the usecase with some simple examples here
Factory pattern is more useful when creating API library classes (classes which can be used by other classes). Hope the below example will explain it clearly,
trait ContentAPI {
def getContentById(id : Int) : String
def getContentByTitle(title: String) : String
def getAllContent(title: String) : String }
object ContentAPI {
protected class ContentAPI(config: APIConfig) extends PageContentAPI {
/**
* get all content of a page parsing the page title
*
* #param query title parsed
* #return all content as a String
*/
override def getAllContent(query: String) : String = {
var pageContent: String = " Some text"
pageContent
}
/**
* get only the content body text parsing the page title
*
* #param query title parsed
* #return content as a String
*/
override def getContentByTitle(query: String) : String = {
var pageContent: String = " Some String "
pageContent
}
/**
* get only the content body text parsing the page id
*
* #param query id parsed
* #return content as a string
*/
override def getContentById(query: Int) : String
var pageContent: String = "some string"
pageContent
}
}
class APIConfig(path: String) {
val inputPath = path
}
/** Configuration object for the Content API */
object APIConfig {
protected class APIConfigBuilder(dataPath: String) {
def setDataPath(path: String): APIConfigBuilder = {
new APIConfigBuilder(path)
}
def getOrCreate(): APIConfig = {
new APIConfig(dataPath)
}
}
def withBuilder(): APIConfigBuilder = {
new APIConfigBuilder("")
}
}
def apply(config: APIConfig): ContentAPI = {
new ContentAPI(config)
}
}
/** Client Object */
object APIClient{
def main(args: Array[String]): Unit = {
import Arguments.WIKI_DUMP_BASE
val dataPath = "path"
val contentAPI = ContentAPI(APIConfig.withBuilder().setDataPath(dataPath).getOrCreate())
contentAPI.getAllContent("Anarchism").show()
contentAPI.getContentByTitle("Anarchism").show()
contentAPI.getContentById(12).show()
}
}
I've found similar issues of this particular problem, however the problem was due to someone trying to instantiate T directly. Here I'm trying to create a trait that is a general interface to extend classes and store them automatically in a database such as Riak using classOf[T]. Using Scala 2.10.
Here's my code:
trait RiakWriteable[T] {
/**
* bucket name of data in Riak holding class data
*/
def bucketName: String
/**
* determine whether secondary indices will be added
*/
def enable2i: Boolean
/**
* the actual bucket
*/
val bucket: Bucket = enable2i match {
case true => DB.client.createBucket(bucketName).enableForSearch().execute()
case false => DB.client.createBucket(bucketName).disableSearch().execute()
}
/**
* register the scala module for Jackson
*/
val converter = {
val c = new JSONConverter[T](classOf[T], bucketName)
JSONConverter.registerJacksonModule(DefaultScalaModule)
c
}
/**
* store operation
*/
def store = bucket.store(this).withConverter(converter).withRetrier(DB.retrier).execute()
/**
* fetch operation
*/
def fetch(id: String): Option[T] = {
val u = bucket.fetch(id, classOf[T]).withConverter(converter).withRetrier(DB.retrier).r(DB.N_READ).execute()
u match {
case null => None
case _ => Some(u)
}
}
}
Compiler error is class type required but T found.
Example usage (pseudo-code):
class Foo
object Foo extends RiakWriteable[Foo]
Foo.store(object)
So I'm guessing that a manifest of T is not being properly defined. Do I need to implicitly define this somewhere?
Thanks!
Here's an intermediary solution, though it leaves out the converter registration (which I may leave permanently for this use case, not sure yet).
/**
* trait for adding write methods to classes
*/
trait RiakWriteable[T] {
/**
* bucket name of data in Riak holding class data
*/
def bucketName: String
/**
* determine whether secondary indices will be added
*/
def enable2i: Boolean
/**
* the actual bucket
*/
val bucket: Bucket = enable2i match {
case true => DB.client.createBucket(bucketName).enableForSearch().execute()
case false => DB.client.createBucket(bucketName).disableSearch().execute()
}
/**
* store operation
*/
def store(o: T) = bucket.store(o).withRetrier(DB.retrier).execute()
/**
* fetch operation
*/
def fetch(id: String)(implicit m: ClassTag[T]) = {
val u = bucket.fetch(id, classTag[T].runtimeClass).withRetrier(DB.retrier).r(DB.N_READ).execute()
u match {
case null => None
case _ => Some(u)
}
}
}
Let's say we have
class A
{ ... };
class B
{ ... };
class C
{ ... };
and let's say we have a free-function like
C operator*(A, B)
{ .... }
Is there a way to make operator* to appear in the related functions section of all A, B and C ?
I tried \relatedalso, but it seem to work only once.
Where did you place \relatedalso - documentation of the class(es) or the operator?
You can insert \relates for eacht class at your operators documentation:
/** This is class A. */
class A
{
// ...
};
/** This is class B. */
class B
{
// ...
};
/** This is class C. */
class C
{
// ...
};
/**
* This is an operator.
*
* \relates A
* \relates B
* \relates C
*
* #param a Class A
* #param b Class B
* #return Something
*/
C operator*(A a, B b)
{
// ...
}
Doxygen (html):
Related Functions
(Note that these are not member functions.)
C operator* (A a, B b)
(operator* is linked to it's documentation)