Metadataを活用し、動的にDtoを作る
JavascriptからDataを取得する場合、Entityの一部のみで良い場合が良くあります。
その度に、Dtoを作るのが面倒ですので、slim3のMetadataを使用して、作るRoutineを書いてみました。
使用方法は、
private LginMeta m = LginMeta.get(); DtoAdhoc da = DatastoreUtil.dto().add(m.logi, m.name, m.sec); HashMap hm = da.toMapWithKeyJSON(res); //尚一回だけの使用であれば下記の様に勿論書けます。流れるインターフェースは良いですね。 HashMap hm = DatastoreUtil.dto().add(m.logi, m.name, m.sec).toMapWithKeyJSON(res);
ソースは下記の様に簡単です。
public class DatastoreUtil { public static DtoAdhoc dto() { return new DtoAdhoc(); } } public class DtoAdhoc { private ArrayListfields = new ArrayList(); private BeanDesc beanDesc; public DtoAdhoc add(CoreAttributeMeta... flds) { for (CoreAttributeMeta fld : flds) { fields.add(fld.getName()); } return this; } public HashMap toMap(Object o) { HashMap res = new HashMap(); for (String fld : fields) { res.put(fld, getBeanDesc(o).getPropertyDesc(fld).getValue(o)); } return res; } public HashMap toMapWithKeyJSON(Object o) { HashMap res = toMap(o); res.put("key", JSON.encode(getBeanDesc(o).getPropertyDesc("key") .getValue(o))); return res; } protected BeanDesc getBeanDesc(Object o) { if (beanDesc != null) { return beanDesc; } beanDesc = BeanUtil.getBeanDesc(o.getClass()); return beanDesc; } }
GAE/J JDO Query Eclipse Plugin
やっぱり手作業で Entity ClassにConstantを作るのは面倒なので、Eclipse Pluginを作りました。
はじめての Pluginでしたが、竹添さんの本と Google先生の助けで、意外と簡単にできました。
Mainの部分は以下の通りです。
public Object execute(ExecutionEvent event) throws ExecutionException {
IWorkbenchWindow window = HandlerUtil
.getActiveWorkbenchWindowChecked(event);
IEditorPart editorPart = window.getActivePage().getActiveEditor();
IEditorInput editorInput = editorPart.getEditorInput();
ICompilationUnit iCompilationUnit = (ICompilationUnit) editorInput
.getAdapter(IJavaElement.class);try {
IType itypes = iCompilationUnit.getAllTypes();
if (itypes.length ==1){
IType it = itypes[0];
IField fields=it.getFields();
for (IField iField : fields) {
IAnnotation annos = iField.getAnnotations();
for (IAnnotation iAnnotation : annos) {
if (iAnnotation.getElementName().equals("Persistent")){
checkAndCreateClassField(iField.getElementName(),fields,it);
}
}
}
}
} catch (JavaModelException e) {
e.printStackTrace();
}MessageDialog.openInformation(window.getShell(), "Generete Datastore Constant",
"Constant Generated");
return null;
}private void checkAndCreateClassField(String elementName, IField fields,
IType itype) {
for (IField field : fields) {
if (field.getElementName().equals("C_"+elementName)){
return;
}
}
try {
itype.createField("static public final String C_"+elementName+" = \""+elementName+"\" ;", null, true, new NullProgressMonitor());
} catch (JavaModelException e) {
e.printStackTrace();
}
}
GAE/J JDO Query 流れるインターフェース Typesafe
GAE/Jの場合、結合はすべて ANDなので、Filterの自動作成がやり易い。
下記 Utilityを作成した。
これを使うと、
query.setFilter( ( new QueryFilter( ) ).sEq("delete", "N").toString());
と書ける。(勿論流れる インターフェスなので複数連続できる)
このままでは typesafeにならないし、あえてMETA Classに定義するのは
面倒なので、entity Classに下記定義を行う。
static public final String C_delete = "delete";
これにより、上記は、次の様に書ける。
query.setFilter ( ( new QueryFilter( )).sEq(Table.C_delete, "N").toString());
これも、いちいち手作業で間違えたら元も子もないし、EclipseのPluginを作る
程でもないので、下記 GenerateEntityConstant Classを作ったので、
mainから呼び出して、ConsoleにPrintして コピペで OK.
これで使い易くなった。
public class QueryFilter {
private StringBuffer fstring = new StringBuffer();public QueryFilter eq(String element, Object value) {
checkAnd();
fstring.append(element +" == "+value);
return this;
}public QueryFilter sEq(String element, String value) {
checkAnd();
fstring.append(element +" == '"+value+"'");
return this;
}
public QueryFilter ge(String element, Object value) {
checkAnd();
fstring.append(element +" >= "+value);
return this;
}public QueryFilter sGe(String element, String value) {
checkAnd();
fstring.append(element +" >= '"+value+"'");
return this;
}
public QueryFilter gr(String element, Object value) {
checkAnd();
fstring.append(element +" > "+value);
return this;
}public QueryFilter sGr(String element, String value) {
checkAnd();
fstring.append(element +" > '"+value+"'");
return this;
}
public QueryFilter le(String element, Object value) {
checkAnd();
fstring.append(element +" <= "+value);
return this;
}public QueryFilter sLe(String element, String value) {
checkAnd();
fstring.append(element +" <= '"+value+"'");
return this;
}
public QueryFilter between(String element, Object from, Object to) {
checkAnd();
fstring.append(element +" >= "+from + " && "+element + " <= " +to);
return this;
}public QueryFilter sBetween(String element, Object from, Object to) {
checkAnd();
fstring.append(element +" >= '"+from + "' && "+element + " <= '" +to+"'");
return this;
}
public QueryFilter lt(String element, Object value) {
checkAnd();
fstring.append(element +" < "+value);
return this;
}public QueryFilter sLt(String element, String value) {
checkAnd();
fstring.append(element +" < '"+value+"'");
return this;
}
public QueryFilter startWith(String element, String value) {
checkAnd();
char c = 255;
fstring.append(element +" >= '"+value+"' && "+element +" <= '"+value+Character.toString(c)+"'");
return this;
}
public String toString(){
return fstring.toString();
}
private void checkAnd() {
if (fstring.length() > 0) {
fstring.append(" && ");
}
}}
public static void main(String[] args) {
System.out.print(GenerateEntityConstant.getGenerateProgram(Table.class));
}
public class GenerateEntityConstant {
static public String getGenerateProgram(Class clazz){
StringBuffer sb = new StringBuffer();
try {
BeanInfo info = Introspector.getBeanInfo(clazz, Object.class);
PropertyDescriptor[] pds= info.getPropertyDescriptors();
for (PropertyDescriptor pdone : pds) {
String name = pdone.getName();
sb.append("static public final String C_"+name+" = \""+name+"\";\n");
}
} catch (IntrospectionException e) {e.printStackTrace();
}
return sb.toString();
}}
GAE/J VersionStrategy.VERSION_NUMBER
GAE/J で Versionを使って Controlすると、自動的に「OPT_VERSION」
という Columnが Generateされて使われる。
これを、DTOに詰めて Clientにわたすには、Integer で OPT_VERSIONのFieldを
作ったら、上手くいった。
GAE/Jはまだなかなか情報が無くて、手探りですね。
SmartClient AJAX + GAE/J+GOOGLE APPS
EXT-JSは LicenseがLGPLでなくなって、使用に制約が多く、YUIもやってみましたが、機能が今一でした。
SmartClientの 7.0 RCが出たというので、使ってみましたら、Conceptとしては、EXT−JSに非常に近く、機能 特に Table関連やDynamic Form関連が大変使いやすそうです。
GAE/JのFront Endに使って見ます。
先日 まさたかさんのはてなで、GAEのPresentationがあるとの事で、サイオスのGOOGLE APPSのセミナーに行ってきました。
APPSのStandard Versionは無償で50人まで管理出来る事がわかったので早速やってみました。
申し込みと同時に Domainを取得すると、Google Apps経由ですべて作業が完了でき、費用も年$10でした。
登録直後は、AppsのDashboardに自分のDomainが表示されるものの、設定が出来ない状態でしたので、Google Check経由で問い合わせをしていましたら、2日弱で正常に接続できました。
AppsのDomainで GAEのサイトも接続できるので、大変お勧めです。
GAE/J 日本語文字化け Patch
下記 URLにある C#のPatch JAVAC.EXEを作ったら、とりあえず文字化けなしに
Upload可能となりました。
http://groups.google.com/group/google-appengine-java/browse_thread/thread/1345bf330766d8be
That's great!
And I have an alternative way to fix this problem.
I wrote a simple tool to add the encoding argument to javac.exe.
Just rename javac.exe to javac1.exe, and rename the tool to javac.exe.
Here is the main part of the tool (wrote in C#):
static int Main(string[] args)
{
string arg = "";
var cmd = Environment.CommandLine;
arg = cmd.Substring(cmd.IndexOf(args[0]));
if (!arg.Contains(" -encoding"))
arg += " -encoding UTF8";
Console.WriteLine("argment:{0}", arg);
Process p = new Process();
p.StartInfo.FileName = "javac1.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.Arguments = arg;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = false;
p.Start();
while (true)
{
var msgStd = p.StandardOutput.ReadLine();
if (msgStd != null)
Console.WriteLine(msgStd);
var msgErr = p.StandardError.ReadLine();
if (msgErr != null)
Console.WriteLine(msgErr);
if (msgStd == null && msgErr == null)
break;
}
return p.ExitCode;
}