Transform _id to id with JSON format macro - playframework-2.1

I use reactivemongo in my Play application. My models use the property id and not _id. How can I automatically transform the object ID(_id), so that it will be mapped to the id property of my models.
Currently I write the format by hand:
implicit val adviceFormat = (
(__ \ '_id).format[BSONObjectID] and
(__ \ 'lang).format[Lang] and
(__ \ 'title).format[String] and
(__ \ 'text).format[String] and
(__ \ 'reads).formatNullable[Seq[PeriodCounter]] and
(__ \ 'creationDate).format[DateTime] and
(__ \ 'updateDate).format[DateTime]
)(Advice.apply, unlift(Advice.unapply))
But I would like to write only:
implicit val adviceFormat = Json.format[Advice]
Update:
Based on the answer of trevor.reznik I have figured it out.
implicit val adviceJSONReads = __.json.update((__ \ 'id).json.copyFrom((__ \ '_id).json.pick[JsObject] )) andThen Json.reads[Advice]
implicit val adviceJSONWrites = Json.writes[Advice].transform( js => js.as[JsObject] - "id" ++ Json.obj("_id" -> js \ "id") )

For Json writes you can do something like :
val userWrites = Json.writes[User].transform( js => js.as[JsObject] - "id" ++ Json.obj("_id" -> js \ "id") )
But I'm not sure you can do something similar with reads.

Related

Caused by: java.lang.IllegalStateException: Could not read class: VirtualFile: Kotlin+ Apache Beam defined runner

I implemented an example using Kotlin + Apache Beam to define the Kotlin properties of the pipes but when I ran the project I got the error:
Caused by: java.lang.IllegalStateException: Could not read class: VirtualFile: /Users/duanybaro/.gradle/caches/modules-2/files-2.1/org.apache.beam/beam-runners-google-cloud-dataflow-java/2.27.0/3e551e54b23441cc58c9d01e6614ff67216a7e87/beam-runners-google-cloud-dataflow-java-2.27.0.jar!/org/apache/beam/runners/dataflow/DataflowPipelineJob.class
at org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass.<init>(BinaryJavaClass.kt:122)
at org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass.<init>(BinaryJavaClass.kt:34)
This error only occurs in Kotlin because, with the code made in java, it works perfectly. Can you give me any suggestions to solve the error?
I really recommend you using the latest version of Apache Beam, your version is very old.
You can also use the starter for Beam Kotlin.
I share with your an example of Kotlin Beam project from my Github repo based on Maven.
For the Beam pipeline options, can you try with instead of using DataflowPipelineOptions :
val options = PipelineOptionsFactory
.fromArgs(*args)
.withValidation()
.`as`(TeamLeagueOptions::class.java)
val pipeline = Pipeline.create(options)
Example of PipelineOptions :
import org.apache.beam.sdk.options.Description
import org.apache.beam.sdk.options.PipelineOptions
interface TeamLeagueOptions : PipelineOptions {
#get:Description("Path of the input Json file to read from")
var inputJsonFile: String
#get:Description("Path of the slogans file to read from")
var inputFileSlogans: String
#get:Description("Path of the file to write to")
var teamLeagueDataset: String
#get:Description("Team stats table")
var teamStatsTable: String
#get:Description("Job type")
var jobType: String
#get:Description("Failure output dataset")
var failureOutputDataset: String
#get:Description("Failure output table")
var failureOutputTable: String
#get:Description("Feature name for failures")
var failureFeatureName: String
}
And pass program argument in the mvn command line :
mvn compile exec:java \
-Dexec.mainClass=fr.groupbees.application.TeamLeagueApp \
-Dexec.args=" \
--project=my-project \
--runner=DataflowRunner \
--jobName=team-league-kotlin-job-$(date +'%Y-%m-%d-%H-%M-%S') \
--region=europe-west1 \
--streaming=false \
--zone=europe-west1-d \
--tempLocation=gs://mazlum_dev/dataflow/temp \
--gcpTempLocation=gs://mazlum_dev/dataflow/temp \
--stagingLocation=gs://mazlum_dev/dataflow/staging \
--inputJsonFile=gs://mazlum_dev/team_league/input/json/input_teams_stats_raw.json \
--inputFileSlogans=gs://mazlum_dev/team_league/input/json/input_team_slogans.json \
--teamLeagueDataset=mazlum_test \
--teamStatsTable=team_stat \
--jobType=team_league_kotlin_ingestion_job \
--failureOutputDataset=mazlum_test \
--failureOutputTable=job_failure \
--failureFeatureName=team_league \
" \
-Pdataflow-runner

Long code line continuation method in GAP language

Take the following code snippet as an example:
f:= FreeGroup("P","Q","R","S");
AssignGeneratorVariables(f);
g:= f/ParseRelators(f, "P^12=Q^4=R^4=S^8=1, Q^2=R^2, S^2 = P^6*Q^2*R,
Q*P=P^7*Q^2*R, Q*P^3=P^3*Q, R*P=P^10*Q*R, R*Q=P^6*Q^3*R, S*P=P^2*R*S,
S*Q=P^3*Q^3*R*S, S*R=R*S" );
I'm not sure if there is a long code line continuation method
implemented in GAP language.
Edit: Based on the nice tricks and tips given by Olexandr and Horn, I would like to add some corresponding supplementary information as follows:
"Triple Quoted Strings" is described here.
The handling mechanism of line continuation, i.e., backslash followed by new line, is described here.
In addition, the gap source code also includes the following description:
$ ugrep -i 'line continuation.*backslash'
bin/x86_64-pc-linux-gnu-default64-kv8/src/io.c: // handle line continuation, i.e., backslash followed by new line; and
src/io.c: // handle line continuation, i.e., backslash followed by new line; and
Regards,
HZ
The problem here is not with the command occupying several lines, but with the string including a line break, as the error message says:
gap> g:= f/ParseRelators(f, "P^12=Q^4=R^4=S^8=1, Q^2=R^2, S^2 = P^6*Q^2*R,
Syntax error: String must not include <newline>
g:= f/ParseRelators(f, "P^12=Q^4=R^4=S^8=1, Q^2=R^2, S^2 = P^6*Q^2*R,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You have to use backslash \ to continue the string from a new line. This input works:
f:= FreeGroup("P","Q","R","S");
AssignGeneratorVariables(f);
g:= f/ParseRelators(f, "P^12=Q^4=R^4=S^8=1, Q^2=R^2, S^2 = P^6*Q^2*R,\
Q*P=P^7*Q^2*R, Q*P^3=P^3*Q, R*P=P^10*Q*R, R*Q=P^6*Q^3*R, S*P=P^2*R*S,\
S*Q=P^3*Q^3*R*S, S*R=R*S" );
You can also use spaces as you like to indent and format it, e.g.
f:= FreeGroup("P","Q","R","S");
AssignGeneratorVariables(f);
g:= f/ParseRelators(f,
"P^12 = Q^4 = R^4 = S^8 = 1, \
Q^2 = R^2, S^2 = P^6*Q^2*R, \
Q*P = P^7*Q^2*R, \
Q*P^3 = P^3*Q, \
R*P = P^10*Q*R, \
R*Q = P^6*Q^3*R, \
S*P = P^2*R*S, \
S*Q = P^3*Q^3*R*S, \
S*R = R*S" );
or so.
As an alternative to the nice answer by Olexandr, let me mention that you can also use triple quoted strings to avoid the need for line continuations. E.g. like this:
f:= FreeGroup("P","Q","R","S");
AssignGeneratorVariables(f);
g:= f/ParseRelators(f, """
P^12 = Q^4 = R^4 = S^8 = 1,
Q^2 = R^2, S^2 = P^6*Q^2*R,
Q*P = P^7*Q^2*R,
Q*P^3 = P^3*Q,
R*P = P^10*Q*R,
R*Q = P^6*Q^3*R,
S*P = P^2*R*S,
S*Q = P^3*Q^3*R*S,
S*R = R*S
""" );

ESP32 SSL connection works when CA Certificate is a constant, but not when read from a file

I have the following Arduino code I'm using with an ESP32:
if(!SPIFFS.begin(true)) {
Serial.println("Error mounting SPIFFS.");
}
File file = SPIFFS.open("/root.cer");
if(!file) {
Serial.println("Error opening the file.");
}
Serial.println("CA Root certificate: ");
String ca_cert = file.readString();
Serial.println(ca_cert);
espClient.setCACert(ca_cert.c_str());
file.close();
This is the relevant code for loading a file and setting the WiFiClientSecure's CA certificate. This code does not work.
However, if I replace espClient.setCACert(ca_cert.c_str()); with espClient.setCACert(ROOTCERT); where ROOTCERT is defined as such:
#define ROOTCERT "-----BEGIN CERTIFICATE-----\n" \
"MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\n" \
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \
"DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\n" \
"PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\n" \
"Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n" \
"AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\n" \
"rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\n" \
"OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\n" \
"xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n" \
"7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\n" \
"aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\n" \
"HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\n" \
"SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\n" \
"ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\n" \
"AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\n" \
"R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\n" \
"JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\n" \
"Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n" \
"-----END CERTIFICATE-----\n"
The code works.
The ROOTCERT string is taken directly from the certificate file, so they must be identical.
The certificate file was downloaded and exported using Windows's certificate exporter. I've tried converting line endings to no avail.
EDIT: I've found a clue.
If I do the following:
String constString = ROOTCERT;
espClient.setCACert(constString.c_str());
It also does not work.
And I added this code:
if(strcmp(constString.c_str(), ROOTCERT))
Serial.println("Constant and converted string are equal.");
else
Serial.println("Constant and converted string are different.");
And it prints "Constant and converted string are different."
So it appears to be some kind of problem with how .c_str() does things? I have no idea what this could be, though. When printed to the console, the .c_str(), ROOTCERT and ca_cert Strings all appear IDENTICAL.
I am completely confused here.
Turns out I was using strcmp() incorrectly. Things are still not working.
After messing around, I fixed it.
So .c_str() is just another way of pointing to the internal buffer of the String object.
Somehow that was messing things up. Using this code fixed it.
char *dest;
dest = (char *)malloc(sizeof(char) * (ca_cert.length()+1));
strcpy(dest, ca_cert.c_str());
espClient.setCACert(dest);

Pandoc: Is there a way to include an appendix of links in a PDF from markdown?

I use Markdown and Pandoc extensively. However, I would like to generate a PDF with embedded links (like usual), but in the event the document is printed, I'd like to also include a table of links at the end of the document. Is there a way to do this automatically?
Ex.
Title
-----
[Python][] is cool!
...
## Links ##
[Python]: http://python.org
[Pip]: https://pip.readthedocs.org
where I would actually get an extra page in my PDF with something like
Python: http://python.org
Pip: https://pip.readthedocs.org
Thanks!
This is something that is easy to achieve with filters.
Here is linkTable.hs. A filter which adds a table of links to the end of your document.
import Text.Pandoc.JSON
import Text.Pandoc.Walk
import Data.Monoid
main :: IO ()
main = toJSONFilter appendLinkTable
appendLinkTable :: Pandoc -> Pandoc
appendLinkTable (Pandoc m bs) = Pandoc m (bs ++ linkTable bs)
linkTable :: [Block] -> [Block]
linkTable p = [Header 2 ("linkTable", [], []) [Str "Links"] , Para links]
where
links = concatMap makeRow $ query getLink p
getLink (Link txt (url, _)) = [(url,txt)]
getLink _ = []
makeRow (url, txt) = txt ++ [Str ":", Space, Link [Str url] (url, ""), LineBreak]
Compile the filter with ghc linkTable.hs. The output is as follows.
> ghc linkTable.hs
[1 of 1] Compiling Main ( linkTable.hs, linkTable.o )
Linking linkTable ...
> cat example.md
Title
-----
[Python][] is cool!
[Pip] is a package manager.
...
[Python]: http://python.org
[Pip]: https://pip.readthedocs.org
Then running pandoc with the filter.
> pandoc -t markdown --filter=./linkTable example.md
Title
-----
[Python](http://python.org) is cool!
[Pip](https://pip.readthedocs.org) is a package manager.
...
Links {#linkTable}
-----
Python: <http://python.org>\
Pip: <https://pip.readthedocs.org>\

FBML multi friend selector in fb:dialog

Is there a way to show the multi friend selector widget (fb:multi-friend-selector) in an fb:dialog?
I have a button, on selecting which I would like to show the friend selector popup and users can send invite to their friends. I got the friend selector working on the main page but have no clue on how to display that widget in fb:dialog.
Thanks
Jugs
You'll have to edit this, but here's a jist:
popupInviteFriends : function (e) {
if (e) { e.preventDefault(); }
var fbml = '<fb:request-form \
action="." \
method="GET" \
invite="true" \
type="TWO" \
content="This is an invitation from ' + TWOFace.BRAND + '. \
<fb:req-choice url=\'' + TWOFace.INVITE_DIALOG.postBack + '\' \
label=\'Join ' + TWOFace.BRAND + '\' />"> \
<fb:multi-friend-selector \
showborder="false" \
rows="4" \
actiontext="Invite your friends to use ' + TWOFace.BRAND + '"> \
</fb:multi-friend-selector> \
</fb:request-form';
var container = document.createElement('div');
container.innerHTML = fbml;
var inviteIFrame = new FB.UI.PopupDialog(TWOFace.INVITE_DIALOG.title, container);
inviteIFrame.setContentWidth(590);
inviteIFrame.setContentHeight(400);
inviteIFrame.show();
},