OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Compare Revisions

Regard whitespace Rev 62 → Rev 63

/trunk/OpenConcerto/lib/jOpenDocument-1.3b1.jar
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/OpenConcerto/lib/fb-annotations-2.0.0.jar
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/OpenConcerto/lib/fb-annotations-2.0.0.jar
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/OOXMLCache.java
28,7 → 28,11
import java.util.Map;
 
public class OOXMLCache {
protected static SQLRowAccessor getForeignRow(SQLRowAccessor row, SQLField field) {
 
private Map<SQLRowAccessor, Map<SQLTable, List<SQLRowAccessor>>> cacheReferent = new HashMap<SQLRowAccessor, Map<SQLTable, List<SQLRowAccessor>>>();
private Map<String, Map<Integer, SQLRowAccessor>> cacheForeign = new HashMap<String, Map<Integer, SQLRowAccessor>>();
 
protected SQLRowAccessor getForeignRow(SQLRowAccessor row, SQLField field) {
Map<Integer, SQLRowAccessor> c = cacheForeign.get(field.getName());
 
if (row.getObject(field.getName()) == null) {
54,15 → 58,14
 
return foreign;
}
// return row.getForeignRow(field.getName());
 
}
 
protected static List<? extends SQLRowAccessor> getReferentRows(List<? extends SQLRowAccessor> row, SQLTable tableForeign) {
protected List<? extends SQLRowAccessor> getReferentRows(List<? extends SQLRowAccessor> row, SQLTable tableForeign) {
return getReferentRows(row, tableForeign, null);
}
 
protected static List<? extends SQLRowAccessor> getReferentRows(List<? extends SQLRowAccessor> row, final SQLTable tableForeign, String groupBy) {
protected List<? extends SQLRowAccessor> getReferentRows(List<? extends SQLRowAccessor> row, final SQLTable tableForeign, String groupBy) {
Map<SQLTable, List<SQLRowAccessor>> c = cacheReferent.get(row.get(0));
 
if (c != null && c.get(tableForeign) != null) {
132,7 → 135,7
// return row.getReferentRows(tableForeign);
}
 
private static void cumulRows(final List<String> params, SQLRow sqlRow, SQLRowValues rowVals) {
private void cumulRows(final List<String> params, SQLRow sqlRow, SQLRowValues rowVals) {
 
for (int i = 1; i < params.size(); i++) {
 
150,14 → 153,11
}
}
 
private static Map<SQLRowAccessor, Map<SQLTable, List<SQLRowAccessor>>> cacheReferent = new HashMap<SQLRowAccessor, Map<SQLTable, List<SQLRowAccessor>>>();
private static Map<String, Map<Integer, SQLRowAccessor>> cacheForeign = new HashMap<String, Map<Integer, SQLRowAccessor>>();
 
public static Map<SQLRowAccessor, Map<SQLTable, List<SQLRowAccessor>>> getCacheReferent() {
public Map<SQLRowAccessor, Map<SQLTable, List<SQLRowAccessor>>> getCacheReferent() {
return cacheReferent;
}
 
public static void clearCache() {
public void clearCache() {
cacheReferent.clear();
cacheForeign.clear();
}
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/OOXMLField.java
48,8 → 48,8
 
private String op = "";
 
public OOXMLField(Element eltField, SQLRowAccessor row, SQLElement sqlElt, int id, SQLRow rowLanguage) {
super(eltField, sqlElt, id, rowLanguage);
public OOXMLField(Element eltField, SQLRowAccessor row, SQLElement sqlElt, int id, SQLRow rowLanguage, OOXMLCache cache) {
super(eltField, sqlElt, id, rowLanguage, cache);
 
String base = eltField.getAttributeValue("base");
this.op = eltField.getAttributeValue("op");
97,7 → 97,7
}
}
 
SQLRowAccessor foreignRow = OOXMLCache.getForeignRow(this.row, sqlField);
SQLRowAccessor foreignRow = cache.getForeignRow(this.row, sqlField);
if (foreignRow != null && foreignRow.getID() > 1) {
final List<Element> children = this.elt.getChildren("field");
if (children.size() > 1) {
105,7 → 105,7
 
String result = "";
for (Element ssComposant : children) {
OOXMLField childElt = new OOXMLField(ssComposant, foreignRow, this.sqlElt, this.id, this.rowLanguage);
OOXMLField childElt = new OOXMLField(ssComposant, foreignRow, this.sqlElt, this.id, this.rowLanguage, cache);
final Object valueComposantO = childElt.getValue();
result += (valueComposantO == null) ? "" : valueComposantO.toString() + " ";
}
119,7 → 119,7
}
} else {
if (isValid()) {
OOXMLField childElt = new OOXMLField(this.elt.getChild("field"), foreignRow, this.sqlElt, this.id, this.rowLanguage);
OOXMLField childElt = new OOXMLField(this.elt.getChild("field"), foreignRow, this.sqlElt, this.id, this.rowLanguage, cache);
return childElt.getValue();
} else {
return "";
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/SpreadSheetCellValueContext.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.erp.generationDoc;
 
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.utils.StringUtils;
 
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
public class SpreadSheetCellValueContext {
private SQLRowAccessor row;
private Map<String, String> map = new HashMap<String, String>();
 
public SpreadSheetCellValueContext(SQLRowAccessor row) {
this.row = row;
}
 
public void dump() {
dump(System.out);
}
 
public void dump(PrintStream prt) {
prt.println("Row id: " + row.getID() + " table:" + row.getTable());
List<String> fields = new ArrayList<String>();
fields.addAll(row.getFields());
Collections.sort(fields);
for (String field : fields) {
prt.print(StringUtils.rightAlign(field, 20));
prt.print(" : ");
prt.println(row.getObject(field));
}
prt.println("Parameters:");
List<String> params = new ArrayList<String>();
params.addAll(map.keySet());
Collections.sort(params);
for (String param : params) {
prt.print(StringUtils.rightAlign(param, 20));
prt.print(" : ");
prt.println(row.getObject(param));
}
 
}
 
public SQLRowAccessor getRow() {
return row;
}
 
public void put(String name, String value) {
map.put(name, value);
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/SpreadSheetCellValueProviderManager.java
New file
0,0 → 1,39
/*
* 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.generationDoc;
 
import java.util.HashMap;
import java.util.Map;
 
public class SpreadSheetCellValueProviderManager {
private final static SpreadSheetCellValueProviderManager instance = new SpreadSheetCellValueProviderManager();
private final Map<String, SpreadSheetCellValueProvider> map = new HashMap<String, SpreadSheetCellValueProvider>();
 
public static void put(String id, SpreadSheetCellValueProvider provider) {
instance.putProvider(id, provider);
}
 
public static SpreadSheetCellValueProvider get(String id) {
return instance.getProvider(id);
}
 
private synchronized void putProvider(String id, SpreadSheetCellValueProvider provider) {
map.put(id, provider);
}
 
private synchronized SpreadSheetCellValueProvider getProvider(String id) {
return map.get(id);
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/OOgenerationXML.java
62,21 → 62,28
*
*/
public class OOgenerationXML {
private static int answer = JOptionPane.NO_OPTION;
 
private static DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
private DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
 
// Cache pour la recherche des styles
private static Map<Sheet, Map<String, Map<Integer, String>>> cacheStyle = new HashMap<Sheet, Map<String, Map<Integer, String>>>();
private Map<Sheet, Map<String, Map<Integer, String>>> cacheStyle = new HashMap<Sheet, Map<String, Map<Integer, String>>>();
private Map<SQLRowAccessor, Map<String, Object>> taxe = new HashMap<SQLRowAccessor, Map<String, Object>>();
private Map<String, Map<Integer, SQLRowAccessor>> cacheForeign = new HashMap<String, Map<Integer, SQLRowAccessor>>();
 
// Cache pour les SQLRow du tableau
private static Map<String, List<? extends SQLRowAccessor>> rowsEltCache = new HashMap<String, List<? extends SQLRowAccessor>>();
private Map<String, List<? extends SQLRowAccessor>> rowsEltCache = new HashMap<String, List<? extends SQLRowAccessor>>();
private final OOXMLCache rowRefCache = new OOXMLCache();
private final SQLRow row;
 
private static int answer = JOptionPane.NO_OPTION;
public OOgenerationXML(SQLRow row) {
this.row = row;
}
 
public static synchronized File createDocument(String templateId, File outputDirectory, final String expectedFileName, SQLRow row, SQLRow rowLanguage) {
public synchronized File createDocument(String templateId, File outputDirectory, final String expectedFileName, SQLRow rowLanguage) {
final String langage = rowLanguage != null ? rowLanguage.getString("CHEMIN") : null;
cacheStyle.clear();
OOXMLCache.clearCache();
rowRefCache.clearCache();
rowsEltCache.clear();
taxe.clear();
cacheForeign.clear();
146,7 → 153,7
 
for (Element tableChild : listTable) {
// On remplit les cellules du tableau
parseTableauXML(tableChild, row, spreadSheet, rowLanguage);
parseTableauXML(tableChild, spreadSheet, rowLanguage);
}
} catch (Exception e) {
ExceptionHandler.handle("Impossible de remplir le document " + templateId + " " + ((rowLanguage == null) ? "" : rowLanguage.getString("CHEMIN")), e);
182,7 → 189,7
* @param id
* @param sheet
*/
private static void parseTableauXML(Element tableau, SQLRow row, SpreadSheet spreadsheet, SQLRow rowLanguage) {
private void parseTableauXML(Element tableau, SpreadSheet spreadsheet, SQLRow rowLanguage) {
 
if (tableau == null) {
return;
284,10 → 291,8
* @param test remplir ou non avec les valeurs
* @return le nombre de page
*/
static Map<SQLRowAccessor, Map<String, Object>> taxe = new HashMap<SQLRowAccessor, Map<String, Object>>();
private static Map<String, Map<Integer, SQLRowAccessor>> cacheForeign = new HashMap<String, Map<Integer, SQLRowAccessor>>();
 
protected static SQLRowAccessor getForeignRow(SQLRowAccessor row, SQLField field) {
protected SQLRowAccessor getForeignRow(SQLRowAccessor row, SQLField field) {
Map<Integer, SQLRowAccessor> c = cacheForeign.get(field.getName());
 
int i = row.getInt(field.getName());
313,7 → 318,7
 
}
 
private static int fillTable(Element tableau, SQLRow row, Sheet sheet, Map<String, Map<Integer, String>> mapStyle, boolean test, SQLRow rowLanguage) {
private int fillTable(Element tableau, SQLRow row, Sheet sheet, Map<String, Map<Integer, String>> mapStyle, boolean test, SQLRow rowLanguage) {
 
if (tableau == null) {
return 1;
322,7 → 327,7
int nbPage = 1;
int nbCellules = 0;
 
OOXMLTableElement tableElement = new OOXMLTableElement(tableau, row);
OOXMLTableElement tableElement = new OOXMLTableElement(tableau, row, this.rowRefCache);
int currentLineTmp = tableElement.getFirstLine();
int currentLine = tableElement.getFirstLine();
 
395,7 → 400,7
for (Element e : listElts) {
 
OOXMLTableField tableField = new OOXMLTableField(e, rowElt, tableElement.getSQLElement(), rowElt.getID(), tableElement.getTypeStyleWhere() ? -1 : tableElement.getFilterId(),
rowLanguage, numeroRef);
rowLanguage, numeroRef, this.rowRefCache);
final Object value = tableField.getValue();
 
mapValues.put(e, value);
413,7 → 418,7
for (Element e : listElts) {
 
OOXMLTableField tableField = new OOXMLTableField(e, rowElt, tableElement.getSQLElement(), rowElt.getID(), tableElement.getTypeStyleWhere() ? -1 : tableElement.getFilterId(),
rowLanguage, numeroRef);
rowLanguage, numeroRef, this.rowRefCache);
 
if (!test && styleName != null && tableElement.getListBlankLineStyle().contains(styleName) && first) {
toAdd++;
518,7 → 523,7
return d;
}
 
private static void fillTaxe(Element tableau, Sheet sheet, Map<String, Map<Integer, String>> mapStyle, boolean test) {
private void fillTaxe(Element tableau, Sheet sheet, Map<String, Map<Integer, String>> mapStyle, boolean test) {
 
int line = Integer.valueOf(tableau.getAttributeValue("firstLine"));
List<Element> listElts = tableau.getChildren("element");
568,11 → 573,11
* @param sqlElt
* @param id
*/
private static void parseElementsXML(List<Element> elts, SQLRow row, SpreadSheet spreadSheet) {
private void parseElementsXML(List<Element> elts, SQLRow row, SpreadSheet spreadSheet) {
SQLElement sqlElt = Configuration.getInstance().getDirectory().getElement(row.getTable());
for (Element elt : elts) {
 
OOXMLElement OOElt = new OOXMLElement(elt, sqlElt, row.getID(), row);
OOXMLElement OOElt = new OOXMLElement(elt, sqlElt, row.getID(), row, this.rowRefCache);
Object result = OOElt.getValue();
if (result != null) {
Object o = elt.getAttributeValue("sheet");
612,7 → 617,7
* @param replace efface ou non le contenu original de la cellule
* @param styleOO style à appliquer
*/
private static int fill(String location, Object value, Sheet sheet, boolean replace, String replacePattern, String styleOO, boolean test, boolean controleMultiline) {
private int fill(String location, Object value, Sheet sheet, boolean replace, String replacePattern, String styleOO, boolean test, boolean controleMultiline) {
 
int nbCellule = (test && styleOO == null) ? 2 : 1;
// est ce que la cellule est valide
681,7 → 686,7
* @param value
* @param replace
*/
private static void setCellValue(MutableCell cell, Object value, boolean replace, String replacePattern) {
private void setCellValue(MutableCell cell, Object value, boolean replace, String replacePattern) {
if (value == null) {
return;
// value = "";
759,7 → 764,7
/**
* parcourt l'ensemble de la feuille pour trouver les style définit
*/
private static Map<String, Map<Integer, String>> searchStyle(Sheet sheet, int colEnd, int rowEnd) {
private Map<String, Map<Integer, String>> searchStyle(Sheet sheet, int colEnd, int rowEnd) {
 
if (cacheStyle.get(sheet) != null) {
return cacheStyle.get(sheet);
818,7 → 823,7
return mapStyleDef;
}
 
public static boolean needAnnexe(String templateId, SQLRow row, SQLRow rowLanguage) {
public boolean needAnnexe(String templateId, SQLRow row, SQLRow rowLanguage) {
final String langage = rowLanguage != null ? rowLanguage.getString("CHEMIN") : null;
final SAXBuilder builder = new SAXBuilder();
try {
868,8 → 873,7
return false;
}
 
protected static String getStringProposition(SQLRow rowProp) {
 
protected String getStringProposition(SQLRow rowProp) {
return "Notre proposition " + rowProp.getString("NUMERO") + " du " + dateFormat.format(rowProp.getObject("DATE"));
}
 
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/AbstractSheetXml.java
57,8 → 57,8
});
templateId = getDefaultTemplateId();
}
AbstractSheetXml.this.generatedOpenDocumentFile = OOgenerationXML.createDocument(templateId, getDocumentOutputDirectory(), getValidFileName(getName()), AbstractSheetXml.this.row,
getRowLanguage());
final OOgenerationXML oXML = new OOgenerationXML(AbstractSheetXml.this.row);
AbstractSheetXml.this.generatedOpenDocumentFile = oXML.createDocument(templateId, getDocumentOutputDirectory(), getValidFileName(getName()), getRowLanguage());
 
} catch (Exception e) {
DEFAULT_HANDLER.uncaughtException(null, e);
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/SpreadSheetCellValueProvider.java
New file
0,0 → 1,18
/*
* 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.generationDoc;
 
public interface SpreadSheetCellValueProvider {
public Object getValue(final SpreadSheetCellValueContext context);
}
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/OOXMLTableElement.java
34,10 → 34,12
private SQLElement elt;
private String foreignTableWhere, typeWhere, fieldWhere;
private Element tableau;
private OOXMLCache cache;
 
public OOXMLTableElement(Element tableau, SQLRow row) {
public OOXMLTableElement(Element tableau, SQLRow row, OOXMLCache cache) {
 
this.tableau = tableau;
this.cache = cache;
this.foreignTableWhere = tableau.getAttributeValue("tableForeignWhere");
this.fieldWhere = tableau.getAttributeValue("fieldWhere");
 
122,7 → 124,7
// }
// // #endif
 
return OOXMLCache.getReferentRows(this.row, tableElt, this.tableau.getAttributeValue("groupBy"));
return cache.getReferentRows(this.row, tableElt, this.tableau.getAttributeValue("groupBy"));
 
} else {
System.err.println("OOXMLTableElement.getRows() Table " + tableElt + " is null!");
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/OOXMLElement.java
19,7 → 19,6
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.users.UserManager;
import org.openconcerto.utils.GestionDevise;
 
import java.text.DateFormat;
29,6 → 28,7
import java.util.Date;
import java.util.List;
 
import org.jdom.Attribute;
import org.jdom.Element;
 
public class OOXMLElement {
35,46 → 35,43
protected Element elt;
protected SQLElement sqlElt;
protected int id;
protected SQLRowAccessor row = null;
protected SQLRowAccessor row;
protected SQLRow rowLanguage;
protected OOXMLCache cache;
 
public OOXMLElement(Element elt, SQLElement sqlElt, int id, SQLRow rowLanguage) {
this.elt = elt;
this.sqlElt = sqlElt;
this.id = id;
this.rowLanguage = rowLanguage;
public OOXMLElement(Element elt, SQLElement sqlElt, int id, SQLRow rowLanguage, OOXMLCache cache) {
this(elt, sqlElt, id, null, rowLanguage, cache);
 
}
 
public OOXMLElement(Element elt, SQLElement sqlElt, int id, SQLRowAccessor row, SQLRow rowLanguage) {
public OOXMLElement(Element elt, SQLElement sqlElt, int id, SQLRowAccessor row, SQLRow rowLanguage, OOXMLCache cache) {
this.elt = elt;
this.sqlElt = sqlElt;
this.id = id;
this.row = row;
this.rowLanguage = rowLanguage;
this.cache = cache;
}
 
public Object getValue() {
Object res = "";
 
final String attributeValue = this.elt.getAttributeValue("type");
 
if (attributeValue.equalsIgnoreCase("InitialesUtilisateur")) {
return getInitialesUser();
final String type = this.elt.getAttributeValue("type");
SpreadSheetCellValueProvider provider = SpreadSheetCellValueProviderManager.get(type);
if (provider != null) {
final SpreadSheetCellValueContext context = new SpreadSheetCellValueContext(this.row);
List<Attribute> attrs = this.elt.getAttributes();
for (Attribute attr : attrs) {
context.put(attr.getName(), attr.getValue());
}
 
if (attributeValue.equalsIgnoreCase("InitialesUtilisateurModif")) {
return getInitialesUserModify();
return provider.getValue(context);
}
 
if (attributeValue.equalsIgnoreCase("InitialesUtilisateurCreate")) {
return getInitialesUserCreate();
}
 
if (attributeValue.equalsIgnoreCase("TotalHTTable")) {
if (type.equalsIgnoreCase("TotalHTTable")) {
return getTotalHTTable(row);
}
 
if (attributeValue.equalsIgnoreCase("DateEcheance")) {
if (type.equalsIgnoreCase("DateEcheance")) {
int idModeReglement = row.getInt("ID_MODE_REGLEMENT");
Date d = (Date) row.getObject("DATE");
return getDateEcheance(idModeReglement, d, this.elt.getAttributeValue("DatePattern"));
87,7 → 84,7
String result = "";
for (Element eltField : eltFields) {
 
OOXMLField field = new OOXMLField(eltField, this.row, this.sqlElt, this.id, this.rowLanguage);
OOXMLField field = new OOXMLField(eltField, this.row, this.sqlElt, this.id, this.rowLanguage, cache);
 
Object value = field.getValue();
if (value != null) {
96,7 → 93,7
}
res = result;
} else {
OOXMLField field = new OOXMLField(eltFields.get(0), this.row, this.sqlElt, this.id, this.rowLanguage);
OOXMLField field = new OOXMLField(eltFields.get(0), this.row, this.sqlElt, this.id, this.rowLanguage, cache);
res = field.getValue();
}
}
103,53 → 100,7
return res;
}
 
private String getInitialesUserModify() {
 
SQLRowAccessor rowUser = this.row.getForeign("ID_USER_COMMON_MODIFY");
String s = rowUser.getString("NOM");
String s2 = rowUser.getString("PRENOM");
 
StringBuffer result = new StringBuffer(4);
if (s2 != null && s2.trim().length() > 0) {
result.append(s2.charAt(0));
}
if (s != null && s.trim().length() > 0) {
result.append(s.charAt(0));
}
return result.toString();
}
 
private String getInitialesUserCreate() {
SQLRowAccessor rowUser = this.row.getForeign("ID_USER_COMMON_CREATE");
String s = rowUser.getString("NOM");
String s2 = rowUser.getString("PRENOM");
 
StringBuffer result = new StringBuffer(4);
if (s2 != null && s2.trim().length() > 0) {
result.append(s2.charAt(0));
}
if (s != null && s.trim().length() > 0) {
result.append(s.charAt(0));
}
return result.toString();
}
 
private String getInitialesUser() {
 
String s = UserManager.getInstance().getCurrentUser().getLastName();
String s2 = UserManager.getInstance().getCurrentUser().getName();
 
StringBuffer result = new StringBuffer(4);
if (s2 != null && s2.trim().length() > 0) {
result.append(s2.charAt(0));
}
if (s != null && s.trim().length() > 0) {
result.append(s.charAt(0));
}
return result.toString();
}
 
 
public static DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
 
protected String getStringProposition(SQLRowAccessor rowProp) {
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/OOXMLTableField.java
29,6 → 29,7
import java.util.Date;
import java.util.List;
 
import org.jdom.Attribute;
import org.jdom.Element;
 
public class OOXMLTableField extends OOXMLField {
39,8 → 40,8
private int idRef;
private String style = "";
 
public OOXMLTableField(Element eltField, SQLRowAccessor row, SQLElement sqlElt, int id, int filterId, SQLRow rowLanguage, int idRef) {
super(eltField, row, sqlElt, id, rowLanguage);
public OOXMLTableField(Element eltField, SQLRowAccessor row, SQLElement sqlElt, int id, int filterId, SQLRow rowLanguage, int idRef, OOXMLCache cache) {
super(eltField, row, sqlElt, id, rowLanguage, cache);
this.type = eltField.getAttributeValue("type");
this.lineOption = eltField.getAttributeValue("lineOption");
this.filterId = filterId;
62,6 → 63,16
public Object getValue() {
Object value = null;
 
SpreadSheetCellValueProvider provider = SpreadSheetCellValueProviderManager.get(type);
if (provider != null) {
final SpreadSheetCellValueContext context = new SpreadSheetCellValueContext(this.row);
List<Attribute> attrs = this.elt.getAttributes();
for (Attribute attr : attrs) {
context.put(attr.getName(), attr.getValue());
}
return provider.getValue(context);
}
 
if (this.type.equalsIgnoreCase("LineReference")) {
return idRef;
} else if (this.type.equalsIgnoreCase("DescriptifArticle")) {
73,7 → 84,7
} else if (this.type.equalsIgnoreCase("Localisation")) {
value = getLocalisation(this.row);
} else {
OOXMLElement eltXml = new OOXMLElement(this.elt, this.sqlElt, this.id, this.row, this.rowLanguage);
OOXMLElement eltXml = new OOXMLElement(this.elt, this.sqlElt, this.id, this.row, this.rowLanguage, cache);
value = eltXml.getValue();
}
 
147,7 → 158,7
* @param row
* @return la formule de calcul du montant revise
*/
private static String getMontantRevise(SQLRowAccessor row) {
private String getMontantRevise(SQLRowAccessor row) {
long indice0 = (Long) row.getObject("INDICE_0");
long indiceN = (Long) row.getObject("INDICE_N");
long montantInit = (Long) row.getObject("MONTANT_INITIAL");
160,12 → 171,12
try {
SQLRowAccessor rowFact;
if (row.getTable().getName().startsWith("SAISIE_VENTE_FACTURE")) {
rowFact = OOXMLCache.getForeignRow(row, row.getTable().getField("ID_SAISIE_VENTE_FACTURE"));
rowFact = cache.getForeignRow(row, row.getTable().getField("ID_SAISIE_VENTE_FACTURE"));
} else {
rowFact = OOXMLCache.getForeignRow(row, row.getTable().getField("ID_AVOIR_CLIENT"));
rowFact = cache.getForeignRow(row, row.getTable().getField("ID_AVOIR_CLIENT"));
}
if (rowFact != null) {
SQLRowAccessor rowClient = OOXMLCache.getForeignRow(rowFact, rowFact.getTable().getField("ID_CLIENT"));
SQLRowAccessor rowClient = cache.getForeignRow(rowFact, rowFact.getTable().getField("ID_CLIENT"));
if (rowClient != null) {
clientPrive = rowClient.getBoolean("MARCHE_PRIVE");
}
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/provider/PrixUnitaireRemiseProvider.java
New file
0,0 → 1,38
/*
* 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.generationDoc.provider;
 
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueContext;
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueProviderManager;
import org.openconcerto.sql.model.SQLRowAccessor;
 
import java.math.BigDecimal;
import java.math.MathContext;
 
public class PrixUnitaireRemiseProvider extends UserInitialsValueProvider {
 
@Override
public Object getValue(SpreadSheetCellValueContext context) {
SQLRowAccessor row = context.getRow();
final Long pv = row.getLong("PV_HT");
final BigDecimal remise = (BigDecimal) row.getObject("POURCENT_REMISE");
BigDecimal result = BigDecimal.ONE.subtract(remise.movePointLeft(2)).multiply(new BigDecimal(pv), MathContext.DECIMAL128);
result = result.movePointLeft(2);
return result;
}
 
public static void register() {
SpreadSheetCellValueProviderManager.put("PrixUnitaireRemise", new PrixUnitaireRemiseProvider());
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/provider/UserInitialsValueProvider.java
New file
0,0 → 1,41
/*
* 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.generationDoc.provider;
 
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueContext;
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueProvider;
 
public abstract class UserInitialsValueProvider implements SpreadSheetCellValueProvider {
 
@Override
public abstract Object getValue(SpreadSheetCellValueContext context);
 
public String getInitials(String firstName, String name) {
String initials = "";
if (firstName != null) {
final String tFirstName = firstName.trim();
if (!tFirstName.isEmpty()) {
initials += tFirstName.charAt(0);
}
}
if (name != null) {
final String tName = name.trim();
if (!tName.isEmpty()) {
initials += tName.charAt(0);
}
}
return initials.toUpperCase();
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/provider/UserCurrentInitialsValueProvider.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.generationDoc.provider;
 
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueContext;
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueProviderManager;
import org.openconcerto.sql.users.User;
import org.openconcerto.sql.users.UserManager;
 
public class UserCurrentInitialsValueProvider extends UserInitialsValueProvider {
 
@Override
public Object getValue(SpreadSheetCellValueContext context) {
final User currentUser = UserManager.getInstance().getCurrentUser();
final String firstName = currentUser.getFirstName();
final String name = currentUser.getName();
return getInitials(firstName, name);
}
 
public static void register() {
SpreadSheetCellValueProviderManager.put("InitialesUtilisateur", new UserCurrentInitialsValueProvider());
SpreadSheetCellValueProviderManager.put("user.current.initials", new UserCurrentInitialsValueProvider());
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/provider/UserCreateInitialsValueProvider.java
New file
0,0 → 1,34
/*
* 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.generationDoc.provider;
 
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueContext;
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueProviderManager;
import org.openconcerto.sql.model.SQLRowAccessor;
 
public class UserCreateInitialsValueProvider extends UserInitialsValueProvider {
 
@Override
public Object getValue(SpreadSheetCellValueContext context) {
final SQLRowAccessor rowUser = context.getRow().getForeign("ID_USER_COMMON_CREATE");
final String firstName = rowUser.getString("PRENOM");
final String name = rowUser.getString("NOM");
return getInitials(firstName, name);
}
 
public static void register() {
SpreadSheetCellValueProviderManager.put("InitialesUtilisateurCreate", new UserCreateInitialsValueProvider());
SpreadSheetCellValueProviderManager.put("user.create.initials", new UserCreateInitialsValueProvider());
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/provider/UserModifyInitialsValueProvider.java
New file
0,0 → 1,34
/*
* 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.generationDoc.provider;
 
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueContext;
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueProviderManager;
import org.openconcerto.sql.model.SQLRowAccessor;
 
public class UserModifyInitialsValueProvider extends UserInitialsValueProvider {
 
@Override
public Object getValue(SpreadSheetCellValueContext context) {
final SQLRowAccessor rowUser = context.getRow().getForeign("ID_USER_COMMON_MODIFY");
final String firstName = rowUser.getString("PRENOM");
final String name = rowUser.getString("NOM");
return getInitials(firstName, name);
}
 
public static void register() {
SpreadSheetCellValueProviderManager.put("InitialesUtilisateurModif", new UserModifyInitialsValueProvider());
SpreadSheetCellValueProviderManager.put("user.modify.initials", new UserModifyInitialsValueProvider());
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/shipment/component/BonDeLivraisonSQLComponent.java
15,6 → 15,7
 
import static org.openconcerto.utils.CollectionUtils.createSet;
import org.openconcerto.erp.core.common.component.TransfertBaseSQLComponent;
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement;
import org.openconcerto.erp.core.common.ui.DeviseField;
import org.openconcerto.erp.core.sales.invoice.element.SaisieVenteFactureItemSQLElement;
116,7 → 117,7
c.gridx = 0;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel addP = new JPanel();
final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
this.setAdditionalFieldsPanel(new FormLayouter(addP, 2));
this.add(addP, c);
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/credit/component/AvoirClientSQLComponent.java
17,6 → 17,7
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.component.SocieteCommonSQLElement;
import org.openconcerto.erp.core.common.component.TransfertBaseSQLComponent;
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement;
import org.openconcerto.erp.core.common.ui.AbstractArticleItemTable;
import org.openconcerto.erp.core.common.ui.DeviseField;
208,7 → 209,7
c.gridx = 0;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel addP = new JPanel();
final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
this.setAdditionalFieldsPanel(new FormLayouter(addP, 1));
this.add(addP, c);
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/order/component/CommandeClientSQLComponent.java
16,6 → 16,7
import static org.openconcerto.utils.CollectionUtils.createSet;
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.component.TransfertBaseSQLComponent;
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement;
import org.openconcerto.erp.core.common.ui.DeviseField;
import org.openconcerto.erp.core.common.ui.TotalPanel;
115,9 → 116,8
c.gridx = 0;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel addP = new JPanel();
final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
 
 
this.setAdditionalFieldsPanel(new FormLayouter(addP, 2));
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/invoice/component/SaisieVenteFactureSQLComponent.java
16,6 → 16,7
import static org.openconcerto.utils.CollectionUtils.createSet;
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.component.TransfertBaseSQLComponent;
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement;
import org.openconcerto.erp.core.common.ui.AbstractArticleItemTable;
import org.openconcerto.erp.core.common.ui.DeviseField;
191,7 → 192,7
c.gridx = 0;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel addP = new JPanel();
final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
this.setAdditionalFieldsPanel(new FormLayouter(addP, 1));
this.add(addP, c);
 
996,16 → 997,8
this.tableFacture.updateField("ID_SAISIE_VENTE_FACTURE", idSaisieVF);
 
 
// generation du document
final VenteFactureXmlSheet sheet = new VenteFactureXmlSheet(rowFacture);
createDocument(rowFacture);
 
try {
sheet.createDocumentAsynchronous();
sheet.showPrintAndExportAsynchronous(panelOO.isVisualisationSelected(), panelOO.isImpressionSelected(), true);
} catch (Exception e) {
ExceptionHandler.handle("Impossible de générer la facture", e);
}
 
int idMvt = -1;
if (getMode() == Mode.MODIFICATION) {
 
1102,6 → 1095,18
return idSaisieVF;
}
 
public void createDocument(SQLRow row) {
// generation du document
final VenteFactureXmlSheet sheet = new VenteFactureXmlSheet(row);
 
try {
sheet.createDocumentAsynchronous();
sheet.showPrintAndExportAsynchronous(panelOO.isVisualisationSelected(), panelOO.isImpressionSelected(), true);
} catch (Exception e) {
ExceptionHandler.handle("Impossible de générer la facture", e);
}
}
 
@Override
public void update() {
commit(null);
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/quote/component/DevisSQLComponent.java
15,6 → 15,7
 
import static org.openconcerto.utils.CollectionUtils.createSet;
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement;
import org.openconcerto.erp.core.common.ui.DeviseField;
import org.openconcerto.erp.core.common.ui.TotalPanel;
102,7 → 103,7
c.gridx = 0;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel addP = new JPanel();
final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
this.setAdditionalFieldsPanel(new FormLayouter(addP, 2));
this.add(addP, c);
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/product/component/ReferenceArticleSQLComponent.java
14,6 → 14,7
package org.openconcerto.erp.core.sales.product.component;
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.ui.DeviseField;
import org.openconcerto.erp.core.common.ui.TotalPanel;
import org.openconcerto.erp.core.finance.tax.model.TaxeCache;
321,7 → 322,7
c.gridx = 0;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel addP = new JPanel();
final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
this.setAdditionalFieldsPanel(new FormLayouter(addP, 2));
this.add(addP, c);
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/product/element/FamilleArticleSQLElement.java
94,7 → 94,7
c.gridx = 0;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel addP = new JPanel();
final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
 
this.setAdditionalFieldsPanel(new FormLayouter(addP, 2));
c.fill = GridBagConstraints.HORIZONTAL;
/trunk/OpenConcerto/src/org/openconcerto/erp/core/common/element/ComptaSQLConfElement.java
15,11 → 15,11
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.GlobalMapper;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.view.list.SQLTableModelColumn;
import org.openconcerto.sql.view.list.SQLTableModelSourceOnline;
import org.openconcerto.ui.AutoHideListener;
import org.openconcerto.ui.table.TableCellRendererUtils;
import org.openconcerto.utils.GestionDevise;
import org.openconcerto.utils.convertor.ValueConvertor;
29,6 → 29,7
import java.math.BigInteger;
 
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
57,6 → 58,10
}
};
 
static public final JPanel createAdditionalPanel() {
return AutoHideListener.listen(new JPanel());
}
 
private static DBRoot getBaseSociete() {
if (baseSociete == null)
baseSociete = ((ComptaPropsConfiguration) Configuration.getInstance()).getRootSociete();
/trunk/OpenConcerto/src/org/openconcerto/erp/core/common/element/LangueSQLElement.java
15,7 → 15,6
 
import org.openconcerto.sql.element.BaseSQLComponent;
import org.openconcerto.sql.element.SQLComponent;
import org.openconcerto.sql.sqlobject.ElementComboBox;
import org.openconcerto.ui.DefaultGridBagConstraints;
 
import java.awt.GridBagConstraints;
34,9 → 33,7
 
protected List<String> getListFields() {
final List<String> l = new ArrayList<String>();
 
l.add("NOM");
 
return l;
}
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/common/ui/TotalPanel.java
14,6 → 14,7
package org.openconcerto.erp.core.common.ui;
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.finance.tax.model.TaxeCache;
import org.openconcerto.erp.model.PrixHT;
import org.openconcerto.erp.preferences.DefaultNXProps;
import org.openconcerto.sql.Configuration;
408,11 → 409,13
Map<SQLRowAccessor, Long> mapHtTVA = new HashMap<SQLRowAccessor, Long>();
Map<SQLRowAccessor, Long> mapHtTVASel = new HashMap<SQLRowAccessor, Long>();
 
 
for (int i = 0; i < this.table.getRowValuesTableModel().getRowCount(); i++) {
 
Number nHT = (Number) this.table.getRowValuesTableModel().getValueAt(i, this.columnIndexHT);
totalHT += nHT.longValue();
 
// Total HA
if (this.gestionHA) {
Number nHA = (Number) this.table.getRowValuesTableModel().getValueAt(i, this.columnIndexHA);
Number nQte = (Number) this.table.getRowValuesTableModel().getValueAt(i, this.columnIndexQte);
422,6 → 425,8
totalHA += (nHA.longValue() * nQte.intValue());
}
}
 
// Total Service
String val = DefaultNXProps.getInstance().getStringProperty("ArticleService");
Boolean bServiceActive = Boolean.valueOf(val);
if (bServiceActive != null && bServiceActive) {
430,14 → 435,15
totalService += nHT.longValue();
}
}
 
// Total Devise
Number nDevise = null;
if (this.textTotalDevise != null) {
nDevise = (Number) this.table.getRowValuesTableModel().getValueAt(i, this.columnIndexDevise);
totalDevise += nDevise.longValue();
}
// Number nTTC = (Number) this.table.getRowValuesTableModel().getValueAt(i,
// this.columnIndexTTC);
// totalTTC += nTTC.longValue();
 
// Total TVA
if (mapHtTVA.get(this.table.getRowValuesTableModel().getRowValuesAt(i).getForeign("ID_TAXE")) == null) {
mapHtTVA.put(this.table.getRowValuesTableModel().getRowValuesAt(i).getForeign("ID_TAXE"), nHT.longValue());
} else {
445,9 → 451,11
mapHtTVA.put(this.table.getRowValuesTableModel().getRowValuesAt(i).getForeign("ID_TAXE"), l + nHT.longValue());
}
 
// Total Poids
Number nPoids = (Number) this.table.getRowValuesTableModel().getValueAt(i, this.columnIndexPoids);
totalPoids += nPoids == null ? 0 : nPoids.doubleValue();
 
// Calcul total sélectionné
if (containsInt(selectedRows, i)) {
 
totalHTSel += nHT.longValue();
482,6 → 490,7
}
}
 
// Frais de port à inclure
if (this.textPortHT.getText().trim().length() > 0) {
if (!this.textPortHT.getText().trim().equals("-")) {
valPortHT = GestionDevise.parseLongCurrency(this.textPortHT.getText().trim());
492,6 → 501,7
valPortHT = 0;
}
 
// Remise à inclure
if (this.textRemiseHT.getText().trim().length() > 0) {
if (!this.textRemiseHT.getText().trim().equals("-")) {
valRemiseHT = GestionDevise.parseLongCurrency(this.textRemiseHT.getText().trim());
508,7 → 518,7
 
long realTotalTVA = 0;
for (SQLRowAccessor row : mapHtTVA.keySet()) {
BigDecimal d = new BigDecimal(row.getFloat("TAUX"));
BigDecimal d = new BigDecimal(TaxeCache.getCache().getTauxFromId(row.getID()));
BigDecimal result = d.multiply(new BigDecimal(mapHtTVA.get(row)), MathContext.DECIMAL128).movePointLeft(2);
realTotalTVA += result.setScale(0, BigDecimal.ROUND_HALF_UP).longValue();
}
529,7 → 539,7
 
long realTotalTVASel = 0;
for (SQLRowAccessor row : mapHtTVASel.keySet()) {
BigDecimal d = new BigDecimal(row.getFloat("TAUX"));
BigDecimal d = new BigDecimal(TaxeCache.getCache().getTauxFromId(row.getID()));
BigDecimal result = d.multiply(new BigDecimal(mapHtTVASel.get(row)), MathContext.DECIMAL128).movePointLeft(2);
realTotalTVASel += result.setScale(0, BigDecimal.ROUND_HALF_UP).longValue();
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/credit/component/AvoirFournisseurSQLComponent.java
15,6 → 15,7
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.component.TransfertBaseSQLComponent;
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement;
import org.openconcerto.erp.core.common.ui.MontantPanel;
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement;
125,7 → 126,7
c.gridx = 0;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel addP = new JPanel();
final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
this.setAdditionalFieldsPanel(new FormLayouter(addP, 1));
this.add(addP, c);
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/component/CommandeSQLComponent.java
15,6 → 15,7
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.component.TransfertBaseSQLComponent;
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement;
import org.openconcerto.erp.core.common.ui.AbstractVenteArticleItemTable;
import org.openconcerto.erp.core.common.ui.DeviseField;
322,7 → 323,7
c.gridx = 0;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel addP = new JPanel();
final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
this.setAdditionalFieldsPanel(new FormLayouter(addP, 2));
this.add(addP, c);
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/component/SaisieAchatSQLComponent.java
13,6 → 13,7
package org.openconcerto.erp.core.supplychain.order.component;
 
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.ui.DeviseField;
import org.openconcerto.erp.core.common.ui.MontantPanel;
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement;
151,7 → 152,7
c.gridx = 0;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel addP = new JPanel();
final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
this.setAdditionalFieldsPanel(new FormLayouter(addP, 1));
this.add(addP, c);
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/receipt/component/BonReceptionSQLComponent.java
15,6 → 15,7
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.component.TransfertBaseSQLComponent;
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement;
import org.openconcerto.erp.core.common.ui.DeviseField;
import org.openconcerto.erp.core.sales.product.element.ReferenceArticleSQLElement;
96,7 → 97,7
c.gridx = 0;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel addP = new JPanel();
final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
this.setAdditionalFieldsPanel(new FormLayouter(addP, 1));
this.add(addP, c);
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/supplier/component/FournisseurSQLComponent.java
17,6 → 17,7
package org.openconcerto.erp.core.supplychain.supplier.component;
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.customerrelationship.customer.element.ContactItemTable;
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement;
import org.openconcerto.erp.model.ISQLCompteSelector;
188,7 → 189,7
c.gridx = 0;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel addP = new JPanel();
final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
this.setAdditionalFieldsPanel(new FormLayouter(addP, 2));
this.add(addP, c);
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/element/ClientNormalSQLComponent.java
45,6 → 45,7
import javax.swing.event.DocumentListener;
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.ui.DeviseField;
import org.openconcerto.erp.core.customerrelationship.customer.ui.AdresseClientItemTable;
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement;
344,7 → 345,7
c.gridx = 0;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel addP = new JPanel();
final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
this.setAdditionalFieldsPanel(new FormLayouter(addP, 1));
this.add(addP, c);
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/humanresources/employe/element/CommercialSQLComponent.java
16,6 → 16,7
*/
package org.openconcerto.erp.core.humanresources.employe.element;
 
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.humanresources.employe.panel.ObjectifEditPanel;
import org.openconcerto.sql.element.BaseSQLComponent;
import org.openconcerto.sql.element.SQLElement;
219,7 → 220,7
c.gridx = 0;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel addP = new JPanel();
final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
addP.setOpaque(false);
this.setAdditionalFieldsPanel(new FormLayouter(addP, 1));
panelInfos.add(addP, c);
/trunk/OpenConcerto/src/org/openconcerto/erp/panel/PanelOOSQLComponent.java
64,9 → 64,8
@Override
public SQLSelect transformChecked(SQLSelect input) {
SQLTable table = Configuration.getInstance().getDirectory().getElement("TYPE_MODELE").getTable();
Where w = new Where(table.getField("TABLE"), "=", comp.getElement().getTable().getName());
Where w = new Where(input.getAlias(table.getField("TABLE")), "=", comp.getElement().getTable().getName());
input.setWhere(w);
System.err.println(input.asString());
return input;
}
});
/trunk/OpenConcerto/src/org/openconcerto/erp/config/ComptaPropsConfiguration.java
135,6 → 135,10
import org.openconcerto.erp.core.supplychain.supplier.element.FournisseurSQLElement;
import org.openconcerto.erp.generationDoc.element.ModeleSQLElement;
import org.openconcerto.erp.generationDoc.element.TypeModeleSQLElement;
import org.openconcerto.erp.generationDoc.provider.PrixUnitaireRemiseProvider;
import org.openconcerto.erp.generationDoc.provider.UserCreateInitialsValueProvider;
import org.openconcerto.erp.generationDoc.provider.UserCurrentInitialsValueProvider;
import org.openconcerto.erp.generationDoc.provider.UserModifyInitialsValueProvider;
import org.openconcerto.erp.injector.ArticleCommandeEltSQLInjector;
import org.openconcerto.erp.injector.BonFactureSQLInjector;
import org.openconcerto.erp.injector.BrFactureAchatSQLInjector;
166,6 → 170,7
import org.openconcerto.sql.element.SharedSQLElement;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.model.DBSystemRoot;
import org.openconcerto.sql.model.LoadingListener;
import org.openconcerto.sql.model.SQLDataSource;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLServer;
179,6 → 184,7
import org.openconcerto.utils.NetUtils;
import org.openconcerto.utils.ProductInfo;
import org.openconcerto.utils.StringInputStream;
import org.openconcerto.utils.SwingWorker2;
 
import java.awt.Color;
import java.awt.Font;
192,7 → 198,6
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
201,8 → 206,14
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
 
import javax.imageio.ImageIO;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
321,7 → 332,9
 
//
String token = getToken();
SwingWorker2.setMaxWorkerThreads(4);
if (token != null) {
SwingWorker2.setMaxWorkerThreads(2);
this.isServerless = false;
this.isOnCloud = true;
if (this.getProperty("storage.server") == null) {
375,10 → 388,72
// ATTN this works because this is executed last (i.e. if you put this in a superclass
// this won't work since e.g. app.name won't have its correct value)
this.setupLogging("logs");
 
registerCellValueProvider();
UserRightsManager.getInstance().register(new ComptaTotalUserRight());
}
 
private void registerCellValueProvider() {
UserCreateInitialsValueProvider.register();
UserModifyInitialsValueProvider.register();
UserCurrentInitialsValueProvider.register();
PrixUnitaireRemiseProvider.register();
}
 
@Override
protected void initSystemRoot(DBSystemRoot input) {
super.initSystemRoot(input);
final JDialog f = new JOptionPane("Mise à jour des caches en cours...\nCette opération prend généralement moins d'une minute.", JOptionPane.INFORMATION_MESSAGE, JOptionPane.DEFAULT_OPTION,
null, new Object[] {}).createDialog("Veuillez patienter");
input.addLoadingListener(new LoadingListener() {
 
private int loadingCount = 0;
private final ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "Loading listener thread");
}
});
private ScheduledFuture<?> future = null;
 
@Override
public synchronized void loading(LoadingEvent evt) {
this.loadingCount += evt.isStarting() ? 1 : -1;
if (this.loadingCount < 0) {
throw new IllegalStateException();
} else if (this.loadingCount == 0) {
this.future.cancel(false);
this.future = null;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
f.setVisible(false);
}
});
} else if (this.future == null) {
this.future = this.exec.schedule(new Runnable() {
@Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
f.setVisible(true);
}
});
}
}, 1, TimeUnit.SECONDS);
}
}
});
}
 
@Override
protected void initDS(SQLDataSource ds) {
super.initDS(ds);
ds.setInitialSize(3);
ds.setMinIdle(2);
ds.setMaxActive(4);
}
 
public String getToken() {
return getProperty("token");
}
825,6 → 900,7
setSocieteShowAs();
setSocieteSQLInjector();
setMapper();
 
String sfe = DefaultNXProps.getInstance().getStringProperty("ArticleSFE");
Boolean bSfe = Boolean.valueOf(sfe);
boolean isSFE = bSfe != null && bSfe.booleanValue();
/trunk/OpenConcerto/src/org/openconcerto/erp/config/InstallationPanel.java
669,6 → 669,19
rowVals.commit();
}
 
// Ajout de la TVA à 0
SQLSelect selTVA = new SQLSelect(root.getBase());
SQLTable tableTaxe = root.getTable("TAXE");
selTVA.addSelect(tableTaxe.getKey(), "COUNT");
selTVA.setWhere(new Where(tableTaxe.getField("TAUX"), "=", 0));
Object result = root.getBase().getDataSource().executeScalar(selTVA.asString());
if (result == null || ((Number) result).longValue() == 0) {
SQLRowValues rowVals = new SQLRowValues(tableTaxe);
rowVals.put("NOM", "Non applicable");
rowVals.put("TAUX", Float.valueOf(0));
rowVals.commit();
}
 
// Bon de livraison
{
SQLTable tableBL = root.getTable("BON_DE_LIVRAISON");
/trunk/OpenConcerto/src/org/openconcerto/ui/component/IComboCacheListModel.java
14,6 → 14,7
package org.openconcerto.ui.component;
 
import org.openconcerto.ui.component.combo.ISearchableCombo;
import org.openconcerto.utils.SwingWorker2;
import org.openconcerto.utils.change.CollectionChangeEvent;
import org.openconcerto.utils.change.IListDataEvent;
import org.openconcerto.utils.model.DefaultIMutableListModel;
22,7 → 23,6
import java.util.Collection;
import java.util.List;
 
import javax.swing.SwingWorker;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
 
76,7 → 76,7
 
public final void load(final Runnable r, final boolean readCache) {
if (this.cache.isValid()) {
new SwingWorker<List<String>, Object>() {
new SwingWorker2<List<String>, Object>() {
 
@Override
protected List<String> doInBackground() throws Exception {
/trunk/OpenConcerto/src/org/openconcerto/ui/component/ITextCombo.java
22,6 → 22,7
import org.openconcerto.ui.valuewrapper.ValueChangeSupport;
import org.openconcerto.ui.valuewrapper.ValueWrapper;
import org.openconcerto.utils.CompareUtils;
import org.openconcerto.utils.SwingWorker2;
import org.openconcerto.utils.checks.ValidListener;
import org.openconcerto.utils.checks.ValidState;
import org.openconcerto.utils.model.ListComboBoxModel;
43,7 → 44,6
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.SwingWorker;
import javax.swing.event.DocumentEvent;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
301,7 → 301,7
this.setEnabled(false);
this.objToSelect = this.getValue();
this.cacheLoading = true;
final SwingWorker<List<String>, Object> sw = new SwingWorker<List<String>, Object>() {
final SwingWorker2<List<String>, Object> sw = new SwingWorker2<List<String>, Object>() {
@Override
protected List<String> doInBackground() throws Exception {
return force ? ITextCombo.this.cache.loadCache(false) : ITextCombo.this.cache.getCache();
/trunk/OpenConcerto/src/org/openconcerto/ui/AutoHideListener.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.ui;
 
import java.awt.Container;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
 
/**
* A listener that hides components when they're empty.
*
* @author Sylvain CUAZ
*/
public class AutoHideListener implements ContainerListener {
 
static private final AutoHideListener instance = new AutoHideListener();
 
static public <T extends Container> T listen(T comp) {
comp.addContainerListener(instance);
setVisible(comp);
return comp;
}
 
static public <T extends Container> T unlisten(T comp) {
comp.removeContainerListener(instance);
return comp;
}
 
static private void setVisible(Container comp) {
comp.setVisible(comp.getComponentCount() > 0);
}
 
// singleton
private AutoHideListener() {
}
 
@Override
public void componentAdded(ContainerEvent e) {
setVisible(e.getContainer());
}
 
@Override
public void componentRemoved(ContainerEvent e) {
setVisible(e.getContainer());
}
}
/trunk/OpenConcerto/src/org/openconcerto/sql/Configuration.java
30,6 → 30,8
 
import java.io.File;
import java.io.IOException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
 
/**
* Regroupe les objets nécessaires au framework.
56,6 → 58,8
Configuration.instance = instance;
}
 
private Executor nonInteractiveSQLExecutor;
 
public abstract ShowAs getShowAs();
 
public abstract SQLBase getBase();
143,4 → 147,15
* Signal that this conf will not be used anymore.
*/
public abstract void destroy();
 
public Executor getNonInteractiveSQLExecutor() {
if (nonInteractiveSQLExecutor == null) {
nonInteractiveSQLExecutor = createNonInteractiveSQLExecutor();
}
return nonInteractiveSQLExecutor;
}
 
protected Executor createNonInteractiveSQLExecutor() {
return Executors.newFixedThreadPool(2);
}
}
/trunk/OpenConcerto/src/org/openconcerto/sql/element/BaseSQLComponent.java
60,7 → 60,6
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
355,13 → 354,8
if (spec.isAdditional()) {
if (this.additionalFieldsPanel == null)
Log.get().warning("No additionalFieldsPanel for " + v.getField() + " : " + v);
else {
final Container component = this.additionalFieldsPanel.getComponent();
if (!component.isVisible()) {
component.setVisible(true);
}
else
this.additionalFieldsPanel.add(getDesc(v), v.getComp());
}
} else {
this.addToUI(v, spec.getWhere());
}
438,7 → 432,6
}
 
protected final void setAdditionalFieldsPanel(FormLayouter panel) {
panel.getComponent().setVisible(false);
this.additionalFieldsPanel = panel;
}
 
/trunk/OpenConcerto/src/org/openconcerto/sql/element/RowBacked.java
137,8 → 137,8
return this.r;
}
 
protected final SQLRow getSQLRow() {
return (SQLRow) this.getRow();
public final SQLRow getSQLRow() {
return this.getRow().asRow();
}
 
public final int getID() {
/trunk/OpenConcerto/src/org/openconcerto/sql/utils/ReOrder.java
13,8 → 13,10
package org.openconcerto.sql.utils;
 
import org.openconcerto.sql.model.ConnectionHandlerNoSetup;
import org.openconcerto.sql.model.FieldRef;
import org.openconcerto.sql.model.SQLBase;
import org.openconcerto.sql.model.SQLDataSource;
import org.openconcerto.sql.model.SQLField;
import org.openconcerto.sql.model.SQLSelect;
import org.openconcerto.sql.model.SQLSyntax;
22,7 → 24,6
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.request.UpdateBuilder;
import org.openconcerto.sql.utils.SQLUtils.SQLFactory;
 
import java.math.BigDecimal;
import java.sql.Connection;
102,12 → 103,12
 
// MAYBE return affected IDs
public final void exec() throws SQLException {
final Connection conn = this.t.getBase().getDataSource().getConnection();
final UpdateBuilder updateUndef = new UpdateBuilder(this.t).set(this.t.getOrderField().getName(), MIN_ORDER.toPlainString());
updateUndef.setWhere(new Where(this.t.getKey(), "=", this.t.getUndefinedID()));
SQLUtils.executeAtomic(conn, new SQLFactory<Object>() {
SQLUtils.executeAtomic(this.t.getBase().getDataSource(), new ConnectionHandlerNoSetup<Object, SQLException>() {
@Override
public Object create() throws SQLException {
public Object handle(SQLDataSource ds) throws SQLException, SQLException {
final Connection conn = ds.getConnection();
final Statement stmt = conn.createStatement();
if (isAll()) {
// reorder all, undef must be at 0
/trunk/OpenConcerto/src/org/openconcerto/sql/utils/BackupPanel.java
308,7 → 308,6
// FIXME Close Connection
 
try {
Configuration.getInstance().getBase().getDataSource().closeConnection();
Configuration.getInstance().getBase().getDataSource().close();
 
} catch (SQLException e) {
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLServer.java
16,6 → 16,7
*/
package org.openconcerto.sql.model;
 
import org.openconcerto.sql.model.LoadingListener.StructureLoadingEvent;
import org.openconcerto.sql.utils.SQL_URL;
import org.openconcerto.utils.CollectionUtils;
import org.openconcerto.utils.cc.CopyOnWriteMap;
23,6 → 24,7
import org.openconcerto.utils.cc.ITransformer;
import org.openconcerto.utils.change.CollectionChangeEventCreator;
 
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
206,15 → 208,23
if (this.getDS() != null) {
// for mysql we must know our children, since they can reference each other and thus the
// graph needs them
final StructureLoadingEvent evt = new StructureLoadingEvent(this, namesToRefresh);
try {
this.getDBSystemRoot().fireLoading(evt);
synchronized (this.getTreeMutex()) {
final Set<String> childrenToRefresh = CollectionUtils.inter(namesToRefresh, this.getChildrenNames());
// don't save the result in files since getCatalogs() is at least as quick as
// executing a request to check if the cache is obsolete
final Set<String> allCats;
final Connection conn = this.getDS().getNewConnection();
try {
@SuppressWarnings("unchecked")
final List<String> allCats = (List<String>) SQLDataSource.COLUMN_LIST_HANDLER.handle(this.getDS().getConnection().getMetaData().getCatalogs());
this.getDS().returnConnection();
final Set<String> cats = CollectionUtils.inter(namesToRefresh, new HashSet<String>(allCats));
final List<String> allCatsList = (List<String>) SQLDataSource.COLUMN_LIST_HANDLER.handle(conn.getMetaData().getCatalogs());
allCats = new HashSet<String>(allCatsList);
} finally {
this.getDS().returnConnection(conn);
}
final Set<String> cats = CollectionUtils.inter(namesToRefresh, allCats);
this.getDBSystemRoot().filterNodes(this, cats);
 
SQLBase.mustContain(this, cats, childrenToRefresh, "bases");
255,6 → 265,8
}
} catch (SQLException e) {
throw new IllegalStateException("could not get children names", e);
} finally {
this.getDBSystemRoot().fireLoading(evt.createFinishingEvent());
}
} else if (!init) {
throw new IllegalArgumentException("Cannot create bases since this server cannot have a connection");
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLSyntaxPG.java
292,10 → 292,20
// you can't specify line separator to pg, so use STDOUT as it always use \n
try {
final String sql = "COPY (" + selectAll(t).asString() + ") to STDOUT " + getDataOptions(t.getBase()) + " FORCE QUOTE " + cols + " ;";
final Connection conn = ((DelegatingConnection) t.getBase().getDataSource().getConnection()).getInnermostDelegate();
final FileOutputStream out = new FileOutputStream(f);
((PGConnection) conn).getCopyAPI().copyOut(sql, out);
t.getDBSystemRoot().getDataSource().useConnection(new ConnectionHandlerNoSetup<Number, IOException>() {
@Override
public Number handle(SQLDataSource ds) throws SQLException, IOException {
final Connection conn = ((DelegatingConnection) ds.getConnection()).getInnermostDelegate();
FileOutputStream out = null;
try {
out = new FileOutputStream(f);
return ((PGConnection) conn).getCopyAPI().copyOut(sql, out);
} finally {
if (out != null)
out.close();
}
}
});
} catch (Exception e) {
throw new IllegalStateException("unable to store " + t + " into " + f, e);
}
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLDataSource.java
154,9 → 154,6
private static int count = 0; // compteur de requetes
 
private final SQLServer server;
// une connexion par thread
@GuardedBy("this")
private final Map<Thread, Connection> connections;
// no need to synchronize multiple call to this attribute since we only access the
// Thread.currentThread() key
@GuardedBy("handlers")
165,9 → 162,6
@GuardedBy("this")
private ExecutorService exec = null;
 
@GuardedBy("this")
private CleanUp cleanUp;
 
// linked to initialSchema and uptodate
@GuardedBy("this")
private boolean initialShemaSet;
178,6 → 172,8
private final Map<Connection, Object> uptodate;
 
private volatile int retryWait;
@GuardedBy("this")
private boolean blockWhenExhausted;
 
private final ReentrantLock testLock = new ReentrantLock();
 
269,13 → 265,11
/* pour le clonage */
private SQLDataSource(SQLServer server) {
this.server = server;
this.connections = new HashMap<Thread, Connection>();
// on a besoin d'une implementation synchronisée
this.handlers = new Hashtable<Thread, HandlersStack>();
// weak, since this is only a hint to avoid initializing the connection
// on each borrowal
this.uptodate = new WeakHashMap<Connection, Object>();
this.cleanUp = null;
this.initialShemaSet = false;
this.initialShema = null;
 
289,6 → 283,7
this.setMinIdle(2);
// but not too much as it can lock out other users (the server has a max connection count)
this.setMaxIdle(16);
this.setBlockWhenExhausted(false);
// see #createDataSource() for properties not supported by this class
this.tables = Collections.emptySet();
this.cache = null;
445,6 → 440,7
try {
info = new QueryInfo(query, changeState, passedConn);
try {
long tStartSQL = System.nanoTime();
final Object[] res = this.executeTwice(info);
final Statement stmt = (Statement) res[0];
ResultSet rs = (ResultSet) res[1];
457,7 → 453,7
// }
// });
// and OK won't be returned if "req" returns a null rs.
durationSQL = System.nanoTime() - time;
durationSQL = System.nanoTime() - tStartSQL;
if (rsh != null && rs != null) {
if (this.getSystem() == SQLSystem.DERBY || this.getSystem() == SQLSystem.POSTGRESQL) {
rs = new SQLResultSet(rs);
948,18 → 944,7
// super close and unset our pool, but we need to keep it
// to allow used connections to be closed, see #closeConnection(Connection)
this.connectionPool = pool;
// cleanUp will be recreated if necessary
final CleanUp toStop = this.cleanUp;
this.cleanUp = null;
// happens if the datasource was never used
if (toStop != null)
toStop.interrupt();
// since we're stopping cleanUp we have to close connections
// if you don't want your connections to close at any time: #useConnection()
for (final Connection conn : this.connections.values()) {
this.closeConnection(conn);
}
this.connections.clear();
 
// interrupt to force waiting threads to close their connections
if (this.exec != null) {
this.exec.shutdownNow();
985,79 → 970,32
}
 
/**
* Invalide la connection actuelle.
* Retourne la connection à cette source de donnée.
*
* @return la connection à cette source de donnée.
* @throws IllegalStateException if not called from within useConnection().
* @see #useConnection(ConnectionHandler)
*/
public void closeConnection() {
this.releaseConnection(Thread.currentThread(), true);
public final Connection getConnection() {
final HandlersStack res = this.handlers.get(Thread.currentThread());
if (res == null)
throw new IllegalStateException("useConnection() wasn't called");
return res.getConnection();
}
 
/**
* Retourne la connexion actuelle dans le pool des connexions libres. Attention à partir de ce
* moment cette connexion peut être utilisée par d'autres.
*/
public void returnConnection() {
this.releaseConnection(Thread.currentThread(), false);
}
 
// remove the connection for the passed thread, the calling method must
// then return or close it otherwise it will stay borrowed.
protected synchronized Connection rmConnection(Thread th) {
return this.connections.remove(th);
}
 
public synchronized void releaseConnection(Thread th, final boolean close) {
if (this.handlers.containsKey(th)) {
if (close)
throw new IllegalArgumentException("cannot close the connection, it is in use by " + this.handlers.get(th));
// else nothing it will be released by useConnection().
Log.get().fine("ignoring " + close + " for " + th);
} else if (this.connections.containsKey(th)) {
if (close)
this.closeConnection(this.rmConnection(th));
else
this.returnConnection(this.rmConnection(th));
}
}
 
protected synchronized boolean isInCharge(final CleanUp cleanUp) {
return this.cleanUp == cleanUp;
}
 
final Set<Thread> getThreads(final Set<Thread> threads) {
threads.clear();
synchronized (this) {
threads.addAll(this.connections.keySet());
}
return threads;
}
 
/**
* Retourne une connection à cette source de donnée. Si la connexion échoue cette méthode va
* réessayer quelques secondes plus tard.
* Retourne une connection à cette source de donnée (generally
* {@link #useConnection(ConnectionHandler)} should be used). Si la connexion échoue cette
* méthode va réessayer quelques secondes plus tard.
* <p>
* Note : il y a une connexion par thread donc attention a ne pas créer d'instance de Thread a
* la pelle.
* Note : you <b>must</b> return this connection (e.g. use try/finally).
* <p>
*
* @return une connection à cette source de donnée.
* @see #returnConnection(Connection)
* @see #closeConnection(Connection)
*/
public Connection getConnection() {
return this.getConnection(Thread.currentThread());
}
 
private synchronized Connection getConnection(Thread th) {
if (this.handlers.containsKey(th)) {
return this.handlers.get(th).getConnection();
}
Connection res = this.connections.get(th);
if (res == null) {
res = this.getNewConnection();
this.connections.put(th, res);
}
return res;
}
 
private final Connection getNewConnection() {
protected final Connection getNewConnection() {
try {
return this.borrowConnection(false);
} catch (RTInterruptedException e) {
1122,6 → 1060,7
private static final String pgInterrupted = GT.tr("Interrupted while attempting to connect.");
 
private Connection getRawConnection() {
assert !Thread.holdsLock(this) : "super.getConnection() might block (see setWhenExhaustedAction()), and since return/closeConnection() need this lock, this method cannot wait while holding the lock";
Connection result = null;
try {
result = super.getConnection();
1153,10 → 1092,17
return this.connectionPool.getNumActive();
}
 
public synchronized final Set<Thread> getThreadsWithConnection() {
return this.connections.keySet();
public synchronized boolean blocksWhenExhausted() {
return this.blockWhenExhausted;
}
 
public synchronized void setBlockWhenExhausted(boolean block) {
this.blockWhenExhausted = block;
if (this.connectionPool != null) {
this.connectionPool.setWhenExhaustedAction(block ? GenericObjectPool.WHEN_EXHAUSTED_BLOCK : GenericObjectPool.WHEN_EXHAUSTED_GROW);
}
}
 
@Override
protected synchronized DataSource createDataSource() throws SQLException {
if (isClosed()) {
1163,9 → 1109,7
// initialize lotta things
super.createDataSource();
this.connectionPool.setLifo(true);
// don't block (threads block while owning SQLDataSource lock, thus preventing others
// from releasing connections)
this.connectionPool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW);
this.setBlockWhenExhausted(this.blockWhenExhausted);
// after 40s idle connections are closed
this.connectionPool.setTimeBetweenEvictionRunsMillis(4000);
this.connectionPool.setNumTestsPerEvictionRun(5);
1195,7 → 1139,6
throw new UnsupportedOperationException();
}
};
this.cleanUp = new CleanUp(15000);
}
return this.dataSource;
}
1277,10 → 1220,12
final Connection newConn = this.getNewConnection();
try {
this.setSchema(schemaName, newConn);
} finally {
} catch (RuntimeException e) {
this.closeConnection(newConn);
throw e;
}
this.setInitialSchema(true, schemaName);
this.returnConnection(newConn);
} else if (this.server.getSQLSystem().isDBPathEmpty()) {
this.unsetInitialSchema();
} else
1399,40 → 1344,4
ds.setDriverClassName(this.getDriverClassName());
return ds;
}
 
/**
* This thread periodically check for dead borrowers and return their connection.
*/
final private class CleanUp extends Thread {
private final int period;
 
public CleanUp(final int period) {
super("Clean up for " + SQLDataSource.this);
this.period = period;
this.setDaemon(true);
this.start();
}
 
public void run() {
final Set<Thread> threads = new HashSet<Thread>();
while (SQLDataSource.this.isInCharge(this)) {
for (final Thread th : getThreads(threads)) {
// a thread cannot re-live, so it's safe to return its connection
// likewise it's ok if it has already returned its connection
// (on its own, or even by another CleanUp instance)
if (!th.isAlive()) {
SQLDataSource.this.releaseConnection(th, false);
}
}
try {
Thread.sleep(this.period);
} catch (InterruptedException e) {
// ignore, ne s'arrêter que lorsque le while le dit
Log.get().fine("Interruption ignored for " + this);
}
}
Log.get().fine("done " + this);
}
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLRowListRSH.java
24,6 → 24,37
 
public final class SQLRowListRSH implements ResultSetHandler {
 
// hashCode()/equals() needed for data source cache
private static final class RSH implements ResultSetHandler {
private final Tuple2<SQLTable, List<String>> names;
 
private RSH(Tuple2<SQLTable, List<String>> names) {
this.names = names;
}
 
@Override
public List<SQLRow> handle(ResultSet rs) throws SQLException {
return SQLRow.createListFromRS(this.names.get0(), rs, this.names.get1());
}
 
@Override
public int hashCode() {
return this.names.hashCode();
}
 
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final RSH other = (RSH) obj;
return this.names.equals(other.names);
}
}
 
private static Tuple2<SQLTable, List<String>> getIndexes(SQLSelect sel, final SQLTable passedTable, final boolean findTable) {
final List<SQLField> selectFields = sel.getSelectFields();
final int size = selectFields.size();
80,13 → 111,8
}
 
static private ResultSetHandler create(final Tuple2<SQLTable, List<String>> names) {
return new ResultSetHandler() {
@Override
public Object handle(ResultSet rs) throws SQLException {
return SQLRow.createListFromRS(names.get0(), rs, names.get1());
return new RSH(names);
}
};
}
 
@SuppressWarnings("unchecked")
static public List<SQLRow> execute(final SQLSelect sel) {
/trunk/OpenConcerto/src/org/openconcerto/sql/model/graph/Path.java
288,6 → 288,10
return this.add(item.getLabel());
}
 
public final List<Step> getSteps() {
return Collections.unmodifiableList(this.fields);
}
 
/**
* The step connecting the table i to i+1.
*
/trunk/OpenConcerto/src/org/openconcerto/sql/model/DBSystemRoot.java
14,6 → 14,9
package org.openconcerto.sql.model;
 
import org.openconcerto.sql.Log;
import org.openconcerto.sql.model.LoadingListener.GraphLoadingEvent;
import org.openconcerto.sql.model.LoadingListener.LoadingChangeSupport;
import org.openconcerto.sql.model.LoadingListener.LoadingEvent;
import org.openconcerto.sql.model.graph.DatabaseGraph;
import org.openconcerto.utils.CollectionUtils;
import org.openconcerto.utils.cc.IClosure;
65,6 → 68,8
private boolean incoherentPath;
private final PropertyChangeListener coherenceListener;
 
private final LoadingChangeSupport loadingListenersSupp;
 
DBSystemRoot(DBStructureItemJDBC delegate) {
super(delegate);
this.graph = null;
80,6 → 85,7
rootsChanged(evt);
}
};
this.loadingListenersSupp = new LoadingChangeSupport(this);
 
this.getServer().init(this);
}
240,12 → 246,16
synchronized (this.getTreeMutex()) {
synchronized (this.graphMutex) {
if (this.graph == null) {
final LoadingEvent evt = new GraphLoadingEvent(this);
try {
fireLoading(evt);
// keep new DatabaseGraph() inside the synchronized to prevent two
// concurrent expensive creations
this.setGraph(new DatabaseGraph(this));
} catch (SQLException e) {
throw new IllegalStateException("could not graph " + this, e);
} finally {
fireLoading(evt.createFinishingEvent());
}
}
return this.graph;
307,6 → 317,23
}
 
/**
* Adds a listener for this and its children.
*
* @param l the listener.
*/
public final void addLoadingListener(LoadingListener l) {
this.loadingListenersSupp.addLoadingListener(l);
}
 
final void fireLoading(LoadingEvent evt) {
this.loadingListenersSupp.fireLoading(evt);
}
 
public final void removeLoadingListener(LoadingListener l) {
this.loadingListenersSupp.removeLoadingListener(l);
}
 
/**
* Add the passed roots to {@link #getRootsToMap()} and to root path and {@link #reload(Set)}.
*
* @param roots the roots names to add.
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLTable.java
173,8 → 173,9
private Set<Constraint> constraints;
// always immutable so that fire can iterate safely ; to modify it, simply copy it before
// (adding listeners is a lot less common than firing events)
@GuardedBy("this")
@GuardedBy("listenersMutex")
private List<SQLTableModifiedListener> tableModifiedListeners;
private final Object listenersMutex = new String("tableModifiedListeners mutex");
// the id that foreign keys pointing to this, can use instead of NULL
// a null value meaning not yet known
@GuardedBy("this")
395,13 → 396,17
}
 
// must be called in setState() after fields have been set (for isRowable())
synchronized private int fetchUndefID() {
private int fetchUndefID() {
final int res;
if (isRowable()) {
final SQLField pk;
synchronized (this) {
pk = isRowable() ? this.getKey() : null;
}
if (pk != null) {
final Tuple2<Boolean, Number> currentValue = getUndefID(this.getSchema(), this.getName());
if (!currentValue.get0()) {
// no row
res = this.findMinID();
res = this.findMinID(pk);
} else {
// a row
final Number id = currentValue.get1();
413,7 → 418,7
}
 
// no undef id found
synchronized private int findMinID() {
private int findMinID(SQLField pk) {
final String debugUndef = "fwk_sql.debug.undefined_id";
if (System.getProperty(debugUndef) != null)
Log.get().warning("The system property '" + debugUndef + "' is deprecated, use the '" + UNDEFINED_ID_POLICY + "' metadata");
420,7 → 425,7
 
final String policy = getSchema().getFwkMetadata(UNDEFINED_ID_POLICY);
if (Boolean.getBoolean(debugUndef) || "min".equals(policy)) {
final SQLSelect sel = new SQLSelect(this.getBase(), true).addSelect(this.getKey(), "min");
final SQLSelect sel = new SQLSelect(this.getBase(), true).addSelect(pk, "min");
final Number undef = (Number) this.getBase().getDataSource().executeScalar(sel.asString());
if (undef == null) {
// empty table
983,6 → 988,10
* @return the empty id or {@link SQLRow#NONEXISTANT_ID} if this table has no UNDEFINED_ID.
*/
public final int getUndefinedID() {
return this.getUndefinedID(false).intValue();
}
 
private final Integer getUndefinedID(final boolean internal) {
Integer res = null;
synchronized (this) {
if (this.undefinedID != null)
989,16 → 998,14
res = this.undefinedID;
}
if (res == null) {
if (this.getSchema().isFetchAllUndefinedIDs()) {
if (!internal && this.getSchema().isFetchAllUndefinedIDs()) {
// init all undefined, MAYBE one request with UNION ALL
for (final SQLTable sibling : this.getSchema().getTables()) {
synchronized (sibling) {
if (sibling.undefinedID == null)
sibling.undefinedID = sibling.fetchUndefID();
Integer siblingRes = getUndefinedID(true);
assert siblingRes != null;
if (sibling == this)
res = sibling.undefinedID;
res = siblingRes;
}
}
// save all tables
this.getBase().save(this.getSchema().getName());
} else {
1006,10 → 1013,11
synchronized (this) {
this.undefinedID = res;
}
if (!internal)
this.save();
}
}
return res.intValue();
return res;
}
 
public final Number getUndefinedIDNumber() {
1046,7 → 1054,7
}
 
private void addTableModifiedListener(SQLTableModifiedListener l, final boolean before) {
synchronized (this) {
synchronized (this.listenersMutex) {
final List<SQLTableModifiedListener> newListeners = new ArrayList<SQLTableModifiedListener>(this.tableModifiedListeners.size() + 1);
if (before)
newListeners.add(l);
1058,7 → 1066,7
}
 
public void removeTableModifiedListener(SQLTableModifiedListener l) {
synchronized (this) {
synchronized (this.listenersMutex) {
final List<SQLTableModifiedListener> newListeners = new ArrayList<SQLTableModifiedListener>(this.tableModifiedListeners);
if (newListeners.remove(l))
this.tableModifiedListeners = Collections.unmodifiableList(newListeners);
1169,7 → 1177,7
private void fireTableModified(final SQLTableEvent evt) {
// no need to copy since this.tableModifiedListeners is immutable
final List<SQLTableModifiedListener> dispatchingListeners;
synchronized (this) {
synchronized (this.listenersMutex) {
dispatchingListeners = this.tableModifiedListeners;
}
fireTableModified(Tuple2.create(dispatchingListeners.iterator(), evt));
/trunk/OpenConcerto/src/org/openconcerto/sql/model/LoadingListener.java
New file
0,0 → 1,130
/*
* 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.sql.model;
 
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
 
import net.jcip.annotations.ThreadSafe;
 
/**
* The listener interface for receiving loading events.
*/
public interface LoadingListener {
 
static public abstract class LoadingEvent {
private final DBStructureItem<?> source;
private final boolean starting;
 
public LoadingEvent(final DBStructureItem<?> source) {
this(source, true);
}
 
protected LoadingEvent(final DBStructureItem<?> source, boolean starting) {
super();
this.source = source;
this.starting = starting;
}
 
public final DBStructureItem<?> getSource() {
return this.source;
}
 
public final boolean isStarting() {
return this.starting;
}
 
public abstract LoadingEvent createFinishingEvent();
}
 
static public class GraphLoadingEvent extends LoadingEvent {
 
public GraphLoadingEvent(DBSystemRoot source) {
super(source);
}
 
protected GraphLoadingEvent(DBSystemRoot source, boolean starting) {
super(source, starting);
}
 
@Override
public GraphLoadingEvent createFinishingEvent() {
return new GraphLoadingEvent((DBSystemRoot) getSource(), false);
}
 
@Override
public String toString() {
return this.getClass().getSimpleName() + (this.isStarting() ? " starting" : " finishing") + " loading of " + this.getSource();
}
}
 
static public class StructureLoadingEvent extends LoadingEvent {
private final Set<String> children;
 
public StructureLoadingEvent(final DBStructureItemJDBC source, Set<String> children) {
this(source, true, children);
}
 
protected StructureLoadingEvent(final DBStructureItemJDBC source, boolean starting, Set<String> children) {
super(source, starting);
this.children = children;
}
 
public final Set<String> getChildren() {
return this.children;
}
 
@Override
public final StructureLoadingEvent createFinishingEvent() {
if (!this.isStarting())
throw new IllegalStateException("Already a finishing event");
return new StructureLoadingEvent((DBStructureItemJDBC) this.getSource(), false, this.children);
}
 
@Override
public String toString() {
final String children = this.getChildren() == null ? "all children" : this.getChildren().toString();
return this.getClass().getSimpleName() + (this.isStarting() ? " starting" : " finishing") + " loading " + children + " of " + this.getSource();
}
}
 
@ThreadSafe
static public class LoadingChangeSupport {
private final DBSystemRoot source;
private final List<LoadingListener> loadingListeners;
 
public LoadingChangeSupport(DBSystemRoot source) {
this.source = source;
this.loadingListeners = new ArrayList<LoadingListener>(4);
}
 
public synchronized final void addLoadingListener(LoadingListener l) {
this.loadingListeners.add(l);
}
 
public synchronized final void removeLoadingListener(LoadingListener l) {
this.loadingListeners.remove(l);
}
 
public synchronized void fireLoading(LoadingEvent evt) {
assert evt.getSource().getDBSystemRoot() == this.source;
for (final LoadingListener l : this.loadingListeners) {
l.loading(evt);
}
}
}
 
void loading(LoadingEvent evt);
}
/trunk/OpenConcerto/src/org/openconcerto/sql/model/DBStructureItem.java
125,6 → 125,10
 
public abstract void rmChildrenListener(final PropertyChangeListener l);
 
public final D getSibling(String name) {
return this.getParent().getChild(name);
}
 
// ** far
 
public final D getDescendant(SQLName name) {
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLBase.java
17,6 → 17,8
package org.openconcerto.sql.model;
 
import org.openconcerto.sql.Log;
import org.openconcerto.sql.model.LoadingListener.LoadingEvent;
import org.openconcerto.sql.model.LoadingListener.StructureLoadingEvent;
import org.openconcerto.sql.model.StructureSource.PrechangeException;
import org.openconcerto.sql.model.graph.DatabaseGraph;
import org.openconcerto.utils.CollectionUtils;
199,8 → 201,15
}
 
private JDBCStructureSource fetchTablesP(Set<String> childrenNames, Map<String, SQLSchema> newStruct) throws SQLException {
final LoadingEvent evt = new StructureLoadingEvent(this, childrenNames);
final DBSystemRoot sysRoot = this.getDBSystemRoot();
try {
sysRoot.fireLoading(evt);
return this.refreshTables(new JDBCStructureSource(this, childrenNames, newStruct));
} finally {
sysRoot.fireLoading(evt.createFinishingEvent());
}
}
 
public final Set<String> loadTables() throws SQLException {
return this.loadTables(null);
/trunk/OpenConcerto/src/org/openconcerto/sql/users/UserManager.java
70,7 → 70,7
fetcher.setOrdered(true);
for (final SQLRowValues v : fetcher.fetch()) {
final User u = new User(v.getID(), v.getString("NOM"));
u.setLastName(v.getString("PRENOM"));
u.setFirstName(v.getString("PRENOM"));
u.setNickName(v.getString("SURNOM"));
this.byID.put(v.getID(), u);
}
/trunk/OpenConcerto/src/org/openconcerto/sql/users/User.java
17,7 → 17,7
 
public class User {
private final int id;
private String name, lastName, nickName;
private String name, firstName, nickName;
private final UserRights userRights;
 
public User(int id, String name) {
43,8 → 43,8
return this.getFullName() + " /" + getId();
}
 
public void setLastName(String string) {
this.lastName = string;
public void setFirstName(String string) {
this.firstName = string;
}
 
public void setNickName(String string) {
51,8 → 51,8
this.nickName = string;
}
 
public String getLastName() {
return this.lastName;
public String getFirstName() {
return this.firstName;
}
 
public String getNickName() {
60,7 → 60,7
}
 
public String getFullName() {
return getLastName() + " " + getName();
return getFirstName() + " " + getName();
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/MoveQueue.java
20,8 → 20,8
import org.openconcerto.utils.SleepingQueue;
 
import java.sql.SQLException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
 
final class MoveQueue extends SleepingQueue {
 
35,27 → 35,21
public void move(final int id, final int inc) {
this.put(new Runnable() {
public void run() {
final AtomicReference<Integer> destID = new AtomicReference<Integer>();
final CountDownLatch latch = new CountDownLatch(1);
MoveQueue.this.tableModel.invokeLater(new Runnable() {
public void run() {
destID.set(MoveQueue.this.tableModel.getDestID(id, inc));
latch.countDown();
final FutureTask<Integer> destID = new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() {
return MoveQueue.this.tableModel.getDestID(id, inc);
}
});
MoveQueue.this.tableModel.invokeLater(destID);
try {
latch.await();
} catch (InterruptedException e) {
throw ExceptionUtils.createExn(IllegalStateException.class, "move failed", e);
}
if (destID.get() != null) {
try {
moveQuick(id, destID.get());
} catch (SQLException e) {
}
} catch (Exception e) {
throw ExceptionUtils.createExn(IllegalStateException.class, "move failed", e);
}
}
}
});
}
 
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/KeyTableCellRenderer.java
13,6 → 13,7
package org.openconcerto.sql.view.list;
 
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLTableEvent;
86,7 → 87,7
 
private void loadCacheAsynchronous() {
this.isLoading = true;
final Thread thread = new Thread(new Runnable() {
Configuration.getInstance().getNonInteractiveSQLExecutor().execute(new Runnable() {
public void run() {
List<IComboSelectionItem> items = KeyTableCellRenderer.this.el.getComboRequest().getComboItems();
final Map<Integer, IComboSelectionItem> m = new HashMap<Integer, IComboSelectionItem>();
111,6 → 112,6
}
}
});
thread.start();
 
}
}
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/IListe.java
134,7 → 134,7
*
* @author ILM Informatique
*/
public final class IListe extends JPanel implements AncestorListener {
public final class IListe extends JPanel {
 
static private final class FormatRenderer extends DefaultTableCellRenderer {
private final Format fmt;
644,7 → 644,27
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());
this.addAncestorListener(this);
this.addAncestorListener(new AncestorListener() {
 
// these callbacks are called later than the change, and by that time the visibility
// might have changed several times thus use isVisible() to avoid flip-flopping for
// nothing
 
@Override
public void ancestorRemoved(AncestorEvent event) {
visibilityChanged();
}
 
@Override
public void ancestorAdded(AncestorEvent event) {
visibilityChanged();
}
 
@Override
public void ancestorMoved(AncestorEvent event) {
// nothing to do
}
});
// we used to rm this listener, possibly to avoid events once dead, but this doesn't seem
// necessary anymore
this.jTable.getSelectionModel().addListSelectionListener(this.selectionListener);
1003,32 → 1023,14
getModel().rmPropertyChangeListener(l);
}
 
// *** Ancestors ***//
 
@Override
public void ancestorAdded(AncestorEvent event) {
// there was an if added in r989, but from the javadoc it isn't needed
assert event.getAncestor().isVisible();
// ancestorAdded means we've just been added to a visible hierarchy, not that we were added
// to our parent
this.getModel().setSleeping(false);
}
 
@Override
public void ancestorRemoved(AncestorEvent event) {
protected final void visibilityChanged() {
// test isDead() since in JComponent.removeNotify() first setDisplayable(false) (in super)
// then firePropertyChange("ancestor", null).
// thus we can still be visible while not displayable anymore
assert !event.getAncestor().isVisible() || !event.getAncestor().isDisplayable();
if (!this.isDead())
this.getModel().setSleeping(true);
this.getModel().setSleeping(!this.isVisible());
}
 
@Override
public void ancestorMoved(AncestorEvent event) {
// nothing to do
}
 
public void setSQLEditable(boolean b) {
this.getModel().setEditable(b);
}
/trunk/OpenConcerto/src/org/openconcerto/sql/PropsConfiguration.java
381,6 → 381,7
@Override
public void executeChecked(final DBSystemRoot input) {
input.getRootsToMap().addAll(getRootsToMap());
initSystemRoot(input);
}
}, new IClosure<SQLDataSource>() {
@Override
476,6 → 477,10
return res;
}
 
// called at the end of the DBSystemRoot constructor (before having a data source)
protected void initSystemRoot(DBSystemRoot input) {
}
 
protected void initDS(final SQLDataSource ds) {
ds.setCacheEnabled(true);
propIterate(new IClosure<String>() {
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/ConnexionPanel.java
17,6 → 17,7
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.preferences.UserProps;
import org.openconcerto.sql.request.ComboSQLRequest;
import org.openconcerto.sql.sqlobject.IComboModel;
import org.openconcerto.sql.sqlobject.IComboSelectionItem;
import org.openconcerto.sql.sqlobject.SQLRequestComboBox;
68,7 → 69,8
if (Boolean.getBoolean(QUICK_LOGIN) && lastLogin.length() > 0 && pass != null && (!societeSelector || UserProps.getInstance().getLastSocieteID() >= SQLRow.MIN_VALID_ID)) {
final Tuple2<String, String> res = new Login(Configuration.getInstance().getRoot()).connectEnc(lastLogin, pass);
if (res.get0() == null) {
r.run();
// ConnexionPanel normally executes r outside of the EDT, do the same
execute(r);
// no need to display a panel
return true;
}
226,7 → 228,10
}
 
this.comboSociete = new SQLRequestComboBox(false, 25);
final IComboModel model = new IComboModel(Configuration.getInstance().getDirectory().getElement(tableSociete).getComboRequest());
final ComboSQLRequest req = Configuration.getInstance().getDirectory().getElement(tableSociete).getComboRequest(true);
// keep rows for checkValidity()
req.keepRows(true);
final IComboModel model = new IComboModel(req);
final int lastSociete = UserProps.getInstance().getLastSocieteID();
if (lastSociete >= SQLRow.MIN_VALID_ID) {
model.setValue(lastSociete);
280,7 → 285,7
panelButton.add(this.reloadPanel, c2);
c2.gridx++;
c2.weightx = 0;
buttonConnect.setOpaque(false);
this.buttonConnect.setOpaque(false);
panelButton.add(this.buttonConnect, c2);
 
c.gridy++;
325,12 → 330,15
 
setConnecting(true);
 
final Thread t = new Thread(new Runnable() {
execute(new Runnable() {
public void run() {
connect();
}
});
t.setName("ConnexionPanel Login");
}
 
static private void execute(Runnable runnable) {
final Thread t = new Thread(runnable, "ConnexionPanel Login");
t.setPriority(Thread.MIN_PRIORITY);
t.start();
}
/trunk/OpenConcerto/src/org/openconcerto/sql/sqlobject/ITextWithCompletion.java
21,6 → 21,7
import org.openconcerto.sql.request.ComboSQLRequest;
import org.openconcerto.ui.component.text.TextComponent;
import org.openconcerto.utils.OrderedSet;
import org.openconcerto.utils.SwingWorker2;
import org.openconcerto.utils.checks.MutableValueObject;
import org.openconcerto.utils.model.DefaultIMutableListModel;
import org.openconcerto.utils.text.DocumentFilterList;
50,7 → 51,6
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AbstractDocument;
258,7 → 258,7
synchronized (this) {
this.isLoading = true;
}
final SwingWorker worker = new SwingWorker<Object, Object>() {
final SwingWorker2<Object, Object> worker = new SwingWorker2<Object, Object>() {
 
// Runs on the event-dispatching thread.
@Override
/trunk/OpenConcerto/src/org/openconcerto/sql/sqlobject/IComboModel.java
24,6 → 24,7
import org.openconcerto.sql.view.search.SearchSpecUtils;
import org.openconcerto.ui.component.combo.Log;
import org.openconcerto.utils.RTInterruptedException;
import org.openconcerto.utils.SwingWorker2;
import org.openconcerto.utils.cc.ITransformer;
import org.openconcerto.utils.checks.EmptyChangeSupport;
import org.openconcerto.utils.checks.EmptyListener;
42,7 → 43,6
import java.util.concurrent.ExecutionException;
 
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
 
68,7 → 68,7
private final PropertyChangeSupport propSupp;
 
// est ce que la combo va se remplir, access must be synchronized
private SwingWorker<?, ?> willUpdate;
private SwingWorker2<?, ?> willUpdate;
protected final List<Runnable> runnables;
// true from when the combo is filled with the sole "dots" item until it is loaded with actual
// items, no need to synchronize (EDT)
280,7 → 280,7
// copy the current search, if it changes fillCombo() will be called
final SearchSpec search = this.getSearch();
// commencer l'update après, sinon modeToSelect == 0
final SwingWorker<List<IComboSelectionItem>, Object> worker = new SwingWorker<List<IComboSelectionItem>, Object>() {
final SwingWorker2<List<IComboSelectionItem>, Object> worker = new SwingWorker2<List<IComboSelectionItem>, Object>() {
 
@Override
protected List<IComboSelectionItem> doInBackground() throws InterruptedException {
663,7 → 663,7
return this.getSearch() != null && !this.getSearch().isEmpty();
}
 
private synchronized void setWillUpdate(SwingWorker<?, ?> w) {
private synchronized void setWillUpdate(SwingWorker2<?, ?> w) {
this.willUpdate = w;
this.propSupp.firePropertyChange("willUpdate", null, this.willUpdate);
if (this.willUpdate == null) {
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/ITransformer.java
13,8 → 13,9
package org.openconcerto.utils.cc;
 
public interface ITransformer<E, T> {
public interface ITransformer<E, T> extends ITransformerExn<E, T, RuntimeException> {
 
@Override
public abstract T transformChecked(E input);
 
}
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/ExnTransformer.java
26,7 → 26,7
* @param <T> return type
* @param <X> exception type
*/
public abstract class ExnTransformer<E, T, X extends Exception> implements Transformer {
public abstract class ExnTransformer<E, T, X extends Exception> implements Transformer, ITransformerExn<E, T, X> {
 
@SuppressWarnings("unchecked")
public final Object transform(Object input) {
92,6 → 92,7
}
}
 
@Override
public abstract T transformChecked(E input) throws X;
 
}
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/ITransformerExn.java
New file
0,0 → 1,20
/*
* 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.cc;
 
public interface ITransformerExn<E, T, X extends Exception> {
 
public abstract T transformChecked(E input) throws X;
 
}
/trunk/OpenConcerto/src/org/openconcerto/utils/OSXAdapter.java
70,7 → 70,10
 
package org.openconcerto.utils;
 
import java.lang.reflect.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
public class OSXAdapter implements InvocationHandler {
 
/trunk/OpenConcerto/src/org/openconcerto/utils/Messages.java
15,7 → 15,6
 
 
 
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
 
/trunk/OpenConcerto/src/org/openconcerto/utils/html/HTMLManipulatorFrame.java
16,7 → 16,6
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/trunk/OpenConcerto/src/org/openconcerto/utils/SwingWorker2.java
New file
0,0 → 1,808
/*
* 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.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ThreadFactory;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
 
import sun.awt.AppContext;
import sun.swing.AccumulativeRunnable;
 
/**
* An abstract class to perform lengthy GUI-interacting tasks in a dedicated thread.
*
* <p>
* When writing a multi-threaded application using Swing, there are two constraints to keep in mind:
* (refer to <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html"> How to Use
* Threads </a> for more details):
* <ul>
* <li>Time-consuming tasks should not be run on the <i>Event Dispatch Thread</i>. Otherwise the
* application becomes unresponsive.</li>
* <li>Swing components should be accessed on the <i>Event Dispatch Thread</i> only.</li>
* </ul>
*
* <p>
*
* <p>
* These constraints mean that a GUI application with time intensive computing needs at least two
* threads: 1) a thread to perform the lengthy task and 2) the <i>Event Dispatch Thread</i> (EDT)
* for all GUI-related activities. This involves inter-thread communication which can be tricky to
* implement.
*
* <p>
* {@code SwingWorker2} is designed for situations where you need to have a long running task run in
* a background thread and provide updates to the UI either when done, or while processing.
* Subclasses of {@code SwingWorker2} must implement the {@link #doInBackground} method to perform
* the background computation.
*
*
* <p>
* <b>Workflow</b>
* <p>
* There are three threads involved in the life cycle of a {@code SwingWorker2} :
* <ul>
* <li>
* <p>
* <i>Current</i> thread: The {@link #execute} method is called on this thread. It schedules
* {@code SwingWorker2} for the execution on a <i>worker</i> thread and returns immediately. One can
* wait for the {@code SwingWorker2} to complete using the {@link #get get} methods.
* <li>
* <p>
* <i>Worker</i> thread: The {@link #doInBackground} method is called on this thread. This is where
* all background activities should happen. To notify {@code PropertyChangeListeners} about bound
* properties changes use the {@link #firePropertyChange firePropertyChange} and
* {@link #getPropertyChangeSupport} methods. By default there are two bound properties available:
* {@code state} and {@code progress}.
* <li>
* <p>
* <i>Event Dispatch Thread</i>: All Swing related activities occur on this thread.
* {@code SwingWorker2} invokes the {@link #process process} and {@link #done} methods and notifies
* any {@code PropertyChangeListeners} on this thread.
* </ul>
*
* <p>
* Often, the <i>Current</i> thread is the <i>Event Dispatch Thread</i>.
*
*
* <p>
* Before the {@code doInBackground} method is invoked on a <i>worker</i> thread,
* {@code SwingWorker2} notifies any {@code PropertyChangeListeners} about the {@code state}
* property change to {@code StateValue.STARTED}. After the {@code doInBackground} method is
* finished the {@code done} method is executed. Then {@code SwingWorker2} notifies any
* {@code PropertyChangeListeners} about the {@code state} property change to
* {@code StateValue.DONE}.
*
* <p>
* {@code SwingWorker2} is only designed to be executed once. Executing a {@code SwingWorker2} more
* than once will not result in invoking the {@code doInBackground} method twice.
*
* <p>
* <b>Sample Usage</b>
* <p>
* The following example illustrates the simplest use case. Some processing is done in the
* background and when done you update a Swing component.
*
* <p>
* Say we want to find the "Meaning of Life" and display the result in a {@code JLabel}.
*
* <pre>
* final JLabel label;
* class MeaningOfLifeFinder extends SwingWorker2&lt;String, Object&gt; {
* {@code @Override}
* public String doInBackground() {
* return findTheMeaningOfLife();
* }
*
* {@code @Override}
* protected void done() {
* try {
* label.setText(get());
* } catch (Exception ignore) {
* }
* }
* }
*
* (new MeaningOfLifeFinder()).execute();
* </pre>
*
* <p>
* The next example is useful in situations where you wish to process data as it is ready on the
* <i>Event Dispatch Thread</i>.
*
* <p>
* Now we want to find the first N prime numbers and display the results in a {@code JTextArea}.
* While this is computing, we want to update our progress in a {@code JProgressBar}. Finally, we
* also want to print the prime numbers to {@code System.out}.
*
* <pre>
* class PrimeNumbersTask extends
* SwingWorker2&lt;List&lt;Integer&gt;, Integer&gt; {
* PrimeNumbersTask(JTextArea textArea, int numbersToFind) {
* //initialize
* }
*
* {@code @Override}
* public List&lt;Integer&gt; doInBackground() {
* while (! enough &amp;&amp; ! isCancelled()) {
* number = nextPrimeNumber();
* publish(number);
* setProgress(100 * numbers.size() / numbersToFind);
* }
* }
* return numbers;
* }
*
* {@code @Override}
* protected void process(List&lt;Integer&gt; chunks) {
* for (int number : chunks) {
* textArea.append(number + &quot;\n&quot;);
* }
* }
* }
*
* JTextArea textArea = new JTextArea();
* final JProgressBar progressBar = new JProgressBar(0, 100);
* PrimeNumbersTask task = new PrimeNumbersTask(textArea, N);
* task.addPropertyChangeListener(
* new PropertyChangeListener() {
* public void propertyChange(PropertyChangeEvent evt) {
* if (&quot;progress&quot;.equals(evt.getPropertyName())) {
* progressBar.setValue((Integer)evt.getNewValue());
* }
* }
* });
*
* task.execute();
* System.out.println(task.get()); //prints all prime numbers we have got
* </pre>
*
* <p>
* Because {@code SwingWorker2} implements {@code Runnable}, a {@code SwingWorker2} can be submitted
* to an {@link java.util.concurrent.Executor} for execution.
*
* @author Igor Kushnirskiy
* @version %I% %G%
*
* @param <T> the result type returned by this {@code SwingWorker2's} {@code doInBackground} and
* {@code get} methods
* @param <V> the type used for carrying out intermediate results by this {@code SwingWorker2's}
* {@code publish} and {@code process} methods
*
* @since 1.6
*/
public abstract class SwingWorker2<T, V> implements RunnableFuture<T> {
/**
* number of worker threads.
*/
private static int maxWorkerThreads = 10;
 
/**
* current progress.
*/
private volatile int progress;
 
/**
* current state.
*/
private volatile StateValue state;
 
/**
* everything is run inside this FutureTask. Also it is used as a delegatee for the Future API.
*/
private final FutureTask<T> future;
 
/**
* all propertyChangeSupport goes through this.
*/
private final PropertyChangeSupport propertyChangeSupport;
 
/**
* handler for {@code process} mehtod.
*/
private AccumulativeRunnable<V> doProcess;
 
/**
* handler for progress property change notifications.
*/
private AccumulativeRunnable<Integer> doNotifyProgressChange;
 
private final AccumulativeRunnable<Runnable> doSubmit = getDoSubmit();
 
/**
* Values for the {@code state} bound property.
*
* @since 1.6
*/
public enum StateValue {
/**
* Initial {@code SwingWorker2} state.
*/
PENDING,
/**
* {@code SwingWorker2} is {@code STARTED} before invoking {@code doInBackground}.
*/
STARTED,
 
/**
* {@code SwingWorker2} is {@code DONE} after {@code doInBackground} method is finished.
*/
DONE
};
 
/**
* Constructs this {@code SwingWorker2}.
*/
public SwingWorker2() {
Callable<T> callable = new Callable<T>() {
public T call() throws Exception {
setState(StateValue.STARTED);
return doInBackground();
}
};
 
future = new FutureTask<T>(callable) {
@Override
protected void done() {
doneEDT();
setState(StateValue.DONE);
}
};
 
state = StateValue.PENDING;
propertyChangeSupport = new SwingWorker2PropertyChangeSupport(this);
doProcess = null;
doNotifyProgressChange = null;
}
 
/**
* Defines the maximum number of threads the worker will use It MUST be called before the first
* SwingWorker2 use
*
* @param max the max number of threads
* */
public static void setMaxWorkerThreads(int max) {
maxWorkerThreads = max;
}
 
/**
* Computes a result, or throws an exception if unable to do so.
*
* <p>
* Note that this method is executed only once.
*
* <p>
* Note: this method is executed in a background thread.
*
*
* @return the computed result
* @throws Exception if unable to compute a result
*
*/
protected abstract T doInBackground() throws Exception;
 
/**
* Sets this {@code Future} to the result of computation unless it has been cancelled.
*/
public final void run() {
future.run();
}
 
/**
* Sends data chunks to the {@link #process} method. This method is to be used from inside the
* {@code doInBackground} method to deliver intermediate results for processing on the <i>Event
* Dispatch Thread</i> inside the {@code process} method.
*
* <p>
* Because the {@code process} method is invoked asynchronously on the <i>Event Dispatch
* Thread</i> multiple invocations to the {@code publish} method might occur before the
* {@code process} method is executed. For performance purposes all these invocations are
* coalesced into one invocation with concatenated arguments.
*
* <p>
* For example:
*
* <pre>
* publish(&quot;1&quot;);
* publish(&quot;2&quot;, &quot;3&quot;);
* publish(&quot;4&quot;, &quot;5&quot;, &quot;6&quot;);
* </pre>
*
* might result in:
*
* <pre>
* process(&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;, &quot;6&quot;)
* </pre>
*
* <p>
* <b>Sample Usage</b>. This code snippet loads some tabular data and updates
* {@code DefaultTableModel} with it. Note that it safe to mutate the tableModel from inside the
* {@code process} method because it is invoked on the <i>Event Dispatch Thread</i>.
*
* <pre>
* class TableSwingWorker2 extends
* SwingWorker2&lt;DefaultTableModel, Object[]&gt; {
* private final DefaultTableModel tableModel;
*
* public TableSwingWorker2(DefaultTableModel tableModel) {
* this.tableModel = tableModel;
* }
*
* {@code @Override}
* protected DefaultTableModel doInBackground() throws Exception {
* for (Object[] row = loadData();
* ! isCancelled() &amp;&amp; row != null;
* row = loadData()) {
* publish((Object[]) row);
* }
* return tableModel;
* }
*
* {@code @Override}
* protected void process(List&lt;Object[]&gt; chunks) {
* for (Object[] row : chunks) {
* tableModel.addRow(row);
* }
* }
* }
* </pre>
*
* @param chunks intermediate results to process
*
* @see #process
*
*/
protected final void publish(V... chunks) {
synchronized (this) {
if (doProcess == null) {
doProcess = new AccumulativeRunnable<V>() {
@Override
public void run(List<V> args) {
process(args);
}
 
@Override
protected void submit() {
doSubmit.add(this);
}
};
}
}
doProcess.add(chunks);
}
 
/**
* Receives data chunks from the {@code publish} method asynchronously on the <i>Event Dispatch
* Thread</i>.
*
* <p>
* Please refer to the {@link #publish} method for more details.
*
* @param chunks intermediate results to process
*
* @see #publish
*
*/
protected void process(List<V> chunks) {
}
 
/**
* Executed on the <i>Event Dispatch Thread</i> after the {@code doInBackground} method is
* finished. The default implementation does nothing. Subclasses may override this method to
* perform completion actions on the <i>Event Dispatch Thread</i>. Note that you can query
* status inside the implementation of this method to determine the result of this task or
* whether this task has been cancelled.
*
* @see #doInBackground
* @see #isCancelled()
* @see #get
*/
protected void done() {
}
 
/**
* Sets the {@code progress} bound property. The value should be from 0 to 100.
*
* <p>
* Because {@code PropertyChangeListener}s are notified asynchronously on the <i>Event Dispatch
* Thread</i> multiple invocations to the {@code setProgress} method might occur before any
* {@code PropertyChangeListeners} are invoked. For performance purposes all these invocations
* are coalesced into one invocation with the last invocation argument only.
*
* <p>
* For example, the following invokations:
*
* <pre>
* setProgress(1);
* setProgress(2);
* setProgress(3);
* </pre>
*
* might result in a single {@code PropertyChangeListener} notification with the value {@code 3}.
*
* @param progress the progress value to set
* @throws IllegalArgumentException is value not from 0 to 100
*/
protected final void setProgress(int progress) {
if (progress < 0 || progress > 100) {
throw new IllegalArgumentException("the value should be from 0 to 100");
}
if (this.progress == progress) {
return;
}
int oldProgress = this.progress;
this.progress = progress;
if (!getPropertyChangeSupport().hasListeners("progress")) {
return;
}
synchronized (this) {
if (doNotifyProgressChange == null) {
doNotifyProgressChange = new AccumulativeRunnable<Integer>() {
@Override
public void run(List<Integer> args) {
firePropertyChange("progress", args.get(0), args.get(args.size() - 1));
}
 
@Override
protected void submit() {
doSubmit.add(this);
}
};
}
}
doNotifyProgressChange.add(oldProgress, progress);
}
 
/**
* Returns the {@code progress} bound property.
*
* @return the progress bound property.
*/
public final int getProgress() {
return progress;
}
 
/**
* Schedules this {@code SwingWorker2} for execution on a <i>worker</i> thread. There are a
* number of <i>worker</i> threads available. In the event all <i>worker</i> threads are busy
* handling other {@code SwingWorker2s} this {@code SwingWorker2} is placed in a waiting queue.
*
* <p>
* Note: {@code SwingWorker2} is only designed to be executed once. Executing a
* {@code SwingWorker2} more than once will not result in invoking the {@code doInBackground}
* method twice.
*/
public final void execute() {
getWorkersExecutorService().execute(this);
}
 
// Future methods START
/**
* {@inheritDoc}
*/
public final boolean cancel(boolean mayInterruptIfRunning) {
return future.cancel(mayInterruptIfRunning);
}
 
/**
* {@inheritDoc}
*/
public final boolean isCancelled() {
return future.isCancelled();
}
 
/**
* {@inheritDoc}
*/
public final boolean isDone() {
return future.isDone();
}
 
/**
* {@inheritDoc}
* <p>
* Note: calling {@code get} on the <i>Event Dispatch Thread</i> blocks <i>all</i> events,
* including repaints, from being processed until this {@code SwingWorker2} is complete.
*
* <p>
* When you want the {@code SwingWorker2} to block on the <i>Event Dispatch Thread</i> we
* recommend that you use a <i>modal dialog</i>.
*
* <p>
* For example:
*
* <pre>
* class SwingWorker2CompletionWaiter extends PropertyChangeListener {
* private JDialog dialog;
*
* public SwingWorker2CompletionWaiter(JDialog dialog) {
* this.dialog = dialog;
* }
*
* public void propertyChange(PropertyChangeEvent event) {
* if (&quot;state&quot;.equals(event.getPropertyName()) &amp;&amp; SwingWorker2.StateValue.DONE == event.getNewValue()) {
* dialog.setVisible(false);
* dialog.dispose();
* }
* }
* }
* JDialog dialog = new JDialog(owner, true);
* swingWorker.addPropertyChangeListener(new SwingWorker2CompletionWaiter(dialog));
* swingWorker.execute();
* // the dialog will be visible until the SwingWorker2 is done
* dialog.setVisible(true);
* </pre>
*/
public final T get() throws InterruptedException, ExecutionException {
return future.get();
}
 
/**
* {@inheritDoc}
* <p>
* Please refer to {@link #get} for more details.
*/
public final T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return future.get(timeout, unit);
}
 
// Future methods END
 
// PropertyChangeSupports methods START
/**
* Adds a {@code PropertyChangeListener} to the listener list. The listener is registered for
* all properties. The same listener object may be added more than once, and will be called as
* many times as it is added. If {@code listener} is {@code null}, no exception is thrown and no
* action is taken.
*
* <p>
* Note: This is merely a convenience wrapper. All work is delegated to
* {@code PropertyChangeSupport} from {@link #getPropertyChangeSupport}.
*
* @param listener the {@code PropertyChangeListener} to be added
*/
public final void addPropertyChangeListener(PropertyChangeListener listener) {
getPropertyChangeSupport().addPropertyChangeListener(listener);
}
 
/**
* Removes a {@code PropertyChangeListener} from the listener list. This removes a
* {@code PropertyChangeListener} that was registered for all properties. If {@code listener}
* was added more than once to the same event source, it will be notified one less time after
* being removed. If {@code listener} is {@code null}, or was never added, no exception is
* thrown and no action is taken.
*
* <p>
* Note: This is merely a convenience wrapper. All work is delegated to
* {@code PropertyChangeSupport} from {@link #getPropertyChangeSupport}.
*
* @param listener the {@code PropertyChangeListener} to be removed
*/
public final void removePropertyChangeListener(PropertyChangeListener listener) {
getPropertyChangeSupport().removePropertyChangeListener(listener);
}
 
/**
* Reports a bound property update to any registered listeners. No event is fired if {@code old}
* and {@code new} are equal and non-null.
*
* <p>
* This {@code SwingWorker2} will be the source for any generated events.
*
* <p>
* When called off the <i>Event Dispatch Thread</i> {@code PropertyChangeListeners} are notified
* asynchronously on the <i>Event Dispatch Thread</i>.
* <p>
* Note: This is merely a convenience wrapper. All work is delegated to
* {@code PropertyChangeSupport} from {@link #getPropertyChangeSupport}.
*
*
* @param propertyName the programmatic name of the property that was changed
* @param oldValue the old value of the property
* @param newValue the new value of the property
*/
public final void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
getPropertyChangeSupport().firePropertyChange(propertyName, oldValue, newValue);
}
 
/**
* Returns the {@code PropertyChangeSupport} for this {@code SwingWorker2}. This method is used
* when flexible access to bound properties support is needed.
* <p>
* This {@code SwingWorker2} will be the source for any generated events.
*
* <p>
* Note: The returned {@code PropertyChangeSupport} notifies any {@code PropertyChangeListener}s
* asynchronously on the <i>Event Dispatch Thread</i> in the event that
* {@code firePropertyChange} or {@code fireIndexedPropertyChange} are called off the <i>Event
* Dispatch Thread</i>.
*
* @return {@code PropertyChangeSupport} for this {@code SwingWorker2}
*/
public final PropertyChangeSupport getPropertyChangeSupport() {
return propertyChangeSupport;
}
 
// PropertyChangeSupports methods END
 
/**
* Returns the {@code SwingWorker2} state bound property.
*
* @return the current state
*/
public final StateValue getState() {
/*
* DONE is a speacial case to keep getState and isDone is sync
*/
if (isDone()) {
return StateValue.DONE;
} else {
return state;
}
}
 
/**
* Sets this {@code SwingWorker2} state bound property.
*
* @param state the state to set
*/
private void setState(StateValue state) {
StateValue old = this.state;
this.state = state;
firePropertyChange("state", old, state);
}
 
/**
* Invokes {@code done} on the EDT.
*/
private void doneEDT() {
Runnable doDone = new Runnable() {
public void run() {
done();
}
};
if (SwingUtilities.isEventDispatchThread()) {
doDone.run();
} else {
doSubmit.add(doDone);
}
}
 
/**
* returns workersExecutorService.
*
* returns the service stored in the appContext or creates it if necessary.
*
* @return ExecutorService for the {@code SwingWorker2s}
*/
private static synchronized ExecutorService getWorkersExecutorService() {
final AppContext appContext = AppContext.getAppContext();
ExecutorService executorService = (ExecutorService) appContext.get(SwingWorker2.class);
if (executorService == null) {
// this creates daemon threads.
ThreadFactory threadFactory = new ThreadFactory() {
final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
 
public Thread newThread(final Runnable r) {
Thread thread = defaultFactory.newThread(r);
thread.setName("SwingWorker2-" + thread.getName());
thread.setDaemon(true);
return thread;
}
};
 
executorService = new ThreadPoolExecutor(maxWorkerThreads, maxWorkerThreads, 10L, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(), threadFactory);
 
appContext.put(SwingWorker2.class, executorService);
 
// Don't use ShutdownHook here as it's not enough. We should track
// AppContext disposal instead of JVM shutdown, see 6799345 for details
final ExecutorService es = executorService;
 
appContext.addPropertyChangeListener(AppContext.DISPOSED_PROPERTY_NAME, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent pce) {
boolean disposed = (Boolean) pce.getNewValue();
if (disposed) {
final WeakReference<ExecutorService> executorServiceRef = new WeakReference<ExecutorService>(es);
final ExecutorService executorService = executorServiceRef.get();
if (executorService != null) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
executorService.shutdown();
return null;
}
});
}
}
}
});
}
return executorService;
}
 
private static final Object DO_SUBMIT_KEY = new Object(); // doSubmit
 
private static AccumulativeRunnable<Runnable> getDoSubmit() {
synchronized (DO_SUBMIT_KEY) {
final AppContext appContext = AppContext.getAppContext();
Object doSubmit = appContext.get(DO_SUBMIT_KEY);
if (doSubmit == null) {
doSubmit = new DoSubmitAccumulativeRunnable();
appContext.put(DO_SUBMIT_KEY, doSubmit);
}
return (AccumulativeRunnable<Runnable>) doSubmit;
}
}
 
private static class DoSubmitAccumulativeRunnable extends AccumulativeRunnable<Runnable> implements ActionListener {
private final static int DELAY = (int) (1000 / 30);
 
@Override
protected void run(List<Runnable> args) {
for (Runnable runnable : args) {
runnable.run();
}
}
 
@Override
protected void submit() {
Timer timer = new Timer(DELAY, this);
timer.setRepeats(false);
timer.start();
}
 
public void actionPerformed(ActionEvent event) {
run();
}
}
 
private class SwingWorker2PropertyChangeSupport extends PropertyChangeSupport {
SwingWorker2PropertyChangeSupport(Object source) {
super(source);
}
 
@Override
public void firePropertyChange(final PropertyChangeEvent evt) {
if (SwingUtilities.isEventDispatchThread()) {
super.firePropertyChange(evt);
} else {
doSubmit.add(new Runnable() {
public void run() {
SwingWorker2PropertyChangeSupport.this.firePropertyChange(evt);
}
});
}
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/task/TodoListPanel.java
249,7 → 249,7
c.weighty = 0;
c.gridwidth = 6;
// SEP
TitledSeparator sep = new TitledSeparator(currentUser.getLastName() + " " + currentUser.getName().toUpperCase() + " Tâches en cours...");
TitledSeparator sep = new TitledSeparator(currentUser.getFirstName() + " " + currentUser.getName().toUpperCase() + " Tâches en cours...");
this.add(sep, c);
 
c.gridwidth = 1;
/trunk/OpenConcerto/src/org/openconcerto/task/ui/UserRightPanelDetail.java
225,7 → 225,7
 
this.selectedUser = selectedUser;
 
labelDocumentation1.setText(" Autorisations de l'utilisateur " + selectedUser.getLastName() + " " + selectedUser.getName());
labelDocumentation1.setText(" Autorisations de l'utilisateur " + selectedUser.getFirstName() + " " + selectedUser.getName());
labelDocumentation2.setText(" Double cliquez sur un nom d'une des colonnes suivantes pour activer/désactiver le droit correspondant.");
List<UserTaskRight> l = UserTaskRight.getUserTaskRight(selectedUser);
cellRenderer1.setUserTaskRight(l);
/trunk/OpenConcerto/src/org/openconcerto/task/ui/UserListCellRenderer.java
24,7 → 24,7
 
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
User user=(User)value;
String newValue=user.getLastName()+" "+user.getName();
String newValue=user.getFirstName()+" "+user.getName();
return super.getListCellRendererComponent(list, newValue, index, isSelected, cellHasFocus);
}
 
/trunk/OpenConcerto/src/org/openconcerto/task/ui/UserTaskRightListCellRenderer.java
38,7 → 38,7
 
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
User user = (User) value;
String newValue = user.getLastName() + " " + user.getName();
String newValue = user.getFirstName() + " " + user.getName();
Component c = super.getListCellRendererComponent(list, newValue, index, false, cellHasFocus);
setForeground(Color.LIGHT_GRAY);
if (usersRight != null) {
/trunk/OpenConcerto/src/product.properties
1,2 → 1,2
NAME=OpenConcerto
VERSION=1.2b4
VERSION=1.2b5