OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Compare Revisions

Regard whitespace Rev 19 → Rev 20

/trunk/OpenConcerto/src/org/openconcerto/erp/action/NouvelleConnexionAction.java
15,6 → 15,7
 
import static org.openconcerto.task.config.ComptaBasePropsConfiguration.getStreamStatic;
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.config.Gestion;
import org.openconcerto.erp.config.MainFrame;
import org.openconcerto.erp.core.common.ui.PanelFrame;
import org.openconcerto.erp.core.common.ui.StatusPanel;
36,6 → 37,7
import org.openconcerto.sql.model.UndefinedRowValuesCache;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.preferences.UserProps;
import org.openconcerto.sql.sqlobject.IComboSelectionItem;
import org.openconcerto.sql.ui.ConnexionPanel;
import org.openconcerto.sql.users.User;
import org.openconcerto.sql.users.UserManager;
45,17 → 47,13
import org.openconcerto.task.config.ComptaBasePropsConfiguration;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.FrameUtil;
import org.openconcerto.ui.state.WindowStateManager;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.ExceptionUtils;
import org.openconcerto.utils.JImage;
 
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.io.File;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.ArrayList;
99,8 → 97,20
}
});
}
final int selectedSociete = NouvelleConnexionAction.this.connexionPanel == null ? UserProps.getInstance().getLastSocieteID() : NouvelleConnexionAction.this.connexionPanel
.getSelectedSociete();
int selectedSociete;
if (NouvelleConnexionAction.this.connexionPanel != null && !Gestion.isMinimalMode()) {
selectedSociete = NouvelleConnexionAction.this.connexionPanel.getSelectedSociete();
} else {
selectedSociete = UserProps.getInstance().getLastSocieteID();
if (selectedSociete < SQLRow.MIN_VALID_ID) {
final SQLElement elem = comptaPropsConfiguration.getDirectory().getElement(comptaPropsConfiguration.getRoot().getTable("SOCIETE_COMMON"));
final List<IComboSelectionItem> comboItems = elem.getComboRequest().getComboItems();
if (comboItems.size() > 0)
selectedSociete = comboItems.get(0).getId();
else
throw new IllegalStateException("No " + elem + " found");
}
}
comptaPropsConfiguration.setUpSocieteDataBaseConnexion(selectedSociete);
 
 
112,14 → 122,10
 
StatusPanel.getInstance().fireStatusChanged();
final JFrame f = new MainFrame();
final File f2 = new File(Configuration.getInstance().getConfDir(), "Configuration" + File.separator + "Frame" + File.separator + "mainFrame.xml");
WindowStateManager manager = new WindowStateManager(f, f2);
String version = comptaPropsConfiguration.getVersion();
f.setTitle(comptaPropsConfiguration.getAppName() + " " + version + ", " + " [Société " + comptaPropsConfiguration.getRowSociete().getString("NOM") + "]");
f.setMinimumSize(new Dimension(800, 600));
// f.setResizable(false);
final String socTitle = comptaPropsConfiguration.getRowSociete() == null ? "" : ", [Société " + comptaPropsConfiguration.getRowSociete().getString("NOM") + "]";
f.setTitle(comptaPropsConfiguration.getAppName() + " " + version + socTitle);
f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
manager.loadState();
 
FrameUtil.show(f);
}
173,7 → 179,7
c.insets = new Insets(0, 0, 0, 0);
c.fill = GridBagConstraints.BOTH;
 
this.connexionPanel = ConnexionPanel.create(r, image, true);
this.connexionPanel = ConnexionPanel.create(r, image, !Gestion.isMinimalMode());
if (this.connexionPanel == null)
return null;
 
/trunk/OpenConcerto/src/org/openconcerto/erp/panel/ChargementCreationSocietePanel.java
23,6 → 23,7
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.ui.JLabelBold;
import org.openconcerto.utils.ExceptionHandler;
 
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
71,8 → 72,9
this.add(this.progressBar, c);
this.progressBar.setIndeterminate(true);
 
new Thread() {
new Thread("Creation de societe") {
public void run() {
try {
creationBase(idSoc);
 
statusChanged("Importation du plan comptable");
86,11 → 88,14
((JFrame) SwingUtilities.getRoot(ChargementCreationSocietePanel.this)).dispose();
}
});
} catch (Throwable e) {
ExceptionHandler.handle("Erreur pendant la création de la base!", e);
}
}
}.start();
}
 
