シンプルなXMLフレームワーク-DIAダイアグラムを操作するためのAPIの作成

シンプルなxmlフレームワークDia Diagram Editor Dia Diagram Editor



シンプルなXMLフレームワーク-多くの人に知られていますが、そのシンプルさから、大規模な「中間」JAXBの可能性と競合することができ、同時にAndroidと互換性があります。



その使用に関する記事は「大量」ではありませんが、十分です。 Framefork Habré で言及されましたがibm developerworksに関する記事があります。結局、公式サイトには良いガイドがあります。



一般に、フレームワークの使用方法は明確です。 しかし、マニュアルやチュートリアルで説明されている方法がすでに十分でない構造がある場合があります。 これはまさに、DIAがダイアグラムを保存する方法を理解し始めたときに発見したXML構造の種類です。



この記事では、この状況で動作するようにSimple Frameworkを教える方法について説明します。 Simple Frameworkの独自の「戦略」を作成します。 TreeStrategyクラスから継承し、DIA xmlファイルの要素をJavaクラスにマップする方法の「難しいロジック」を説明します。



そして、はい、読者はSimple XML Frameworkの使用の基本に精通していると思います。



DIAについてのいくつかの言葉と物語の始まり



DIAチャートエディターはほとんどの人に知られていると思います。 ある意味では、これは「ジャンルの古典」です。



ずっと前に作成されましたが、ファイル形式の説明は多かれ少なかれ明確ではありません。 .diaファイルは、拡張子が.diaのxmlファイルのzipアーカイブであることが知られています(ちなみに、チャートエディターは非圧縮ファイルを操作できます。設定で圧縮せずに保存を有効にできます)。



そして...さらに、彼らは、「自分でそれを考え出してください。難しいことではありません」と言います。



数年前のメーリングリストでは、ある程度関連する説明が参照されていましたが、現在は無効になっています。



ダイアグラムを生成または編集するためのソフトウェアインターフェイスの存在についても、疑問はありません。 Dia形式にエクスポートできるチャートエディターのリストがありますが、自分に適したものは見つかりませんでした。



「プログラムは優れています」と思ったのですが、「APIが必要です。 すぐに使用できます。 できればJavaで。」



最終的に、私は自分の自転車を作ることにしました。 私にとって快適で、座席の下に形作られ、

私の手の形をした車輪と、私が歩く道のくぼみの形をした車輪で。



Diaにダイアグラムを保存するためのフォーマットとその機能



ここでは、構造全体を分析するのではなく、「問題のある機能」にすぐに進みます。



.diaでは、チャート要素のストレージ構造が統一されています。オブジェクトのすべての特性を記述する属性タグのリストを「フレーム化」するオブジェクトタグです。



たとえば、これは、DIAベースパレットのライン要素の記述方法です。
<dia:object type="Standard - Line" version="0" id="O10"> <dia:attribute name="obj_pos"> <dia:point val="2.99224,32.237"/> </dia:attribute> <dia:attribute name="obj_bb"> <dia:rectangle val="2.92606,32.1708;7.37558,34.382"/> </dia:attribute> <dia:attribute name="conn_endpoints"> <dia:point val="2.99224,32.237"/> <dia:point val="7.3094,34.1931"/> </dia:attribute> <dia:attribute name="numcp"> <dia:int val="1"/> </dia:attribute> <dia:attribute name="end_arrow"> <dia:enum val="5"/> </dia:attribute> <dia:attribute name="end_arrow_length"> <dia:real val="0.5"/> </dia:attribute> <dia:attribute name="end_arrow_width"> <dia:real val="0.5"/> </dia:attribute> </dia:object>
      
      





ここでの主な問題は、すべてのタイプの要素が単一のタグで記述されることです。

その結果、Simple Frameworkの言い方が明確ではありません。

 <dia:object type="Standard - Line" version="0" id="O10">
      
      



-クラスLineのオブジェクトに解析する必要があります。

 <dia:object type="Standard - Box" version="0" id="O0">
      
      



-クラスBoxのオブジェクトへ。 通常のSimple Frameworkツールキットでは、この問題を解決する方法が見つかりませんでした。 そのため、「戦略」DiaTreeStrategyが説明されました。その歴史を以下に示します。



