JavaCCを利用して、「 -{ 」と「 }- 」で囲んだ文字列を取得する
JavaCCを利用して、「 -{ 」と「 }- 」で囲んだ文字列を取得する時の方法。
「 /* 」と「 */ 」に置き換えれば、C言語の複数行コメントの中身を取得するときに利用できる。
SPECIAL_TOKENに、「 -{ 」と「 }- 」で囲まれる文字列を指定するのが肝要。SPECIAL_TOKENで指定したパターンにヒットした文字列は、その後にヒットしたTokenで
(Token名).specialToken.image
を呼び出すことで取得できる。
jjtファイル
options { //(略) UNICODE_INPUT=true; //日本語が扱えるようにUnicodeの入力にする //(略) } // (前略) TOKEN: { <NATIVE_CODE_START: "-{" (" ")? >: NATIVE_CODE // -{ にマッチ } <NATIVE_CODE> TOKEN : { <NATIVE_CODE_END: (" ")? "}-" >: DEFAULT // }- にマッチ } <NATIVE_CODE> SPECIAL_TOKEN: { <NATIVE_CODE_BLOCK: (~["}"] | "}" ~["-"])+ > // }- 以外にマッチ } // (中略) //ノード生成部 void NativeCodeBlock(): { Token t; } { // native code block is a SPECIAL_TOKEN, so we need to get it from NATIVE_CODE_END <NATIVE_CODE_START> t=<NATIVE_CODE_END> { jjtThis.jjtSetValue(t.specialToken.image); } Type() }
参考:
hlang/HLisp.jjt at 630a4a439f507729cc8c4833cd37e91e1b8e96f2 · hrehfeld/hlang · GitHub
GWTの正規表現(RegExp)でsオプションを指定したいとき
GWTでは正規表現にはRegExpクラスを使用するが、RegExpクラスはsオプション(シングルラインとして処理)が指定できない。
つまり、「.」は「\n」にマッチしない。
すべての文字と改行をマッチさせたいときは
[\s\S]
を利用するとよい。
参考:How to use JavaScript regex over multiple lines? - Stack Overflow
例
private MatchResult _matchSentenceBlock(String target) { String regex = "([\\s\\S]*?)_\\[([\\s\\S]+?)\\]_([\\s\\S]*)"; RegExp pattern = RegExp.compile(regex, "g"); return pattern.exec(target); }
GWTのTextBoxで透かし文字を入れたいとき
GWTのTextBoxで、テキストボックスに入力を開始すると消える透かし文字の入れ方。
html5では、inputタグにplaceholder属性を指定すると実現できる。これを利用する。
参考
テキストボックスに透かし文字を表示する方法 | JavaScript プログラミング解説
html - How to add a placeholder to a GWT text input field - Stack Overflow
TextBox tb = new TextBox(); tb.getElement().setPropertyString("placeholder", "enter your first name");
GWTコンパイルをantから行う
2015.4.18
下のantソースコードを実行すればいい。
参照するパスなどは必要に応じて書き換えること。
<property name="gwt.module" value="com.example.project.Model com.example.project.Client" />
の部分で指定する。半角スペースで区切ることで複数指定できる。
参考:
GWT Project
build-gwtc.xml
<?xml version="1.0" encoding="utf-8" ?> <project name="gwt-compile" default="build" basedir="."> <!-- コンパイルしたいgwtモジュール 複数指定するときはスペース区切り --> <property name="gwt.module" value="com.example.project.Model com.example.project.Client" /> <!-- gwt SDKのあるディレクトリを指定 --> <property name="gwt.sdk" location="C:\MyPrograms\eclipse_4.4\plugins\com.google.gwt.eclipse.sdkbundle_2.6.0\gwt-2.6.0" /> <!-- コンパイルしたいソースファイルの存在するディレクトリ --> <path id="source.path"> <pathelement location=".apt_generated" /> <pathelement location="src" /> </path> <!-- javaファイルのコンパイルに必要なファイルは lib か war/WEB-INF/lib に入れておくこと --> <path id="project.class.path"> <pathelement location="war/WEB-INF/classes" /> <pathelement location="${gwt.sdk}/gwt-user.jar" /> <fileset dir="${gwt.sdk}" includes="gwt-dev*.jar" /> <!-- Add any additional non-server libs (such as JUnit) --> <fileset dir="war/WEB-INF/lib" includes="**/*.jar" /> <fileset dir="lib" includes="**/*.jar" /> </path> <target name="delombok and gwtc" depends="delombok,gwtc" description="delombok before GWT compile" /> <!-- 1.delombok 2.javac 3.gwtc --> <target name="gwtc" depends="javac" description="GWT compile to JavaScript"> <java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler"> <classpath> <path refid="source.path" /> <path refid="project.class.path" /> </classpath> <!-- add jvmarg -Xss16M or similar if you see a StackOverflowError --> <jvmarg value="-Xmx256M" /> <!-- Additional arguments like -style PRETTY or -logLevel DEBUG --> <arg line="${gwt.module}" /> </java> </target> <target name="libs" description="Copy libs to WEB-INF/lib"> <mkdir dir="war/WEB-INF/lib" /> <copy todir="war/WEB-INF/lib" file="${gwt.sdk}/gwt-servlet.jar" /> <!-- Add any additional server libs that need to be copied --> </target> <target name="javac" depends="libs"> <mkdir dir="war/WEB-INF/classes" /> <javac includes="**" encoding="utf-8" destdir="war/WEB-INF/classes" source="1.5" target="1.5" nowarn="true" debug="true" debuglevel="lines,vars,source"> <classpath refid="project.class.path" /> <src refid="source.path" /> </javac> <copy todir="war/WEB-INF/classes"> <fileset dir="src" excludes="**/*.java" /> </copy> </target> <target name="build" depends="gwtc" description="Build this project" /> <target name="war" depends="build" description="Create a war file"> <zip destfile="Foo.war" basedir="war" /> </target> <target name="clean" description="Cleans this project"> <delete dir="war/WEB-INF/classes" failonerror="false" /> <delete dir="war/foo" failonerror="false" /> </target> </project>
GWT + delombok でantタスクからGWTコンパイルする
2015.4.14
このブログの内容を行う前の注意
- lombok.jarをGWTで利用する(GWTでlombokを使用する - busimotegeek’s blog)と以前にコンパイルが通ったjavaファイルでも、ある日突然エラーが出てコンパイルが通らなくなるという問題がある
- delombok を利用してlombokを利用して書かれたソースコードから、アクセッサメソッドを含むソースファイルを生成し、それをGWTコンパイルするというのが本記事の目的
- 本記事の内容を利用することで、delombokしてからGWTコンパイルということがantコマンド1つでできる。
- しかし、手順が多くファイル構造が冗長になってしまった。ゆえに、本記事の内容をそのまま利用するのは非推奨。
動機
lombokでjavaファイルのボイラーコードを減らしたかったが、lombokでAST変換してからGWTコンパイルすると、以前にコンパイルが通ったjavaファイルでエラーが出るという問題が出たので、delombokを利用するようにした。
環境
antのビルドタスクの作成
- 記事末尾のxmlファイル2つをプロジェクトのトップディレクトリに置くこと
- パスなどを適宜修正すること
delombokするファイルについての注意
- delombokしたいファイルの末尾にはBaseをつけること(*Base.java)。delombokターゲット実行時に、ファイル名・クラス名からBaseを除外したjavaファイルが作成される(*.java)。
ex. ModelDataBase.java(ModelDataBaseクラスを含む)
-> ModelData.java(ModelDataクラスを含む)
- ファイルを修正したいときは、いったん *Base.java を編集してから再度delombokターゲットを実行すること。
(junit実行時などはこれがすごく手間)
- 他のクラスから利用するときは、*Baseクラスではなく、delombokで生成したクラスのほうを使用すること。
GWT Super Dev Modeでのデバッグ手順
(すでにGWT Super Dev Modeでローカルサーバ実行中の前提で)
- *Base.java の修正
- gwtcターゲット実行
- プロジェクトのリフレッシュ
- HTMLページを再読み込み
build-gwtc.xml (GWT Project からデバッグとテストの内容を除外したもの)
<?xml version="1.0" encoding="utf-8" ?> <project name="gwt-compile" default="build" basedir="."> <import file="build-delombok.xml" /> <!-- コンパイルしたいgwtモジュール 複数指定するときはスペース区切り --> <property name="gwt.module" value="com.example.project.Model com.example.project.Client" /> <!-- gwt SDKのあるディレクトリを指定 --> <property name="gwt.sdk" location="C:\MyPrograms\eclipse_4.4\plugins\com.google.gwt.eclipse.sdkbundle_2.6.0\gwt-2.6.0" /> <!-- javaファイルのコンパイルに必要なファイルは lib か war/WEB-INF/lib に入れておくこと --> <path id="project.class.path"> <pathelement location="war/WEB-INF/classes" /> <pathelement location="${gwt.sdk}/gwt-user.jar" /> <fileset dir="${gwt.sdk}" includes="gwt-dev*.jar" /> <!-- Add any additional non-server libs (such as JUnit) --> <fileset dir="war/WEB-INF/lib" includes="**/*.jar" /> <fileset dir="lib" includes="**/*.jar" /> </path> <!-- コンパイルしたいソースファイルの存在するディレクトリ --> <path id="source.path"> <pathelement location=".apt_generated" /> <pathelement location="src" /> </path> <target name="delombok and gwtc" depends="delombok,gwtc" description="delombok before GWT compile" /> <!-- 1.delombok 2.javac 3.gwtc --> <target name="gwtc" depends="javac" description="GWT compile to JavaScript"> <java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler"> <classpath> <path refid="source.path" /> <path refid="project.class.path" /> </classpath> <!-- add jvmarg -Xss16M or similar if you see a StackOverflowError --> <jvmarg value="-Xmx256M" /> <!-- Additional arguments like -style PRETTY or -logLevel DEBUG --> <arg line="${gwt.module}" /> </java> </target> <target name="libs" description="Copy libs to WEB-INF/lib"> <mkdir dir="war/WEB-INF/lib" /> <copy todir="war/WEB-INF/lib" file="${gwt.sdk}/gwt-servlet.jar" /> <!-- Add any additional server libs that need to be copied --> </target> <target name="javac" depends="libs"> <mkdir dir="war/WEB-INF/classes" /> <javac includes="**" encoding="utf-8" destdir="war/WEB-INF/classes" source="1.5" target="1.5" nowarn="true" debug="true" debuglevel="lines,vars,source"> <classpath refid="project.class.path" /> <src refid="source.path" /> </javac> <copy todir="war/WEB-INF/classes"> <fileset dir="src" excludes="**/*.java" /> </copy> </target> <target name="build" depends="gwtc" description="Build this project" /> <target name="war" depends="build" description="Create a war file"> <zip destfile="Foo.war" basedir="war" /> </target> <target name="clean" description="Cleans this project"> <delete dir="war/WEB-INF/classes" failonerror="false" /> <delete dir="war/foo" failonerror="false" /> </target> </project>
build-delombok.xml
<?xml version="1.0" encoding="utf-8" ?> <project name="delombok" default="delombok" basedir="."> <!-- delombokする前のファイルの一時フォルダ --> <property name="dir.delombok.pickup" value=".delombok_generated/source" /> <!-- delombokした後のファイルの一時フォルダ --> <property name="dir.delombok.generated" value=".delombok_generated/dist" /> <!-- delombokするjavaクラスの接尾辞 --> <property name="delombok.template.suffix" value="Base" /> <target name="delombok" description=""> <fileset dir="src" id="delombok-src"> <include name="**/*${delombok.template.suffix}.java" /> <!-- <exclude name="exclude"/> --> </fileset> <taskdef classname="lombok.delombok.ant.Tasks$Delombok" classpath="lib/lombok.jar" name="delombok" /> <delete dir="${dir.delombok.pickup}" /> <mkdir dir="${dir.delombok.pickup}" /> <delete dir="${dir.delombok.generated}" /> <mkdir dir="${dir.delombok.generated}" /> <_copy-delombok-source /> <delombok verbose="true" encoding="UTF-8" to="${dir.delombok.generated}" from="${dir.delombok.pickup}"> <format value="suppressWarnings:skip" /> </delombok> <_copy-delombok-dist /> <!-- <eclipse.refreshLocal /> --> </target> <!-- delombokされたファイルをsrcにコピー --> <macrodef name="_copy-delombok-dist"> <sequential> <echo message="delombokされたファイルをsrcにコピー" /> <replaceregexp byline="true" flags="g"> <regexp pattern="(\w+)${delombok.template.suffix}" /> <substitution expression="\1" /> <fileset dir="${dir.delombok.generated}" id="_delombok-dist"> <include name="**/*${delombok.template.suffix}.java" /> </fileset> </replaceregexp> <!-- delombokした後のjavaファイルのサブパッケージ <property name="delombok.package.generated" value="generated" /> <replaceregexp byline="true" flags="g"> <regexp pattern="^package\s(.+);$" /> <substitution expression="package \1.${delombok.package.generated};" /> <fileset dir="${dir.delombok.generated}" id="_delombok-dist"> <include name="**/*${delombok.template.suffix}.java" /> </fileset> </replaceregexp> --> <copy todir="src" overwrite="true"> <fileset dir="${dir.delombok.generated}" id="_delombok-dist"> <include name="**/*${delombok.template.suffix}.java" /> </fileset> <mapper type="glob" from="*${delombok.template.suffix}.java" to="*.java" /> <!-- <mapper type="regexp" from="^(.+)/([^/]+)${delombok.template.suffix}.java" to="\1/${delombok.package.generated}/\2.java" /> --> </copy> <pathconvert property="convert-path" refid="_delombok-dist" /> <echo message="${convert-path}" /> </sequential> </macrodef> <!-- delombokするファイルをsrcからコピー --> <macrodef name="_copy-delombok-source"> <sequential> <echo message="delombokするファイルをsrcにコピー" /> <copy todir="${dir.delombok.pickup}" overwrite="true"> <fileset dir="src" id="_delombok-source"> <include name="**/*${delombok.template.suffix}.java" /> <!-- <exclude name="exclude"/> --> </fileset> </copy> <pathconvert property="convert-path" refid="_delombok-source" /> <echo message="${convert-path}" /> </sequential> </macrodef> </project>
GWTでlombokを使用する
- eclipseにlombokをインストール
- (lombokを使用してjavaファイルを作成)
- GWT Compile Project -> Advanced -> VM arguments: に次の文を追加
- javaagent:lib/lombok.jar=ECJ (プロジェクトのlibフォルダにlombok.jarを入れているとき)
「(ゲッター名)is undefined for the type」のようなエラーが出たとき
対象のフィールドにいったん @Getterをつけてから再コンパイルすると直ることがある。
参考:
Project Lombok
@Data @Model(schemaVersion = 1) public class MyModel implements Serializable { private static final long serialVersionUID = 1L; @Attribute(primaryKey = true) private Key key; @Attribute(version = true) private Long version; // @Getter private String title; @Attribute(unindexed=true) private String content; @Attribute(lob=true) private String description; }