private void creationBase(int id) {
private void creationBase(int id) throws SQLException {
 
System.err.println("Création de la base");
 
99,13 → 104,10
statusChanged("Mise à jour des sociétés");
SQLRowValues rowVals = new SQLRowValues(Configuration.getInstance().getBase().getTable("SOCIETE_COMMON"));
rowVals.put("DATABASE_NAME", "OpenConcerto" + id);
try {
 
rowVals.update(id);
} catch (SQLException e) {
 
e.printStackTrace();
}
}
 
private void importationPlanComptable(int id, int typePCG) {
 
/trunk/OpenConcerto/src/org/openconcerto/erp/utils/ActionDB.java
116,7 → 116,7
 
log(l, "Duplication terminée");
 
} catch (SQLException e) {
} catch (Throwable e) {
e.printStackTrace();
ExceptionHandler.handle("Erreur pendant la création de la base!", e);
log(l, "Erreur pendant la duplication");
/trunk/OpenConcerto/src/org/openconcerto/erp/importer/DataImporter.java
35,7 → 35,6
import java.nio.charset.Charset;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
/trunk/OpenConcerto/src/org/openconcerto/erp/importer/EqualsConstraint.java
New file
0,0 → 1,35
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.erp.importer;
 
public class EqualsConstraint implements Constraint {
 
private String value;
 
public EqualsConstraint(String string) {
this.value = string;
}
 
@Override
public boolean isValid(Object obj) {
if (obj == null) {
return (value == null);
}
if (obj instanceof String) {
return value.equals((String) obj);
}
return value.equals(obj.toString());
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/importer/CentsValueConverter.java
New file
0,0 → 1,45
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.erp.importer;
 
import org.openconcerto.sql.model.SQLField;
 
public class CentsValueConverter extends ValueConverter {
public CentsValueConverter(SQLField f) {
super(f);
}
 
public Object convertFrom(Object obj) {
long result = 0;
if (obj != null) {
try {
 
String string = obj.toString();
int index = string.indexOf(".");
if (index >= 0) {
string = string.substring(0, index) + string.substring(index + 1, string.length());
} else {
index = string.indexOf(",");
if (index >= 0) {
string = string.substring(0, index) + string.substring(index + 1, string.length());
}
}
result = Integer.parseInt(string);
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/importer/RowValuesNavigatorPanel.java
New file
0,0 → 1,145
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.erp.importer;
 
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.ui.DefaultGridBagConstraints;
 
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collections;
import java.util.List;
 
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
 
public class RowValuesNavigatorPanel extends JPanel implements ActionListener {
private JTabbedPane tabbedPane;
private List<SQLRowValues> updateList = Collections.EMPTY_LIST;
private List<SQLRowValues> insertList = Collections.EMPTY_LIST;;
private JProgressBar pBar;
private JButton bImport;
private JLabel pLabel = new JLabel("Prêt à importer");
final JLabel lNothing = new JLabel(" Pas de données à importer");
 
public RowValuesNavigatorPanel() {
this.setLayout(new GridBagLayout());
GridBagConstraints c = new DefaultGridBagConstraints();
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 3;
c.fill = GridBagConstraints.BOTH;
tabbedPane = new JTabbedPane();
tabbedPane.setMinimumSize(new Dimension(480, 640));
tabbedPane.setPreferredSize(new Dimension(480, 640));
 
tabbedPane.add("Données à importer", lNothing);
 
this.add(tabbedPane, c);
// Line 2
c.gridwidth = 1;
c.gridy++;
pBar = new JProgressBar();
c.weighty = 0;
c.fill = GridBagConstraints.HORIZONTAL;
this.add(pBar, c);
c.gridx++;
c.fill = GridBagConstraints.NONE;
c.weightx = 0;
pLabel.setMinimumSize(pLabel.getPreferredSize());
this.add(pLabel, c);
c.gridx++;
 
bImport = new JButton("Importer les données");
bImport.addActionListener(this);
this.add(bImport, c);
}
 
public void setRowValuesToUpdate(List<SQLRowValues> list) {
this.updateList = list;
if (list.size() > 0) {
tabbedPane.remove(lNothing);
tabbedPane.add("Lignes à modifier", new RowValuesNavigatorMainPanel(list));
}
}
 
public void setRowValuesToInsert(List<SQLRowValues> list) {
this.insertList = list;
if (list.size() > 0) {
tabbedPane.remove(lNothing);
tabbedPane.add("Lignes à ajouter", new RowValuesNavigatorMainPanel(list));
}
}
 
int c = 0;
 
@Override
public void actionPerformed(ActionEvent e) {
pBar.setMinimum(0);
final int size = this.insertList.size() + this.updateList.size();
pBar.setMaximum(size);
bImport.setEnabled(false);
Thread t = new Thread("Importer") {
public void run() {
c = 0;
try {
for (SQLRowValues row : insertList) {
row.insert();
updateBar();
}
for (SQLRowValues row : updateList) {
row.update();
updateBar();
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
pBar.setValue(pBar.getMaximum());
pLabel.setText("Import terminé");
}
});
JOptionPane.showMessageDialog(RowValuesNavigatorPanel.this, "Import terminé");
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(RowValuesNavigatorPanel.this, "Erreur pendant l'importation");
}
 
}
 
private void updateBar() {
c++;
if (c % 5 == 0) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
pBar.setValue(c);
pLabel.setText((c + 1) + "/" + size);
}
});
}
};
 
};
t.start();
 
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/importer/DoubleAsLongValueConverter.java
New file
0,0 → 1,33
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.erp.importer;
 
import org.openconcerto.sql.model.SQLField;
 
public class DoubleAsLongValueConverter extends ValueConverter {
 
public DoubleAsLongValueConverter(SQLField f) {
super(f);
 
}
 
@Override
public Object convertFrom(Object obj) {
if (obj instanceof Double) {
Long l = Math.round((Double) obj);
return super.convertFrom(l);
}
return super.convertFrom(obj);
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/importer/RowValuesNavigatorPanel2.java
New file
0,0 → 1,131
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.erp.importer;
 
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.ui.DefaultGridBagConstraints;
 
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
 
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
 
public class RowValuesNavigatorPanel2 extends JPanel implements ActionListener {
 
private List<SQLRowValues> list;
private int currentIndex = -1;
private GridBagConstraints pConstraint;
JPanel currentPanel;
JButton bFirst = new JButton("<<");
JButton bPrevious = new JButton("<");
JButton bNext = new JButton(">");
JButton bLast = new JButton(">>");
private JTextField indexText;
 
public RowValuesNavigatorPanel2(List<SQLRowValues> list) {
this.setOpaque(false);
this.list = list;
this.setLayout(new GridBagLayout());
GridBagConstraints c = new DefaultGridBagConstraints();
c.fill = GridBagConstraints.NONE;
 
final JPanel buttons = new JPanel();
buttons.setOpaque(false);
buttons.setLayout(new FlowLayout());
 
buttons.add(bFirst);
 
buttons.add(bPrevious);
 
buttons.add(bNext);
 
buttons.add(bLast);
indexText = new JTextField(6);
indexText.setText("1");
buttons.add(indexText);
buttons.add(new JLabel(" / " + list.size()));
 
this.add(buttons, c);
 
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 0;
c.gridy++;
 
pConstraint = (GridBagConstraints) c.clone();
currentPanel = new JPanel();
this.add(currentPanel, c);
setCurrentIndex(0);
 
JPanel spacer = new JPanel();
spacer.setOpaque(false);
c.gridy++;
c.weighty = 1;
this.add(spacer, c);
 
bFirst.setOpaque(false);
bPrevious.setOpaque(false);
bNext.setOpaque(false);
bLast.setOpaque(false);
 
bFirst.addActionListener(this);
bPrevious.addActionListener(this);
bNext.addActionListener(this);
bLast.addActionListener(this);
}
 
private void setCurrentIndex(int i) {
if (this.currentIndex == i) {
return;
}
this.indexText.setText(String.valueOf(i + 1));
this.currentIndex = i;
this.remove(currentPanel);
RowValuesPanel p = new RowValuesPanel(this.list.get(i));
p.setOpaque(false);
this.invalidate();
this.currentPanel = p;
this.add(currentPanel, pConstraint);
this.revalidate();
this.repaint();
this.bFirst.setEnabled(currentIndex > 0);
this.bPrevious.setEnabled(currentIndex > 0);
this.bNext.setEnabled(currentIndex < list.size() - 1);
this.bLast.setEnabled(currentIndex < list.size() - 1);
}
 
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(bFirst)) {
setCurrentIndex(0);
}
if (e.getSource().equals(bPrevious)) {
setCurrentIndex(currentIndex - 1);
}
if (e.getSource().equals(bNext)) {
setCurrentIndex(currentIndex + 1);
}
if (e.getSource().equals(bLast)) {
setCurrentIndex(this.list.size() - 1);
}
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/importer/RowValuesNavigatorMainPanel.java
New file
0,0 → 1,131
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.erp.importer;
 
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.ui.DefaultGridBagConstraints;
 
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
 
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
 
public class RowValuesNavigatorMainPanel extends JPanel implements ActionListener {
 
private List<SQLRowValues> list;
private int currentIndex = -1;
private GridBagConstraints pConstraint;
JPanel currentPanel;
JButton bFirst = new JButton("<<");
JButton bPrevious = new JButton("<");
JButton bNext = new JButton(">");
JButton bLast = new JButton(">>");
private JTextField indexText;
 
public RowValuesNavigatorMainPanel(List<SQLRowValues> list) {
this.setOpaque(false);
this.list = list;
this.setLayout(new GridBagLayout());
GridBagConstraints c = new DefaultGridBagConstraints();
c.fill = GridBagConstraints.NONE;
 
final JPanel buttons = new JPanel();
buttons.setOpaque(false);
buttons.setLayout(new FlowLayout());
 
buttons.add(bFirst);
 
buttons.add(bPrevious);
 
buttons.add(bNext);
 
buttons.add(bLast);
indexText = new JTextField(6);
indexText.setText("1");
buttons.add(indexText);
buttons.add(new JLabel(" / " + list.size()));
 
this.add(buttons, c);
 
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 0;
c.gridy++;
 
pConstraint = (GridBagConstraints) c.clone();
currentPanel = new JPanel();
this.add(currentPanel, c);
setCurrentIndex(0);
 
JPanel spacer = new JPanel();
spacer.setOpaque(false);
c.gridy++;
c.weighty = 1;
this.add(spacer, c);
 
bFirst.setOpaque(false);
bPrevious.setOpaque(false);
bNext.setOpaque(false);
bLast.setOpaque(false);
 
bFirst.addActionListener(this);
bPrevious.addActionListener(this);
bNext.addActionListener(this);
bLast.addActionListener(this);
}
 
private void setCurrentIndex(int i) {
if (this.currentIndex == i) {
return;
}
this.indexText.setText(String.valueOf(i + 1));
this.currentIndex = i;
this.remove(currentPanel);
RowValuesPanel p = new RowValuesPanel(this.list.get(i));
p.setOpaque(false);
this.invalidate();
this.currentPanel = p;
this.add(currentPanel, pConstraint);
this.revalidate();
this.repaint();
this.bFirst.setEnabled(currentIndex > 0);
this.bPrevious.setEnabled(currentIndex > 0);
this.bNext.setEnabled(currentIndex < list.size() - 1);
this.bLast.setEnabled(currentIndex < list.size() - 1);
}
 
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(bFirst)) {
setCurrentIndex(0);
}
if (e.getSource().equals(bPrevious)) {
setCurrentIndex(currentIndex - 1);
}
if (e.getSource().equals(bNext)) {
setCurrentIndex(currentIndex + 1);
}
if (e.getSource().equals(bLast)) {
setCurrentIndex(this.list.size() - 1);
}
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/importer/RowValuesPanel.java
New file
0,0 → 1,80
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.erp.importer;
 
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.model.SQLField;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.ui.DefaultGridBagConstraints;
 
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.Map;
 
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
 
public class RowValuesPanel extends JPanel {
 
public RowValuesPanel(SQLRowValues sqlRowValues) {
this.setLayout(new GridBagLayout());
GridBagConstraints c = new DefaultGridBagConstraints();
Map<String, Object> m = sqlRowValues.getAbsolutelyAll();
String[] p = m.keySet().toArray(new String[0]);
 
for (int i = 0; i < p.length; i++) {
c.gridx = 0;
c.weightx = 0;
 
String key = p[i];
SQLField f = sqlRowValues.getTable().getField(key);
String name = Configuration.getTranslator(f.getTable()).getDescFor(f.getTable(), f.getName()).getLabel();
if (name == null) {
name = key;
}
 
String value = "null";
if (m.get(key) != null) {
if (m.get(key) instanceof SQLRowValues) {
SQLRowValues rv = (SQLRowValues) m.get(key);
 
this.add(new JLabel(name, SwingConstants.RIGHT), c);
c.gridx++;
 
c.weightx = 1;
final RowValuesPanel comp = new RowValuesPanel(rv);
comp.setOpaque(false);
this.add(comp, c);
 
} else {
c.gridwidth = 1;
value = m.get(key).toString();
this.add(new JLabel(name, SwingConstants.RIGHT), c);
c.gridx++;
c.weightx = 1;
 
final JTextField comp = new JTextField(20);
comp.setText(value);
comp.setEditable(false);
this.add(comp, c);
}
}
 
c.gridy++;
 
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/config/Gestion.java
71,6 → 71,12
 
public class Gestion {
 
/**
* When this system property is set to <code>true</code>, Gestion will hide most of its normal
* UI. E.g. no SOCIETE selection in the login panel, minimalist menu bar, etc.
*/
public static final String MINIMAL_PROP = "org.openconcerto.erp.minimal";
 
private static List<Image> frameIcon;
// Check that we are on Mac OS X. This is crucial to loading and using the OSXAdapter class.
static final boolean MAC_OS_X = System.getProperty("os.name").toLowerCase().startsWith("mac os x");
104,6 → 110,10
}
}
 
public static final boolean isMinimalMode() {
return Boolean.getBoolean(MINIMAL_PROP);
}
 
/**
* @param args
*/
/trunk/OpenConcerto/src/org/openconcerto/erp/config/InstallationPanel.java
20,6 → 20,7
import org.openconcerto.sql.model.DBSystemRoot;
import org.openconcerto.sql.model.SQLBase;
import org.openconcerto.sql.model.SQLDataSource;
import org.openconcerto.sql.model.SQLField;
import org.openconcerto.sql.model.SQLField.Properties;
import org.openconcerto.sql.model.SQLName;
import org.openconcerto.sql.model.SQLRow;
49,6 → 50,7
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
180,6 → 182,7
SQLUtils.executeAtomic(ds, new SQLUtils.SQLFactory<Object>() {
@Override
public Object create() throws SQLException {
fixUnboundedVarchar(root);
updateSocieteSchema(root);
updateToV1Dot2(root);
return null;
403,6 → 406,36
this.add(comp, c);
}
 
private void fixUnboundedVarchar(DBRoot root) throws SQLException {
final Set<String> namesSet = CollectionUtils.createSet("NOM", "PRENOM", "SURNOM", "LOGIN", "PASSWORD");
final List<AlterTable> alters = new ArrayList<AlterTable>();
for (final SQLTable t : root.getTables()) {
final AlterTable alter = new AlterTable(t);
for (final SQLField f : t.getFields()) {
if (f.getType().getType() == Types.VARCHAR && f.getType().getSize() == Integer.MAX_VALUE) {
final String fName = f.getName();
final int size;
if (namesSet.contains(fName))
size = 64;
else if (fName.equals("TEL") || fName.startsWith("TEL_"))
size = 16;
else
size = 128;
alter.alterColumn(fName, EnumSet.allOf(Properties.class), "varchar(" + size + ")", "''", false);
}
}
if (!alter.isEmpty())
alters.add(alter);
}
if (alters.size() > 0) {
final SQLDataSource ds = root.getDBSystemRoot().getDataSource();
for (final String sql : ChangeTable.cat(alters, root.getName())) {
ds.execute(sql);
}
root.refetch();
}
}
 
private void updateToV1Dot2(final DBRoot root) throws SQLException {
final SQLTable tableDevis = root.getTable("DEVIS");
final SQLDataSource ds = root.getDBSystemRoot().getDataSource();
/trunk/OpenConcerto/src/org/openconcerto/erp/config/ComptaPropsConfiguration.java
444,13 → 444,9
dir.addSQLElement(new SaisieKmItemSQLElement());
dir.addSQLElement(new EcritureSQLElement());
 
dir.addSQLElement(new SharedSQLElement("ACCES_SOCIETE"));
dir.addSQLElement(new SharedSQLElement("PREFS_COMPTE"));
dir.addSQLElement(new SharedSQLElement("EMPLOYEUR_MULTIPLE"));
dir.addSQLElement(new SharedSQLElement("REPARTITION_ANALYTIQUE_ELEMENT"));
dir.addSQLElement(PosteAnalytiqueSQLElement.class);
dir.addSQLElement(new SharedSQLElement("CLASSE_COMPTE"));
dir.addSQLElement(new SharedSQLElement("PREFERENCES"));
 
dir.addSQLElement(new CaisseCotisationSQLElement());
dir.addSQLElement(CaisseTicketSQLElement.class);
/trunk/OpenConcerto/src/org/openconcerto/erp/config/MainFrame.java
115,8 → 115,10
import org.openconcerto.sql.users.rights.UserRights;
import org.openconcerto.task.TodoListPanel;
import org.openconcerto.task.config.ComptaBasePropsConfiguration;
import org.openconcerto.ui.AutoHideTabbedPane;
import org.openconcerto.ui.MenuUtils;
import org.openconcerto.ui.SwingThreadUtils;
import org.openconcerto.ui.state.WindowStateManager;
import org.openconcerto.utils.JImage;
import org.openconcerto.utils.OSXAdapter;
 
128,6 → 130,7
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
153,6 → 156,7
public static final String LIST_MENU = "Gestion";
public static final String CREATE_MENU = "Saisie";
public static final String FILE_MENU = "Fichier";
private static final String HELP_MENU = "Aide";
 
static private final List<Runnable> runnables = new ArrayList<Runnable>();
static private MainFrame instance = null;
192,7 → 196,8
});
}
 
private TodoListPanel todoPanel = new TodoListPanel();
private final AutoHideTabbedPane tabContainer;
private TodoListPanel todoPanel;
private JImage image;
 
public TodoListPanel getTodoPanel() {
203,7 → 208,7
super();
 
this.setIconImage(new ImageIcon(this.getClass().getResource("frameicon.png")).getImage());
this.setJMenuBar(createMenu());
this.setJMenuBar(Gestion.isMinimalMode() ? createMinimalMenu() : createMenu());
Container co = this.getContentPane();
co.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
213,10 → 218,10
// // co.add(new RangeSlider(2005), c);
c.weightx = 1;
c.weighty = 0;
image = new JImage(ComptaBasePropsConfiguration.class.getResource("logo.png"));
image.setBackground(Color.WHITE);
image.check();
co.add(image, c);
this.image = new JImage(ComptaBasePropsConfiguration.class.getResource("logo.png"));
this.image.setBackground(Color.WHITE);
this.image.check();
co.add(this.image, c);
c.weighty = 0;
c.gridy++;
c.fill = GridBagConstraints.BOTH;
223,15 → 228,37
co.add(new JSeparator(JSeparator.HORIZONTAL), c);
c.gridy++;
c.weighty = 1;
co.add(this.todoPanel, c);
this.tabContainer = new AutoHideTabbedPane();
co.add(this.tabContainer, c);
Dimension minSize;
final String confSuffix;
if (!Gestion.isMinimalMode()) {
this.todoPanel = new TodoListPanel();
this.getTabbedPane().addTab("Tâches", this.todoPanel);
minSize = new Dimension(800, 600);
confSuffix = "";
} else {
minSize = null;
confSuffix = "-minimal";
}
c.weighty = 0;
c.gridy++;
c.fill = GridBagConstraints.HORIZONTAL;
co.add(StatusPanel.getInstance(), c);
 
if (minSize == null) {
this.pack();
minSize = new Dimension(this.getSize());
}
this.setMinimumSize(minSize);
 
final File confFile = new File(Configuration.getInstance().getConfDir(), "Configuration" + File.separator + "Frame" + File.separator + "mainFrame" + confSuffix + ".xml");
new WindowStateManager(this, confFile).loadState();
 
registerForMacOSXEvents();
 
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
quit();
}
238,10 → 265,38
});
 
setInstance(this);
new NewsUpdater(image);
new NewsUpdater(this.image);
}
 
public JMenuBar createMenu() {
private final JMenuBar createMinimalMenu() {
final JMenuBar res = new JMenuBar();
final JMenu fileMenu = new JMenu(FILE_MENU);
fileMenu.add(new SauvegardeBaseAction());
if (!Gestion.MAC_OS_X) {
fileMenu.add(new JMenuItem(new AbstractAction("Quitter") {
@Override
public void actionPerformed(ActionEvent e) {
quit();
}
}));
}
res.add(fileMenu);
 
final UserRights rights = UserManager.getInstance().getCurrentUser().getRights();
if (rights.haveRight(LockAdminUserRight.LOCK_MENU_ADMIN)) {
final JMenu structMenu = new JMenu(STRUCTURE_MENU);
structMenu.add(new JMenuItem(new ListeDesUsersCommonAction()));
res.add(structMenu);
}
 
final JMenu helpMenu = new JMenu(HELP_MENU);
helpMenu.add(new JMenuItem(AboutAction.getInstance()));
res.add(helpMenu);
 
return res;
}
 
private final JMenuBar createMenu() {
JMenuBar result = new JMenuBar();
 
JMenu menu;
284,6 → 339,7
if (!Gestion.MAC_OS_X) {
menu.add(new JMenuItem(new PreferencesAction()));
menu.add(new JMenuItem(new AbstractAction("Quitter") {
@Override
public void actionPerformed(ActionEvent e) {
quit();
}
494,7 → 550,7
result.add(menu);
}
// Aide
menu = new JMenu("Aide");
menu = new JMenu(HELP_MENU);
menu.add(new JMenuItem(AboutAction.getInstance()));
menu.add(new JMenuItem(new AstuceAction()));
 
529,7 → 585,8
final JMenu res;
if (existing == null) {
res = new JMenu(name);
this.getJMenuBar().add(res);
// insert before the help menu
this.getJMenuBar().add(res, this.getJMenuBar().getComponentCount() - 1);
} else {
res = existing;
}
578,8 → 635,13
}
 
public boolean quit() {
if (this.getTodoPanel() != null)
this.getTodoPanel().stopUpdate();
Gestion.askForExit();
return false;
}
 
public final AutoHideTabbedPane getTabbedPane() {
return this.tabContainer;
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/modules/ComponentsContext.java
18,7 → 18,6
import org.openconcerto.sql.element.SQLElementDirectory;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.model.SQLName;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.sqlobject.SQLTextCombo;
import org.openconcerto.sql.view.DropManager;
import org.openconcerto.sql.view.FileDropHandler;
25,6 → 24,7
import org.openconcerto.sql.view.SQLMenuItemHelper;
import org.openconcerto.sql.view.SQLMenuItemHelper.SQLMenuItemAction;
import org.openconcerto.sql.view.list.RowAction;
import org.openconcerto.sql.view.list.RowActionFactory;
import org.openconcerto.utils.CollectionMap;
 
import java.util.ArrayList;
37,8 → 37,6
import javax.swing.JMenuItem;
import javax.swing.text.JTextComponent;
 
import org.openconcerto.sql.view.list.RowActionFactory;
 
/**
* Allow a module to add JComponent to edit fields.
*
174,7 → 172,7
return this.menuItems;
}
 
public final void addFileDropHandler(SQLTable table, FileDropHandler handler) {
DropManager.getInstance().add(table, handler);
public final void addFileDropHandler(final String tableName, FileDropHandler handler) {
DropManager.getInstance().add(this.getRoot().getTable(tableName), handler);
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/modules/DBContext.java
27,7 → 27,9
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
/**
121,10 → 123,14
// getter
 
final List<String> getAddedTables() {
final List<String> res = new ArrayList<String>();
return new ArrayList<String>(getCreateTables().keySet());
}
 
final Map<String, SQLCreateTableBase<?>> getCreateTables() {
final Map<String, SQLCreateTableBase<?>> res = new LinkedHashMap<String, SQLCreateTableBase<?>>();
for (final ChangeTable<?> a : this.changeTables) {
if (a instanceof SQLCreateTableBase<?>) {
res.add(a.getName());
res.put(a.getName(), (SQLCreateTableBase<?>) a);
}
}
return res;
/trunk/OpenConcerto/src/org/openconcerto/erp/modules/AlterTableRestricted.java
19,6 → 19,7
import org.openconcerto.sql.model.SQLSyntax;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.utils.AlterTable;
import org.openconcerto.sql.utils.SQLCreateTableBase;
import org.openconcerto.utils.CollectionUtils;
 
import java.util.HashSet;
97,15 → 98,20
return this.alter.addDateAndTimeColumn(name);
}
 
public final AlterTable addIntegerColumn(String name, int defaultVal) {
addCol(name);
return this.alter.addIntegerColumn(name, defaultVal);
}
 
public AlterTable addForeignColumn(String fk, String table) {
return this.addForeignColumn(fk, new SQLName(table));
}
 
public AlterTable addForeignColumn(String fk, SQLName tableName) {
if (tableName.getItemCount() == 1 && this.ctxt.getAddedTables().contains(tableName.getFirst())) {
SQLCreateTableBase<?> createTable;
if (tableName.getItemCount() == 1 && (createTable = this.ctxt.getCreateTables().get(tableName.getFirst())) != null) {
addCol(fk);
// see DBContext.execute()
return this.alter.addForeignColumn(fk, tableName, SQLSyntax.ID_NAME, "NULL");
return this.alter.addForeignColumn(fk, createTable);
} else {
return this.addForeignColumn(fk, this.table.getDesc(tableName, SQLTable.class));
}
/trunk/OpenConcerto/src/org/openconcerto/erp/modules/ModuleManager.java
60,8 → 60,8
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
915,7 → 915,9
final SQLField f = root.getDesc(field, SQLField.class);
// dropped by DROP TABLE
if (!tableNames.contains(f.getTable().getName())) {
l.add(new AlterTable(f.getTable()).dropColumn(f.getName()));
// cascade needed since the module might have created constraints
// (e.g. on H2 a foreign column cannot be dropped)
l.add(new AlterTable(f.getTable()).dropColumnCascade(f.getName()));
}
}
for (final String table : tableNames) {
/trunk/OpenConcerto/src/org/openconcerto/erp/modules/ModulePackager.java
25,7 → 25,9
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
42,13 → 44,26
private final List<File> classesDirs;
private final List<File> jars = new ArrayList<File>();
private final File propsFile;
private final Set<String> dirEntries, fileEntries;
private boolean skipDuplicateFiles;
 
public ModulePackager(final File propsFile, final File classes) {
this.propsFile = propsFile;
this.classesDirs = new ArrayList<File>(8);
this.classesDirs.add(classes);
this.dirEntries = new HashSet<String>();
this.fileEntries = new HashSet<String>();
this.setSkipDuplicateFiles(false);
}
 
public final void setSkipDuplicateFiles(boolean skipDuplicateFiles) {
this.skipDuplicateFiles = skipDuplicateFiles;
}
 
public final boolean getSkipDuplicateFiles() {
return this.skipDuplicateFiles;
}
 
public final void addDir(final File classesDir) {
this.classesDirs.add(classesDir);
}
90,6 → 105,8
final RuntimeModuleFactory f = new RuntimeModuleFactory(this.propsFile);
final File jarFile = new File(dir, f.getID() + "-" + f.getMajorVersion() + "." + f.getMinorVersion() + ".jar");
final JarOutputStream jarStream = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(jarFile)));
this.dirEntries.clear();
this.fileEntries.clear();
try {
if (!this.zipExistingFile(jarStream, this.propsFile, MODULE_PROPERTIES_PATH))
throw new IllegalStateException("Missing properties file : " + this.propsFile);
101,6 → 118,8
}
} finally {
jarStream.close();
this.dirEntries.clear();
this.fileEntries.clear();
}
return jarFile;
}
172,6 → 191,13
}
 
private void zip(JarOutputStream jarStream, final JarEntry entry, InputStream in) throws IOException {
// ignore duplicate directories
final boolean isDir = entry.isDirectory();
if (isDir && !this.dirEntries.add(entry.getName()))
return;
if (!isDir && this.getSkipDuplicateFiles() && !this.fileEntries.add(entry.getName()))
return;
 
jarStream.putNextEntry(entry);
if (in != null) {
StreamUtils.copy(in, jarStream);
/trunk/OpenConcerto/src/org/openconcerto/openoffice/generation/ReportGeneration.java
161,7 → 161,7
*/
@SuppressWarnings("unchecked")
protected C createCommon(String name) {
return (C) new GenerationCommon<ReportGeneration>(this);
return (C) new GenerationCommon<ReportGeneration<?>>(this);
}
 
/**
/trunk/OpenConcerto/src/org/openconcerto/openoffice/ODFrame.java
34,22 → 34,16
* @return the length, eg 15.3.
*/
public static final float parseLength(final String l, final LengthUnit to) {
return parseLengthDecimal(l, to).floatValue();
return LengthUnit.parseLength(l, to).floatValue();
}
 
public static final BigDecimal parseLengthDecimal(final String l, final LengthUnit to) {
if (l == null)
return null;
return LengthUnit.parseLength(l, to).stripTrailingZeros();
}
 
// BigDecimal are exact and they can be null (eg optional attribute)
private final BigDecimal width, height;
 
public ODFrame(D parent, Element frame) {
super(parent, frame, GraphicStyle.class);
this.width = parseLengthDecimal(this.getSVGAttr("width"), getUnit());
this.height = parseLengthDecimal(this.getSVGAttr("height"), getUnit());
this.width = LengthUnit.parseLength(this.getSVGAttr("width"), getUnit());
this.height = LengthUnit.parseLength(this.getSVGAttr("height"), getUnit());
}
 
public final BigDecimal getWidth() {
95,11 → 89,11
}
 
public final BigDecimal getX() {
return parseLengthDecimal(this.getSVGAttr("x"), getUnit());
return LengthUnit.parseLength(this.getSVGAttr("x"), getUnit());
}
 
public final BigDecimal getY() {
return parseLengthDecimal(this.getSVGAttr("y"), getUnit());
return LengthUnit.parseLength(this.getSVGAttr("y"), getUnit());
}
 
/**
/trunk/OpenConcerto/src/org/openconcerto/openoffice/StyleProperties.java
23,6 → 23,18
public static final Color TRANSPARENT = new Color(0, 0, 0, 0);
public static final String TRANSPARENT_NAME = "transparent";
 
static public final boolean parseBoolean(final String s, boolean def) {
return s == null ? def : Boolean.parseBoolean(s);
}
 
static public final int parseInt(final String s, int def) {
return s == null ? def : Integer.parseInt(s);
}
 
static public final Integer parseInteger(final String s) {
return s == null ? null : Integer.valueOf(s);
}
 
private final Style parentStyle;
private final String propPrefix;
 
36,13 → 48,36
}
 
public final Element getElement() {
return this.getParentStyle().getFormattingProperties(this.propPrefix);
return getElement(this.getParentStyle(), true);
}
 
protected final boolean parseBoolean(final String s, boolean def) {
return s == null ? def : Boolean.parseBoolean(s);
protected final Element getElement(final Style s, final boolean create) {
return s.getFormattingProperties(this.propPrefix, create);
}
 
private final String getAttributeValue(final Style s, final String attrName, final Namespace attrNS) {
// e.g. no default style defined
if (s == null)
return null;
final Element elem = this.getElement(s, false);
if (elem == null)
return null;
return elem.getAttributeValue(attrName, attrNS);
}
 
// if a formatting property is not defined locally, the default style should be searched
protected final String getAttributeValue(final String attrName, final Namespace attrNS) {
final String localRes = getAttributeValue(this.getParentStyle(), attrName, attrNS);
if (localRes != null)
return localRes;
if (this.getParentStyle() instanceof StyleStyle) {
final StyleStyle defaultStyle = ((StyleStyle) this.getParentStyle()).getDefaultStyle();
return getAttributeValue(defaultStyle, attrName, attrNS);
} else {
return null;
}
}
 
protected final Namespace getNS(final String prefix) {
return this.getParentStyle().getNS().getNS(prefix);
}
53,7 → 88,7
// <style:table-properties>, <style:table-row-properties> and <style:text-properties>
 
public final String getRawBackgroundColor() {
return this.getElement().getAttributeValue("background-color", this.getNS("fo"));
return this.getAttributeValue("background-color", this.getNS("fo"));
}
 
public final Color getBackgroundColor() {
/trunk/OpenConcerto/src/org/openconcerto/openoffice/StyleStyleDesc.java
28,9 → 28,10
public abstract class StyleStyleDesc<S extends StyleStyle> extends StyleDesc<S> {
 
static final String ELEMENT_NAME = "style";
static final String ELEMENT_DEFAULT_NAME = "default-style";
 
static String getFamily(final Element styleElem) {
assert styleElem.getName().equals(ELEMENT_NAME);
assert styleElem.getName().equals(ELEMENT_NAME) || styleElem.getName().equals(ELEMENT_DEFAULT_NAME);
return styleElem.getAttributeValue("family", styleElem.getNamespace("style"));
}
 
71,4 → 72,9
super.initStyle(elem);
elem.setAttribute("family", this.getFamily(), elem.getNamespace());
}
 
public final S findDefaultStyle(final ODPackage pkg) {
final Element styleElem = pkg.getDefaultStyle(this);
return styleElem == null ? null : this.create(pkg, styleElem);
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/StyleStyle.java
32,6 → 32,13
}
 
@Override
protected void checkElemName() {
// allow use of default styles
if (!StyleStyleDesc.ELEMENT_DEFAULT_NAME.equals(this.getElement().getName()) && !this.getDesc().getElementName().equals(this.getElement().getName()))
throw new IllegalArgumentException("expected a default style (" + StyleStyleDesc.ELEMENT_DEFAULT_NAME + ") or " + this.getDesc().getElementName() + " but got " + getElement());
}
 
@Override
protected StyleStyleDesc<?> getDesc() {
return (StyleStyleDesc<?>) super.getDesc();
}
44,6 → 51,10
return this.getFormattingProperties(this.getFamily());
}
 
public final StyleStyle getDefaultStyle() {
return this.getDesc().findDefaultStyle(getPackage());
}
 
@Override
public final boolean equals(Object obj) {
if (!(obj instanceof StyleStyle) || !super.equals(obj))
/trunk/OpenConcerto/src/org/openconcerto/openoffice/spreadsheet/RowStyle.java
13,12 → 13,15
package org.openconcerto.openoffice.spreadsheet;
 
import org.openconcerto.openoffice.ODFrame;
import org.openconcerto.openoffice.LengthUnit;
import org.openconcerto.openoffice.ODPackage;
import org.openconcerto.openoffice.StyleProperties;
import org.openconcerto.openoffice.StyleStyle;
import org.openconcerto.openoffice.StyleStyleDesc;
import org.openconcerto.openoffice.XMLVersion;
 
import java.math.BigDecimal;
 
import org.jdom.Element;
 
public class RowStyle extends StyleStyle {
31,12 → 34,35
}
};
 
private StyleTableRowProperties rowProps;
 
public RowStyle(final ODPackage pkg, Element tableColElem) {
super(pkg, tableColElem);
}
 
public final float getHeight() {
return ODFrame.parseLength(getFormattingProperties().getAttributeValue("row-height", this.getSTYLE()), TableStyle.DEFAULT_UNIT);
public final StyleTableRowProperties getTableRowProperties() {
if (this.rowProps == null)
this.rowProps = new StyleTableRowProperties(this);
return this.rowProps;
}
 
// see 17.17 of v1.2-cs01-part1
public static class StyleTableRowProperties extends StyleProperties {
 
public StyleTableRowProperties(StyleStyle style) {
super(style, style.getFamily());
}
 
public final BigDecimal getHeight(final LengthUnit in) {
return LengthUnit.parseLength(getAttributeValue("row-height", this.getNS("style")), in);
}
 
public final String getBreakBefore() {
return getAttributeValue("break-before", this.getNS("fo"));
}
 
public final String getBreakAfter() {
return getAttributeValue("break-after", this.getNS("fo"));
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/spreadsheet/TableStyle.java
14,12 → 14,13
package org.openconcerto.openoffice.spreadsheet;
 
import org.openconcerto.openoffice.LengthUnit;
import org.openconcerto.openoffice.ODFrame;
import org.openconcerto.openoffice.ODPackage;
import org.openconcerto.openoffice.StyleStyle;
import org.openconcerto.openoffice.StyleStyleDesc;
import org.openconcerto.openoffice.StyleStyle;
import org.openconcerto.openoffice.XMLVersion;
import org.openconcerto.openoffice.style.SideStyleProperties;
 
import java.math.BigDecimal;
import java.util.Arrays;
 
import org.jdom.Element;
35,13 → 36,21
}
};
 
private StyleTableProperties tableProps;
 
public TableStyle(final ODPackage pkg, Element tableColElem) {
super(pkg, tableColElem);
}
 
public final StyleTableProperties getTableProperties() {
if (this.tableProps == null)
this.tableProps = new StyleTableProperties(this);
return this.tableProps;
}
 
public final Float getWidth() {
final String width = getFormattingProperties().getAttributeValue("width", this.getSTYLE());
return width == null ? null : ODFrame.parseLength(width, TableStyle.DEFAULT_UNIT);
final BigDecimal width = getTableProperties().getWidth(TableStyle.DEFAULT_UNIT);
return width == null ? null : width.floatValue();
}
 
void setWidth(float f) {
48,4 → 57,30
getFormattingProperties().setAttribute("width", f + DEFAULT_UNIT.getSymbol(), this.getSTYLE());
}
 
// see 17.15 of v1.2-cs01-part1
public static class StyleTableProperties extends SideStyleProperties {
 
public StyleTableProperties(StyleStyle style) {
super(style, style.getFamily());
}
 
public final String getRawMargin(final Side s) {
return getSideAttribute(s, "margin", this.getNS("fo"));
}
 
/**
* Get the margin of one of the side.
*
* @param s which side.
* @param in the desired unit.
* @return the margin.
*/
public final BigDecimal getMargin(final Side s, final LengthUnit in) {
return LengthUnit.parseLength(getRawMargin(s), in);
}
 
public final BigDecimal getWidth(final LengthUnit in) {
return LengthUnit.parseLength(getAttributeValue("width", this.getNS("style")), in);
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/spreadsheet/MutableCell.java
13,11 → 13,15
package org.openconcerto.openoffice.spreadsheet;
 
import org.openconcerto.openoffice.Log;
import org.openconcerto.openoffice.ODDocument;
import org.openconcerto.openoffice.ODFrame;
import org.openconcerto.openoffice.ODValueType;
import org.openconcerto.openoffice.OOXML;
import org.openconcerto.openoffice.spreadsheet.BytesProducer.ByteArrayProducer;
import org.openconcerto.openoffice.spreadsheet.BytesProducer.ImageProducer;
import org.openconcerto.openoffice.style.data.DataStyle;
import org.openconcerto.utils.ExceptionUtils;
import org.openconcerto.utils.FileUtils;
 
import java.awt.Color;
27,7 → 31,7
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
 
44,9 → 48,33
*/
public class MutableCell<D extends ODDocument> extends Cell<D> {
 
static private final DateFormat TextPDateFormat = new SimpleDateFormat("dd/MM/yyyy");
static private final NumberFormat TextPFloatFormat = new DecimalFormat(",##0.00");
static private final DateFormat TextPDateFormat = DateFormat.getDateInstance();
static private final DateFormat TextPTimeFormat = DateFormat.getTimeInstance();
static private final NumberFormat TextPFloatFormat = DecimalFormat.getNumberInstance();
static private final NumberFormat TextPPercentFormat = DecimalFormat.getPercentInstance();
static private final NumberFormat TextPCurrencyFormat = DecimalFormat.getCurrencyInstance();
 
static public String formatNumber(Number n, final CellStyle defaultStyle) {
return formatNumber(TextPFloatFormat, n, defaultStyle, false);
}
 
static public String formatPercent(Number n, final CellStyle defaultStyle) {
return formatNumber(TextPPercentFormat, n, defaultStyle, true);
}
 
static public String formatCurrency(Number n, final CellStyle defaultStyle) {
return formatNumber(TextPCurrencyFormat, n, defaultStyle, true);
}
 
static private String formatNumber(NumberFormat format, Number n, final CellStyle defaultStyle, boolean forceFraction) {
synchronized (format) {
final int decPlaces = DataStyle.getDecimalPlaces(defaultStyle);
format.setMinimumFractionDigits(forceFraction ? decPlaces : 0);
format.setMaximumFractionDigits(decPlaces);
return format.format(n);
}
}
 
MutableCell(Row<D> parent, Element elem) {
super(parent, elem);
}
86,7 → 114,7
// try to reuse the first text:p to keep style
final Element child = this.getElement().getChild("p", getNS().getTEXT());
final Element t = child != null ? child : new Element("p", getNS().getTEXT());
t.setContent(new Text(value));
t.setContent(OOXML.get(this.getODDocument().getFormatVersion()).encodeWSasList(value));
 
this.getElement().setContent(t);
}
102,30 → 130,99
}
 
public void setValue(Object obj) {
// FIXME use arbitrary textP format, should use the cell format
// TODO handle all type of objects as in ODUserDefinedMeta
// setValue(Object o, final ODValueType vt)
if (obj instanceof Number)
// 5.2
// FIXME voir avec Sylvain : probleme avec le viewer si Integer ou Long le textp ne doit
// avoir de décimal
if (obj instanceof Integer || obj instanceof Long) {
this.setValue(ODValueType.FLOAT, obj, (obj == null) ? "" : obj.toString());
final ODValueType type;
final ODValueType currentType = getValueType();
// try to keep current type, since for example a Number can work with FLOAT, PERCENTAGE
// and CURRENCY
if (currentType != null && currentType.canFormat(obj.getClass())) {
type = currentType;
} else if (obj instanceof Number) {
type = ODValueType.FLOAT;
} else if (obj instanceof Date || obj instanceof Calendar) {
type = ODValueType.DATE;
} else if (obj instanceof Boolean) {
type = ODValueType.BOOLEAN;
} else if (obj instanceof String) {
type = ODValueType.STRING;
} else {
this.setValue(ODValueType.FLOAT, obj, TextPFloatFormat.format(obj));
throw new IllegalArgumentException("Couldn't infer type of " + obj);
}
else if (obj instanceof Date)
this.setValue(ODValueType.DATE, obj, TextPDateFormat.format(obj));
this.setValue(obj, type, true);
}
 
/**
* Change the value of this cell.
*
* @param obj the new cell value.
* @param vt the value type.
* @param lenient <code>false</code> to throw an exception if we can't format according to the
* ODF, <code>true</code> to try best-effort.
* @throws UnsupportedOperationException if <code>obj</code> couldn't be formatted.
*/
public void setValue(final Object obj, final ODValueType vt, final boolean lenient) throws UnsupportedOperationException {
final String text;
final String formatted = format(obj, lenient);
 
if (formatted != null) {
text = formatted;
} else {
// either there were no format or formatting failed
if (vt == ODValueType.FLOAT) {
text = formatNumber((Number) obj, getDefaultStyle());
} else if (vt == ODValueType.PERCENTAGE) {
text = formatPercent((Number) obj, getDefaultStyle());
} else if (vt == ODValueType.CURRENCY) {
text = formatCurrency((Number) obj, getDefaultStyle());
} else if (vt == ODValueType.DATE) {
text = TextPDateFormat.format(obj);
} else if (vt == ODValueType.TIME) {
text = TextPTimeFormat.format(obj);
} else if (vt == ODValueType.BOOLEAN) {
if (lenient)
text = obj.toString();
else
this.setValue(null, null, obj.toString());
throw new UnsupportedOperationException(vt + " not supported");
} else if (vt == ODValueType.STRING) {
text = obj.toString();
} else {
throw new IllegalStateException(vt + " unknown");
}
}
this.setValue(vt, obj, text);
}
 
// return null if no data style exists, or if one exists but we couldn't use it
private String format(Object obj, boolean lenient) {
try {
final DataStyle ds = getDataStyle();
// act like OO, that is if we set a String to a Date cell, change the value and
// value-type but leave the data-style untouched
if (ds != null && ds.canFormat(obj.getClass()))
return ds.format(obj, getDefaultStyle(), lenient);
} catch (UnsupportedOperationException e) {
if (lenient)
Log.get().warning(ExceptionUtils.getStackTrace(e));
else
throw e;
}
return null;
}
 
public final DataStyle getDataStyle() {
final CellStyle s = this.getStyle();
return s != null ? getStyle().getDataStyle() : null;
}
 
protected final CellStyle getDefaultStyle() {
return this.getRow().getSheet().getDefaultCellStyle();
}
 
public void replaceBy(String oldValue, String newValue) {
replaceContentBy(this.getElement(), oldValue, newValue);
}
 
private void replaceContentBy(Element l, String oldValue, String newValue) {
final List content = l.getContent();
final List<?> content = l.getContent();
for (int i = 0; i < content.size(); i++) {
final Object obj = content.get(i);
if (obj instanceof Text) {
/trunk/OpenConcerto/src/org/openconcerto/openoffice/spreadsheet/ColumnStyle.java
13,12 → 13,16
package org.openconcerto.openoffice.spreadsheet;
 
import org.openconcerto.openoffice.LengthUnit;
import org.openconcerto.openoffice.ODFrame;
import org.openconcerto.openoffice.ODPackage;
import org.openconcerto.openoffice.StyleProperties;
import org.openconcerto.openoffice.StyleStyle;
import org.openconcerto.openoffice.StyleStyleDesc;
import org.openconcerto.openoffice.XMLVersion;
 
import java.math.BigDecimal;
 
import org.jdom.Element;
 
public class ColumnStyle extends StyleStyle {
31,17 → 35,21
}
};
 
private StyleTableColumnProperties colProps;
 
public ColumnStyle(final ODPackage pkg, Element tableColElem) {
super(pkg, tableColElem);
}
 
public final Float getWidth() {
final String attr = getFormattingProperties().getAttributeValue("column-width", this.getSTYLE());
return attr == null ? null : ODFrame.parseLength(attr, TableStyle.DEFAULT_UNIT);
public final StyleTableColumnProperties getTableColumnProperties() {
if (this.colProps == null)
this.colProps = new StyleTableColumnProperties(this);
return this.colProps;
}
 
public final String getBreakBefore() {
return getFormattingProperties().getAttributeValue("break-before", this.getNS().getNS("fo"));
public final Float getWidth() {
final BigDecimal res = this.getTableColumnProperties().getWidth(TableStyle.DEFAULT_UNIT);
return res == null ? null : res.floatValue();
}
 
void setWidth(float f) {
53,4 → 61,24
void rmRelWidth() {
getFormattingProperties().removeAttribute("rel-column-width", this.getSTYLE());
}
 
// see 17.16 of v1.2-cs01-part1
public static class StyleTableColumnProperties extends StyleProperties {
 
public StyleTableColumnProperties(StyleStyle style) {
super(style, style.getFamily());
}
 
public final BigDecimal getWidth(final LengthUnit in) {
return LengthUnit.parseLength(getAttributeValue("column-width", this.getNS("style")), in);
}
 
public final String getBreakBefore() {
return getAttributeValue("break-before", this.getNS("fo"));
}
 
public final String getBreakAfter() {
return getAttributeValue("break-after", this.getNS("fo"));
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/spreadsheet/Cell.java
18,9 → 18,11
 
import org.openconcerto.openoffice.ODDocument;
import org.openconcerto.openoffice.ODValueType;
import org.openconcerto.openoffice.OOXML;
import org.openconcerto.openoffice.XMLFormatVersion;
import org.openconcerto.openoffice.XMLVersion;
import org.openconcerto.utils.CollectionUtils;
import org.openconcerto.xml.JDOMUtils;
 
import java.util.ArrayList;
import java.util.Arrays;
168,10 → 170,13
private String getStringValue(final Element pElem, final boolean ooMode) {
final StringBuilder sb = new StringBuilder();
final Namespace textNS = pElem.getNamespace();
final OOXML xml = OOXML.get(getODDocument().getFormatVersion());
final Element tabElem = xml.getTab();
final Element newLineElem = xml.getLineBreak();
// true if the string ends with a space that wasn't expanded from an XML element (e.g.
// <tab/> or <text:s/>)
boolean spaceSuffix = false;
final Iterator iter = pElem.getDescendants();
final Iterator<?> iter = pElem.getDescendants();
while (iter.hasNext()) {
final Object o = iter.next();
if (o instanceof Text) {
184,9 → 189,9
spaceSuffix = text.endsWith(" ");
} else if (o instanceof Element) {
final Element elem = (Element) o;
if (elem.getName().equals("tab") && elem.getNamespace().equals(textNS)) {
if (JDOMUtils.equals(elem, tabElem)) {
sb.append("\t");
} else if (elem.getName().equals("line-break") && elem.getNamespace().equals(textNS)) {
} else if (JDOMUtils.equals(elem, newLineElem)) {
sb.append("\n");
} else if (elem.getName().equals("s") && elem.getNamespace().equals(textNS)) {
final int count = Integer.valueOf(elem.getAttributeValue("c", textNS, "1"));
/trunk/OpenConcerto/src/org/openconcerto/openoffice/spreadsheet/CellStyle.java
14,10 → 14,12
package org.openconcerto.openoffice.spreadsheet;
 
import org.openconcerto.openoffice.ODPackage;
import org.openconcerto.openoffice.Style;
import org.openconcerto.openoffice.StyleStyle;
import org.openconcerto.openoffice.StyleStyleDesc;
import org.openconcerto.openoffice.XMLVersion;
import org.openconcerto.openoffice.style.SideStyleProperties;
import org.openconcerto.openoffice.style.data.DataStyle;
import org.openconcerto.openoffice.text.ParagraphStyle.StyleParagraphProperties;
import org.openconcerto.openoffice.text.TextStyle.StyleTextProperties;
 
50,6 → 52,10
super(pkg, tableColElem);
}
 
public final DataStyle getDataStyle() {
return (DataStyle) Style.getReferencedStyle(getPackage(), getElement().getAttribute("data-style-name", getSTYLE()));
}
 
public final Color getBackgroundColor() {
return getTableCellProperties().getBackgroundColor();
}
84,21 → 90,25
}
 
public final int getRotationAngle() {
final String s = this.getElement().getAttributeValue("rotation-angle", this.getElement().getNamespace("style"));
return s == null ? 0 : Integer.parseInt(s);
final String s = this.getAttributeValue("rotation-angle", this.getElement().getNamespace("style"));
return parseInt(s, 0);
}
 
public final boolean isContentPrinted() {
return parseBoolean(this.getElement().getAttributeValue("print-content", this.getElement().getNamespace("style")), true);
return parseBoolean(this.getAttributeValue("print-content", this.getElement().getNamespace("style")), true);
}
 
public final boolean isContentRepeated() {
return parseBoolean(this.getElement().getAttributeValue("repeat-content", this.getElement().getNamespace("style")), false);
return parseBoolean(this.getAttributeValue("repeat-content", this.getElement().getNamespace("style")), false);
}
 
public final boolean isShrinkToFit() {
return parseBoolean(this.getElement().getAttributeValue("shrink-to-fit", this.getElement().getNamespace("style")), false);
return parseBoolean(this.getAttributeValue("shrink-to-fit", this.getElement().getNamespace("style")), false);
}
 
public final Integer getDecimalPlaces() {
return parseInteger(this.getAttributeValue("decimal-places", this.getElement().getNamespace("style")));
}
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/spreadsheet/Table.java
14,6 → 14,8
package org.openconcerto.openoffice.spreadsheet;
 
import org.openconcerto.openoffice.ODDocument;
import org.openconcerto.openoffice.Style;
import org.openconcerto.openoffice.StyleStyleDesc;
import org.openconcerto.openoffice.XMLVersion;
import org.openconcerto.openoffice.spreadsheet.SheetTableModel.MutableTableModel;
import org.openconcerto.utils.CollectionUtils;
346,9 → 348,17
}
 
public final CellStyle getStyleAt(int column, int row) {
return CellStyle.DESC.findStyle(this.getODDocument().getPackage(), this.getElement().getDocument(), this.getStyleNameAt(column, row));
return getCellStyleDesc().findStyle(this.getODDocument().getPackage(), this.getElement().getDocument(), this.getStyleNameAt(column, row));
}
 
protected StyleStyleDesc<CellStyle> getCellStyleDesc() {
return Style.getStyleStyleDesc(CellStyle.class, getODDocument().getVersion());
}
 
public final CellStyle getDefaultCellStyle() {
return getCellStyleDesc().findDefaultStyle(this.getODDocument().getPackage());
}
 
/**
* Return the coordinates of cells using the passed style.
*
/trunk/OpenConcerto/src/org/openconcerto/openoffice/OOXML.java
254,7 → 254,7
return new Element("span", getVersion().getTEXT()).setContent(encodeWSasList(s));
}
 
private final List<Content> encodeWSasList(final String s) {
public final List<Content> encodeWSasList(final String s) {
final List<Content> res = new ArrayList<Content>();
final Matcher m = Pattern.compile("\n|\t| {2,}").matcher(s);
int last = 0;
/trunk/OpenConcerto/src/org/openconcerto/openoffice/GraphicStyle.java
95,19 → 95,19
}
 
public final String getHorizontalPosition() {
return this.getElement().getAttributeValue("horizontal-pos", this.getElement().getNamespace("style"));
return this.getAttributeValue("horizontal-pos", this.getElement().getNamespace("style"));
}
 
public final String getHorizontalRelation() {
return this.getElement().getAttributeValue("horizontal-rel", this.getElement().getNamespace("style"));
return this.getAttributeValue("horizontal-rel", this.getElement().getNamespace("style"));
}
 
public final String getVerticalPosition() {
return this.getElement().getAttributeValue("vertical-pos", this.getElement().getNamespace("style"));
return this.getAttributeValue("vertical-pos", this.getElement().getNamespace("style"));
}
 
public final String getVerticalRelation() {
return this.getElement().getAttributeValue("vertical-rel", this.getElement().getNamespace("style"));
return this.getAttributeValue("vertical-rel", this.getElement().getNamespace("style"));
}
 
/**
116,7 → 116,7
* @return a list that consists of any of the values content, position, or size.
*/
public final List<String> getProtected() {
final String val = this.getElement().getAttributeValue("protect", this.getElement().getNamespace("style"));
final String val = this.getAttributeValue("protect", this.getElement().getNamespace("style"));
if (val == null || "none".equals(val))
return Collections.emptyList();
else
124,7 → 124,7
}
 
public final boolean isContentPrinted() {
return parseBoolean(this.getElement().getAttributeValue("print-content", this.getElement().getNamespace("style")), true);
return parseBoolean(this.getAttributeValue("print-content", this.getElement().getNamespace("style")), true);
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/StyleDesc.java
75,6 → 75,7
// need version since each one might have different attributes and elements (plus we need it
// anyway for the XPath, otherwise it fails when searching for an inexistant namespace)
private final XMLVersion version;
private Namespace elemNS;
private final String elemName, baseName;
// { attribute -> element }
private final CollectionMap<String, String> refElements;
90,6 → 91,7
super();
this.clazz = clazz;
this.version = version;
this.elemNS = version.getSTYLE();
this.elemName = elemName;
this.baseName = baseName;
this.refElements = new CollectionMap<String, String>();
108,6 → 110,14
return this.version;
}
 
protected final void setElementNS(Namespace elemNS) {
this.elemNS = elemNS;
}
 
public final Namespace getElementNS() {
return this.elemNS;
}
 
/**
* The name of the XML element for this type of style.
*
163,11 → 173,14
}
 
// e.g. { "text:style-name" -> ["text:h", "text:p"] }
// if a property of the style is changed it will affect only the referent element
protected final CollectionMap<String, String> getRefElementsMap() {
return this.refElements;
}
 
// e.g. { "table:default-cell-style-name" -> ["table:table-column", "table:table-row"] }
// if a property of the style is changed it will affect multiple cells even if only one element
// (e.g. a column) references the style
protected final CollectionMap<String, String> getMultiRefElementsMap() {
return this.multiRefElements;
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/Style.java
20,6 → 20,7
import org.openconcerto.openoffice.spreadsheet.RowStyle;
import org.openconcerto.openoffice.spreadsheet.TableStyle;
import org.openconcerto.openoffice.style.PageLayoutStyle;
import org.openconcerto.openoffice.style.data.DataStyle;
import org.openconcerto.openoffice.text.ParagraphStyle;
import org.openconcerto.openoffice.text.TextStyle;
import org.openconcerto.utils.CollectionMap;
48,18 → 49,20
private static final Map<XMLVersion, Map<String, StyleDesc<?>>> elemName2Desc;
private static final Map<XMLVersion, Map<Class<? extends Style>, StyleDesc<?>>> class2Desc;
private static boolean descsLoaded = false;
private static final Map<XMLVersion, Map<Tuple2<String, String>, StyleDesc<?>>> attribute2Desc;
// need a CollectionMap e.g. [ "style:style", "style:data-style-name" ] ->
// DataStyle.DATA_STYLES_DESCS
private static final Map<XMLVersion, CollectionMap<Tuple2<String, String>, StyleDesc<?>>> attribute2Desc;
static {
final int versionsCount = XMLVersion.values().length;
family2Desc = new HashMap<XMLVersion, Map<String, StyleDesc<?>>>(versionsCount);
elemName2Desc = new HashMap<XMLVersion, Map<String, StyleDesc<?>>>(versionsCount);
class2Desc = new HashMap<XMLVersion, Map<Class<? extends Style>, StyleDesc<?>>>(versionsCount);
attribute2Desc = new HashMap<XMLVersion, Map<Tuple2<String, String>, StyleDesc<?>>>(versionsCount);
attribute2Desc = new HashMap<XMLVersion, CollectionMap<Tuple2<String, String>, StyleDesc<?>>>(versionsCount);
for (final XMLVersion v : XMLVersion.values()) {
family2Desc.put(v, new HashMap<String, StyleDesc<?>>());
elemName2Desc.put(v, new HashMap<String, StyleDesc<?>>());
class2Desc.put(v, new HashMap<Class<? extends Style>, StyleDesc<?>>());
attribute2Desc.put(v, new HashMap<Tuple2<String, String>, StyleDesc<?>>(128));
attribute2Desc.put(v, new CollectionMap<Tuple2<String, String>, StyleDesc<?>>(128));
}
}
 
73,6 → 76,8
registerAllVersions(TableStyle.DESC);
registerAllVersions(TextStyle.DESC);
registerAllVersions(ParagraphStyle.DESC);
for (final StyleDesc<?> d : DataStyle.DATA_STYLES_DESCS)
registerAllVersions(d);
register(GraphicStyle.DESC);
register(GraphicStyle.DESC_OO);
register(PageLayoutStyle.DESC);
128,8 → 133,8
* @param version the version.
* @return the mapping from attribute to description.
*/
private static Map<Tuple2<String, String>, StyleDesc<?>> getAttr2Desc(final XMLVersion version) {
final Map<Tuple2<String, String>, StyleDesc<?>> map = attribute2Desc.get(version);
private static CollectionMap<Tuple2<String, String>, StyleDesc<?>> getAttr2Desc(final XMLVersion version) {
final CollectionMap<Tuple2<String, String>, StyleDesc<?>> map = attribute2Desc.get(version);
if (map.isEmpty()) {
for (final StyleDesc<?> desc : getDesc(version)) {
fillMap(map, desc, desc.getRefElementsMap());
140,13 → 145,11
return map;
}
 
private static void fillMap(final Map<Tuple2<String, String>, StyleDesc<?>> map, final StyleDesc<?> desc, final CollectionMap<String, String> elemsByAttrs) {
private static void fillMap(final CollectionMap<Tuple2<String, String>, StyleDesc<?>> map, final StyleDesc<?> desc, final CollectionMap<String, String> elemsByAttrs) {
for (final Entry<String, Collection<String>> e : elemsByAttrs.entrySet()) {
for (final String elementName : e.getValue()) {
final Tuple2<String, String> key = Tuple2.create(elementName, e.getKey());
final StyleDesc<?> previous = map.put(key, desc);
if (previous != null)
throw new IllegalStateException("Duplicate desc for " + key + " : " + previous + " and " + desc);
map.put(key, desc);
}
}
}
195,12 → 198,24
* <code><style:page-layout style:name="pm1"></code>.
*/
public static Element getReferencedStyleElement(final ODPackage pkg, final Attribute styleAttr) {
final Style res = getReferencedStyle(pkg, styleAttr);
if (res != null)
return res.getElement();
else
return null;
}
 
public static Style getReferencedStyle(final ODPackage pkg, final Attribute styleAttr) {
if (styleAttr == null)
return null;
assert styleAttr.getDocument() == pkg.getDocument(RootElement.CONTENT.getZipEntry()) || styleAttr.getDocument() == pkg.getDocument(RootElement.STYLES.getZipEntry()) : "attribute not defined in either the content or the styles of "
+ pkg;
final StyleDesc<?> desc = getAttr2Desc(pkg.getVersion()).get(Tuple2.create(styleAttr.getParent().getQualifiedName(), styleAttr.getQualifiedName()));
if (desc != null) {
return pkg.getStyle(styleAttr.getDocument(), desc, styleAttr.getValue());
} else
final Collection<StyleDesc<?>> descs = getAttr2Desc(pkg.getVersion()).getNonNull(Tuple2.create(styleAttr.getParent().getQualifiedName(), styleAttr.getQualifiedName()));
for (final StyleDesc<?> desc : descs) {
final Element res = pkg.getStyle(styleAttr.getDocument(), desc, styleAttr.getValue());
if (res != null)
return desc.create(pkg, res);
}
return null;
}
 
208,6 → 223,10
return getStyleDesc(clazz, version, true);
}
 
public static <S extends StyleStyle> StyleStyleDesc<S> getStyleStyleDesc(Class<S> clazz, final XMLVersion version) {
return (StyleStyleDesc<S>) getStyleDesc(clazz, version);
}
 
@SuppressWarnings("unchecked")
private static <S extends Style> StyleDesc<S> getStyleDesc(Class<S> clazz, final XMLVersion version, final boolean mustExist) {
loadDescs();
257,13 → 276,21
this.name = this.getElement().getAttributeValue("name", this.getSTYLE());
this.ns = this.pkg.getFormatVersion();
this.desc = getNonNullStyleDesc(this.getClass(), this.ns.getXMLVersion(), styleElem, getName());
if (!this.desc.getElementName().equals(this.getElement().getName()))
throw new IllegalArgumentException("expected " + this.desc.getElementName() + " but got " + this.getElement().getName() + " for " + styleElem);
checkElemName();
// assert that styleElem is in pkg (and thus have the same version)
assert this.pkg.getXMLFile(getElement().getDocument()) != null;
assert this.pkg.getFormatVersion().equals(XMLFormatVersion.get(getElement().getDocument()));
}
 
protected void checkElemName() {
if (!this.desc.getElementName().equals(this.getElement().getName()))
throw new IllegalArgumentException("expected " + this.desc.getElementName() + " but got " + this.getElement().getName() + " for " + getElement());
}
 
protected final ODPackage getPackage() {
return this.pkg;
}
 
protected final Namespace getSTYLE() {
return this.getElement().getNamespace("style");
}
291,9 → 318,13
* @return the matching properties, eg &lt;text-properties&gt;.
*/
public final Element getFormattingProperties(final String family) {
return getFormattingProperties(family, true);
}
 
public final Element getFormattingProperties(final String family, final boolean create) {
final Element elem = this.ns.getXML().createFormattingProperties(family);
Element res = this.getElement().getChild(elem.getName(), elem.getNamespace());
if (res == null) {
if (res == null && create) {
res = elem;
this.getElement().addContent(res);
}
352,6 → 383,8
final ODXMLDocument xmlFile = this.pkg.getXMLFile(this.getElement().getDocument());
final String unusedName = xmlFile.findUnusedName(this.desc, this.desc.getBaseName());
final Element clone = (Element) this.getElement().clone();
// needed if this is a default-style
clone.setName(this.desc.getElementName());
clone.setAttribute("name", unusedName, this.getSTYLE());
JDOMUtils.insertAfter(this.getElement(), singleton(clone));
return this.desc.create(this.pkg, clone);
/trunk/OpenConcerto/src/org/openconcerto/openoffice/text/TextStyle.java
16,6 → 16,7
import static java.util.Arrays.asList;
import org.openconcerto.openoffice.ODPackage;
import org.openconcerto.openoffice.OOUtils;
import org.openconcerto.openoffice.Style;
import org.openconcerto.openoffice.StyleProperties;
import org.openconcerto.openoffice.StyleStyle;
import org.openconcerto.openoffice.StyleStyleDesc;
64,12 → 65,12
// cf style-text-properties-content-strict in the relaxNG
public static class StyleTextProperties extends StyleProperties {
 
public StyleTextProperties(StyleStyle style) {
public StyleTextProperties(Style style) {
super(style, DESC.getFamily());
}
 
public final Color getColor() {
return OOUtils.decodeRGB(this.getElement().getAttributeValue("color", this.getNS("fo")));
return OOUtils.decodeRGB(this.getAttributeValue("color", this.getNS("fo")));
}
 
public final void setColor(Color color) {
77,19 → 78,19
}
 
public final String getFontName() {
return this.getElement().getAttributeValue("font-name", this.getElement().getNamespace("style"));
return this.getAttributeValue("font-name", this.getElement().getNamespace("style"));
}
 
public final String getLanguage() {
return this.getElement().getAttributeValue("language", this.getNS("fo"));
return this.getAttributeValue("language", this.getNS("fo"));
}
 
public final String getCountry() {
return this.getElement().getAttributeValue("country", this.getNS("fo"));
return this.getAttributeValue("country", this.getNS("fo"));
}
 
public final String getWeight() {
return this.getElement().getAttributeValue("font-weight", this.getNS("fo"));
return this.getAttributeValue("font-weight", this.getNS("fo"));
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/text/ParagraphStyle.java
78,7 → 78,7
}
 
public final String getAlignment() {
return getElement().getAttributeValue("text-align", this.getNS("fo"));
return getAttributeValue("text-align", this.getNS("fo"));
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/text/Heading.java
13,6 → 13,7
package org.openconcerto.openoffice.text;
 
import org.openconcerto.openoffice.StyleProperties;
import org.openconcerto.openoffice.XMLVersion;
 
import org.jdom.Element;
39,7 → 40,7
public final int getLevel() {
final String attr = this.getElement().getAttributeValue("outline-level", this.getElement().getNamespace());
// see 4.1.1
return attr == null ? 1 : Integer.parseInt(attr);
return StyleProperties.parseInt(attr, 1);
}
 
public final void setLevel(int level) {
/trunk/OpenConcerto/src/org/openconcerto/openoffice/XMLVersion.java
33,7 → 33,6
this.putMandatory(OFFICE_1, STYLE_1, TEXT_1, TABLE_1);
this.put("number", NUMBER_1);
this.put("draw", DRAW_1);
this.put("number", NUMBER_1);
this.put("fo", FO_1);
this.put("form", "http://openoffice.org/2000/form");
this.put("xlink", "http://www.w3.org/1999/xlink");
49,7 → 48,6
this.putMandatory(OFFICE_2, STYLE_2, TEXT_2, TABLE_2);
this.put("number", NUMBER_2);
this.put("draw", DRAW_2);
this.put("number", NUMBER_2);
this.put("fo", FO_2);
this.put("form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0");
this.put("xlink", "http://www.w3.org/1999/xlink");
/trunk/OpenConcerto/src/org/openconcerto/openoffice/ODPackage.java
360,6 → 360,21
return null;
}
 
/**
* The XML document where are located the common styles.
*
* @return the document where are located styles.
*/
public final ODXMLDocument getStyles() {
final ODXMLDocument res;
if (this.isSingle())
res = this.getContent();
else {
res = this.getXMLFile(STYLES.getZipEntry());
}
return res;
}
 
public final ODXMLDocument getContent() {
return this.getXMLFile(CONTENT.getZipEntry());
}
427,6 → 442,11
return res;
}
 
public final Element getDefaultStyle(final StyleStyleDesc<?> desc) {
// from 16.4 of OpenDocument-v1.2-cs01-part1, default-style only usable in office:styles
return getStyles().getDefaultStyle(desc);
}
 
// *** setter
 
public void putFile(String entry, Object data) {
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/PageLayoutStyle.java
99,7 → 99,7
}
 
private final BigDecimal getLengthAttr(final String attrName, final String attrNS, final LengthUnit in) {
return LengthUnit.parseLength(getElement().getAttributeValue(attrName, this.getNS(attrNS)), in);
return LengthUnit.parseLength(getAttributeValue(attrName, this.getNS(attrNS)), in);
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/SideStyleProperties.java
69,12 → 69,12
}
 
protected final String getSideAttribute(final Side s, final String attrName, final Namespace ns) {
final String allBorder = getElement().getAttributeValue(attrName, ns);
final String allBorder = getAttributeValue(attrName, ns);
final String res;
if (allBorder != null)
res = allBorder;
else
res = getElement().getAttributeValue(attrName + "-" + s.name().toLowerCase(), ns);
res = getAttributeValue(attrName + "-" + s.name().toLowerCase(), ns);
return res;
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/TimeStyle.java
New file
0,0 → 1,43
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.openoffice.style.data;
 
import org.openconcerto.openoffice.ODPackage;
import org.openconcerto.openoffice.XMLVersion;
import org.openconcerto.openoffice.spreadsheet.CellStyle;
 
import javax.xml.datatype.Duration;
 
import org.jdom.Element;
 
// from section 16.27.18 in v1.2-cs01-part1
public class TimeStyle extends DataStyle {
 
public static final DataStyleDesc<TimeStyle> DESC = new DataStyleDesc<TimeStyle>(TimeStyle.class, XMLVersion.OD, "time-style", "N") {
@Override
public TimeStyle create(ODPackage pkg, Element e) {
return new TimeStyle(pkg, e);
}
};
 
public TimeStyle(final ODPackage pkg, Element elem) {
super(pkg, elem, Duration.class);
}
 
@Override
public String format(Object o, CellStyle defaultStyle, boolean lenient) {
// TODO time
throw new UnsupportedOperationException(DESC.getElementName() + " unsupported");
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/BooleanStyle.java
New file
0,0 → 1,58
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.openoffice.style.data;
 
import org.openconcerto.openoffice.ODPackage;
import org.openconcerto.openoffice.XMLVersion;
import org.openconcerto.openoffice.spreadsheet.CellStyle;
 
import java.util.List;
 
import org.jdom.Element;
import org.jdom.Namespace;
 
// from section 16.27.23 in v1.2-cs01-part1
public class BooleanStyle extends DataStyle {
 
public static final DataStyleDesc<BooleanStyle> DESC = new DataStyleDesc<BooleanStyle>(BooleanStyle.class, XMLVersion.OD, "boolean-style", "N") {
@Override
public BooleanStyle create(ODPackage pkg, Element e) {
return new BooleanStyle(pkg, e);
}
};
 
public BooleanStyle(final ODPackage pkg, Element elem) {
super(pkg, elem, Boolean.class);
}
 
@Override
public String format(Object o, CellStyle defaultStyle, boolean lenient) {
final Namespace numberNS = this.getElement().getNamespace();
final StringBuilder sb = new StringBuilder();
@SuppressWarnings("unchecked")
final List<Element> children = this.getElement().getChildren();
for (final Element elem : children) {
if (elem.getNamespace().equals(numberNS)) {
if (elem.getName().equals("text")) {
sb.append(elem.getText());
} else if (elem.getName().equals("boolean")) {
// TODO localize
reportError("Boolean not localized", lenient);
sb.append(o.toString());
}
}
}
return sb.toString();
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/PercentStyle.java
New file
0,0 → 1,57
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.openoffice.style.data;
 
import org.openconcerto.openoffice.ODPackage;
import org.openconcerto.openoffice.XMLVersion;
import org.openconcerto.openoffice.spreadsheet.CellStyle;
 
import java.util.List;
 
import org.jdom.Element;
import org.jdom.Namespace;
 
// from section 16.27.9 in v1.2-cs01-part1
public class PercentStyle extends DataStyle {
 
public static final DataStyleDesc<PercentStyle> DESC = new DataStyleDesc<PercentStyle>(PercentStyle.class, XMLVersion.OD, "percentage-style", "N") {
@Override
public PercentStyle create(ODPackage pkg, Element e) {
return new PercentStyle(pkg, e);
}
};
 
public PercentStyle(final ODPackage pkg, Element elem) {
super(pkg, elem, Number.class);
}
 
@Override
public String format(Object o, CellStyle defaultStyle, boolean lenient) {
final Number n = (Number) o;
final Namespace numberNS = this.getElement().getNamespace();
final StringBuilder sb = new StringBuilder();
@SuppressWarnings("unchecked")
final List<Element> children = this.getElement().getChildren();
for (final Element elem : children) {
if (elem.getNamespace().equals(numberNS)) {
if (elem.getName().equals("text")) {
sb.append(elem.getText());
} else if (elem.getName().equals("number")) {
sb.append(formatNumberOrScientificNumber(elem, n, 100, defaultStyle));
}
}
}
return sb.toString();
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/TextStyle.java
New file
0,0 → 1,56
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.openoffice.style.data;
 
import org.openconcerto.openoffice.ODPackage;
import org.openconcerto.openoffice.XMLVersion;
import org.openconcerto.openoffice.spreadsheet.CellStyle;
 
import java.util.List;
 
import org.jdom.Element;
import org.jdom.Namespace;
 
// from section 16.27.25 in v1.2-cs01-part1
public class TextStyle extends DataStyle {
 
public static final DataStyleDesc<TextStyle> DESC = new DataStyleDesc<TextStyle>(TextStyle.class, XMLVersion.OD, "text-style", "N") {
@Override
public TextStyle create(ODPackage pkg, Element e) {
return new TextStyle(pkg, e);
}
};
 
public TextStyle(final ODPackage pkg, Element elem) {
super(pkg, elem, Object.class);
}
 
@Override
public String format(Object o, CellStyle defaultStyle, boolean lenient) {
final Namespace numberNS = this.getElement().getNamespace();
final StringBuilder sb = new StringBuilder();
@SuppressWarnings("unchecked")
final List<Element> children = this.getElement().getChildren();
for (final Element elem : children) {
if (elem.getNamespace().equals(numberNS)) {
if (elem.getName().equals("text")) {
sb.append(elem.getText());
} else if (elem.getName().equals("text-content")) {
sb.append(o.toString());
}
}
}
return sb.toString();
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/NumberStyle.java
New file
0,0 → 1,62
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.openoffice.style.data;
 
import org.openconcerto.openoffice.ODPackage;
import org.openconcerto.openoffice.XMLVersion;
import org.openconcerto.openoffice.spreadsheet.CellStyle;
import org.openconcerto.openoffice.spreadsheet.MutableCell;
 
import java.util.List;
 
import org.jdom.Element;
import org.jdom.Namespace;
 
// from section 16.27.2 in v1.2-cs01-part1
public class NumberStyle extends DataStyle {
 
public static final DataStyleDesc<NumberStyle> DESC = new DataStyleDesc<NumberStyle>(NumberStyle.class, XMLVersion.OD, "number-style", "N") {
@Override
public NumberStyle create(ODPackage pkg, Element e) {
return new NumberStyle(pkg, e);
}
};
 
public NumberStyle(final ODPackage pkg, Element elem) {
super(pkg, elem, Number.class);
}
 
@Override
public String format(Object o, CellStyle defaultStyle, boolean lenient) {
final Number n = (Number) o;
final Namespace numberNS = this.getElement().getNamespace();
final StringBuilder sb = new StringBuilder();
@SuppressWarnings("unchecked")
final List<Element> children = this.getElement().getChildren();
for (final Element elem : children) {
if (elem.getNamespace().equals(numberNS)) {
if (elem.getName().equals("text")) {
sb.append(elem.getText());
} else if (elem.getName().equals("number") || elem.getName().equals("scientific-number")) {
sb.append(formatNumberOrScientificNumber(elem, n, defaultStyle));
} else if (elem.getName().equals("fraction")) {
// TODO fractions
reportError("Fractions not supported", lenient);
sb.append(MutableCell.formatNumber(n, defaultStyle));
}
}
}
return sb.toString();
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/DataStyle.java
New file
0,0 → 1,207
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.openoffice.style.data;
 
import org.openconcerto.openoffice.Log;
import org.openconcerto.openoffice.ODPackage;
import org.openconcerto.openoffice.Style;
import org.openconcerto.openoffice.StyleDesc;
import org.openconcerto.openoffice.StyleProperties;
import org.openconcerto.openoffice.XMLVersion;
import org.openconcerto.openoffice.spreadsheet.CellStyle;
import org.openconcerto.openoffice.text.TextStyle.StyleTextProperties;
import org.openconcerto.utils.NumberUtils;
 
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
import org.jdom.Attribute;
import org.jdom.Element;
import org.jdom.Namespace;
 
// from section 16.27 in v1.2-cs01-part1
public abstract class DataStyle extends Style {
private static final int DEFAULT_GROUPING_SIZE = new DecimalFormat().getGroupingSize();
private static final int DEFAULT_DECIMAL_PLACES = 2;
private static final Pattern QUOTE_PATRN = Pattern.compile("'", Pattern.LITERAL);
private static final Pattern EXP_PATTERN = Pattern.compile("E(\\d+)$");
 
public static int getDecimalPlaces(final CellStyle defaultStyle) {
final int res;
if (defaultStyle != null && defaultStyle.getTableCellProperties().getDecimalPlaces() != null)
res = defaultStyle.getTableCellProperties().getDecimalPlaces().intValue();
else
res = DEFAULT_DECIMAL_PLACES;
return res;
}
 
public static void addStringLiteral(final StringBuilder formatSB, final String s) {
formatSB.append('\'');
formatSB.append(QUOTE_PATRN.matcher(s).replaceAll("''"));
formatSB.append('\'');
}
 
public static final DataStyleDesc<?>[] DATA_STYLES_DESCS = new DataStyleDesc<?>[] { NumberStyle.DESC, PercentStyle.DESC, TextStyle.DESC, CurrencyStyle.DESC, DateStyle.DESC, TimeStyle.DESC,
BooleanStyle.DESC };
 
public static abstract class DataStyleDesc<S extends DataStyle> extends StyleDesc<S> {
 
protected DataStyleDesc(Class<S> clazz, XMLVersion version, String elemName, String baseName) {
super(clazz, version, elemName, baseName);
this.setElementNS(getVersion().getNS("number"));
// from 19.469 in v1.2-cs01-part1
this.getRefElementsMap().putAll(
"style:data-style-name",
Arrays.asList("presentation:date-time-decl", "style:style", "text:creation-date", "text:creation-time", "text:database-display", "text:date", "text:editing-duration",
"text:expression", "text:meta-field", "text:modification-date", "text:modification-time", "text:print-date", "text:print-time", "text:table-formula", "text:time",
"text:user-defined", "text:user-field-get", "text:user-field-input", "text:variable-get", "text:variable-input", "text:variable-set"));
}
}
 
// type accepted by #format()
private final Class<?> type;
private StyleTextProperties textProps;
 
protected DataStyle(final ODPackage pkg, Element elem, final Class<?> type) {
super(pkg, elem);
this.type = type;
}
 
protected final Class<?> getDataType() {
return this.type;
}
 
public final boolean canFormat(Class<?> toFormat) {
return this.getDataType().isAssignableFrom(toFormat);
}
 
public final String getTitle() {
return this.getElement().getAttributeValue("title", getElement().getNamespace());
}
 
public final StyleTextProperties getTextProperties() {
if (this.textProps == null)
this.textProps = new StyleTextProperties(this);
return this.textProps;
}
 
public abstract String format(final Object o, final CellStyle defaultStyle, boolean lenient) throws UnsupportedOperationException;
 
protected final void reportError(String msg, boolean lenient) throws UnsupportedOperationException {
if (lenient)
Log.get().warning(msg);
else
throw new UnsupportedOperationException(msg);
}
 
protected final String formatNumberOrScientificNumber(final Element elem, final Number n, CellStyle defaultStyle) {
return this.formatNumberOrScientificNumber(elem, n, 1, defaultStyle);
}
 
protected final String formatNumberOrScientificNumber(final Element elem, final Number n, final int multiplier, CellStyle defaultStyle) {
final Namespace numberNS = this.getElement().getNamespace();
final StringBuilder numberSB = new StringBuilder();
 
final List<?> embeddedTexts = elem.getChildren("embedded-text", numberNS);
final SortedMap<Integer, String> embeddedTextByPosition = new TreeMap<Integer, String>(Collections.reverseOrder());
for (final Object o : embeddedTexts) {
final Element embeddedText = (Element) o;
embeddedTextByPosition.put(Integer.valueOf(embeddedText.getAttributeValue("position", numberNS)), embeddedText.getText());
}
 
final Attribute factorAttr = elem.getAttribute("display-factor", numberNS);
final double factor = (factorAttr != null ? Double.valueOf(factorAttr.getValue()) : 1) / multiplier;
 
// default value from 19.348
final boolean grouping = StyleProperties.parseBoolean(elem.getAttributeValue("grouping", numberNS), false);
 
final String minIntDigitsAttr = elem.getAttributeValue("min-integer-digits", numberNS);
final int minIntDig = minIntDigitsAttr == null ? 0 : Integer.parseInt(minIntDigitsAttr);
if (minIntDig == 0) {
numberSB.append('#');
} else {
for (int i = 0; i < minIntDig; i++)
numberSB.append('0');
}
 
// e.g. if it's "--", 12,3 is displayed "12,3" and 12 is displayed "12,--"
final String decReplacement = elem.getAttributeValue("decimal-replacement", numberNS);
final boolean decSeparatorAlwaysShown;
if (decReplacement != null && !NumberUtils.hasFractionalPart(n)) {
decSeparatorAlwaysShown = true;
numberSB.append('.');
// escape quote in replacement
addStringLiteral(numberSB, decReplacement);
} else {
decSeparatorAlwaysShown = false;
// see 19.343.2
final Attribute decPlacesAttr = elem.getAttribute("decimal-places", numberNS);
final int decPlaces;
if (decPlacesAttr != null)
decPlaces = Integer.parseInt(decPlacesAttr.getValue());
else
decPlaces = getDecimalPlaces(defaultStyle);
 
if (decPlaces > 0) {
numberSB.append('.');
for (int i = 0; i < decPlaces; i++)
numberSB.append('0');
}
}
 
final Attribute minExpAttr = elem.getAttribute("min-exponent-digits", numberNS);
if (minExpAttr != null) {
numberSB.append('E');
for (int i = 0; i < Integer.parseInt(minExpAttr.getValue()); i++)
numberSB.append('0');
}
 
final DecimalFormat decFormat = new DecimalFormat(numberSB.toString());
// Java always use HALF_EVEN
decFormat.setRoundingMode(RoundingMode.HALF_UP);
decFormat.setGroupingUsed(grouping);
// needed since the default size is overwritten by the pattern
decFormat.setGroupingSize(DEFAULT_GROUPING_SIZE);
decFormat.setDecimalSeparatorAlwaysShown(decSeparatorAlwaysShown);
String res = decFormat.format(NumberUtils.divide(n, factor));
// java only puts the minus sign, OO also puts the plus sign
if (minExpAttr != null) {
final Matcher m = EXP_PATTERN.matcher(res);
if (m.find())
res = res.substring(0, m.start()) + "E+" + m.group(1);
}
if (embeddedTextByPosition.size() > 0) {
final int intDigits = Math.max(minIntDig, NumberUtils.intDigits(n));
// each time we insert text the decimal point moves
int offset = 0;
// sorted descending to avoid overwriting
for (Entry<Integer, String> e : embeddedTextByPosition.entrySet()) {
final String embeddedText = e.getValue();
// the text will be before this index
final int index = Math.max(0, offset + intDigits - e.getKey().intValue());
res = res.substring(0, index) + embeddedText + res.substring(index);
offset += embeddedText.length();
}
}
return res;
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/CurrencyStyle.java
New file
0,0 → 1,67
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.openoffice.style.data;
 
import org.openconcerto.openoffice.ODPackage;
import org.openconcerto.openoffice.XMLVersion;
import org.openconcerto.openoffice.spreadsheet.CellStyle;
 
import java.text.DecimalFormatSymbols;
import java.util.List;
 
import org.jdom.Element;
import org.jdom.Namespace;
 
// from section 16.27.7 in v1.2-cs01-part1
public class CurrencyStyle extends DataStyle {
 
public static final DataStyleDesc<CurrencyStyle> DESC = new DataStyleDesc<CurrencyStyle>(CurrencyStyle.class, XMLVersion.OD, "currency-style", "N") {
@Override
public CurrencyStyle create(ODPackage pkg, Element e) {
return new CurrencyStyle(pkg, e);
}
};
 
public CurrencyStyle(final ODPackage pkg, Element elem) {
super(pkg, elem, Number.class);
}
 
@Override
public String format(Object o, CellStyle defaultStyle, boolean lenient) {
final Number n = (Number) o;
final Namespace numberNS = this.getElement().getNamespace();
final StringBuilder sb = new StringBuilder();
@SuppressWarnings("unchecked")
final List<Element> children = this.getElement().getChildren();
for (final Element elem : children) {
if (elem.getNamespace().equals(numberNS)) {
if (elem.getName().equals("text")) {
sb.append(elem.getText());
} else if (elem.getName().equals("number")) {
// ATTN OpenOffice Fix (it generates <text>-</text>, so we have to use the
// absolute value)
final int multiplier = n.doubleValue() > 0 ? 1 : -1;
sb.append(formatNumberOrScientificNumber(elem, n, multiplier, defaultStyle));
} else if (elem.getName().equals("currency-symbol")) {
if (elem.getTextTrim().length() > 0) {
sb.append(elem.getText());
} else {
sb.append(new DecimalFormatSymbols(DateStyle.getLocale(elem)).getCurrencySymbol());
}
}
}
}
return sb.toString();
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/DateStyle.java
New file
0,0 → 1,179
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.openoffice.style.data;
 
import org.openconcerto.openoffice.ODPackage;
import org.openconcerto.openoffice.StyleProperties;
import org.openconcerto.openoffice.XMLVersion;
import org.openconcerto.openoffice.spreadsheet.CellStyle;
 
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
 
import org.jdom.Attribute;
import org.jdom.Element;
import org.jdom.Namespace;
 
// from section 16.27.10 in v1.2-cs01-part1
public class DateStyle extends DataStyle {
 
// see http://download.oracle.com/javase/6/docs/technotes/guides/intl/calendar.doc.html
private static final Locale BUDDHIST_LOCALE = new Locale("th", "TH");
private static final Locale JAPANESE_LOCALE = new Locale("ja", "JP", "JP");
private static final Locale GREGORIAN_LOCALE = new Locale("fr", "FR");
 
public static final DataStyleDesc<DateStyle> DESC = new DataStyleDesc<DateStyle>(DateStyle.class, XMLVersion.OD, "date-style", "N") {
@Override
public DateStyle create(ODPackage pkg, Element e) {
return new DateStyle(pkg, e);
}
};
 
private static final boolean isShort(final Element elem) {
return "short".equals(elem.getAttributeValue("style", elem.getNamespace("number")));
}
 
public static final Locale getLocale(final Element elem) {
final Locale res;
final String country = elem.getAttributeValue("country", elem.getNamespace());
final String lang = elem.getAttributeValue("language", elem.getNamespace());
if (lang != null) {
res = new Locale(lang, country == null ? "" : country);
} else {
res = Locale.getDefault();
}
return res;
}
 
private static final Locale getCalendarLocale(final Element elem, Locale defaultLocale) {
final Locale res;
final String cal = elem.getAttributeValue("calendar", elem.getNamespace());
if (cal == null) {
res = defaultLocale;
} else if ("buddhist".equals(cal)) {
res = BUDDHIST_LOCALE;
} else if ("gengou".equals(cal)) {
res = JAPANESE_LOCALE;
} else if ("gregorian".equals(cal)) {
res = GREGORIAN_LOCALE;
} else {
throw new IllegalArgumentException("Unsupported calendar : " + cal);
}
return res;
}
 
private static final Locale getCalendarLocale(final Locale locale) {
final Locale res;
if (locale.equals(BUDDHIST_LOCALE) || locale.equals(JAPANESE_LOCALE)) {
res = locale;
} else {
res = GREGORIAN_LOCALE;
}
return res;
}
 
public DateStyle(final ODPackage pkg, Element elem) {
super(pkg, elem, Date.class);
}
 
@Override
public String format(Object o, CellStyle defaultStyle, boolean lenient) {
final Date d = o instanceof Calendar ? ((Calendar) o).getTime() : (Date) o;
final Namespace numberNS = this.getElement().getNamespace();
final Locale styleLocale = getLocale(getElement());
final Locale styleCalendarLocale = getCalendarLocale(styleLocale);
final StringBuilder res = new StringBuilder();
 
Locale currentCalendarLocale = styleCalendarLocale;
final StringBuilder sb = new StringBuilder();
 
@SuppressWarnings("unchecked")
final List<Element> children = this.getElement().getChildren();
for (final Element elem : children) {
if (elem.getNamespace().equals(numberNS)) {
final Locale calendarLocaleElem = getCalendarLocale(elem, styleCalendarLocale);
if (!calendarLocaleElem.equals(currentCalendarLocale)) {
if (sb.length() > 0) {
res.append(new SimpleDateFormat(sb.toString(), currentCalendarLocale).format(d));
sb.setLength(0);
}
currentCalendarLocale = calendarLocaleElem;
}
 
if (elem.getName().equals("text")) {
DataStyle.addStringLiteral(sb, elem.getText());
} else if (elem.getName().equals("era")) {
sb.append(isShort(elem) ? "G" : "GGGG");
} else if (elem.getName().equals("year")) {
sb.append(isShort(elem) ? "yy" : "yyyy");
} else if (elem.getName().equals("quarter")) {
final int quarter = Calendar.getInstance(GREGORIAN_LOCALE).get(Calendar.MONTH) / 3 + 1;
// TODO localize and honor short/long style
reportError("Quarters are not localized", lenient);
DataStyle.addStringLiteral(sb, isShort(elem) ? "Q" + quarter : "Q" + quarter);
} else if (elem.getName().equals("month")) {
final Attribute possessive = elem.getAttribute("possessive-form", numberNS);
if (possessive != null)
reportError("Ignoring " + possessive, lenient);
if (!StyleProperties.parseBoolean(elem.getAttributeValue("textual", numberNS), false))
sb.append(isShort(elem) ? "M" : "MM");
else
sb.append(isShort(elem) ? "MMM" : "MMMM");
} else if (elem.getName().equals("week-of-year")) {
sb.append("w");
} else if (elem.getName().equals("day")) {
sb.append(isShort(elem) ? "d" : "dd");
} else if (elem.getName().equals("day-of-week")) {
sb.append(isShort(elem) ? "E" : "EEEE");
} else if (elem.getName().equals("am-pm")) {
sb.append("a");
} else if (elem.getName().equals("hours")) {
// see 16.27.22 : If a <number:am-pm> element is contained in a date or time
// style, hours are displayed using values from 1 to 12 only.
if (getElement().getChild("am-pm", numberNS) == null)
sb.append(isShort(elem) ? "H" : "HH");
else
sb.append(isShort(elem) ? "h" : "hh");
} else if (elem.getName().equals("minutes")) {
sb.append(isShort(elem) ? "m" : "mm");
} else if (elem.getName().equals("seconds")) {
sb.append(isShort(elem) ? "s" : "ss");
final int decPlaces = StyleProperties.parseInt(elem.getAttributeValue("decimal-places", numberNS), 0);
if (decPlaces > 0) {
// use styleLocale since <seconds> hasn't @calendar
final Calendar cal = Calendar.getInstance(styleLocale);
cal.setTime(d);
final DecimalFormat decFormat = new DecimalFormat();
decFormat.setDecimalFormatSymbols(new DecimalFormatSymbols(styleLocale));
decFormat.setMinimumIntegerDigits(0);
decFormat.setMinimumFractionDigits(decPlaces);
decFormat.setMaximumFractionDigits(decPlaces);
final BigDecimal secondFractions = new BigDecimal(cal.get(Calendar.MILLISECOND)).movePointLeft(3);
assert secondFractions.compareTo(BigDecimal.ONE) < 0;
// .12 or .578
final String fractionPart = decFormat.format(secondFractions);
DataStyle.addStringLiteral(sb, fractionPart);
}
}
}
}
return new SimpleDateFormat(sb.toString(), currentCalendarLocale).format(d);
}
}
/trunk/OpenConcerto/src/org/openconcerto/openoffice/ODXMLDocument.java
218,12 → 218,12
// " | ./office:master-styles/style:master-page/" + stylePath);
final Element root = this.getDocument().getRootElement();
final Namespace office = getVersion().getOFFICE();
Element res = this.findStyleChild(root.getChild("styles", office), styleDesc.getElementName(), family, name);
Element res = this.findStyleChild(root.getChild("styles", office), styleDesc.getElementNS(), styleDesc.getElementName(), family, name);
if (res != null) {
return res;
}
 
res = this.findStyleChild(root.getChild("automatic-styles", office), styleDesc.getElementName(), family, name);
res = this.findStyleChild(root.getChild("automatic-styles", office), styleDesc.getElementNS(), styleDesc.getElementName(), family, name);
if (res != null) {
return res;
}
230,7 → 230,7
 
final Element masterStyles = root.getChild("master-styles", office);
if (masterStyles != null) {
res = this.findStyleChild(root.getChild("master-page", getVersion().getSTYLE()), styleDesc.getElementName(), family, name);
res = this.findStyleChild(root.getChild("master-page", getVersion().getSTYLE()), styleDesc.getElementNS(), styleDesc.getElementName(), family, name);
if (res != null) {
return res;
}
239,16 → 239,22
return null;
}
 
private final Element findStyleChild(final Element styles, final String elemName, final String family, final String name) {
public final Element getDefaultStyle(final StyleStyleDesc<?> styleDesc) {
final Element root = this.getDocument().getRootElement();
final Namespace office = getVersion().getOFFICE();
return this.findStyleChild(root.getChild("styles", office), styleDesc.getElementNS(), StyleStyleDesc.ELEMENT_DEFAULT_NAME, styleDesc.getFamily(), null);
}
 
private final Element findStyleChild(final Element styles, final Namespace elemNS, final String elemName, final String family, final String name) {
if (styles == null)
return null;
 
final Namespace styleNS = getVersion().getSTYLE();
// from JDOM : traversal through the List is best done with a Iterator
for (final Object o : styles.getChildren(elemName, styleNS)) {
for (final Object o : styles.getChildren(elemName, elemNS)) {
final Element styleElem = (Element) o;
// name first since it is more specific (and often includes family, eg "co2")
if (name.equals(styleElem.getAttributeValue("name", styleNS)) && (family == null || family.equals(StyleStyleDesc.getFamily(styleElem)))) {
if ((name == null || name.equals(styleElem.getAttributeValue("name", styleNS))) && (family == null || family.equals(StyleStyleDesc.getFamily(styleElem)))) {
return styleElem;
}
}
/trunk/OpenConcerto/src/org/openconcerto/ui/JTime.java
15,9 → 15,11
 
import org.openconcerto.ui.component.text.TextComponent;
import org.openconcerto.ui.valuewrapper.ValueWrapper;
import org.openconcerto.utils.checks.ValidChangeSupport;
import org.openconcerto.utils.checks.ValidListener;
 
import java.awt.BorderLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.SimpleDateFormat;
import java.util.Calendar;
64,6 → 66,7
 
private final boolean fillWithCurrentTime;
private final JFormattedTextField text;
private final ValidChangeSupport validSupp;
 
/**
* Create the component, empty.
79,10 → 82,14
* else empty.
*/
public JTime(final boolean fillWithCurrentTime) {
this(fillWithCurrentTime, false);
}
 
public JTime(final boolean fillWithCurrentTime, final boolean withSeconds) {
super(new BorderLayout());
this.fillWithCurrentTime = fillWithCurrentTime;
 
final DateFormatter formatter = new DateFormatter(new SimpleDateFormat("HH:mm"));
final DateFormatter formatter = new DateFormatter(new SimpleDateFormat(withSeconds ? "HH:mm:ss" : "HH:mm"));
formatter.setOverwriteMode(true);
// don't setAllowsInvalid(false) otherwise we can't replace 07:00 by 21:00
formatter.setMaximum(dateFromTimeInMillis(DAY_LENGTH - 1));
90,6 → 97,15
this.text = new JFormattedTextField(formatter);
this.add(this.text, BorderLayout.CENTER);
 
this.text.addPropertyChangeListener("editValid", new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
setValidated((Boolean) evt.getNewValue());
}
});
// initial value
this.validSupp = new ValidChangeSupport(this, this.text.isEditValid());
 
this.resetValue();
}
 
158,19 → 174,23
return this;
}
 
protected final void setValidated(boolean newValue) {
this.validSupp.fireValidChange(newValue);
}
 
@Override
public boolean isValidated() {
return true;
return this.validSupp.getValidState();
}
 
@Override
public void addValidListener(ValidListener l) {
// nothing to do
this.validSupp.addValidListener(l);
}
 
@Override
public void removeValidListener(ValidListener l) {
// nothing to do
this.validSupp.removeValidListener(l);
}
 
@Override
/trunk/OpenConcerto/src/org/openconcerto/ui/preferences/AbstractProps.java
99,14 → 99,13
return "";
}
 
public int getIntProperty(String name) {
public final int getIntProperty(String name) {
return getIntProperty(name, getDefautIntValue());
}
 
public final int getIntProperty(String name, int defaultVal) {
final String property = this.getProperty(name);
int result;
if (property == null)
result = getDefautIntValue();
else
result = Integer.valueOf(property).intValue();
return result;
return property == null ? defaultVal : Integer.valueOf(property).intValue();
}
 
protected int getDefautIntValue() {
/trunk/OpenConcerto/src/org/openconcerto/ui/AutoHideTabbedPane.java
New file
0,0 → 1,157
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.ui;
 
import org.openconcerto.utils.Tuple2;
import org.openconcerto.utils.cc.IClosure;
 
import java.awt.Component;
import java.awt.Container;
import java.awt.GridLayout;
import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.Map;
 
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
 
/**
* A component like {@link JTabbedPane} but hiding the tab bar when there's only one tab.
*
* @author Sylvain CUAZ
*/
public class AutoHideTabbedPane extends JPanel {
 
private static final String TITLE_PROP = AutoHideTabbedPane.class.getName() + " title prop";
private static final String ICON_PROP = AutoHideTabbedPane.class.getName() + " icon prop";
private static final String TOOLTIP_PROP = AutoHideTabbedPane.class.getName() + " tooltip prop";
 
private final JTabbedPane tabbedPane;
// can't use putClientProperty() since we can't retrieve it from JTabbedPane
private final Map<JComponent, IClosure<Tuple2<JTabbedPane, Integer>>> customizers;
 
public AutoHideTabbedPane() {
this(new JTabbedPane());
}
 
public AutoHideTabbedPane(final JTabbedPane tabbedPane) {
this.tabbedPane = tabbedPane;
this.customizers = new IdentityHashMap<JComponent, IClosure<Tuple2<JTabbedPane, Integer>>>();
this.setLayout(new GridLayout(1, 1));
}
 
public final void addTab(final String title, final JComponent comp) {
insertTab(title, null, comp, null, -1);
}
 
/**
* Insert a tab at the specified index.
*
* @param title the title to be displayed in this tab.
* @param icon the icon to be displayed in this tab, can be <code>null</code>.
* @param component the component to be displayed when this tab is clicked.
* @param tip the tooltip to be displayed for this tab, can be <code>null</code>.
* @param index the position to insert this new tab, -1 meaning at the end.
*/
public final void insertTab(String title, Icon icon, JComponent comp, String tip, final int index) {
this.insertTab(title, icon, comp, tip, index, null);
}
 
public final void insertTab(String title, Icon icon, JComponent comp, String tip, final int index, final IClosure<Tuple2<JTabbedPane, Integer>> customize) {
this.customizers.put(comp, customize);
if (getComponentCount() == 0) {
putClientProps(title, icon, comp, tip);
this.add(comp);
} else {
JTabbedPane tabbedPane = this.getDisplayedTabbedPane();
// if there was no tabbedPane move the current component to it
if (tabbedPane == null) {
final JComponent onlyComp = (JComponent) this.getComponent(0);
this.remove(0);
tabbedPane = this.tabbedPane;
tabbedPane.addTab((String) onlyComp.getClientProperty(TITLE_PROP), (Icon) onlyComp.getClientProperty(ICON_PROP), onlyComp, (String) onlyComp.getClientProperty(TOOLTIP_PROP));
final IClosure<Tuple2<JTabbedPane, Integer>> closure = this.customizers.get(onlyComp);
if (closure != null)
closure.executeChecked(Tuple2.create(tabbedPane, 0));
this.add(tabbedPane);
assert tabbedPane == this.getDisplayedTabbedPane();
}
final int realIndex = index < 0 ? tabbedPane.getTabCount() : index;
tabbedPane.insertTab(title, icon, comp, tip, realIndex);
if (customize != null)
customize.executeChecked(Tuple2.create(tabbedPane, realIndex));
}
assert this.customizers.size() == getTabContainer().getComponentCount();
this.revalidate();
this.repaint();
}
 
private final void putClientProps(String title, Icon icon, JComponent comp, String tip) {
comp.putClientProperty(TITLE_PROP, title);
comp.putClientProperty(ICON_PROP, icon);
comp.putClientProperty(TOOLTIP_PROP, tip);
}
 
public final int removeTab(final JComponent comp) {
if (comp == null)
throw new NullPointerException("Null component");
final int index = Arrays.asList(getTabContainer().getComponents()).indexOf(comp);
if (index >= 0)
this.removeTabAt(index);
return index;
}
 
public final JComponent removeTabAt(final int index) {
final JComponent res;
final JTabbedPane tabbedPane = this.getDisplayedTabbedPane();
if (tabbedPane == null) {
res = (JComponent) this.getComponent(index);
this.remove(index);
this.customizers.clear();
} else {
res = (JComponent) tabbedPane.getComponentAt(index);
this.customizers.remove(res);
tabbedPane.removeTabAt(index);
// remove the tabbedPane if there's only one tab
if (tabbedPane.getTabCount() == 1) {
final JComponent onlyComp = (JComponent) tabbedPane.getComponentAt(0);
// store tab properties, so that it can be recreated later
putClientProps(tabbedPane.getTitleAt(0), tabbedPane.getIconAt(0), onlyComp, tabbedPane.getToolTipTextAt(0));
tabbedPane.removeTabAt(0);
this.remove(0);
this.add(onlyComp);
}
}
assert this.customizers.size() == getTabContainer().getComponentCount();
this.revalidate();
this.repaint();
return res;
}
 
// Allow to access the {@link JTabbedPane}. Note: if you use the result to add a tab, some of
// its properties might get lost, and if you remove a tab this instance will leak memory
protected final JTabbedPane getDisplayedTabbedPane() {
if (this.getComponentCount() == 0)
return null;
final Component res = this.getComponent(0);
return res instanceof JTabbedPane ? (JTabbedPane) res : null;
}
 
private final Container getTabContainer() {
final JTabbedPane tabbedPane = this.getDisplayedTabbedPane();
return tabbedPane == null ? this : tabbedPane;
}
}
/trunk/OpenConcerto/src/org/openconcerto/sql/request/BaseFillSQLRequest.java
37,6 → 37,13
*/
public static final boolean lockSelect = !Boolean.getBoolean("org.openconcerto.sql.noSelectLock");
 
static public void setupForeign(final SQLRowValuesListFetcher fetcher) {
// include rows having NULL (not undefined ID) foreign keys
fetcher.setFullOnly(false);
// treat the same way tables with or without undefined ID
fetcher.setIncludeForeignUndef(false);
}
 
private final SQLTable primaryTable;
private Where where;
private ITransformer<SQLSelect, SQLSelect> selTransf;
117,10 → 124,7
protected final SQLRowValuesListFetcher getFetcher(final Where w) {
final String tableName = getPrimaryTable().getName();
final SQLRowValuesListFetcher fetcher = new SQLRowValuesListFetcher(getGraphToFetch(), true);
// include rows having NULL (not undefined ID) foreign keys
fetcher.setFullOnly(false);
// treat the same way tables with or without undefined ID
fetcher.setIncludeForeignUndef(false);
setupForeign(fetcher);
fetcher.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() {
@Override
public SQLSelect transformChecked(SQLSelect sel) {
/trunk/OpenConcerto/src/org/openconcerto/sql/utils/DropTable.java
67,4 → 67,9
throw new UnsupportedOperationException();
}
 
@Override
protected String getConstraintPrefix() {
// FIXME make a superclass w/o it
throw new UnsupportedOperationException();
}
}
/trunk/OpenConcerto/src/org/openconcerto/sql/utils/AlterTable.java
51,6 → 51,11
this.t = null;
}
 
@Override
protected String getConstraintPrefix() {
return "ADD ";
}
 
public final AlterTable addColumn(String name, String definition) {
// column keyword is not accepted by H2
return this.addClause("ADD " + SQLBase.quoteIdentifier(name) + " " + definition, ClauseType.ADD_COL);
/trunk/OpenConcerto/src/org/openconcerto/sql/utils/SQLCreateTableBase.java
21,6 → 21,7
 
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
33,7 → 34,7
*/
public abstract class SQLCreateTableBase<T extends SQLCreateTableBase<T>> extends ChangeTable<T> {
 
private String pk;
private List<String> pk;
private boolean tmp;
 
public SQLCreateTableBase(final SQLSyntax syntax, final String name) {
44,10 → 45,15
@Override
public void reset() {
super.reset();
this.pk = null;
this.pk = Collections.emptyList();
this.tmp = false;
}
 
@Override
protected String getConstraintPrefix() {
return "";
}
 
public final T addColumn(String name, String definition) {
return this.addClause(SQLBase.quoteIdentifier(name) + " " + definition, ClauseType.ADD_COL);
}
62,18 → 68,14
 
public final T setPrimaryKey(List<String> fields) {
this.checkPK();
if (fields.size() > 0) {
this.pk = "PRIMARY KEY (" + CollectionUtils.join(fields, ",", new ITransformer<String, String>() {
@Override
public String transformChecked(String input) {
return SQLBase.quoteIdentifier(input);
}
}) + ")";
} else
this.pk = null;
this.pk = Collections.unmodifiableList(new ArrayList<String>(fields));
return thisAsT();
}
 
public List<String> getPrimaryKey() {
return this.pk;
}
 
protected void checkPK() {
}
 
111,8 → 113,13
 
final List<String> genClauses = new ArrayList<String>(this.getClauses(tableName, types));
this.modifyClauses(genClauses);
if (this.pk != null && types.contains(ClauseType.ADD_COL))
genClauses.add(this.pk);
if (this.pk.size() > 0 && types.contains(ClauseType.ADD_COL))
genClauses.add("PRIMARY KEY (" + CollectionUtils.join(this.pk, ",", new ITransformer<String, String>() {
@Override
public String transformChecked(String input) {
return SQLBase.quoteIdentifier(input);
}
}) + ")");
if (types.contains(ClauseType.ADD_CONSTRAINT)) {
genClauses.addAll(this.getForeignConstraints(rootName));
}
/trunk/OpenConcerto/src/org/openconcerto/sql/utils/SQLCreateTable.java
21,6 → 21,7
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.graph.SQLKey;
 
import java.util.Collections;
import java.util.List;
 
/**
65,9 → 66,16
public SQLCreateTable addForeignColumn(String foreignTableN, String suffix) {
final String fk = SQLKey.PREFIX + foreignTableN + (suffix.length() == 0 ? "" : "_" + suffix);
final SQLTable foreignTable = this.b.getTable(foreignTableN);
if (foreignTable == null)
throw new IllegalArgumentException("Unknown table in " + this.b + " : " + foreignTableN);
return this.addForeignColumn(fk, foreignTable, true);
}
 
@Override
public List<String> getPrimaryKey() {
return this.plain ? super.getPrimaryKey() : Collections.singletonList(SQLSyntax.ID_NAME);
}
 
protected void checkPK() {
if (!this.plain)
throw new IllegalStateException("can only set primary key in plain mode, otherwise it is automatically added");
/trunk/OpenConcerto/src/org/openconcerto/sql/utils/ChangeTable.java
23,6 → 23,7
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.SQLTable.Index;
import org.openconcerto.sql.model.graph.Link;
import org.openconcerto.sql.model.graph.SQLKey;
import org.openconcerto.utils.CollectionMap;
import org.openconcerto.utils.CollectionUtils;
import org.openconcerto.utils.ReflectUtils;
202,6 → 203,29
return this.addColumn(name, getSyntax().getDateAndTimeType());
}
 
/**
* Adds a non-null integer column.
*
* @param name the name of the column.
* @param defaultVal the default value of the column.
* @return this.
*/
public final T addIntegerColumn(String name, int defaultVal) {
return this.addIntegerColumn(name, defaultVal, false);
}
 
/**
* Adds an integer column.
*
* @param name the name of the column.
* @param defaultVal the default value of the column, can be <code>null</code>.
* @param nullable whether the column accepts NULL.
* @return this.
*/
public final T addIntegerColumn(String name, Integer defaultVal, boolean nullable) {
return this.addColumn(name, "integer " + getSyntax().getDefaultClause(defaultVal == null ? null : defaultVal.toString()) + " " + getSyntax().getNullableClause(nullable));
}
 
public abstract T addColumn(String name, String definition);
 
public final T addColumn(SQLField f) {
255,7 → 279,42
 
// * addForeignColumn = addColumn + addForeignConstraint
 
public T addForeignColumn(SQLCreateTableBase<?> createTable) {
return this.addForeignColumnWithSuffix("", createTable);
}
 
/**
* Add a foreign column to a table not yet created.
*
* @param suffix the suffix of the column, used to tell apart multiple columns pointing to the
* same table, e.g. "" or "2".
* @param createTable the table the new column must point to.
* @return this.
* @see #addForeignColumn(String, SQLCreateTableBase)
*/
public T addForeignColumnWithSuffix(String suffix, SQLCreateTableBase<?> createTable) {
final String fk = SQLKey.PREFIX + createTable.getName() + (suffix.length() == 0 ? "" : "_" + suffix);
return this.addForeignColumn(fk, createTable);
}
 
/**
* Add a foreign column to a table not yet created. Note: this method assumes that the foreign
* table will be created in the same root as this table, like with
* {@link ChangeTable#cat(List, String)}.
*
* @param fk the field name, e.g. "ID_BAT".
* @param createTable the table the new column must point to.
* @return this.
* @see #addForeignColumn(String, SQLName, String, String)
*/
public T addForeignColumn(String fk, SQLCreateTableBase<?> createTable) {
final List<String> primaryKey = createTable.getPrimaryKey();
if (primaryKey.size() != 1)
throw new IllegalArgumentException("Not exactly one field in the foreign primary key : " + primaryKey);
return this.addForeignColumn(fk, new SQLName(createTable.getName()), primaryKey.get(0), null);
}
 
/**
* Add a column and its foreign constraint. If <code>table</code> is of length 1 it will be
* prepended the root name of this table.
*
306,9 → 365,7
});
}
 
private final String getConstraintPrefix() {
return this instanceof AlterTable ? "ADD " : "";
}
protected abstract String getConstraintPrefix();
 
/**
* Add a clause inside the "CREATE TABLE".
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLSyntax.java
338,7 → 338,7
return !Boolean.FALSE.equals(f.isNullable());
}
 
protected final String getNullableClause(boolean nullable) {
public final String getNullableClause(boolean nullable) {
return nullable ? " " : " NOT NULL ";
}
 
404,7 → 404,7
* @param def the default, e.g. "0".
* @return the default clause, e.g. "DEFAULT 0".
*/
protected final String getDefaultClause(final String def) {
public final String getDefaultClause(final String def) {
if (def == null)
return " ";
else
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLType.java
23,6 → 23,7
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Arrays;
66,6 → 67,8
return Timestamp.class;
case Types.DATE:
return java.util.Date.class;
case Types.TIME:
return java.sql.Time.class;
case Types.INTEGER:
case Types.SMALLINT:
case Types.TINYINT:
121,6 → 124,8
res = new BooleanType(type, size, typeName, clazz);
else if (Number.class.isAssignableFrom(clazz))
res = new NumberType(type, size, decDigits, typeName, clazz);
else if (Time.class.isAssignableFrom(clazz))
res = new TimeType(type, size, decDigits, typeName, clazz);
else if (Timestamp.class.isAssignableFrom(clazz))
res = new TimestampType(type, size, decDigits, typeName, clazz);
// Date en dernier surclasse des autres
469,6 → 474,22
}
}
 
private static class TimeType extends DateOrTimeType {
public TimeType(int type, int size, Integer decDigits, String typeName, Class clazz) {
super(type, size, decDigits, typeName, clazz);
}
 
@Override
protected String toStringRaw(Object o) {
final Time ts;
if (o instanceof Time)
ts = (Time) o;
else
ts = new Time(getTime(o));
return "'" + ts.toString() + "'";
}
}
 
private static class StringType extends SQLType {
public StringType(int type, int size, String typeName, Class clazz) {
super(type, size, null, typeName, clazz);
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLBase.java
63,6 → 63,11
*/
public static final String ALLOW_OBJECT_REMOVAL = "org.openconcerto.sql.identifier.allowRemoval";
 
static public final void logCacheError(final DBItemFileCache dir, Exception e) {
Log.get().info("invalid files in " + dir + "\n" + e.getMessage());
Log.get().config("invalid files in " + dir + "\n" + ExceptionUtils.getStackTrace(e));
}
 
// null is a valid name (MySQL doesn't support schemas)
private final Map<String, SQLSchema> schemas;
private int[] dbVersion;
140,7 → 145,7
final long t2 = System.currentTimeMillis();
Log.get().config("XML took " + (t2 - t1) + "ms for mapping " + this.getName() + "." + xmlStructSrc.getSchemas());
} catch (Exception e) {
Log.get().info("invalid files in " + dir + "\n" + ExceptionUtils.getStackTrace(e));
logCacheError(dir, e);
// delete all files not just structure, since every information about obsolete
// schemas is obsolete
// delete all schemas, otherwise if afterwards we load one file it might be valid
/trunk/OpenConcerto/src/org/openconcerto/sql/model/graph/DatabaseGraph.java
24,6 → 24,7
import org.openconcerto.sql.model.DBItemFileCache;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.model.DBSystemRoot;
import org.openconcerto.sql.model.SQLBase;
import org.openconcerto.sql.model.SQLDataSource;
import org.openconcerto.sql.model.SQLField;
import org.openconcerto.sql.model.SQLSchema;
142,7 → 143,7
Log.get().config("XML took " + (t2 - t1) + "ms for mapping the graph of " + this.base.getName() + "." + res);
}
} catch (Exception e) {
Log.get().info("invalid files in " + dir + "\n" + ExceptionUtils.getStackTrace(e));
SQLBase.logCacheError(dir, e);
this.deleteGraphFiles();
}
if (!childrenToFetch.isEmpty()) {
/trunk/OpenConcerto/src/org/openconcerto/sql/preferences/UserProps.java
14,6 → 14,7
package org.openconcerto.sql.preferences;
 
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.ui.preferences.AbstractProps;
 
import java.io.File;
42,7 → 43,7
}
 
public int getLastSocieteID() {
return getIntProperty(UserProps.LAST_SOCIETE);
return getIntProperty(UserProps.LAST_SOCIETE, SQLRow.NONEXISTANT_ID);
}
 
public void setLastSocieteID(int id) {
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/SQLTableModelSource.java
191,6 → 191,13
 
protected abstract SQLTableModelLinesSource _createLinesSource(ITableModel model);
 
/**
* The maximum graph of the lines returned by {@link #createLinesSource(ITableModel)}.
*
* @return the maximum graph of our lines.
*/
public abstract SQLRowValues getMaxGraph();
 
// * columns
 
/**
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/AbstractUpdateOneRunnable.java
21,6 → 21,7
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.model.graph.Path;
import org.openconcerto.sql.request.BaseFillSQLRequest;
import org.openconcerto.sql.request.ListSQLRequest;
import org.openconcerto.utils.CollectionMap;
import org.openconcerto.utils.cc.ITransformer;
50,19 → 51,18
if (!lines.isEmpty()) {
// deepCopy() instead of new SQLRowValues() otherwise the used line's graph will be
// modified (eg the new instance would be linked to it)
final SQLRowValues proto = lines.get(0).getRow().followPath(p).deepCopy();
final SQLRowValues proto = getModel().getLinesSource().getParent().getMaxGraph().followPath(p).deepCopy();
// keep only what has changed, eg CONTACT.NOM
proto.retainAll(getModifedFields());
// fetch the changed rowValues
// ATTN this doesn't use the original fetcher that was used in the updateAll
// MAYBE add a slower but accurate mode using the updateAll fetcher (and thus
// reloading rows from the primary table and not just the changed rows)
final SQLRowValuesListFetcher fetcher = new SQLRowValuesListFetcher(proto);
// the result should have the same graph as proto
fetcher.setFullOnly(true);
BaseFillSQLRequest.setupForeign(fetcher);
final ITransformer<SQLSelect, SQLSelect> transf = new ITransformer<SQLSelect, SQLSelect>() {
@Override
public SQLSelect transformChecked(SQLSelect input) {
// don't exclude undef, eg either RECEPTEUR pointing to undef OBS
// or even refreshing that undef OBS
input.setExcludeUndefined(false);
if (ListSQLRequest.lockSelect)
input.addWaitPreviousWriteTXTable(getTable().getName());
return input.setWhere(new Where(getTable().getKey(), "=", getID()));
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/SQLTableModelSourceOffline.java
14,6 → 14,7
package org.openconcerto.sql.view.list;
 
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
 
/**
46,4 → 47,9
protected SQLTableModelLinesSourceOffline _createLinesSource(final ITableModel model) {
return new SQLTableModelLinesSourceOffline(this, model);
}
 
@Override
public SQLRowValues getMaxGraph() {
return this.getFetcher().getGraph();
}
}
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/SQLTableModelSourceOnline.java
59,4 → 59,9
protected SQLTableModelLinesSourceOnline _createLinesSource(final ITableModel model) {
return new SQLTableModelLinesSourceOnline(this, model);
}
 
@Override
public SQLRowValues getMaxGraph() {
return this.getReq().getGraphToFetch();
}
}
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/search/SearchQueue.java
15,8 → 15,8
 
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLRowValuesCluster.State;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.SQLRowValuesCluster.State;
import org.openconcerto.sql.model.graph.Path;
import org.openconcerto.sql.view.list.ITableModel;
import org.openconcerto.sql.view.list.LineListener;
124,7 → 124,7
if (id < SQLRow.MIN_VALID_ID)
throw new IllegalArgumentException("invalid ID: " + id);
if (!this.fullList.isEmpty()) {
final SQLRowValues proto = this.fullList.get(0).getRow();
final SQLRowValues proto = this.getModel().getLinesSource().getParent().getMaxGraph();
final List<Path> pathsToT = new ArrayList<Path>();
proto.walkGraph(pathsToT, new ITransformer<State<List<Path>>, List<Path>>() {
@Override
137,9 → 137,9
});
for (final Path p : pathsToT) {
for (final ListSQLLine line : this.fullList) {
final SQLRowValues current = line.getRow().assurePath(p);
final SQLRowValues current = line.getRow().followPath(p);
// works for rowValues w/o any ID
if (current.getID() == id) {
if (current != null && current.getID() == id) {
// add to the list of paths that have been refreshed
if (byLine)
res.put(line, p);
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/IListe.java
73,6 → 73,7
import java.io.File;
import java.io.IOException;
import java.sql.Clob;
import java.sql.Time;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
125,10 → 126,13
private static boolean FORCE_ALT_CELL_RENDERER = false;
private static final DateFormat MODIF_DATE_FORMAT = new SimpleDateFormat("'le' dd MMMM yyyy 'à' HH:mm:ss");
static final String SEP = " ► ";
private static final DateFormat TIME_FORMAT = DateFormat.getTimeInstance(DateFormat.SHORT);
private static final Map<Class<?>, FormatGroup> FORMATS;
static {
FORMATS = new HashMap<Class<?>, FormatGroup>();
FORMATS.put(Date.class, new FormatGroup(DateFormat.getDateInstance(DateFormat.SHORT), DateFormat.getDateInstance(DateFormat.MEDIUM), DateFormat.getDateInstance(DateFormat.LONG)));
// longer first otherwise seconds are not displayed by the cell editor and will be lost
FORMATS.put(Time.class, new FormatGroup(DateFormat.getTimeInstance(DateFormat.MEDIUM), DateFormat.getTimeInstance(DateFormat.SHORT)));
}
 
public static final void remove(InputMap m, KeyStroke key) {
556,6 → 560,13
return super.getTableCellRendererComponent(table, StringClobConvertor.INSTANCE.unconvert((Clob) value), isSelected, hasFocus, row, column);
}
});
this.jTable.setDefaultRenderer(Time.class, new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
final String val = value == null ? "" : TIME_FORMAT.format((Time) value);
return super.getTableCellRendererComponent(table, val, isSelected, hasFocus, row, column);
}
});
for (final Map.Entry<Class<?>, FormatGroup> e : this.getFormats().entrySet())
this.jTable.setDefaultEditor(e.getKey(), new FormatEditor(e.getValue()));
this.sorter.setTableHeader(this.jTable.getTableHeader());
/trunk/OpenConcerto/src/org/openconcerto/utils/NumberUtils.java
New file
0,0 → 1,98
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.utils;
 
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
 
public class NumberUtils {
 
/**
* Whether <code>n</code> has a non-zero fractional part.
*
* @param n a number.
* @return <code>true</code> if there is a non-zero fractional part, e.g. <code>true</code> for
* 1.3d and <code>false</code> for <code>new BigDecimal("1.00")</code>.
*/
static public final boolean hasFractionalPart(Number n) {
if (n instanceof Integer || n instanceof Long || n instanceof Short || n instanceof Byte || n instanceof BigInteger || n instanceof AtomicLong || n instanceof AtomicInteger)
return false;
 
final BigDecimal bd;
if (n instanceof BigDecimal)
bd = (BigDecimal) n;
else if (n instanceof Double || n instanceof Float)
bd = new BigDecimal(n.doubleValue());
else
bd = new BigDecimal(n.toString());
return DecimalUtils.decimalDigits(bd) > 0;
}
 
static final int MAX_LONG_LENGTH = String.valueOf(Long.MAX_VALUE).length();
 
static public final int intDigits(final long l) {
final long x = Math.abs(l);
long p = 10;
int i = 1;
while (x >= p && i < MAX_LONG_LENGTH) {
p = 10 * p;
i++;
}
return i;
}
 
/**
* The number of digits of the integer part in decimal representation.
*
* @param n a number, e.g. 123.45.
* @return the number of digits of the integer part, e.g. 3.
*/
static public final int intDigits(Number n) {
if (n instanceof Integer || n instanceof Long || n instanceof Short || n instanceof Byte || n instanceof AtomicLong || n instanceof AtomicInteger)
return intDigits(n.longValue());
 
final BigDecimal bd;
if (n instanceof BigDecimal)
bd = (BigDecimal) n;
else if (n instanceof BigInteger)
bd = new BigDecimal((BigInteger) n);
else if (n instanceof Double || n instanceof Float)
bd = new BigDecimal(n.doubleValue());
else
bd = new BigDecimal(n.toString());
return DecimalUtils.intDigits(bd);
}
 
/**
* High precision divide.
*
* @param n the dividend.
* @param d the divisor.
* @return <code>n / d</code>.
* @see DecimalUtils#HIGH_PRECISION
*/
static public Number divide(Number n, double d) {
if (d == 1)
return n;
if (n instanceof BigDecimal) {
return ((BigDecimal) n).divide(new BigDecimal(d), DecimalUtils.HIGH_PRECISION);
} else if (n instanceof BigInteger) {
return new BigDecimal((BigInteger) n).divide(new BigDecimal(d), DecimalUtils.HIGH_PRECISION);
} else {
return n.doubleValue() / d;
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/utils/CompareUtils.java
18,6 → 18,7
 
import org.openconcerto.utils.cc.ITransformer;
 
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
 
88,6 → 89,7
* @param o1 the first object, can be <code>null</code>.
* @param o2 the second object, can be <code>null</code>.
* @return <code>true</code> if both are <code>null</code> or if o1.equals(o2).
* @see Object#equals(Object)
*/
static public final boolean equals(Object o1, Object o2) {
if (o1 == null && o2 == null)
97,6 → 99,24
return o1.equals(o2);
}
 
/**
* Compare 2 objets pouvant être <code>null</code> avec compareTo(). Useful since for some
* classes equals() is more specific than compareTo()==0, e.g. {@link BigDecimal#equals(Object)}
* doesn't compare the numeric value but instance variables (1E2 is not equal to 100 or 100.00).
*
* @param o1 the first object, can be <code>null</code>.
* @param o2 the second object, can be <code>null</code>.
* @return <code>true</code> if both are <code>null</code> or if o1.compareTo(o2) == 0.
* @see Comparable#compareTo(Object)
*/
static public final <T> boolean equalsWithCompareTo(Comparable<T> o1, T o2) {
if (o1 == null && o2 == null)
return true;
if (o1 == null || o2 == null)
return false;
return o1.compareTo(o2) == 0;
}
 
static public interface Equalizer<T> {
public boolean equals(T o1, T o2);
}
/trunk/OpenConcerto/src/org/openconcerto/utils/checks/ValidChangeSupport.java
36,6 → 36,10
this.validState = initialState;
}
 
public final Boolean getValidState() {
return this.validState;
}
 
public final void fireValidChange(final Boolean newValue) {
if (!newValue.equals(this.validState)) {
this.validState = newValue;
/trunk/OpenConcerto/src/org/openconcerto/utils/convertor/DateToTimeConvertor.java
New file
0,0 → 1,29
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.utils.convertor;
 
import java.sql.Time;
import java.util.Date;
 
public class DateToTimeConvertor extends NullIsNullConvertor<Date, Time> {
@Override
protected Time convertNonNull(Date o) {
return new Time(o.getTime());
}
 
@Override
protected Date unconvertNonNull(Time o) {
return o;
}
}
/trunk/OpenConcerto/src/org/openconcerto/utils/convertor/ValueConvertorFactory.java
24,6 → 24,7
static {
convs = new ArrayList<ValueConvertor<?, ?>>();
convs.add(new DateTSConvertor());
convs.add(new DateToTimeConvertor());
convs.add(StringClobConvertor.INSTANCE);
}
 
/trunk/OpenConcerto/src/org/openconcerto/xml/SimpleXMLPath.java
57,6 → 57,30
return create(Arrays.<Step<?>> asList(first, second), lastStep);
}
 
/**
* Create a path searching for all descendant attributes with the passed name and namespace.
* I.e. in XPath this would be ".//@ns:name".
*
* @param name the name of attributes.
* @param ns the namespace of attributes.
* @return a path searching attributes in all {@link Axis#descendantOrSelf} elements.
*/
public static SimpleXMLPath<Attribute> allAttributes(final String name, final String ns) {
return create(Step.createElementStep(Axis.descendantOrSelf, null), Step.createAttributeStep(name, ns));
}
 
/**
* Create a path searching for all descendant elements with the passed name and namespace. I.e.
* in XPath this would be ".//ns:name".
*
* @param name the name of elements.
* @param ns the namespace of elements.
* @return a path searching all {@link Axis#descendantOrSelf} elements.
*/
public static SimpleXMLPath<Element> allElements(final String name, final String ns) {
return create(Step.createElementStep(Axis.descendantOrSelf, name, ns));
}
 
private final List<Step<?>> items;
private final Step<T> lastItem;
 
65,11 → 89,11
this.items = new ArrayList<Step<?>>();
}
 
public final SimpleXMLPath add(final String name) {
public final SimpleXMLPath<T> add(final String name) {
return this.add(Step.createElementStep(name, null, null));
}
 
public final SimpleXMLPath add(Step<?> step) {
public final SimpleXMLPath<T> add(Step<?> step) {
this.items.add(step);
return this;
}
183,7 → 207,7
if (axis == Axis.ancestor) {
step.add(node.getParent(), res);
} else if (axis == Axis.attribute) {
final List attributes = node.getAttributes();
final List<?> attributes = node.getAttributes();
final int stop = attributes.size();
for (int i = 0; i < stop; i++) {
step.add(attributes.get(i), res);
/trunk/OpenConcerto/src/org/openconcerto/xml/JDOMUtils.java
13,6 → 13,8
package org.openconcerto.xml;
 
import org.openconcerto.utils.cc.IPredicate;
 
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringReader;
151,6 → 153,25
return OUTPUTTER.outputString(xml);
}
 
public static Element getAncestor(Element element, final String name, final Namespace ns) {
return getAncestor(element, new IPredicate<Element>() {
@Override
public boolean evaluateChecked(Element elem) {
return elem.getName().equals(name) && elem.getNamespace().equals(ns);
}
});
}
 
public static Element getAncestor(Element element, final IPredicate<Element> pred) {
Element current = element;
while (current != null) {
if (pred.evaluateChecked(current))
return current;
current = current.getParentElement();
}
return null;
}
 
/**
* Add namespace declaration to <code>elem</code> if needed. Necessary since JDOM uses a simple
* list.
228,6 → 249,23
parentElement.addContent(after ? index + 1 : index, toAdd);
}
 
/**
* Test if two elements have the same namespace and name.
*
* @param elem1 an element, can be <code>null</code>.
* @param elem2 an element, can be <code>null</code>.
* @return <code>true</code> if both elements have the same name and namespace, or if both are
* <code>null</code>.
*/
public static boolean equals(Element elem1, Element elem2) {
if (elem1 == null && elem2 == null)
return true;
else if (elem1 == null || elem2 == null)
return false;
else
return elem1.getName().equals(elem2.getName()) && elem1.getNamespace().equals(elem2.getNamespace());
}
 
// @return SAXException If a SAX error occurs during parsing of doc.
static SAXException validate(final Document doc, final Schema schema, final ErrorHandler errorHandler) {
ByteArrayInputStream ins;
/trunk/OpenConcerto/src/org/openconcerto/task/config/ComptaBasePropsConfiguration.java
163,7 → 163,7
}
 
public final DBRoot getRootSociete() {
if (this.baseSociete == null)
if (this.baseSociete == null && this.rowSociete != null)
this.baseSociete = this.createSQLBaseSociete();
return this.baseSociete;
}