ところで、ミニマリズムについて話しているので、Simple Frameworkは.diaフォーマットの解析に適用できます。@ Xpathアノテーションとその制限について言及する価値があります。
問題は、Diaがxmlに保存するグラフオブジェクトの属性の構成が一定ではなく、このオブジェクトに対して変更したプロパティに依存するという事実にあります。



このため、.diaのxml構造を解析する場合、@ Xpathアノテーションをインデックスとともに使用して、xmlで説明されているクラスプロパティとオブジェクト属性を一致させることはできません。 xpathリクエストでできるように、属性の名前と値を@Xpathで指定できる場合、これによりタスクが簡単になりますが、残念ながら@Xpathで指定できるのはパスとインデックスのみです。 これらの状況から、私のコードでは、属性の配列からクラスのプロパティを入力するための最も便利なメカニズムではなく、別の機会に登場しました。


Simple Frameworkの「戦略」、DiaTreeStrategyの作成を開始



Simple Frameworkで「戦略」(Strategyインターフェースを実装)を実装するクラスは、JavaでXMLノードとクラス間のマッピングを定義することにコミットしています。



このインターフェイスには、読み取り()と書き込み()の2つのメソッドしかありません。 1つ目は、送信されたxml-nodeによって、どのクラスに入力するかを理解しようとするという事実を扱い、2番目は、オブジェクトプロパティを入力するxml-nodeを作成します。



最初から戦略を書くことは「紳士の仕事ではありません」。特に、他のすべてでの通常のTreeStrategy(型オブジェクトのクラスとノードを正しく一致させる方法を知らないことを除く)は非常にうまく機能するからです。 微調整するだけだからです。 継承して修正します。



 public class DiaTreeStrategy extends TreeStrategy
      
      





読者は、おそらく、オブジェクトタグのtypeプロパティを読み取るための「戦略」を教え、「UML-クラス」がクラスdiaXML.shapes.uml.UmlClassに対応することを理解するために「戦略」を教えることであると推測しているでしょう。標準-ボックス」-diaXML.shapes.standart.StdBoxクラスに。



マッピングに関する情報(タイプ+バージョン=>クラス名)を通常のArrayListに保存することにしました。



 ArrayList<DiaObjToClassMapRecord> diaObj2ClassMap;
      
      





