--- /dev/null
+/*
+ * Copyright
+ * 2011 axYus - http://www.axyus.com
+ * 2011 C.Marchand - christophe.marchand@axyus.com
+ *
+ * This file is part of XEMELIOS_NB.
+ *
+ * XEMELIOS_NB is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * XEMELIOS_NB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with XEMELIOS_NB; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+package fr.gouv.finances.cp.buildtools.persist.ora.ihm;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.PlainDocument;
+import javax.swing.tree.TreePath;
+import javax.xml.XMLConstants;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.stream.StreamResult;
+import net.sf.saxon.TransformerFactoryImpl;
+import net.sf.saxon.option.xom.DocumentWrapper;
+import net.sf.saxon.option.xom.XOMObjectModel;
+import nu.xom.Attribute;
+import nu.xom.Builder;
+import nu.xom.Comment;
+import nu.xom.Document;
+import nu.xom.Element;
+import nu.xom.Nodes;
+import nu.xom.Text;
+import org.jdesktop.swingx.treetable.AbstractMutableTreeTableNode;
+import org.jdesktop.swingx.treetable.DefaultTreeTableModel;
+import org.jdesktop.swingx.treetable.TreeTableNode;
+
+/**
+ * Permet d'éditer une configuration
+ * @author cmarchand
+ */
+public class OraGenFrame extends javax.swing.JFrame {
+ private static final int COLUMN_TREE = 2;
+ private static final int COLUMN_ERROR = 0;
+ private static final int COLUMN_EXISTS = 1;
+ private static final int MAX_IDENTIFIER_LENGTH = 30;
+ private File persistenceFile;
+ private File mappingFile;
+ private Document doc;
+ private Document mapping;
+ private Builder builder;
+ private PersistTreeTableModel treeModel;
+
+ public static final String[] RESERVED_WORDS = {
+ "ACCESS", "ACCOUNT", "ACTIVATE", "ADD", "ADMIN", "ADVISE", "AFTER", "ALL",
+ "ALLOCATE", "ALL_ROWS", "ALTER", "ANALYZE", "AND", "ANY", "ARCHIVE", "ARCHIVELOG",
+ "ARRAY", "AS", "ASC", "AT", "AUDIT", "AUTHENTICATED", "AUTHORIZATION", "AUTOEXTEND",
+ "AUTOMATIC", "BACKUP", "BECOME", "BEFORE", "BEGIN", "BETWEEN", "BFILE", "BITMAP",
+ "BLOB", "BLOCK", "BODY", "BY", "CACHE", "CACHE_INSTANCES", "CANCEL", "CASCADE",
+ "CAST", "CFILE", "CHAINED", "CHANGE", "CHAR", "CHARACTER", "CHAR_CS", "CHECK",
+ "CHECKPOINT", "CHOOSE", "CHUNK", "CLEAR", "CLOB", "CLONE", "CLOSE", "CLOSE_CACHED_OPEN_CURSORS",
+ "CLUSTER", "COALESCE", "COLUMN", "COLUMNS", "COMMENT", "COMMIT", "COMMITTED", "COMPATIBILITY",
+ "COMPILE", "COMPLETE", "COMPOSITE_LIMIT", "COMPRESS", "COMPUTE", "CONNECT", "CONNECT_TIME", "CONSTRAINT",
+ "CONSTRAINTS", "CONTENTS", "CONTINUE", "CONTROLFILE", "CONVERT", "COST", "CPU_PER_CALL", "CPU_PER_SESSION",
+ "CREATE", "CURRENT", "CURRENT_SCHEMA", "CURREN_USER", "CURSOR", "CYCLE", "DANGLING", "DATABASE",
+ "DATAFILE", "DATAFILES", "DATAOBJNO", "DATE", "DBA", "DBHIGH", "DBLOW", "DBMAC",
+ "DEALLOCATE", "DEBUG", "DEC", "DECIMAL", "DECLARE", "DEFAULT", "DEFERRABLE", "DEFERRED",
+ "DEGREE", "DELETE", "DEREF", "DESC", "DIRECTORY", "DISABLE", "DISCONNECT", "DISMOUNT",
+ "DISTINCT", "DISTRIBUTED", "DML", "DOUBLE", "DROP", "DUMP", "EACH", "ELSE",
+ "ENABLE", "END", "ENFORCE", "ENTRY", "ESCAPE", "EXCEPT", "EXCEPTIONS", "EXCHANGE",
+ "EXCLUDING", "EXCLUSIVE", "EXECUTE", "EXISTS", "EXPIRE", "EXPLAIN", "EXTENT", "EXTENTS",
+ "EXTERNALLY", "FAILED_LOGIN_ATTEMPTS", "FALSE", "FAST", "FILE", "FIRST_ROWS", "FLAGGER", "FLOAT",
+ "FLOB", "FLUSH", "FOR", "FORCE", "FOREIGN", "FREELIST", "FREELISTS", "FROM",
+ "FULL", "FUNCTION", "GLOBAL", "GLOBALLY", "GLOBAL_NAME", "GRANT", "GROUP", "GROUPS",
+ "HASH", "HASHKEYS", "HAVING", "HEADER", "HEAP", "IDENTIFIED", "IDGENERATORS", "IDLE_TIME",
+ "IF", "IMMEDIATE", "IN", "INCLUDING", "INCREMENT", "INDEX", "INDEXED", "INDEXES",
+ "INDICATOR", "IND_PARTITION", "INITIAL", "INITIALLY", "INITRANS", "INSERT", "INSTANCE", "INSTANCES",
+ "INSTEAD", "INT", "INTEGER", "INTERMEDIATE", "INTERSECT", "INTO", "IS", "ISOLATION",
+ "ISOLATION_LEVEL", "KEEP", "KEY", "KILL", "LABEL", "LAYER", "LESS", "LEVEL",
+ "LIBRARY", "LIKE", "LIMIT", "LINK", "LIST", "LOB", "LOCAL", "LOCK",
+ "LOCKED", "LOG", "LOGFILE", "LOGGING", "LOGICAL_READS_PER_CALL", "LOGICAL_READS_PER_SESSION", "LONG", "MANAGE",
+ "MASTER", "MAX", "MAXARCHLOGS", "MAXDATAFILES", "MAXEXTENTS", "MAXINSTANCES", "MAXLOGFILES", "MAXLOGHISTORY",
+ "MAXLOGMEMBERS", "MAXSIZE", "MAXTRANS", "MAXVALUE", "MEMBER", "MIN", "MINEXTENTS", "MINIMUM",
+ "MINUS", "MINVALUE", "MLSLABEL", "MLS_LABEL_FORMAT", "MODE", "MODIFY", "MOUNT", "MOVE",
+ "MTS_DISPATCHERS", "MULTISET", "NATIONAL", "NCHAR", "NCHAR_CS", "NCLOB", "NEEDED", "NESTED",
+ "NETWORK", "NEW", "NEXT", "NOARCHIVELOG", "NOAUDIT", "NOCACHE", "NOCOMPRESS", "NOCYCLE",
+ "NOFORCE", "NOLOGGING", "NOMAXVALUE", "NOMINVALUE", "NONE", "NOORDER", "NOOVERRIDE", "NOPARALLEL",
+ "NOPARALLEL", "NOREVERSE", "NORMAL", "NOSORT", "NOT", "NOTHING", "NOWAIT", "NULL",
+ "NUMBER", "NUMERIC", "NVARCHAR2", "OBJECT", "OBJNO", "OBJNO_REUSE", "OF", "OFF",
+ "OFFLINE", "OID", "OIDINDEX", "OLD", "ON", "ONLINE", "ONLY", "OPCODE",
+ "OPEN", "OPTIMAL", "OPTIMIZER_GOAL", "OPTION", "OR", "ORDER", "ORGANIZATION", "OSLABEL",
+ "OVERFLOW", "OWN", "PACKAGE", "PARALLEL", "PARTITION", "PASSWORD", "PASSWORD_GRACE_TIME", "PASSWORD_LIFE_TIME",
+ "PASSWORD_LOCK_TIME", "PASSWORD_REUSE_MAX", "PASSWORD_REUSE_TIME", "PASSWORD_VERIFY_FUNCTION", "PCTFREE", "PCTINCREASE", "PCTTHRESHOLD", "PCTUSED",
+ "PCTVERSION", "PERCENT", "PERMANENT", "PLAN", "PLSQL_DEBUG", "POST_TRANSACTION", "PRECISION", "PRESERVE",
+ "PRIMARY", "PRIOR", "PRIVATE", "PRIVATE_SGA", "PRIVILEGE", "PRIVILEGES", "PROCEDURE", "PROFILE",
+ "PUBLIC", "PURGE", "QUEUE", "QUOTA", "RANGE", "RAW", "RBA", "READ",
+ "READUP", "REAL", "REBUILD", "RECOVER", "RECOVERABLE", "RECOVERY", "REF", "REFERENCES",
+ "REFERENCING", "REFRESH", "RENAME", "REPLACE", "RESET", "RESETLOGS", "RESIZE", "RESOURCE",
+ "RESTRICTED", "RETURN", "RETURNING", "REUSE", "REVERSE", "REVOKE", "ROLE", "ROLES",
+ "ROLLBACK", "ROW", "ROWID", "ROWNUM", "ROWS", "RULE", "SAMPLE", "SAVEPOINT",
+ "SB4", "SCAN_INSTANCES", "SCHEMA", "SCN", "SCOPE", "SD_ALL", "SD_INHIBIT", "SD_SHOW",
+ "SEGMENT", "SEG_BLOCK", "SEG_FILE", "SELECT", "SEQUENCE", "SERIALIZABLE", "SESSION", "SESSIONS_PER_USER",
+ "SESSION_CACHED_CURSORS", "SET", "SHARE", "SHARED", "SHARED_POOL", "SHRINK", "SIZE", "SKIP",
+ "SKIP_UNUSABLE_INDEXES", "SMALLINT", "SNAPSHOT", "SOME", "SORT", "SPECIFICATION", "SPLIT", "SQL_TRACE",
+ "STANDBY", "START", "STATEMENT_ID", "STATISTICS", "STOP", "STORAGE", "STORE", "STRUCTURE",
+ "SUCCESSFUL", "SWITCH", "SYNONYM", "SYSDATE", "SYSDBA", "SYSOPER", "SYSTEM", "SYS_OP_ENFORCE_NOT_NULL$",
+ "SYS_OP_NTCIMG$", "TABLE", "TABLES", "TABLESPACE", "TABLESPACE_NO", "TABNO", "TEMPORARY", "THAN",
+ "THE", "THEN", "THREAD", "TIME", "TIMESTAMP", "TO", "TOPLEVEL", "TRACE",
+ "TRACING", "TRANSACTION", "TRANSITIONAL", "TRIGGER", "TRIGGERS", "TRUE", "TRUNCATE", "TX",
+ "TYPE", "UB2", "UBA", "UID", "UNARCHIVED", "UNDO", "UNION", "UNIQUE",
+ "UNLIMITED", "UNLOCK", "UNRECOVERABLE", "UNTIL", "UNUSABLE", "UNUSED", "UPDATABLE", "UPDATE",
+ "USAGE", "USE", "USER", "USING", "VALIDATE", "VALIDATION", "VALUE", "VALUES",
+ "VARCHAR", "VARCHAR2", "VARYING", "VIEW", "WHEN", "WHENEVER", "WHERE", "WITH",
+ "WITHOUT", "WORK", "WRITE", "WRITEDOWN", "WRITEUP", "XID", "YEAR"};
+
+ /** Creates new form OraGenFrame */
+ public OraGenFrame(File persistenceFile) {
+ super("Génération de la configuration de la persistence Oracle");
+ this.persistenceFile = persistenceFile;
+ mappingFile = new File(persistenceFile.getParentFile(), "ora-transform.xml");
+ builder = new Builder();
+ try {
+ doc = builder.build(persistenceFile);
+ if(mappingFile.exists()) mapping = builder.build(mappingFile);
+ initModel(doc, mapping);
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ }
+ initComponents();
+ editorPane.setLayout(new BorderLayout());
+ jxTree.addTreeSelectionListener(new TreeSelectionListener() {
+ @Override
+ public void valueChanged(TreeSelectionEvent e) {
+ for(TreePath path: e.getPaths()) {
+ if(e.isAddedPath(path)) {
+ Object o = path.getLastPathComponent();
+ editorPane.removeAll();
+ JComponent comp = getEditorPane(o);
+ editorPane.add(comp, BorderLayout.NORTH, -1);
+ editorPane.setVisible(false);
+ editorPane.setVisible(true);
+ }
+ }
+ }
+ });
+ jxTree.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ setLocationRelativeTo(null);
+ }
+
+ private void initModel(Document doc, Document mapping) {
+ PersistenceNode persistNode = new PersistenceNode();
+ Nodes tableNodes = doc.query("/persistence-config/layer[@name='mysql']/document/table");
+ Element documentElement = null;
+ if(mapping!=null)
+ documentElement = (Element)mapping.query("/document").get(0);
+ for(int i=0;i<tableNodes.size();i++) {
+ TableNode table = new TableNode((Element)tableNodes.get(i), documentElement);
+ table.checkValidity();
+ persistNode.addDocumentTable(table);
+ }
+ Nodes etatNodes = doc.query("/persistence-config/layer[@name='mysql']/document/etat");
+ for(int i=0;i<etatNodes.size();i++) {
+ Element etatNode = (Element)etatNodes.get(i);
+ Element etatMapping = null;
+ if(mapping!=null) {
+ Nodes nodes = documentElement.query("./etat[@id='"+etatNode.getAttributeValue("id")+"']");
+ if(nodes.size()>0) etatMapping = (Element)nodes.get(0);
+ }
+ EtatNode etat = new EtatNode(etatNode,etatMapping);
+ etat.checkValidity();
+ persistNode.addEtat(etat);
+ }
+ treeModel = new PersistTreeTableModel(persistNode);
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jScrollPane1 = new javax.swing.JScrollPane();
+ jxTree = new org.jdesktop.swingx.JXTreeTable();
+ editorPane = new javax.swing.JPanel();
+ pbCheckValidity = new javax.swing.JButton();
+ pbSavePersistence = new javax.swing.JButton();
+ pbSaveTransform = new javax.swing.JButton();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+
+ jxTree.setSelectionMode(1);
+ jxTree.setTreeTableModel(treeModel);
+ jScrollPane1.setViewportView(jxTree);
+
+ editorPane.setBorder(javax.swing.BorderFactory.createTitledBorder("Editeur"));
+
+ javax.swing.GroupLayout editorPaneLayout = new javax.swing.GroupLayout(editorPane);
+ editorPane.setLayout(editorPaneLayout);
+ editorPaneLayout.setHorizontalGroup(
+ editorPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 659, Short.MAX_VALUE)
+ );
+ editorPaneLayout.setVerticalGroup(
+ editorPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 88, Short.MAX_VALUE)
+ );
+
+ pbCheckValidity.setIcon(new javax.swing.ImageIcon(getClass().getResource("/fr/gouv/finances/cp/buildtools/persist/ora/ihm/view-refresh.png"))); // NOI18N
+ pbCheckValidity.setToolTipText("Vérifier la validité");
+ pbCheckValidity.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ pbCheckValidityActionPerformed(evt);
+ }
+ });
+
+ pbSavePersistence.setIcon(new javax.swing.ImageIcon(getClass().getResource("/fr/gouv/finances/cp/buildtools/persist/ora/ihm/document-save-as.png"))); // NOI18N
+ pbSavePersistence.setToolTipText("Enregistrer la configuration de la persistence");
+ pbSavePersistence.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ pbSavePersistenceActionPerformed(evt);
+ }
+ });
+
+ pbSaveTransform.setIcon(new javax.swing.ImageIcon(getClass().getResource("/fr/gouv/finances/cp/buildtools/persist/ora/ihm/document-save.png"))); // NOI18N
+ pbSaveTransform.setToolTipText("Enregistrer la configuration de la transformation");
+ pbSaveTransform.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ pbSaveTransformActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 649, Short.MAX_VALUE)
+ .addGap(0, 0, 0)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(pbCheckValidity)
+ .addComponent(pbSaveTransform))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED))
+ .addComponent(pbSavePersistence)))
+ .addComponent(editorPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(pbCheckValidity)
+ .addGap(0, 0, 0)
+ .addComponent(pbSaveTransform)
+ .addGap(0, 0, 0)
+ .addComponent(pbSavePersistence))
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 327, Short.MAX_VALUE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(editorPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap())
+ );
+
+ pack();
+ }// </editor-fold>//GEN-END:initComponents
+
+ private void pbCheckValidityActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pbCheckValidityActionPerformed
+ ((TotoNode)treeModel.getRoot()).checkValidity();
+ jxTree.tableChanged(null);
+ }//GEN-LAST:event_pbCheckValidityActionPerformed
+
+ private void pbSavePersistenceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pbSavePersistenceActionPerformed
+ Document newDoc = (Document)doc.copy();
+ Element mySqlLayer = (Element)newDoc.query("/persistence-config/layer[@name='mysql']").get(0);
+ Element oraLayer = null;
+ Nodes nl = newDoc.query("/persistence-config/layer[@name='oracle']");
+ if(nl.size()>0) {
+ oraLayer = (Element)nl.get(0);
+ oraLayer.getParent().removeChild(oraLayer);
+ } else {
+ System.out.println("no oracle layer");
+ }
+ oraLayer = new Element("layer");
+ oraLayer.addAttribute(new Attribute("name","oracle"));
+ oraLayer.addAttribute(new Attribute("persistence-model","xemelios-sql"));
+ Element documentElement = new Element("document");
+ documentElement.addAttribute(new Attribute("id",mySqlLayer.query("document/@id").get(0).getValue()));
+ if(mySqlLayer.query("document/@repository-import-xslt-file").size()>0)
+ documentElement.addAttribute(new Attribute("repository-import-xslt-file", mySqlLayer.query("document/@repository-import-xslt-file").get(0).getValue()));
+ oraLayer.insertChild(documentElement, 0);
+ mySqlLayer.getParent().appendChild(oraLayer);
+ PersistenceNode root = (PersistenceNode)treeModel.getRoot();
+ ArrayList<TableNode> tables = new ArrayList<TableNode>();
+ for(TableNode table: root.getDocumentTables().values()) tables.add(table);
+ Collections.sort(tables);
+ for(TableNode table:tables) documentElement.appendChild(table.getPersistence());
+ for(EtatNode etat:root.etats.values()) {
+ documentElement.appendChild(etat.getPersistence());
+ }
+ TransformerFactoryImpl tFactory = new TransformerFactoryImpl();
+ tFactory.getConfiguration().registerExternalObjectModel(XOMObjectModel.getInstance());
+ try {
+ Transformer trans = tFactory.newTransformer();
+ FileOutputStream fos = new FileOutputStream(persistenceFile);
+ trans.transform(new DocumentWrapper(newDoc, null, tFactory.getConfiguration()), new StreamResult(fos));
+ fos.flush(); fos.close();
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ }
+ }//GEN-LAST:event_pbSavePersistenceActionPerformed
+
+ private void pbSaveTransformActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pbSaveTransformActionPerformed
+ Document newMapping = null;
+ if(mapping!=null) {
+ newMapping = (Document)mapping.copy();
+ newMapping.getRootElement().removeChildren();
+ } else {
+ Element documentElement = new Element("document");
+ newMapping = new Document(documentElement);
+ }
+ Element document = newMapping.getRootElement();
+ PersistenceNode pn = (PersistenceNode)treeModel.getRoot();
+ for(TableNode table: pn.documentTables.values()) {
+ document.insertChild(table.getMapping(), document.getChildCount());
+ }
+ for(EtatNode etat: pn.etats.values()) {
+ document.insertChild(etat.getMapping(), document.getChildCount());
+ }
+ TransformerFactoryImpl tFactory = new TransformerFactoryImpl();
+ tFactory.getConfiguration().registerExternalObjectModel(XOMObjectModel.getInstance());
+ try {
+ Transformer trans = tFactory.newTransformer();
+ FileOutputStream fos = new FileOutputStream(mappingFile);
+ trans.transform(new DocumentWrapper(newMapping, null, tFactory.getConfiguration()), new StreamResult(fos));
+ fos.flush(); fos.close();
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ }
+ }//GEN-LAST:event_pbSaveTransformActionPerformed
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JPanel editorPane;
+ private javax.swing.JScrollPane jScrollPane1;
+ private org.jdesktop.swingx.JXTreeTable jxTree;
+ private javax.swing.JButton pbCheckValidity;
+ private javax.swing.JButton pbSavePersistence;
+ private javax.swing.JButton pbSaveTransform;
+ // End of variables declaration//GEN-END:variables
+
+ public void treeChanged(Object newValue) {
+ TreePath path = jxTree.getPathForRow(jxTree.getSelectedRow());
+ treeModel.setRoot(treeModel.getRoot());
+ jxTree.expandPath(path);
+ jxTree.scrollPathToVisible(path);
+ TreePath newPath = path.pathByAddingChild(newValue);
+ jxTree.getTreeSelectionModel().setSelectionPath(newPath);
+ jxTree.invalidate();
+ }
+ private JComponent getEditorPane(SqlNode sql) {
+ return new PnlEditSql(sql);
+ }
+ private JComponent getEditorPane(TableNode table) {
+ return new PnlEditTable(table, this);
+ }
+ private JComponent getEditorPane(ColumnNode column) {
+ return new PnlEditColumn(column);
+ }
+ private JComponent getEditorPane(IndexNode index) {
+ return new PnlEditIndex(index);
+ }
+ private JComponent getEditorPane(Object o) {
+ if(o instanceof OraGenFrame.TableNode) return getEditorPane((OraGenFrame.TableNode)o);
+ else if(o instanceof OraGenFrame.ColumnNode) return getEditorPane((OraGenFrame.ColumnNode)o);
+ else if(o instanceof OraGenFrame.IndexNode) return getEditorPane((OraGenFrame.IndexNode)o);
+ else if(o instanceof OraGenFrame.SqlNode) return getEditorPane((OraGenFrame.SqlNode)o);
+ else {
+ JLabel lbl = new JLabel("<html>Impossible d'éditer un<br>"+o.getClass().getName()+"</html>");
+ lbl.setForeground(Color.red);
+ return lbl;
+ }
+ }
+ static class PersistTreeTableModel extends DefaultTreeTableModel {
+ public PersistTreeTableModel(TreeTableNode root) {
+ super(root);
+ }
+ @Override
+ public int getColumnCount() {
+ return 3;
+ }
+ @Override
+ public int getHierarchicalColumn() {
+ return COLUMN_TREE;
+ }
+ @Override
+ public Object getValueAt(Object o, int i) {
+ if(o instanceof TreeTableNode) return ((TreeTableNode)o).getValueAt(i);
+ else return null;
+ }
+ @Override
+ public Object getChild(Object parent, int index) {
+ if(parent instanceof TreeTableNode) return ((TreeTableNode)parent).getChildAt(index);
+ else return null;
+ }
+ @Override
+ public int getChildCount(Object parent) {
+ if(parent instanceof TreeTableNode) return ((TreeTableNode)parent).getChildCount();
+ else return 0;
+ }
+ @Override
+ public int getIndexOfChild(Object parent, Object child) {
+ if(parent instanceof TreeTableNode) return ((TreeTableNode)parent).getIndex((TreeTableNode)child);
+ else return -1;
+ }
+ @Override
+ public Class<?> getColumnClass(int column) {
+ switch(column) {
+ case COLUMN_EXISTS:
+ case COLUMN_ERROR: return Boolean.class;
+ default: return String.class;
+ }
+ }
+ @Override
+ public String getColumnName(int column) {
+ switch(column) {
+ case COLUMN_TREE: return "Noeud";
+ case COLUMN_ERROR: return "Valide";
+ case COLUMN_EXISTS: return "Existe ds Oracle";
+ default: return null;
+ }
+ }
+ }
+ interface TotoNode {
+ public void setExists(boolean exists);
+ public boolean checkValidity();
+ }
+ class PersistenceNode extends AbstractMutableTreeTableNode implements OraGenFrame.TotoNode {
+ private HashMap<String,TableNode> documentTables;
+ private HashMap<String, EtatNode> etats;
+ public PersistenceNode() {
+ super(true);
+ documentTables = new HashMap<String, TableNode>();
+ etats = new HashMap<String, EtatNode>();
+ }
+ @Override
+ public Object getValueAt(int column) {
+ switch(column) {
+ case OraGenFrame.COLUMN_TREE: return "persistence-config";
+ default: return null;
+ }
+ }
+ @Override
+ public int getColumnCount() {
+ return 3;
+ }
+ public void addDocumentTable(TableNode table) {
+ insert(table,getChildCount());
+ documentTables.put(table.getId(), table);
+ }
+ public void addEtat(EtatNode etat) {
+ insert(etat,getChildCount());
+ etats.put(etat.id, etat);
+ }
+ @Override
+ public void setExists(boolean exists) { }
+ @Override
+ public boolean checkValidity() {
+ for(int i=0;i<getChildCount();i++) {
+ TotoNode child = (TotoNode)getChildAt(i);
+ child.checkValidity();
+ }
+ return true;
+ }
+ public HashMap<String, TableNode> getDocumentTables() {
+ return documentTables;
+ }
+ public HashMap<String, EtatNode> getEtats() {
+ return etats;
+ }
+ }
+ protected static class TableNode extends AbstractMutableTreeTableNode implements OraGenFrame.TotoNode, Comparable<OraGenFrame.TableNode> {
+ private String id, originalName, newName, originalScript;
+ private String type;
+ private boolean exists, valid;
+ private int rank;
+ private Element originalTable;
+ private HashMap<String,ColumnNode> columns;
+ public TableNode(Element element, Element mapping) {
+ super(true);
+ this.originalTable = element;
+ columns = new HashMap<String, ColumnNode>();
+ id = element.getAttributeValue("id");
+ type = element.getAttributeValue("type");
+ originalName = element.getAttributeValue("base-name");
+ Nodes tables = null;
+ if(mapping!=null) {
+ tables = mapping.query("./table[@base-name='"+originalName+"']");
+ }
+ Element mappingTable = tables!=null && tables.size()>0 ? (Element)tables.get(0) : null;
+ String newNameFromMapping=null;
+ if(mappingTable!=null) {
+ Nodes newNames = mappingTable.query("./@new-name");
+ if(newNames.size()>0) {
+ newNameFromMapping = newNames.get(0).getValue();
+ }
+ }
+ exists = (mappingTable!=null);
+ if(newNameFromMapping!=null) newName = newNameFromMapping;
+ else if(originalName.length()<=MAX_IDENTIFIER_LENGTH) newName = originalName;
+ originalScript = element.query("./text()").get(0).getValue();
+ String inner = originalScript.substring(originalScript.indexOf('(')+1, originalScript.lastIndexOf(')')-1);
+ String[] content = splitInner(inner);
+ ArrayList<IndexNode> indexes = new ArrayList<IndexNode>();
+ if(mappingTable==null) mappingTable = new Element("table");
+ for(String s:content) {
+ String normS = normalizeSpec(s);
+ if(normS.toUpperCase().startsWith("INDEX ")) {
+ // on les met à la fin
+ indexes.add(new IndexNode(normS, this, mappingTable));
+ } else {
+ ColumnNode c = new ColumnNode(normS, mappingTable);
+ insert(c,getChildCount());
+ columns.put(c.originalName, c);
+ }
+ }
+ for(IndexNode in:indexes) insert(in,getChildCount());
+ if(mappingTable!=null) {
+ Nodes sqls = mappingTable.query("sql");
+ for(int i=0;i<sqls.size();i++) {
+ Element el = (Element)sqls.get(i);
+ insert(new SqlNode(el),getChildCount());
+ }
+ }
+ valid = checkValidity();
+ }
+ private ColumnNode getColumn(String originalName) {
+ return columns.get(originalName);
+ }
+ @Override
+ public Object getValueAt(int column) {
+ switch(column) {
+ case COLUMN_TREE: return "Table ".concat(getId());
+ case COLUMN_EXISTS: return exists;
+ case COLUMN_ERROR: return valid;
+ default: return null;
+ }
+ }
+ @Override
+ public int getColumnCount() {
+ return 3;
+ }
+ @Override
+ public void setExists(boolean exists) {
+ this.exists = exists;
+ if(!exists) {
+ for(int i=0; i<getChildCount();i++) {
+ TreeTableNode child = getChildAt(i);
+ if(child instanceof TotoNode) ((TotoNode)child).setExists(exists);
+ }
+ }
+ }
+ @Override
+ public boolean checkValidity() {
+ if(originalName.length()<=MAX_IDENTIFIER_LENGTH && newName==null)
+ newName = originalName;
+ boolean ret = (newName!=null && newName.length()<=MAX_IDENTIFIER_LENGTH) && !isOracleReservedWord(newName);
+ // on parcours les fils quand même
+ for(int i=0;i<getChildCount();i++) {
+ TreeTableNode child = getChildAt(i);
+ if(child instanceof TotoNode) {
+ ret &= ((TotoNode)child).checkValidity();
+ }
+ }
+ valid = ret;
+ return ret;
+ }
+ public String getId() {
+ return type.concat(".").concat(id==null?"":id);
+ }
+ public String getOriginalName() {
+ return originalName;
+ }
+ public void setOriginalName(String originalName) {
+ this.originalName = originalName;
+ }
+ public String getOriginalScript() {
+ return originalScript;
+ }
+ public void setOriginalScript(String originalScript) {
+ this.originalScript = originalScript;
+ }
+ public String getType() {
+ return type;
+ }
+ public String getInternalId() {
+ return id;
+ }
+ public String getNewName() {
+ return newName;
+ }
+ public void setNewName(String newName) {
+ this.newName = newName;
+ }
+ public Element getMapping() {
+ Element mappingTable = new Element("table");
+ mappingTable.addAttribute(new Attribute("base-name", originalName));
+ mappingTable.addAttribute(new Attribute("new-name", newName==null ? originalName : newName));
+ for(int i=0;i<getChildCount();i++) {
+ TotoNode child = (TotoNode)getChildAt(i);
+ if(child instanceof ColumnNode) {
+ mappingTable.insertChild(((ColumnNode)child).getMapping(), mappingTable.getChildCount());
+ } else if(child instanceof IndexNode) {
+ mappingTable.insertChild(((IndexNode)child).getMapping(), mappingTable.getChildCount());
+ } else if(child instanceof SqlNode) {
+ mappingTable.insertChild(((SqlNode)child).getMapping(), mappingTable.getChildCount());
+ }
+ }
+ return mappingTable;
+ }
+ @Override
+ public int compareTo(TableNode o) {
+ return rank - o.rank;
+ }
+ public int getRank() {
+ return rank;
+ }
+ public void setRank(int rank) {
+ this.rank = rank;
+ }
+ public Element getPersistence() {
+ Element el = new Element("table");
+ el.addAttribute(new Attribute("base-name",newName));
+ if(id!=null) el.addAttribute(new Attribute("id",id));
+ if(type!=null) el.addAttribute(new Attribute("type",type));
+ if(originalTable.getAttribute("main")!=null) el.addAttribute((Attribute)originalTable.getAttribute("main").copy());
+ if(originalTable.getAttribute("based-on")!=null)
+ el.addAttribute((Attribute)originalTable.getAttribute("based-on").copy());
+ if(originalTable.getAttribute("ignoreConstraintError")!=null) el.addAttribute((Attribute)originalTable.getAttribute("ignoreConstraintError").copy());
+ // TODO: gérer les versions
+ // pour le moment, on ne gère pas les versions
+ el.addAttribute(new Attribute("version","1"));
+ StringBuilder sb = new StringBuilder();
+ sb.append("CREATE TABLE ${base-name} (");
+ for(ColumnNode column: columns.values()) {
+ if(!column.avoidGenerate) {
+ sb.append("\n\t").append(column.getNewName()).append(" ").append(column.getNewDatatype()!=null ? column.getNewDatatype() : column.getOriginalDatatype());
+ if(column.getNewQualif()!=null) sb.append(" ").append(column.getNewQualif());
+ sb.append(",");
+ }
+ }
+ sb.deleteCharAt(sb.length()-1);
+ sb.append("\n)");
+ Element sql = new Element("sql");
+ sql.addAttribute(new Attribute("xml:space", XMLConstants.XML_NS_URI, "preserve"));
+ sql.appendChild(new Text(sb.toString()));
+ el.appendChild(sql);
+ // il faut maintenant traiter les index
+ for(int i=0;i<getChildCount();i++) {
+ Object o = getChildAt(i);
+ if(o instanceof IndexNode) {
+ IndexNode in = (IndexNode)o;
+ if(!in.avoidGenerate)
+ el.appendChild(in.getPersistence());
+ }
+ }
+ // puis les SQL supplémentaires
+ ArrayList<SqlNode> sqls = new ArrayList<SqlNode>();
+ for(int i=0;i<getChildCount();i++) {
+ Object o = getChildAt(i);
+ if(o instanceof SqlNode)
+ sqls.add((SqlNode)o);
+ }
+ Collections.sort(sqls);
+ for(SqlNode s: sqls)
+ el.appendChild(s.getPersistence());
+ return el;
+ }
+ }
+ protected static class ColumnNode extends AbstractMutableTreeTableNode implements OraGenFrame.TotoNode {
+ private String spec, originalName, newName, originalDatatype, newDatatype, originalQualif, newQualif;
+ private boolean valid, exists, avoidGenerate;
+ public ColumnNode(String spec, Element mappingTable) {
+ super(false);
+ this.spec = normalizeSpec(spec);
+ String[] vals = this.spec.split(" ",3);
+ originalName = vals[0];
+ Nodes mappingColumns=mappingTable.query("./column[@id='"+originalName+"']");
+ Element mappingColumn = null;
+ if(mappingColumns.size()>0) mappingColumn = (Element)mappingColumns.get(0);
+ if(mappingColumn!=null) {
+ exists = true;
+ newName = mappingColumn.getAttributeValue("new-name");
+ if("true".equals(mappingColumn.getAttributeValue("avoid-generate"))) avoidGenerate = true;
+ } else {
+ if(originalName.length()<=MAX_IDENTIFIER_LENGTH) {
+ newName = originalName;
+ if("ENCODING".equals(newName)) avoidGenerate = true;
+ }
+ }
+ originalDatatype = vals[1];
+ if(mappingColumn!=null) newDatatype = mappingColumn.getAttributeValue("new-type");
+ if(newDatatype==null) {
+ if("LONGBLOB".equals(originalDatatype.toUpperCase())) newDatatype="BLOB";
+ else {
+ newDatatype = originalDatatype;
+ if(newDatatype.startsWith("VARCHAR")) {
+ newDatatype = newDatatype.replaceAll("[0-9]+", "1000");
+ }
+ }
+ }
+ if(vals.length==3)
+ originalQualif = vals[2];
+ if(mappingColumn!=null)
+ newQualif = mappingColumn.getAttributeValue("new-qualif");
+ if(newQualif==null && "NOT NULL".equals(originalQualif)) newQualif = originalQualif;
+ }
+ @Override
+ public Object getValueAt(int i) {
+ switch(i) {
+ case COLUMN_TREE: return "Column "+originalName+(newName!=null ? " -> "+newName:"");
+ case COLUMN_ERROR: return valid;
+ case COLUMN_EXISTS: return exists;
+ default: return null;
+ }
+ }
+ @Override
+ public int getColumnCount() {
+ return 3;
+ }
+ @Override
+ public void setExists(boolean exists) {
+ this.exists=exists;
+ }
+ @Override
+ public boolean checkValidity() {
+ // si on ne génère pas, c'est toujorus valide
+ if(avoidGenerate) {
+ valid = true;
+ return true;
+ }
+ boolean ret = false;
+ if(newName==null && originalName.length()<=MAX_IDENTIFIER_LENGTH) {
+ newName = originalName;
+ }
+ if(newName!=null) {
+ ret = newName.length()<=MAX_IDENTIFIER_LENGTH && !isOracleReservedWord(newName);
+ }
+ if(newDatatype==null || newDatatype.trim().length()==0) ret = false;
+ else if(newDatatype.startsWith("INTEGER") && newDatatype.contains("(")) ret=false;
+ valid = ret;
+ return ret;
+ }
+ public String getOriginalDatatype() {
+ return originalDatatype;
+ }
+ public String getOriginalName() {
+ return originalName;
+ }
+ public String getOriginalQualif() {
+ return originalQualif;
+ }
+ public String getSpec() {
+ return spec;
+ }
+ public String getNewDatatype() {
+ return newDatatype;
+ }
+ public void setNewDatatype(String newDatatype) {
+ this.newDatatype = newDatatype;
+ }
+ public String getNewName() {
+ return newName;
+ }
+ public void setNewName(String newName) {
+ this.newName = newName;
+ }
+ public String getNewQualif() {
+ return newQualif;
+ }
+ public void setNewQualif(String newQualif) {
+ this.newQualif = newQualif;
+ }
+ public boolean isAvoidGenerate() {
+ return avoidGenerate;
+ }
+ public void setAvoidGenerate(boolean avoidGenerate) {
+ this.avoidGenerate = avoidGenerate;
+ }
+ public Element getMapping() {
+ Element mapping = new Element("column");
+ mapping.addAttribute(new Attribute("id", originalName));
+ mapping.addAttribute(new Attribute("new-name", newName==null ? originalName : newName));
+ if(newDatatype!=null)
+ mapping.addAttribute(new Attribute("new-type", newDatatype));
+ if(newQualif!=null) mapping.addAttribute(new Attribute("new-qualif", newQualif));
+ if(avoidGenerate) mapping.addAttribute(new Attribute("avoid-generate", "true"));
+ return mapping;
+ }
+ }
+ protected static class SqlNode extends AbstractMutableTreeTableNode implements OraGenFrame.TotoNode, Comparable<SqlNode> {
+ private String desc, code;
+ private int rank;
+ public SqlNode() {
+ super(false);
+ desc = "A modifier";
+ }
+ public SqlNode(Element mapping) {
+ super(false);
+ desc = mapping.getAttributeValue("desc");
+ code = mapping.getValue();
+ String sTmp = mapping.getAttributeValue("rank");
+ try {
+ rank = Integer.parseInt(sTmp);
+ } catch(Throwable t) {}
+ }
+ @Override
+ public Object getValueAt(int i) {
+ switch(i) {
+ case COLUMN_TREE: return desc;
+ default: return true;
+ }
+ }
+ @Override
+ public int getColumnCount() {
+ return 3;
+ }
+ @Override
+ public void setExists(boolean exists) { }
+ @Override
+ public boolean checkValidity() { return true; }
+ public String getCode() {
+ return code;
+ }
+ public void setCode(String code) {
+ this.code = code;
+ }
+ public String getDesc() {
+ return desc;
+ }
+ public void setDesc(String desc) {
+ this.desc = desc;
+ }
+ public Element getMapping() {
+ Element mapping = new Element("sql");
+ mapping.addAttribute(new Attribute("desc",desc));
+ mapping.addAttribute(new Attribute("xml:space", XMLConstants.XML_NS_URI, "preserve"));
+ Text txt = new Text(code);
+ mapping.insertChild(txt, 0);
+ return mapping;
+ }
+ @Override
+ public int compareTo(SqlNode o) {
+ return rank - o.rank;
+ }
+ public int getRank() {
+ return rank;
+ }
+ public void setRank(int rank) {
+ this.rank = rank;
+ }
+ public Element getPersistence() {
+ Element el = new Element("sql");
+ el.appendChild(new Text(code));
+ return el;
+ }
+ }
+ protected static class IndexNode extends AbstractMutableTreeTableNode implements OraGenFrame.TotoNode {
+ private String spec, originalName, newName;
+ private boolean valid, exists, avoidGenerate;
+ private ArrayList<ColumnNode> columns;
+ private TableNode table;
+ public IndexNode(String spec, TableNode table, Element mappingTable) {
+ super(false);
+ columns = new ArrayList<ColumnNode>();
+ this.spec = spec;
+ this.table = table;
+ int pos = spec.indexOf('(');
+ String firstPart = spec.substring(5, pos).trim();
+ String lastPart = spec.substring(pos+1).trim();
+ // normalement, firstPart est le nom de l'index
+ originalName = firstPart;
+ Nodes mappingIndexes = mappingTable.query("./index[@id='"+originalName+"']");
+ Element mappingIndex = null;
+ if(mappingIndexes.size()>0) mappingIndex = (Element)mappingIndexes.get(0);
+ if(mappingIndex!=null) {
+ exists = true;
+ newName = mappingIndex.getAttributeValue("new-name");
+ if(newName.startsWith("IX_")) newName = newName.substring(3);
+ avoidGenerate = "true".equals(mappingIndex.getAttributeValue("avoid-generate"));
+ }
+ String[] cols = lastPart.split(",");
+ for(String colName:cols) {
+ if(colName.endsWith(")")) colName = colName.substring(0, colName.length()-1);
+ columns.add(table.getColumn(colName));
+ }
+ }
+ @Override
+ public Object getValueAt(int i) {
+ switch(i) {
+ case COLUMN_TREE: return "Index "+originalName;
+ case COLUMN_ERROR: return valid;
+ case COLUMN_EXISTS: return exists;
+ default: return null;
+ }
+ }
+ @Override
+ public int getColumnCount() {
+ return 3;
+ }
+ @Override
+ public void setExists(boolean exists) {
+ this.exists = exists;
+ }
+ @Override
+ public boolean checkValidity() {
+ if(avoidGenerate) {
+ valid = true;
+ return true;
+ }
+ boolean ret = false;
+ if(newName==null && originalName.length()<=MAX_IDENTIFIER_LENGTH) {
+ newName = originalName;
+ }
+ if(newName!=null) {
+ String computedName = null;
+ if(table.getNewName()!=null) {
+ computedName = getComputedName();
+ ret = computedName.length()<=MAX_IDENTIFIER_LENGTH && !isOracleReservedWord(computedName);
+ }
+ }
+ valid = ret;
+ return ret;
+ }
+ public String getComputedName() {
+ if(newName==null) return originalName;
+ else {
+ return newName.replaceAll("\\$\\{base-name\\}",table.getNewName());
+ }
+ }
+ public boolean isAvoidGenerate() {
+ return avoidGenerate;
+ }
+ public void setAvoidGenerate(boolean avoidGenerate) {
+ this.avoidGenerate = avoidGenerate;
+ }
+ public String getNewName() {
+ return newName;
+ }
+ public void setNewName(String newName) {
+ this.newName = newName;
+ }
+ public String getOriginalName() {
+ return originalName;
+ }
+ public Element getMapping() {
+ Element mapping = new Element("index");
+ mapping.addAttribute(new Attribute("id",originalName));
+ if(avoidGenerate) mapping.addAttribute(new Attribute("avoid-generate","true"));
+ else mapping.addAttribute(new Attribute("new-name",newName));
+ return mapping;
+ }
+ public Element getPersistence() {
+ Element el = new Element("sql");
+ StringBuilder sb = new StringBuilder();
+ sb.append("CREATE INDEX ").append(newName).append(" ON ${base-name} (");
+ for(ColumnNode column:columns)
+ sb.append(column.newName).append(",");
+ sb.deleteCharAt(sb.length()-1);
+ sb.append(")");
+ el.appendChild(new Text(sb.toString()));
+ return el;
+ }
+ }
+ protected static class EtatNode extends AbstractMutableTreeTableNode implements OraGenFrame.TotoNode {
+ private String id;
+ private boolean valid, exists;
+ private Element elMySql;
+ private HashMap<String, OraGenFrame.TableNode> tables;
+ private HashMap<String, OraGenFrame.TableNode> tablesById;
+ public EtatNode(Element element, Element mapping) {
+ super(true);
+ tables = new HashMap<String, TableNode>();
+ tablesById = new HashMap<String, TableNode>();
+ this.elMySql = element;
+ id = element.getAttributeValue("id");
+ Nodes tableNodes = element.query("table");
+ for(int i=0;i<tableNodes.size();i++) {
+ addTable(new TableNode((Element)tableNodes.get(i),mapping));
+ }
+ exists = mapping!=null;
+ valid = checkValidity();
+ }
+ @Override
+ public Object getValueAt(int i) {
+ switch(i) {
+ case COLUMN_TREE: return "Etat "+id;
+ case COLUMN_ERROR: return valid;
+ case COLUMN_EXISTS: return exists;
+ default: return null;
+ }
+ }
+ @Override
+ public int getColumnCount() {
+ return 3;
+ }
+ @Override
+ public void setExists(boolean exists) {
+ this.exists=exists;
+ if(!exists) {
+ for(TableNode table: tables.values()) {
+ table.setExists(exists);
+ }
+ }
+ }
+ @Override
+ public boolean checkValidity() {
+ boolean ret = true;
+ for(TableNode table: tables.values()) {
+ ret &= table.checkValidity();
+ }
+ valid = ret;
+ return ret;
+ }
+ private void addTable(TableNode table) {
+ insert(table,getChildCount());
+ tables.put(table.getId(), table);
+
+ if(table.id!=null)
+ tablesById.put(table.id, table);
+ }
+ public Element getMapping() {
+ Element mapping = new Element("etat");
+ mapping.addAttribute(new Attribute("id",id));
+ for(TableNode table:tables.values()) {
+ mapping.insertChild(table.getMapping(), mapping.getChildCount());
+ }
+ return mapping;
+ }
+ public Element getPersistence() {
+ Element etat = new Element("etat");
+ etat.addAttribute(new Attribute("id",id));
+ etat.addAttribute(new Attribute("import-xslt-file",elMySql.getAttributeValue("import-xslt-file")));
+ // les key1..keyn
+ Nodes keys = elMySql.query("*[starts-with(name(),'key')]");
+ for(int i=0;i<keys.size();i++) etat.appendChild(keys.get(i).copy());
+ ArrayList<TableNode> __tables = new ArrayList<TableNode>();
+ __tables.addAll(tables.values());
+ Collections.sort(__tables);
+ for(TableNode table:__tables) {
+ etat.appendChild(table.getPersistence());
+ }
+ Nodes criterias = elMySql.query("criteria");
+ for(int i=0;i<criterias.size();i++) {
+ etat.appendChild(criterias.get(i).copy());
+ }
+ Nodes sqlIndexes = elMySql.query("sql-index");
+ for(int i=0;i<sqlIndexes.size();i++) {
+ Element existing = (Element)sqlIndexes.get(i);
+ Element ix = new Element("sql-index");
+ ix.addAttribute(new Attribute("id",existing.getAttributeValue("id")));
+ ix.addAttribute(new Attribute("path",existing.getAttributeValue("path")));
+ ix.addAttribute(new Attribute("datatype",existing.getAttributeValue("datatype")));
+ String tableId = existing.getAttributeValue("table");
+ ix.addAttribute(new Attribute("table",tableId));
+ String originalColumnName = existing.getAttributeValue("column");
+ try {
+ ix.addAttribute(new Attribute("column",tablesById.get(tableId).getColumn(originalColumnName).newName));
+ } catch(RuntimeException rEx) {
+ System.err.println("colonne inconnue utilisée dans sql-index[@id='"+existing.getAttributeValue("id")+"'] : "+originalColumnName);
+ ix.addAttribute(new Attribute("column",originalColumnName));
+ ix.appendChild(new Comment("WARNING: la colonne n'a pas été trouvée dans la définition de la table: "+tableId+"."+originalColumnName));
+ }
+ if(existing.getAttribute("format")!=null)
+ ix.addAttribute(new Attribute("format",existing.getAttributeValue("format")));
+ if(existing.getAttribute("generate")!=null)
+ ix.addAttribute(new Attribute("generate",existing.getAttributeValue("generate")));
+ // normalement plus utilisé, mais on ne sait jamais
+ if(existing.getAttribute("index-type")!=null)
+ ix.addAttribute(new Attribute("index-type",existing.getAttributeValue("index-type")));
+ if(existing.getAttribute("reset-on")!=null)
+ ix.addAttribute(new Attribute("reset-on",existing.getAttributeValue("reset-on")));
+ if(existing.getAttribute("use-in-criteria")!=null)
+ ix.addAttribute(new Attribute("use-in-criteria",existing.getAttributeValue("use-in-criteria")));
+ etat.appendChild(ix);
+ }
+ return etat;
+ }
+ }
+ protected static class NumberFilteredField extends PlainDocument {
+ @Override
+ public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException {
+ if (str == null)
+ return;
+ StringBuilder sb = new StringBuilder();
+ for(char c: str.toCharArray()) {
+ if(Character.isDigit(c)) sb.append(c);
+ }
+ super.insertString(offset, sb.toString(), attr);
+ }
+ }
+ private static String[] splitInner(String inner) {
+ ArrayList<String> content = new ArrayList<String>();
+ String tmp = new String(inner);
+ while(tmp.length()>0) {
+ int indexOfParenth = tmp.indexOf('(');
+ int indexOfVirg = tmp.indexOf(',');
+ StringBuilder sb = new StringBuilder();
+ while(indexOfParenth<indexOfVirg && indexOfVirg>0) {
+ int indexOfClosing = findClosingParenthesis(tmp.substring(indexOfParenth), 0, "()")+indexOfParenth;
+ indexOfParenth = tmp.indexOf('(',indexOfClosing);
+ indexOfVirg = tmp.indexOf(',', indexOfClosing);
+ }
+ if(indexOfVirg>0) {
+ content.add(tmp.substring(0, indexOfVirg).trim());
+ tmp = tmp.substring(indexOfVirg+1);
+ } else {
+ content.add(tmp.trim());
+ tmp = "";
+ }
+ }
+ String[] ret = new String[content.size()];
+ ret = content.toArray(ret);
+ return ret;
+ }
+ private static int findClosingParenthesis(String expr, int first, String delimitors) {
+ final char OPENNING_DELIM = delimitors.charAt(0);
+ final char CLOSING_DELIM = delimitors.charAt(1);
+ int len = expr.length();
+ int close = -1;
+ int pCount = 1;
+ for (int i = (first + 1); i < len; i++) {
+ char c = expr.charAt(i);
+ if (c == OPENNING_DELIM) {
+ pCount++;
+ } else if (c == CLOSING_DELIM) {
+ pCount--;
+ }
+ if (pCount == 0) {
+ close = i;
+ break;
+ }
+ }
+ if (close == (-1)) {
+ throw new RuntimeException("unbalanced delimitor");
+ }
+ return close;
+ }
+ /**
+ * Removes CRLF, trim
+ * @param spec
+ * @return
+ */
+ private static String normalizeSpec(String spec) {
+ StringBuilder sb = new StringBuilder();
+ for(char c:spec.toCharArray()) {
+ if(c==13) sb.append(' ');
+ else if(c==10) sb.append(' ');
+ else if(c==9) sb.append(' ');
+ else sb.append(c);
+ }
+ String s = sb.toString().trim();
+ while(s.indexOf(" ")>=0) s = s.replaceAll(" ", " ");
+ return s;
+ }
+ private static boolean isOracleReservedWord(String s) {
+ return Arrays.binarySearch(RESERVED_WORDS, s)>=0 ;
+ }
+}