広告の真下でマッピングを初期化する
 public ArrayList<DiaObjToClassMapRecord> diaObj2ClassMap = new ArrayList<DiaObjToClassMapRecord>(); { //default base mapping - object type name and version mapped to java class name. //use "*" for 'any class' or 'any version' diaObj2ClassMap.add(new DiaObjToClassMapRecord("UML - Class", "0", "diaXML.shapes.uml.UmlClass" )); diaObj2ClassMap.add(new DiaObjToClassMapRecord("UML - Association", "2", "diaXML.shapes.uml.UmlAssociation" )); diaObj2ClassMap.add(new DiaObjToClassMapRecord("Standard - Box", "0", "diaXML.shapes.standart.StdBox" )); diaObj2ClassMap.add(new DiaObjToClassMapRecord("Standard - Text", "1", "diaXML.shapes.standart.StdText" )); diaObj2ClassMap.add(new DiaObjToClassMapRecord("Standard - ZigZagLine", "1", "diaXML.shapes.standart.StdZigZagLine" )); diaObj2ClassMap.add(new DiaObjToClassMapRecord("Standard - BezierLine", "*", "diaXML.shapes.standart.StdBezierLine" )); //universal diaObj2ClassMap.add(new DiaObjToClassMapRecord("*", "*", "diaXML.shapes.UncknownShapeObject" )); }
      
      





ご覧のとおり、すべてが透明です。 マッピングは、DiaTreeStrategyのインスタンスが作成されるとすぐに、クラスで拡張できます(誰かが別のグラフ要素のクラスを作成する場合)。 これまで、チャートオブジェクトの属性からプロパティを初期化できる5つのクラス(POJO)が説明されました。1つのユニバーサルクラス-UncknownShapeObject-未知のすべてのオブジェクトが含まれます。 何も初期化せず、属性の配列を変更せずに保存します。



この一致する配列の検索メカニズムは、別の関数に入れました
  private Class readValueAdv(Type type, NodeMap node) throws Exception { // we need here catch only <object> tag if( !"object".equals(node.getName()) ) return null; Node entry_type = node.get("type"); Node entry_version = node.get("version"); if( entry_type == null || entry_version==null) { return null; }; String name_type = entry_type.getValue(); String name_version = entry_version.getValue(); String className=null; Class expect=null; for (DiaObjToClassMapRecord crec: diaObj2ClassMap) { if ( ( crec.diaType!=null && (crec.diaType.equals(name_type) || !crec.diaType.isEmpty() && crec.diaType.equals("*") ) ) && ( crec.diaVersion!=null && ( crec.diaVersion.equals(name_version) || !crec.diaVersion.isEmpty() && crec.diaVersion.equals("*") ) ) ) { className = crec.javaClassName; break; } } if (className !=null) { expect = loader.load(className); Node entry = node.remove(label); } return expect; }
      
      





あとは、readメソッドを修正するだけです。



 public class DiaTreeStrategy extends TreeStrategy ... @Override public Value read(Type type, NodeMap node, Map map) throws Exception { Class actualDeclaredByDia = readValueAdv(type, node); if (actualDeclaredByDia==null) return super.read(type, node, map); return new ObjectValue(actualDeclaredByDia); }
      
      





それがほとんどすべてです。 むしろ、「つまずきの角」であり、DIAが生成するファイルを解析するためにSimple Frameworkを使用することはできませんでした。



当然、記事に記載されていることに加えて、クラスの注釈付け、XMLのシリアル化と解析、サービスクラスの作成などのプロセスでの注釈インターセプターの動作方法の調査に関連する他の多くの作業が行われました。 などが、それは別の問題です。



これは何であり、どのように使用するのですか?



最後に、「DiaXML API」の使用方法の例をいくつか示します。 DiaTreeStrategyがなければ、機能しません。 ビルドする前に、diaXmlApi.jarをプロジェクトに接続すること( ここでビルドすること )を忘れないでください。



.diaの読み方
 import java.io.File; import org.simpleframework.xml.strategy.DiaTreeStrategy; import diaXML.Diagram; import diaXML.shapes.standart.StdText; public void main(String[] args) { Strategy strategy = new DiaTreeStrategy(); Serializer serializer = new Persister(strategy); File source = new File("path/to/dia/file/to/read.dia"); Diagram probeDia=null; try { probeDia = serializer.read(Diagram.class, source); } catch (Exception e) { e.printStackTrace(); return ;} System.out.println(" File readed. Here is list of objects at layer 0 :"); for (IDiaObject cObj: probeDia.layers.get(0).objects ) { System.out.println(" dia type ["+cObj.getObjectType()+"]ver.["+cObj.getObjectTypeVersion()+"] objId:["+cObj.getId()+"] name:["+cObj.getName()+"]"); if ( StdText.TYPENAME.equals(cObj.getObjectType()) ) { System.out.println(" text value is:["+((StdText)cObj).textValue+"]"); }; } }
      
      



.diaの作成方法
 import java.io.File; import org.simpleframework.xml.strategy.DiaTreeStrategy; import diaXML.Diagram; import diaXML.shapes.standart.StdText; public void main(String[] args) { Strategy strategy = new DiaTreeStrategy(); Serializer serializer = new Persister(strategy); StdText cText= new StdText(); cText.textValue="this is a demo \n of creating DIA-file"; cText.obj_pos.moveTo(15, 5); Diagram probeDia=new Diagram().initWithDefaults(); probeDia.layers.get(0).objects.add(cText); File resultFile = new File("path/to/dia/file/to/write.dia"); try { serializer.write(probeDia, resultFile); } catch (Exception e) { e.printStackTrace(); } }
      
      





さらにいくつかの例がプロジェクトのソースコードにあります( こちら )。



おわりに



この記事では、Simple XML Frameworkの「戦略」とは何か、通常のツールでは不十分な状況でSimple Strategicを使用する方法、およびSimple Frameworkのいくつかの制限(たとえば、@ Xpathアノテーションができないという事実について) @ Xpathリクエストでできるように、名前と属性値に式を使用します)。



これらの問題の解決により、DiaXML APIプロジェクトの主要なクラスを最小限の労力で正常に実装できました。 完全なソースコードはプロジェクトリポジトリにあります。



リンク集





PS:開発されたAPIを使用して、DIAにデータベーススキーマを描画する(または以前に作成されたスキーマを更新する)ユーティリティが開発されました。 データベーススキーマは、 Apache DDL Utilsが作成できるTurbine XML形式で使用されます。



All Articles