Dépôt officiel du code source de l'ERP OpenConcerto
/trunk/OpenConcerto/lib/jOpenDocument-1.4rc2.jar |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/OpenConcerto/lib/jOpenCalendar.jar |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/OpenConcerto/src/org/jopendocument/link/OOConnexion.java |
---|
84,8 → 84,14 |
perms.add(new RuntimePermission("modifyThread")); |
// needed by PrinterJob.getPrinterJob() |
perms.add(new RuntimePermission("queuePrintJob")); |
// ProcessBuilder.start() calls SecurityManager.checkExec() which requires |
// absolute path (or execute on "<<ALL FILES>>") |
// needed by OOConnexion.init() to find the port |
perms.add(new FilePermission("/usr/bin/lsof", "execute")); |
// macOS path |
perms.add(new FilePermission("/usr/sbin/lsof", "execute")); |
perms.add(new FilePermission("/bin/ps", "execute")); |
perms.add(new FilePermission("C:/Windows/System32/tasklist.exe", "execute")); |
perms.add(new RuntimePermission("getenv.*")); |
/trunk/OpenConcerto/src/org/jopendocument/link/OOInstallation.java |
---|
102,10 → 102,14 |
rootPaths.addAll(Arrays.asList(loRootPaths)); |
rootPaths.addAll(Arrays.asList(ooRootPaths)); |
} |
for (final String p : rootPaths) { |
if (DesktopEnvironment.test("reg", "query", p)) |
// On force à chercher dans le registre 64 bits sinon il va chercher dans le registre 32 |
// bits si os 64b et VM 32b |
if (DesktopEnvironment.test("reg", "query", p, "/reg:64")) |
return p; |
} |
return null; |
} |
123,7 → 127,8 |
// all string values for the passed registry path |
private static Map<String, String> getStringValues(final String path, final String option) throws IOException { |
final Map<String, String> values = new HashMap<String, String>(); |
final String out = DesktopEnvironment.cmdSubstitution(Runtime.getRuntime().exec(new String[] { "reg", "query", path, option })); |
// On force /reg:64 (utile si on utilise une VM 32 avec un systeme 64 bits) |
final String out = DesktopEnvironment.cmdSubstitution(Runtime.getRuntime().exec(new String[] { "reg", "query", path, option, "/reg:64" })); |
final Matcher matcher = stringValuePattern.matcher(out); |
while (matcher.find()) { |
values.put(matcher.group(1), matcher.group(2)); |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/generation/view/BaseGenerationRapport.java |
---|
93,7 → 93,7 |
private JComboBox<FileAction> fileActionCombo; |
private JList<GenerationTask> tasksView; |
private JLabel status; |
private final JLabel status; |
// le groupe dans lequel doivent être toutes les thread de la génération |
private final ThreadGroup thg; |
100,7 → 100,7 |
public BaseGenerationRapport() throws JDOMException, IOException { |
this.thg = new ThreadGroup(this + " thread group"); |
this.uiInit(); |
this.status = new JLabel(); |
this.setStatus("Inactif"); |
} |
112,7 → 112,7 |
return null; |
} |
private void uiInit() throws JDOMException, IOException { |
protected final void uiInit() throws JDOMException, IOException { |
setLayout(new GridBagLayout()); |
final GridBagConstraints c = new GridBagConstraints(); |
c.ipadx = 40; |
171,7 → 171,6 |
c.gridx = 0; |
c.gridy++; |
c.gridwidth = GridBagConstraints.REMAINDER; |
this.status = new JLabel(); |
this.add(this.status, c); |
c.gridy++; |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/cellFormat.ods |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/NumberStyle.java |
---|
18,7 → 18,6 |
import org.openconcerto.openoffice.ODValueType; |
import org.openconcerto.openoffice.XMLVersion; |
import org.openconcerto.openoffice.spreadsheet.CellStyle; |
import org.openconcerto.openoffice.spreadsheet.MutableCell; |
import java.util.Calendar; |
import java.util.Date; |
89,7 → 88,7 |
} else if (elem.getName().equals("fraction")) { |
// TODO fractions |
reportError("Fractions not supported", lenient); |
sb.append(MutableCell.formatNumber(n, defaultStyle)); |
sb.append(getPackage().formatNumber(n, defaultStyle)); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/DataStyle.java |
---|
27,10 → 27,12 |
import java.math.RoundingMode; |
import java.text.DecimalFormat; |
import java.text.DecimalFormatSymbols; |
import java.util.Arrays; |
import java.util.Collections; |
import java.util.HashSet; |
import java.util.List; |
import java.util.Locale; |
import java.util.Map.Entry; |
import java.util.Set; |
import java.util.SortedMap; |
45,7 → 47,11 |
// from section 16.27 in v1.2-cs01-part1 |
public abstract class DataStyle extends Style { |
private static final int DEFAULT_GROUPING_SIZE = new DecimalFormat().getGroupingSize(); |
public static final int DEFAULT_DECIMAL_PLACES = 10; |
// 15 as of LibreOffice 6, was 10 earlier |
/** |
* The default number of decimal digits if neither defined in the style nor in default-style. |
*/ |
public static final int DEFAULT_DECIMAL_PLACES = Integer.parseInt(System.getProperty("openDocument.defaultDecimalPlaces", "15")); |
private static final Pattern QUOTE_PATRN = Pattern.compile("'", Pattern.LITERAL); |
private static final Pattern EXP_PATTERN = Pattern.compile("E(\\d+)$"); |
85,8 → 91,7 |
super(clazz, version, elemName, baseName); |
this.setElementNS(getVersion().getNS("number")); |
// from 19.469 in v1.2-cs01-part1 |
this.getRefElementsMap().addAll( |
"style:data-style-name", |
this.getRefElementsMap().addAll("style:data-style-name", |
Arrays.asList("presentation:date-time-decl", "style:style", "text:creation-date", "text:creation-time", "text:database-display", "text:date", "text:editing-duration", |
"text:expression", "text:meta-field", "text:modification-date", "text:modification-time", "text:print-date", "text:print-time", "text:table-formula", "text:time", |
"text:user-defined", "text:user-field-get", "text:user-field-input", "text:variable-get", "text:variable-input", "text:variable-set")); |
176,6 → 181,15 |
throw new UnsupportedOperationException(msg); |
} |
public final Locale getLocale() { |
return this.getLocale(this.getElement()); |
} |
protected final Locale getLocale(final Element elem) { |
final Locale res = DateStyle.getElementLocale(elem); |
return res != null ? res : this.getPackage().getLocale(); |
} |
protected final String formatNumberOrScientificNumber(final Element elem, final Number n, CellStyle defaultStyle) { |
return this.formatNumberOrScientificNumber(elem, n, 1, defaultStyle); |
} |
243,7 → 257,9 |
numberSB.append('0'); |
} |
final DecimalFormat decFormat = new DecimalFormat(numberSB.toString()); |
final DecimalFormatSymbols symbols = new DecimalFormatSymbols(this.getLocale()); |
final DecimalFormat decFormat = new DecimalFormat(numberSB.toString(), symbols); |
// Java always use HALF_EVEN |
decFormat.setRoundingMode(RoundingMode.HALF_UP); |
decFormat.setGroupingUsed(grouping); |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/CurrencyStyle.java |
---|
63,7 → 63,7 |
if (elem.getTextTrim().length() > 0) { |
sb.append(elem.getText()); |
} else { |
sb.append(new DecimalFormatSymbols(DateStyle.getLocale(elem)).getCurrencySymbol()); |
sb.append(new DecimalFormatSymbols(this.getLocale(elem)).getCurrencySymbol()); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/DateStyle.java |
---|
54,7 → 54,7 |
return !"long".equals(elem.getAttributeValue("style", elem.getNamespace("number"))); |
} |
public static final Locale getLocale(final Element elem) { |
static final Locale getElementLocale(final Element elem) { |
final Locale res; |
final String country = elem.getAttributeValue("country", elem.getNamespace()); |
final String lang = elem.getAttributeValue("language", elem.getNamespace()); |
61,7 → 61,7 |
if (lang != null) { |
res = new Locale(lang, country == null ? "" : country); |
} else { |
res = Locale.getDefault(); |
res = null; |
} |
return res; |
} |
123,7 → 123,7 |
public String format(Object o, CellStyle defaultStyle, boolean lenient) { |
final Date d = o instanceof Calendar ? ((Calendar) o).getTime() : (Date) o; |
final Namespace numberNS = this.getElement().getNamespace(); |
final Locale styleLocale = getLocale(getElement()); |
final Locale styleLocale = this.getLocale(); |
final Calendar styleCalendar = Calendar.getInstance(styleLocale); |
final StringBuilder res = new StringBuilder(); |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/TimeStyle.java |
---|
69,7 → 69,7 |
final Namespace numberNS = this.getElement().getNamespace(); |
final StringBuilder sb = new StringBuilder(); |
final Locale styleLocale = DateStyle.getLocale(getElement()); |
final Locale styleLocale = this.getLocale(); |
final boolean truncate = StyleProperties.parseBoolean(getElement().getAttributeValue("truncate-on-overflow", numberNS), true); |
@SuppressWarnings("unchecked") |
final List<Element> children = this.getElement().getChildren(); |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/BooleanStyle.java |
---|
66,7 → 66,7 |
public String format(Object o, CellStyle defaultStyle, boolean lenient) { |
final Boolean b = (Boolean) o; |
final Namespace numberNS = this.getElement().getNamespace(); |
final Locale styleLocale = DateStyle.getLocale(getElement()); |
final Locale styleLocale = this.getLocale(); |
final StringBuilder sb = new StringBuilder(); |
@SuppressWarnings("unchecked") |
final List<Element> children = this.getElement().getChildren(); |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/cellFormat.fods |
---|
New file |
0,0 → 1,629 |
<?xml version="1.0" encoding="UTF-8"?> |
<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.spreadsheet"> |
<office:meta><meta:creation-date>2011-08-18T14:24:40.28</meta:creation-date><dc:date>2019-03-18T16:35:20.347078479</dc:date><meta:editing-duration>PT12H49M11S</meta:editing-duration><meta:editing-cycles>46</meta:editing-cycles><meta:generator>LibreOffice/6.0.7.3$Linux_X86_64 LibreOffice_project/00m0$Build-3</meta:generator><dc:description>20120330: changed locale of A1 to german</dc:description><meta:document-statistic meta:table-count="1" meta:cell-count="38" meta:object-count="0"/></office:meta> |
<office:settings> |
<config:config-item-set config:name="ooo:view-settings"> |
<config:config-item config:name="VisibleAreaTop" config:type="int">0</config:config-item> |
<config:config-item config:name="VisibleAreaLeft" config:type="int">0</config:config-item> |
<config:config-item config:name="VisibleAreaWidth" config:type="int">12671</config:config-item> |
<config:config-item config:name="VisibleAreaHeight" config:type="int">9203</config:config-item> |
<config:config-item-map-indexed config:name="Views"> |
<config:config-item-map-entry> |
<config:config-item config:name="ViewId" config:type="string">view1</config:config-item> |
<config:config-item-map-named config:name="Tables"> |
<config:config-item-map-entry config:name="Feuille1"> |
<config:config-item config:name="CursorPositionX" config:type="int">1</config:config-item> |
<config:config-item config:name="CursorPositionY" config:type="int">22</config:config-item> |
<config:config-item config:name="HorizontalSplitMode" config:type="short">0</config:config-item> |
<config:config-item config:name="VerticalSplitMode" config:type="short">0</config:config-item> |
<config:config-item config:name="HorizontalSplitPosition" config:type="int">0</config:config-item> |
<config:config-item config:name="VerticalSplitPosition" config:type="int">0</config:config-item> |
<config:config-item config:name="ActiveSplitRange" config:type="short">2</config:config-item> |
<config:config-item config:name="PositionLeft" config:type="int">0</config:config-item> |
<config:config-item config:name="PositionRight" config:type="int">0</config:config-item> |
<config:config-item config:name="PositionTop" config:type="int">0</config:config-item> |
<config:config-item config:name="PositionBottom" config:type="int">0</config:config-item> |
<config:config-item config:name="ZoomType" config:type="short">0</config:config-item> |
<config:config-item config:name="ZoomValue" config:type="int">100</config:config-item> |
<config:config-item config:name="PageViewZoomValue" config:type="int">60</config:config-item> |
<config:config-item config:name="ShowGrid" config:type="boolean">true</config:config-item> |
<config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item> |
</config:config-item-map-entry> |
</config:config-item-map-named> |
<config:config-item config:name="ActiveTable" config:type="string">Feuille1</config:config-item> |
<config:config-item config:name="HorizontalScrollbarWidth" config:type="int">1216</config:config-item> |
<config:config-item config:name="ZoomType" config:type="short">0</config:config-item> |
<config:config-item config:name="ZoomValue" config:type="int">100</config:config-item> |
<config:config-item config:name="PageViewZoomValue" config:type="int">60</config:config-item> |
<config:config-item config:name="ShowPageBreakPreview" config:type="boolean">false</config:config-item> |
<config:config-item config:name="ShowZeroValues" config:type="boolean">true</config:config-item> |
<config:config-item config:name="ShowNotes" config:type="boolean">true</config:config-item> |
<config:config-item config:name="ShowGrid" config:type="boolean">true</config:config-item> |
<config:config-item config:name="GridColor" config:type="long">12632256</config:config-item> |
<config:config-item config:name="ShowPageBreaks" config:type="boolean">true</config:config-item> |
<config:config-item config:name="HasColumnRowHeaders" config:type="boolean">true</config:config-item> |
<config:config-item config:name="HasSheetTabs" config:type="boolean">true</config:config-item> |
<config:config-item config:name="IsOutlineSymbolsSet" config:type="boolean">true</config:config-item> |
<config:config-item config:name="IsValueHighlightingEnabled" config:type="boolean">false</config:config-item> |
<config:config-item config:name="IsSnapToRaster" config:type="boolean">false</config:config-item> |
<config:config-item config:name="RasterIsVisible" config:type="boolean">false</config:config-item> |
<config:config-item config:name="RasterResolutionX" config:type="int">1000</config:config-item> |
<config:config-item config:name="RasterResolutionY" config:type="int">1000</config:config-item> |
<config:config-item config:name="RasterSubdivisionX" config:type="int">1</config:config-item> |
<config:config-item config:name="RasterSubdivisionY" config:type="int">1</config:config-item> |
<config:config-item config:name="IsRasterAxisSynchronized" config:type="boolean">true</config:config-item> |
<config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item> |
</config:config-item-map-entry> |
</config:config-item-map-indexed> |
</config:config-item-set> |
<config:config-item-set config:name="ooo:configuration-settings"> |
<config:config-item config:name="SyntaxStringRef" config:type="short">7</config:config-item> |
<config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item> |
<config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item> |
<config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item> |
<config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item> |
<config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item> |
<config:config-item config:name="PrinterSetup" config:type="base64Binary">kQH+/0dlbmVyaWMgUHJpbnRlcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU0dFTlBSVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWAAMAsgAAAAAAAAAEAAhSAAAEdAAASm9iRGF0YSAxCnByaW50ZXI9R2VuZXJpYyBQcmludGVyCm9yaWVudGF0aW9uPVBvcnRyYWl0CmNvcGllcz0xCm1hcmdpbmRhanVzdG1lbnQ9MCwwLDAsMApjb2xvcmRlcHRoPTI0CnBzbGV2ZWw9MApwZGZkZXZpY2U9MApjb2xvcmRldmljZT0wClBQRENvbnRleERhdGEKUGFnZVNpemU6QTQARHVwbGV4Ok5vbmUAABIAQ09NUEFUX0RVUExFWF9NT0RFDwBEdXBsZXhNb2RlOjpPZmY=</config:config-item> |
<config:config-item config:name="PrinterName" config:type="string">Generic Printer</config:config-item> |
<config:config-item config:name="AutoCalculate" config:type="boolean">true</config:config-item> |
<config:config-item config:name="LinkUpdateMode" config:type="short">3</config:config-item> |
<config:config-item config:name="HasColumnRowHeaders" config:type="boolean">true</config:config-item> |
<config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item> |
<config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item> |
<config:config-item config:name="ShowZeroValues" config:type="boolean">true</config:config-item> |
<config:config-item config:name="GridColor" config:type="long">12632256</config:config-item> |
<config:config-item config:name="ShowPageBreaks" config:type="boolean">true</config:config-item> |
<config:config-item config:name="ShowGrid" config:type="boolean">true</config:config-item> |
<config:config-item config:name="IsOutlineSymbolsSet" config:type="boolean">true</config:config-item> |
<config:config-item config:name="IsDocumentShared" config:type="boolean">false</config:config-item> |
<config:config-item config:name="ShowNotes" config:type="boolean">true</config:config-item> |
<config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item> |
<config:config-item config:name="HasSheetTabs" config:type="boolean">true</config:config-item> |
<config:config-item config:name="RasterSubdivisionY" config:type="int">1</config:config-item> |
<config:config-item config:name="RasterIsVisible" config:type="boolean">false</config:config-item> |
<config:config-item config:name="RasterResolutionX" config:type="int">1000</config:config-item> |
<config:config-item config:name="RasterResolutionY" config:type="int">1000</config:config-item> |
<config:config-item config:name="IsSnapToRaster" config:type="boolean">false</config:config-item> |
<config:config-item config:name="RasterSubdivisionX" config:type="int">1</config:config-item> |
<config:config-item config:name="IsRasterAxisSynchronized" config:type="boolean">true</config:config-item> |
</config:config-item-set> |
</office:settings> |
<office:scripts> |
<office:script script:language="ooo:Basic"> |
<ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"/> |
</office:script> |
</office:scripts> |
<office:font-face-decls> |
<style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/> |
<style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable"/> |
<style:font-face style:name="DejaVu Sans" svg:font-family="'DejaVu Sans'" style:font-family-generic="system" style:font-pitch="variable"/> |
<style:font-face style:name="Lucida Sans Unicode" svg:font-family="'Lucida Sans Unicode'" style:font-family-generic="system" style:font-pitch="variable"/> |
<style:font-face style:name="Mangal" svg:font-family="Mangal" style:font-family-generic="system" style:font-pitch="variable"/> |
<style:font-face style:name="Tahoma" svg:font-family="Tahoma" style:font-family-generic="system" style:font-pitch="variable"/> |
</office:font-face-decls> |
<office:styles> |
<style:default-style style:family="table-cell"> |
<style:table-cell-properties style:decimal-places="7"/> |
<style:paragraph-properties style:tab-stop-distance="12.5mm"/> |
<style:text-properties style:font-name="Arial" fo:language="fr" fo:country="FR" style:font-name-asian="Lucida Sans Unicode" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Tahoma" style:language-complex="hi" style:country-complex="IN"/> |
</style:default-style> |
<number:number-style style:name="N0"> |
<number:number number:min-integer-digits="1"/> |
</number:number-style> |
<number:currency-style style:name="N108P0" style:volatile="true"> |
<number:number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1" number:grouping="true"/> |
<number:text> </number:text> |
<number:currency-symbol number:language="fr" number:country="FR">€</number:currency-symbol> |
</number:currency-style> |
<number:currency-style style:name="N108"> |
<style:text-properties fo:color="#ff0000"/> |
<number:text>-</number:text> |
<number:number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1" number:grouping="true"/> |
<number:text> </number:text> |
<number:currency-symbol number:language="fr" number:country="FR">€</number:currency-symbol> |
<style:map style:condition="value()>=0" style:apply-style-name="N108P0"/> |
</number:currency-style> |
<number:number-style style:name="N109"> |
<number:number number:decimal-places="3" loext:min-decimal-places="3" number:min-integer-digits="1"/> |
</number:number-style> |
<number:number-style style:name="N110"> |
<number:number number:decimal-places="0" loext:min-decimal-places="0" number:min-integer-digits="2"/> |
</number:number-style> |
<number:percentage-style style:name="N111"> |
<number:text>%</number:text> |
<number:number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1"/> |
</number:percentage-style> |
<number:number-style style:name="N112"> |
<number:number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1" number:display-factor="1000"/> |
<number:text> is a number</number:text> |
</number:number-style> |
<number:number-style style:name="N113"> |
<number:number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1"/> |
<number:text> is a number</number:text> |
</number:number-style> |
<number:text-style style:name="N114"> |
<number:text>avant </number:text> |
<number:text-content/> |
<number:text> après</number:text> |
</number:text-style> |
<number:currency-style style:name="N115P0" style:volatile="true"> |
<number:number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1" number:grouping="true"/> |
<number:text> </number:text> |
<number:currency-symbol number:language="fr" number:country="FR">€</number:currency-symbol> |
</number:currency-style> |
<number:currency-style style:name="N115"> |
<number:text>-</number:text> |
<number:number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1" number:grouping="true"/> |
<number:text> </number:text> |
<number:currency-symbol number:language="fr" number:country="FR">€</number:currency-symbol> |
<style:map style:condition="value()>=0" style:apply-style-name="N115P0"/> |
</number:currency-style> |
<number:currency-style style:name="N117P0" style:volatile="true"> |
<number:currency-symbol number:language="en" number:country="GB">£</number:currency-symbol> |
<number:number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1" number:grouping="true"/> |
</number:currency-style> |
<number:currency-style style:name="N117"> |
<style:text-properties fo:color="#ff0000"/> |
<number:text>-</number:text> |
<number:currency-symbol number:language="en" number:country="GB">£</number:currency-symbol> |
<number:number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1" number:grouping="true"/> |
<style:map style:condition="value()>=0" style:apply-style-name="N117P0"/> |
</number:currency-style> |
<number:date-style style:name="N118"> |
<number:day number:style="long"/> |
<number:text>/</number:text> |
<number:month number:style="long"/> |
<number:text>/</number:text> |
<number:year number:style="long"/> |
<number:text> </number:text> |
<number:hours number:style="long"/> |
<number:text>:</number:text> |
<number:minutes number:style="long"/> |
<number:text>:</number:text> |
<number:seconds number:style="long" number:decimal-places="2"/> |
</number:date-style> |
<number:time-style style:name="N119" number:truncate-on-overflow="false"> |
<number:hours number:style="long"/> |
<number:text>:</number:text> |
<number:minutes/> |
<number:text>:</number:text> |
<number:seconds number:style="long" number:decimal-places="1"/> |
</number:time-style> |
<number:number-style style:name="N120P0" style:volatile="true"> |
<number:number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1"/> |
</number:number-style> |
<number:number-style style:name="N120P1" style:volatile="true"> |
<number:number number:decimal-places="0" loext:min-decimal-places="0" number:min-integer-digits="1"/> |
</number:number-style> |
<number:number-style style:name="N120"> |
<number:number number:min-integer-digits="1"/> |
<number:text/> |
<style:map style:condition="value()<0" style:apply-style-name="N120P0"/> |
<style:map style:condition="value()>0" style:apply-style-name="N120P1"/> |
</number:number-style> |
<number:number-style style:name="N121P0" style:volatile="true"> |
<number:number number:decimal-places="0" loext:min-decimal-places="0" number:min-integer-digits="1"/> |
</number:number-style> |
<number:number-style style:name="N121P1" style:volatile="true"> |
<number:number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1"/> |
</number:number-style> |
<number:number-style style:name="N121"> |
<number:number number:min-integer-digits="1"/> |
<number:text/> |
<style:map style:condition="value()<0" style:apply-style-name="N121P0"/> |
<style:map style:condition="value()>0" style:apply-style-name="N121P1"/> |
</number:number-style> |
<number:number-style style:name="N122P0" style:volatile="true"> |
<number:number number:decimal-places="0" loext:min-decimal-places="0" number:min-integer-digits="1"/> |
</number:number-style> |
<number:number-style style:name="N122P1" style:volatile="true"> |
<number:number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1"/> |
</number:number-style> |
<number:number-style style:name="N122"> |
<number:number number:min-integer-digits="1"/> |
<number:text/> |
<style:map style:condition="value()<0" style:apply-style-name="N122P0"/> |
<style:map style:condition="value()>2" style:apply-style-name="N122P1"/> |
</number:number-style> |
<number:number-style style:name="N123P0" style:volatile="true"> |
<number:number number:decimal-places="0" loext:min-decimal-places="0" number:min-integer-digits="1"/> |
</number:number-style> |
<number:number-style style:name="N123P1" style:volatile="true"> |
<number:number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1"/> |
</number:number-style> |
<number:number-style style:name="N123"> |
<number:number number:min-integer-digits="1"/> |
<number:text/> |
<style:map style:condition="value()<0" style:apply-style-name="N123P0"/> |
<style:map style:condition="value()>=1" style:apply-style-name="N123P1"/> |
</number:number-style> |
<number:number-style style:name="N10107" number:language="de" number:country="DE"> |
<number:number number:decimal-places="0" loext:min-decimal-places="0" number:min-integer-digits="2"/> |
</number:number-style> |
<number:number-style style:name="N30111" number:language="en" number:country="GB"> |
<number:number number:decimal-places="3" loext:min-decimal-places="3" number:min-integer-digits="1"/> |
</number:number-style> |
<style:style style:name="Default" style:family="table-cell"> |
<style:text-properties style:font-name-complex="Mangal" style:font-family-complex="Mangal" style:font-family-generic-complex="system" style:font-pitch-complex="variable"/> |
</style:style> |
<style:style style:name="Heading_20__28_user_29_" style:display-name="Heading (user)" style:family="table-cell" style:parent-style-name="Default"> |
<style:text-properties fo:color="#000000" fo:font-size="24pt" fo:font-style="normal" fo:font-weight="bold"/> |
</style:style> |
<style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="table-cell" style:parent-style-name="Heading_20__28_user_29_"> |
<style:text-properties fo:color="#000000" fo:font-size="18pt" fo:font-style="normal" fo:font-weight="normal"/> |
</style:style> |
<style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="table-cell" style:parent-style-name="Heading_20__28_user_29_"> |
<style:text-properties fo:color="#000000" fo:font-size="12pt" fo:font-style="normal" fo:font-weight="normal"/> |
</style:style> |
<style:style style:name="Text" style:family="table-cell" style:parent-style-name="Default"/> |
<style:style style:name="Note" style:family="table-cell" style:parent-style-name="Text"> |
<style:table-cell-properties fo:background-color="#ffffcc" style:diagonal-bl-tr="none" style:diagonal-tl-br="none" fo:border="0.74pt solid #808080"/> |
<style:text-properties fo:color="#333333" fo:font-size="10pt" fo:font-style="normal" fo:font-weight="normal"/> |
</style:style> |
<style:style style:name="Footnote" style:family="table-cell" style:parent-style-name="Text"> |
<style:text-properties fo:color="#808080" fo:font-size="10pt" fo:font-style="italic" fo:font-weight="normal"/> |
</style:style> |
<style:style style:name="Hyperlink" style:family="table-cell" style:parent-style-name="Text"> |
<style:text-properties fo:color="#0000ee" fo:font-size="10pt" fo:font-style="normal" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="#0000ee" fo:font-weight="normal"/> |
</style:style> |
<style:style style:name="Status" style:family="table-cell" style:parent-style-name="Default"/> |
<style:style style:name="Good" style:family="table-cell" style:parent-style-name="Status"> |
<style:table-cell-properties fo:background-color="#ccffcc"/> |
<style:text-properties fo:color="#006600" fo:font-size="10pt" fo:font-style="normal" fo:font-weight="normal"/> |
</style:style> |
<style:style style:name="Neutral" style:family="table-cell" style:parent-style-name="Status"> |
<style:table-cell-properties fo:background-color="#ffffcc"/> |
<style:text-properties fo:color="#996600" fo:font-size="10pt" fo:font-style="normal" fo:font-weight="normal"/> |
</style:style> |
<style:style style:name="Bad" style:family="table-cell" style:parent-style-name="Status"> |
<style:table-cell-properties fo:background-color="#ffcccc"/> |
<style:text-properties fo:color="#cc0000" fo:font-size="10pt" fo:font-style="normal" fo:font-weight="normal"/> |
</style:style> |
<style:style style:name="Warning" style:family="table-cell" style:parent-style-name="Status"> |
<style:text-properties fo:color="#cc0000" fo:font-size="10pt" fo:font-style="normal" fo:font-weight="normal"/> |
</style:style> |
<style:style style:name="Error" style:family="table-cell" style:parent-style-name="Status"> |
<style:table-cell-properties fo:background-color="#cc0000"/> |
<style:text-properties fo:color="#ffffff" fo:font-size="10pt" fo:font-style="normal" fo:font-weight="bold"/> |
</style:style> |
<style:style style:name="Accent" style:family="table-cell" style:parent-style-name="Default"> |
<style:text-properties fo:color="#000000" fo:font-size="10pt" fo:font-style="normal" fo:font-weight="bold"/> |
</style:style> |
<style:style style:name="Accent_20_1" style:display-name="Accent 1" style:family="table-cell" style:parent-style-name="Accent"> |
<style:table-cell-properties fo:background-color="#000000"/> |
<style:text-properties fo:color="#ffffff" fo:font-size="10pt" fo:font-style="normal" fo:font-weight="normal"/> |
</style:style> |
<style:style style:name="Accent_20_2" style:display-name="Accent 2" style:family="table-cell" style:parent-style-name="Accent"> |
<style:table-cell-properties fo:background-color="#808080"/> |
<style:text-properties fo:color="#ffffff" fo:font-size="10pt" fo:font-style="normal" fo:font-weight="normal"/> |
</style:style> |
<style:style style:name="Accent_20_3" style:display-name="Accent 3" style:family="table-cell" style:parent-style-name="Accent"> |
<style:table-cell-properties fo:background-color="#dddddd"/> |
</style:style> |
<style:style style:name="Result" style:family="table-cell" style:parent-style-name="Default"> |
<style:text-properties fo:font-style="italic" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" fo:font-weight="bold"/> |
</style:style> |
<style:style style:name="Result2" style:family="table-cell" style:parent-style-name="Result" style:data-style-name="N108"/> |
<style:style style:name="Heading" style:family="table-cell" style:parent-style-name="Default"> |
<style:table-cell-properties style:text-align-source="fix" style:repeat-content="false"/> |
<style:paragraph-properties fo:text-align="center"/> |
<style:text-properties fo:font-size="16pt" fo:font-style="italic" fo:font-weight="bold"/> |
</style:style> |
<style:style style:name="Heading1" style:family="table-cell" style:parent-style-name="Heading"> |
<style:table-cell-properties style:rotation-angle="90"/> |
</style:style> |
</office:styles> |
<office:automatic-styles> |
<style:style style:name="co1" style:family="table-column"> |
<style:table-column-properties fo:break-before="auto" style:column-width="69.37mm"/> |
</style:style> |
<style:style style:name="co2" style:family="table-column"> |
<style:table-column-properties fo:break-before="auto" style:column-width="34.68mm"/> |
</style:style> |
<style:style style:name="co3" style:family="table-column"> |
<style:table-column-properties fo:break-before="auto" style:column-width="22.67mm"/> |
</style:style> |
<style:style style:name="co4" style:family="table-column"> |
<style:table-column-properties fo:break-before="auto" style:column-width="22.58mm"/> |
</style:style> |
<style:style style:name="ro1" style:family="table-row"> |
<style:table-row-properties style:row-height="4.78mm" fo:break-before="auto" style:use-optimal-row-height="true"/> |
</style:style> |
<style:style style:name="ro2" style:family="table-row"> |
<style:table-row-properties style:row-height="4.52mm" fo:break-before="auto" style:use-optimal-row-height="true"/> |
</style:style> |
<style:style style:name="ro3" style:family="table-row"> |
<style:table-row-properties style:row-height="6.58mm" fo:break-before="auto" style:use-optimal-row-height="true"/> |
</style:style> |
<style:style style:name="ro4" style:family="table-row"> |
<style:table-row-properties style:row-height="4.73mm" fo:break-before="auto" style:use-optimal-row-height="true"/> |
</style:style> |
<style:style style:name="ta1" style:family="table" style:master-page-name="Default"> |
<style:table-properties table:display="true" style:writing-mode="lr-tb"/> |
</style:style> |
<number:number-style style:name="N5"> |
<number:number number:decimal-places="2" loext:min-decimal-places="2" number:grouping="true"/> |
</number:number-style> |
<number:time-style style:name="N41"> |
<number:hours number:style="long"/> |
<number:text>:</number:text> |
<number:minutes number:style="long"/> |
<number:text>:</number:text> |
<number:seconds number:style="long"/> |
</number:time-style> |
<number:number-style style:name="N60"> |
<number:scientific-number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1" number:min-exponent-digits="3" loext:exponent-interval="1" loext:forced-exponent-sign="true"/> |
</number:number-style> |
<number:number-style style:name="N61"> |
<number:scientific-number number:decimal-places="2" loext:min-decimal-places="2" number:min-integer-digits="1" number:min-exponent-digits="2" loext:exponent-interval="1" loext:forced-exponent-sign="true"/> |
</number:number-style> |
<number:date-style style:name="N20076" number:language="th" number:country="TH"> |
<number:day number:calendar="buddhist"/> |
<number:text> </number:text> |
<number:month number:calendar="buddhist" number:style="long" number:textual="true"/> |
<number:text> </number:text> |
<number:year number:calendar="buddhist" number:style="long"/> |
</number:date-style> |
<number:date-style style:name="N30079" number:language="en" number:country="GB" number:automatic-order="true"> |
<number:day-of-week number:style="long"/> |
<number:text> </number:text> |
<number:day/> |
<number:text> </number:text> |
<number:month number:style="long" number:textual="true"/> |
<number:text> </number:text> |
<number:year number:style="long"/> |
</number:date-style> |
<number:boolean-style style:name="N40099" number:language="pt" number:country="PT"> |
<number:boolean/> |
</number:boolean-style> |
<style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N10107"/> |
<style:style style:name="ce2" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N109"/> |
<style:style style:name="ce3" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N5"/> |
<style:style style:name="ce4" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N60"/> |
<style:style style:name="ce5" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N61"/> |
<style:style style:name="ce6" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N113"/> |
<style:style style:name="ce7" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N111"/> |
<style:style style:name="ce8" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N114"/> |
<style:style style:name="ce9" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N115"/> |
<style:style style:name="ce10" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N117"/> |
<style:style style:name="ce11" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N118"/> |
<style:style style:name="ce12" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N20076"/> |
<style:style style:name="ce13" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N30079"/> |
<style:style style:name="ce14" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N119"/> |
<style:style style:name="ce15" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N41"/> |
<style:style style:name="ce16" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N123"/> |
<style:style style:name="ce17" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N40099"/> |
<style:style style:name="ce35" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N30111"/> |
<style:page-layout style:name="pm1"> |
<style:page-layout-properties style:writing-mode="lr-tb"/> |
<style:header-style> |
<style:header-footer-properties fo:min-height="7.51mm" fo:margin-left="0mm" fo:margin-right="0mm" fo:margin-bottom="2.5mm"/> |
</style:header-style> |
<style:footer-style> |
<style:header-footer-properties fo:min-height="7.51mm" fo:margin-left="0mm" fo:margin-right="0mm" fo:margin-top="2.5mm"/> |
</style:footer-style> |
</style:page-layout> |
<style:page-layout style:name="pm2"> |
<style:page-layout-properties style:writing-mode="lr-tb"/> |
<style:header-style> |
<style:header-footer-properties fo:min-height="7.51mm" fo:margin-left="0mm" fo:margin-right="0mm" fo:margin-bottom="2.5mm" fo:border="2.49pt solid #000000" fo:padding="0.18mm" fo:background-color="#c0c0c0"> |
<style:background-image/> |
</style:header-footer-properties> |
</style:header-style> |
<style:footer-style> |
<style:header-footer-properties fo:min-height="7.51mm" fo:margin-left="0mm" fo:margin-right="0mm" fo:margin-top="2.5mm" fo:border="2.49pt solid #000000" fo:padding="0.18mm" fo:background-color="#c0c0c0"> |
<style:background-image/> |
</style:header-footer-properties> |
</style:footer-style> |
</style:page-layout> |
</office:automatic-styles> |
<office:master-styles> |
<style:master-page style:name="Default" style:page-layout-name="pm1"> |
<style:header> |
<text:p><text:sheet-name>???</text:sheet-name></text:p> |
</style:header> |
<style:header-left style:display="false"/> |
<style:footer> |
<text:p>Page <text:page-number>1</text:page-number></text:p> |
</style:footer> |
<style:footer-left style:display="false"/> |
</style:master-page> |
<style:master-page style:name="Report" style:page-layout-name="pm2"> |
<style:header> |
<style:region-left> |
<text:p><text:sheet-name>???</text:sheet-name><text:s/>(<text:title>???</text:title>)</text:p> |
</style:region-left> |
<style:region-right> |
<text:p><text:date style:data-style-name="N2" text:date-value="2019-03-18">00/00/0000</text:date>, <text:time style:data-style-name="N2" text:time-value="16:34:33.840313473">00:00:00</text:time></text:p> |
</style:region-right> |
</style:header> |
<style:header-left style:display="false"/> |
<style:footer> |
<text:p>Page <text:page-number>1</text:page-number><text:s/>/ <text:page-count>99</text:page-count></text:p> |
</style:footer> |
<style:footer-left style:display="false"/> |
</style:master-page> |
</office:master-styles> |
<office:body> |
<office:spreadsheet> |
<table:table table:name="Feuille1" table:style-name="ta1" table:print="false"> |
<table:table-column table:style-name="co1" table:default-cell-style-name="ce1"/> |
<table:table-column table:style-name="co2" table:default-cell-style-name="Default"/> |
<table:table-column table:style-name="co3" table:default-cell-style-name="Default"/> |
<table:table-row table:style-name="ro1"> |
<table:table-cell office:value-type="float" office:value="0.5" calcext:value-type="float"> |
<text:p>01</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>round to int with at least 2 digits</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro2"> |
<table:table-cell table:style-name="ce2" office:value-type="float" office:value="0.5" calcext:value-type="float"> |
<text:p>0,500</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>3 decimals</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell table:style-name="Default" table:formula="of:=1/3" office:value-type="float" office:value="0.333333333333333" calcext:value-type="float"> |
<text:p>0,3333333</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>default</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell table:style-name="ce3" office:value-type="float" office:value="1234567" calcext:value-type="float"> |
<text:p>1 234 567,00</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>grouping</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell table:style-name="ce4" office:value-type="float" office:value="1234" calcext:value-type="float"> |
<text:p>1,23E+003</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>scientific number (3 digits)</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell table:style-name="ce5" office:value-type="float" office:value="0.0123" calcext:value-type="float"> |
<text:p>1,23E-02</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>scientific number (2 digits)</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell table:style-name="ce6" table:formula="of:=1234" office:value-type="float" office:value="1234" calcext:value-type="float"> |
<text:p>1234,00 is a number</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>number with text</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell table:style-name="ce7" office:value-type="percentage" office:value="0.123" calcext:value-type="percentage"> |
<text:p>%12,30</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>percent</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell table:style-name="ce8" office:value-type="string" office:string-value="O" calcext:value-type="string"> |
<text:p>avant O <text:s text:c="2"/>après</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>ATTN only works with 1 char</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell table:style-name="ce9" office:value-type="currency" office:currency="EUR" office:value="-100.01" calcext:value-type="currency"> |
<text:p>-100,01 €</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>currency default</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell table:style-name="ce10" office:value-type="currency" office:currency="GBP" office:value="-50.23" calcext:value-type="currency"> |
<text:p>-£50,23</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>current England</text:p> |
</table:table-cell> |
<table:table-cell table:style-name="ce10" office:value-type="currency" office:currency="GBP" office:value="12.35" calcext:value-type="currency"> |
<text:p>£12,35</text:p> |
</table:table-cell> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell table:style-name="ce11" table:formula="of:=NOW()" office:value-type="date" office:date-value="2019-03-18T16:35:19.075105" calcext:value-type="date"> |
<text:p>18/03/2019 16:35:19,08</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>date time</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro3"> |
<table:table-cell table:style-name="ce12" table:formula="of:=NOW()" office:value-type="date" office:date-value="2019-03-18T16:35:19.075117" calcext:value-type="date"> |
<text:p>18 มีนาคม 2562</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>Thai date</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell table:style-name="ce13" table:formula="of:=NOW()" office:value-type="date" office:date-value="2019-03-18T16:35:19.07512" calcext:value-type="date"> |
<text:p>Monday 18 March 2019</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>Gregorian calendar</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell table:style-name="ce14" office:value-type="time" office:time-value="PT56H05M02.47S" calcext:value-type="time"> |
<text:p>56:5:02,5</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>Time</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell table:style-name="ce15"/> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>Empty cell with a format</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro4"> |
<table:table-cell table:style-name="ce16" office:value-type="float" office:value="12.34321" calcext:value-type="float"> |
<text:p>12,34</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>default between 0 & 1</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell table:style-name="ce17" table:formula="of:=1" office:value-type="boolean" office:boolean-value="true" calcext:value-type="boolean"> |
<text:p>VERDADEIRO</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>boolean</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro2"> |
<table:table-cell table:style-name="ce35" office:value-type="float" office:value="0.5" calcext:value-type="float"> |
<text:p>0.500</text:p> |
</table:table-cell> |
<table:table-cell office:value-type="string" calcext:value-type="string"> |
<text:p>3 decimals in english</text:p> |
</table:table-cell> |
<table:table-cell/> |
</table:table-row> |
</table:table> |
<table:named-expressions/> |
</office:spreadsheet> |
</office:body> |
</office:document> |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/ODPackage.java |
---|
17,7 → 17,9 |
import static org.openconcerto.openoffice.ODPackage.RootElement.META; |
import static org.openconcerto.openoffice.ODPackage.RootElement.STYLES; |
import org.openconcerto.openoffice.spreadsheet.CellStyle; |
import org.openconcerto.openoffice.spreadsheet.SpreadSheet; |
import org.openconcerto.openoffice.style.data.DataStyle; |
import org.openconcerto.openoffice.text.TextDocument; |
import org.openconcerto.utils.CopyUtils; |
import org.openconcerto.utils.ExceptionUtils; |
48,6 → 50,7 |
import java.io.InputStream; |
import java.io.OutputStream; |
import java.nio.charset.Charset; |
import java.text.NumberFormat; |
import java.util.ArrayList; |
import java.util.Arrays; |
import java.util.Collection; |
57,6 → 60,7 |
import java.util.HashSet; |
import java.util.Iterator; |
import java.util.List; |
import java.util.Locale; |
import java.util.Map; |
import java.util.Map.Entry; |
import java.util.Properties; |
69,6 → 73,7 |
import org.jdom.Element; |
import org.jdom.JDOMException; |
import org.jdom.Namespace; |
import org.jdom.input.SAXBuilder; |
import org.jdom.output.Format; |
import org.jdom.output.XMLOutputter; |
377,6 → 382,7 |
private ODMeta meta; |
private File file; |
private ODDocument doc; |
private Locale locale; |
public ODPackage() { |
this.files = new HashMap<String, ODPackageEntry>(); |
402,16 → 408,19 |
protected void processEntry(ZipEntry entry, InputStream in) throws IOException { |
final String name = entry.getName(); |
final Object res; |
out.reset(); |
StreamUtils.copy(in, out); |
if (subdocNames.contains(name)) { |
try { |
res = OOUtils.getBuilder().build(in); |
final SAXBuilder builder = OOUtils.getBuilder(); |
// bytes are read fully first in order to be compatible |
// with SAXParser like Piccolo |
res = builder.build(new ByteArrayInputStream(out.toByteArray())); |
} catch (JDOMException e) { |
// always correct |
throw new IllegalStateException("parse error", e); |
throw new IllegalStateException("parse error on " + name, e); |
} |
} else { |
out.reset(); |
StreamUtils.copy(in, out); |
res = out.toByteArray(); |
} |
// we don't know yet the types |
579,6 → 588,39 |
this.setContentType(newType); |
} |
public final void setLocale(Locale locale) { |
this.locale = locale; |
} |
// http://help.libreoffice.org/Common/Selecting_the_Document_Language |
// The document language is set by default-style/text-properties and is not used for formatting. |
// The formatting used to fill cell content is set by the editor application not read from the |
// document. |
public final Locale getLocale() { |
return this.locale == null ? Locale.getDefault() : this.locale; |
} |
public final String formatNumber(Number n, final CellStyle defaultStyle) { |
return formatNumber(NumberFormat.getNumberInstance(getLocale()), n, defaultStyle); |
} |
public final String formatPercent(Number n, final CellStyle defaultStyle) { |
return formatNumber(NumberFormat.getPercentInstance(getLocale()), n, defaultStyle); |
} |
public final String formatCurrency(Number n, final CellStyle defaultStyle) { |
return formatNumber(NumberFormat.getCurrencyInstance(getLocale()), n, defaultStyle); |
} |
private final String formatNumber(NumberFormat format, Number n, final CellStyle defaultStyle) { |
synchronized (format) { |
final int decPlaces = DataStyle.getDecimalPlaces(defaultStyle); |
format.setMinimumFractionDigits(0); |
format.setMaximumFractionDigits(decPlaces); |
return format.format(n); |
} |
} |
/** |
* Call {@link Validator#isValid()} on each XML subdocuments. |
* |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/spreadsheet/MutableCell.java |
---|
24,7 → 24,6 |
import org.openconcerto.openoffice.spreadsheet.CellStyle.StyleTableCellProperties; |
import org.openconcerto.openoffice.style.data.BooleanStyle; |
import org.openconcerto.openoffice.style.data.DataStyle; |
import org.openconcerto.openoffice.style.data.DateStyle; |
import org.openconcerto.utils.FileUtils; |
import org.openconcerto.utils.TimeUtils; |
import org.openconcerto.utils.TimeUtils.DurationNullsChanger; |
63,31 → 62,7 |
static private final DateFormat TextPDateFormat = DateFormat.getDateInstance(); |
static private final DateFormat TextPTimeFormat = DateFormat.getTimeInstance(); |
static private final NumberFormat TextPMinuteSecondFormat = new DecimalFormat("00.###"); |
static private final NumberFormat TextPFloatFormat = DecimalFormat.getNumberInstance(); |
static private final NumberFormat TextPPercentFormat = DecimalFormat.getPercentInstance(); |
static private final NumberFormat TextPCurrencyFormat = DecimalFormat.getCurrencyInstance(); |
static public String formatNumber(Number n, final CellStyle defaultStyle) { |
return formatNumber(TextPFloatFormat, n, defaultStyle); |
} |
static public String formatPercent(Number n, final CellStyle defaultStyle) { |
return formatNumber(TextPPercentFormat, n, defaultStyle); |
} |
static public String formatCurrency(Number n, final CellStyle defaultStyle) { |
return formatNumber(TextPCurrencyFormat, n, defaultStyle); |
} |
static private String formatNumber(NumberFormat format, Number n, final CellStyle defaultStyle) { |
synchronized (format) { |
final int decPlaces = DataStyle.getDecimalPlaces(defaultStyle); |
format.setMinimumFractionDigits(0); |
format.setMaximumFractionDigits(decPlaces); |
return format.format(n); |
} |
} |
static private boolean LO_MODE = true; |
// no date part, all time part to zero |
static private final DurationNullsChanger TIME_NULLS = new TimeUtils.DurationNullsBuilder(TimeUtils.EmptyFieldPolicy.SET_TO_ZERO).setToNull(TimeUtils.getDateFields()).build(); |
241,11 → 216,11 |
} else { |
// either there were no format or formatting failed |
if (vt == ODValueType.FLOAT) { |
text = formatNumber((Number) obj, getDefaultStyle()); |
text = getODDocument().getPackage().formatNumber((Number) obj, getDefaultStyle()); |
} else if (vt == ODValueType.PERCENTAGE) { |
text = formatPercent((Number) obj, getDefaultStyle()); |
text = getODDocument().getPackage().formatPercent((Number) obj, getDefaultStyle()); |
} else if (vt == ODValueType.CURRENCY) { |
text = formatCurrency((Number) obj, getDefaultStyle()); |
text = getODDocument().getPackage().formatCurrency((Number) obj, getDefaultStyle()); |
} else if (vt == ODValueType.DATE) { |
final Date d; |
if (obj instanceof Calendar) { |
262,16 → 237,15 |
text = TextPTimeFormat.format(((Calendar) obj).getTime()); |
} |
} else if (vt == ODValueType.BOOLEAN) { |
// LO do not use the the document language but the system language |
// http://help.libreoffice.org/Common/Selecting_the_Document_Language |
Locale l = Locale.getDefault(); |
// except of course if there's a data style |
Locale l = null; |
final CellStyle s = getStyle(); |
if (s != null) { |
final DataStyle ds = s.getDataStyle(); |
if (ds != null) |
l = DateStyle.getLocale(ds.getElement()); |
l = ds.getLocale(); |
} |
if (l == null) |
l = getODDocument().getPackage().getLocale(); |
text = BooleanStyle.toString((Boolean) obj, l, lenient); |
} else if (vt == ODValueType.STRING) { |
text = obj.toString(); |
/trunk/OpenConcerto/src/org/openconcerto/ui/state/AbstractStateManager.java |
---|
13,6 → 13,8 |
package org.openconcerto.ui.state; |
import org.openconcerto.utils.FileUtils; |
import java.io.File; |
import java.io.IOException; |
import java.security.AccessController; |
83,10 → 85,7 |
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { |
@Override |
public Object run() throws IOException { |
if (file.getParentFile() != null && !file.getParentFile().exists()) { |
file.getParentFile().mkdirs(); |
} |
FileUtils.mkParentDirs(file); |
writeState(file); |
return null; |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/touch/ScrollableList.java |
---|
62,7 → 62,8 |
private boolean hasScrolled; |
private List<ListSelectionListener> selectionListeners = new ArrayList<ListSelectionListener>(); |
private List<ListSelectionListener> selectionListeners = new ArrayList<>(); |
private List<ActionListener> actionListeners = new ArrayList<>(); |
public ScrollableList(ListModel model) { |
a = new ScrollAnimator(this); |
202,6 → 203,7 |
} else { |
scrollToOffset(targetOffset); |
} |
fireActionPerformed(); |
} |
public void setSelectedIndex(int index) { |
376,6 → 378,18 |
} |
} |
public void addActionListener(ActionListener listener) { |
this.actionListeners.add(listener); |
} |
private void fireActionPerformed() { |
int size = this.actionListeners.size(); |
for (int i = 0; i < size; i++) { |
this.actionListeners.get(i).actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "click")); |
} |
} |
@Override |
public void contentsChanged(ListDataEvent e) { |
this.offsetY = 0; |
/trunk/OpenConcerto/src/org/openconcerto/ui/table/CloseTableHeaderRenderer.java |
---|
82,7 → 82,7 |
header.setReorderingAllowed(false); |
this.editedTable = table; |
this.editedColumn = column; |
this.label.setText(value.toString()); |
this.label.setText(String.valueOf(value)); |
this.header.removeMouseListener(this); |
this.header.addMouseListener(this); |
return this; |
/trunk/OpenConcerto/src/org/openconcerto/ui/table/IconTableCellRenderer.java |
---|
98,7 → 98,7 |
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { |
if (value == null) { |
// Bug remonté sur Linux |
// JTable$AccessibleJTable.getAccessibleChild() |
value = Integer.valueOf(0); |
} |
int val = ((Integer) value).intValue(); |
/trunk/OpenConcerto/src/org/openconcerto/ui/grid/GridItem.java |
---|
New file |
0,0 → 1,95 |
/* |
* 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.grid; |
import java.awt.Color; |
public class GridItem { |
private int x; |
private int y; |
private int w; |
private int h; |
private Color color = new Color(50, 200, 160, 150); |
private Color borderColor = new Color(25, 100, 80, 150); |
private Object cookie; |
public GridItem(int x, int y, int w, int h) { |
this.x = x; |
this.y = y; |
this.w = w; |
this.h = h; |
} |
public final int getX() { |
return this.x; |
} |
public final void setX(int x) { |
this.x = x; |
} |
public final int getY() { |
return this.y; |
} |
public final void setY(int y) { |
this.y = y; |
} |
public final int getW() { |
return this.w; |
} |
public final void setW(int w) { |
this.w = w; |
} |
public final int getH() { |
return this.h; |
} |
public final void setH(int h) { |
this.h = h; |
} |
public final Color getColor() { |
return this.color; |
} |
public final void setColor(Color color) { |
this.color = color; |
} |
public final Color getBorderColor() { |
return this.borderColor; |
} |
public final void setBorderColor(Color borderColor) { |
this.borderColor = borderColor; |
} |
public Object getCookie() { |
return this.cookie; |
} |
public void setCookie(Object cookie) { |
this.cookie = cookie; |
} |
@Override |
public String toString() { |
return this.x + "," + this.y + " [" + this.w + "," + this.h + "]"; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/grid/GridPanel.java |
---|
New file |
0,0 → 1,319 |
/* |
* 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.grid; |
import java.awt.BasicStroke; |
import java.awt.Color; |
import java.awt.Dimension; |
import java.awt.Graphics; |
import java.awt.Graphics2D; |
import java.awt.event.MouseAdapter; |
import java.awt.event.MouseEvent; |
import java.awt.event.MouseMotionListener; |
import java.util.ArrayList; |
import java.util.HashMap; |
import java.util.HashSet; |
import java.util.List; |
import java.util.Map; |
import java.util.Set; |
import javax.swing.JFrame; |
import javax.swing.JPanel; |
import javax.swing.SwingUtilities; |
import javax.swing.UIManager; |
import javax.swing.UnsupportedLookAndFeelException; |
public class GridPanel extends JPanel { |
private static final Color SELECTION_BORDER_COLOR = new Color(200, 210, 220, 250); |
private static final Color SELECTION_COLOR = new Color(230, 240, 250, 180); |
private static final Color CREATION_COLOR = new Color(250, 254, 30, 100); |
private static final Color CREATION_BORDER_COLOR = new Color(250, 254, 60, 180); |
private int cellWidth = 40; |
private final int cellHeight; |
private int gridLineWidth = 1; |
private Color gridVerticalColor = Color.LIGHT_GRAY; |
private Color gridHorizontalColor = Color.DARK_GRAY; |
private int columnCount; |
private int rowCount; |
private List<GridItem> items = new ArrayList<>(); |
private Map<Integer, List<GridItem>> itemsByRow = new HashMap<>(); |
protected GridItem onCreationItem; |
protected int onCreationX; |
protected boolean[] onCreationAllowedColumns; |
private boolean editMode; |
protected GridListener gridListener; |
private Set<GridItem> selectedItems = new HashSet<>(); |
public GridPanel(int columnCount, int rowCount) { |
this(columnCount, rowCount, 40); |
} |
public GridPanel(int columnCount, int rowCount, int rowHeight) { |
this.setBackground(Color.WHITE); |
this.rowCount = rowCount; |
this.columnCount = columnCount; |
this.cellHeight = rowHeight; |
this.addMouseMotionListener(new MouseMotionListener() { |
@Override |
public void mouseMoved(MouseEvent e) { |
// nothing |
} |
@Override |
public void mouseDragged(MouseEvent e) { |
if (GridPanel.this.onCreationItem != null) { |
int x = getColumnFromMouseX(e.getX()); |
if (x >= 0 && x < columnCount && GridPanel.this.onCreationAllowedColumns[x]) { |
if (x > GridPanel.this.onCreationX) { |
GridPanel.this.onCreationItem.setW(x - GridPanel.this.onCreationX + 1); |
} else { |
GridPanel.this.onCreationItem.setX(x); |
GridPanel.this.onCreationItem.setW(GridPanel.this.onCreationX - x + 1); |
} |
} |
repaint(); |
} |
} |
}); |
this.addMouseListener(new MouseAdapter() { |
@Override |
public void mouseReleased(MouseEvent e) { |
final GridItem selectedItem = getItemAtMouse(e.getX(), e.getY()); |
if (!e.isControlDown()) { |
GridPanel.this.selectedItems.clear(); |
} |
if (selectedItem != null) { |
if (GridPanel.this.selectedItems.contains(selectedItem) && !e.isPopupTrigger()) { |
GridPanel.this.selectedItems.remove(selectedItem); |
} else { |
GridPanel.this.selectedItems.add(selectedItem); |
} |
} |
if (GridPanel.this.onCreationItem != null) { |
// Add the item |
GridItem newItem = new GridItem(GridPanel.this.onCreationItem.getX(), GridPanel.this.onCreationItem.getY(), GridPanel.this.onCreationItem.getW(), |
GridPanel.this.onCreationItem.getH()); |
if (GridPanel.this.gridListener != null) { |
boolean added = GridPanel.this.gridListener.add(GridPanel.this, newItem); |
if (added) { |
add(newItem); |
} |
} |
// |
GridPanel.this.onCreationItem = null; |
} |
repaint(); |
if (GridPanel.this.gridListener != null && e.isPopupTrigger()) { |
GridPanel.this.gridListener.triggerPopup(GridPanel.this, e.getX(), e.getY()); |
} |
} |
@Override |
public void mousePressed(MouseEvent e) { |
final GridItem selectedItem = getItemAtMouse(e.getX(), e.getY()); |
if (GridPanel.this.editMode && selectedItem == null && getRowFromMouseY(e.getY()) < rowCount) { |
GridPanel.this.onCreationX = getColumnFromMouseX(e.getX()); |
GridPanel.this.onCreationAllowedColumns = new boolean[columnCount]; |
GridPanel.this.onCreationAllowedColumns[GridPanel.this.onCreationX] = true; |
final int onCreationY = getRowFromMouseY(e.getY()); |
for (int i = GridPanel.this.onCreationX + 1; i < columnCount; i++) { |
if (getItem(onCreationY, i) == null) { |
GridPanel.this.onCreationAllowedColumns[i] = true; |
} else { |
break; |
} |
} |
for (int i = GridPanel.this.onCreationX - 1; i >= 0; i--) { |
if (getItem(onCreationY, i) == null) { |
GridPanel.this.onCreationAllowedColumns[i] = true; |
} else { |
break; |
} |
} |
GridPanel.this.onCreationItem = new GridItem(getColumnFromMouseX(e.getX()), onCreationY, 1, 1); |
GridPanel.this.onCreationItem.setColor(CREATION_COLOR); |
GridPanel.this.onCreationItem.setBorderColor(CREATION_BORDER_COLOR); |
} |
repaint(); |
if (GridPanel.this.gridListener != null) { |
GridPanel.this.gridListener.selectionChanged(GridPanel.this); |
if (e.isPopupTrigger()) { |
GridPanel.this.gridListener.triggerPopup(GridPanel.this, e.getX(), e.getY()); |
} |
} |
} |
}); |
} |
public void add(GridItem item) { |
this.items.add(item); |
for (int n = 0; n < item.getH(); n++) { |
final int y = item.getY() + n; |
List<GridItem> list = this.itemsByRow.get(y); |
if (list == null) { |
list = new ArrayList<>(); |
list.add(item); |
this.itemsByRow.put(Integer.valueOf(y), list); |
} |
list.add(item); |
} |
} |
public int getCellHeight() { |
return this.cellHeight; |
} |
@Override |
public Dimension getPreferredSize() { |
return new Dimension(this.columnCount * this.cellWidth + (1 + this.columnCount) * this.gridLineWidth, this.rowCount * this.cellWidth + (1 + this.rowCount) * this.gridLineWidth); |
} |
@Override |
public Dimension getMinimumSize() { |
return getPreferredSize(); |
} |
@Override |
public Dimension getMaximumSize() { |
return getPreferredSize(); |
} |
@Override |
protected void paintComponent(Graphics g) { |
super.paintComponent(g); |
int x = 0; |
final int h = this.getHeight(); |
Graphics2D g2 = (Graphics2D) g; |
g2.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[] { 4 }, 0)); |
// Vertical lines |
g.setColor(this.gridVerticalColor); |
for (int i = 0; i <= this.columnCount; i++) { |
g.drawLine(x, 0, x, h); |
x += this.gridLineWidth + this.cellWidth; |
} |
// Horizontal lines |
g.setColor(this.gridHorizontalColor); |
int w = this.getWidth(); |
int y = 0; |
for (int i = 0; i <= this.rowCount; i++) { |
g.drawLine(0, y, w, y); |
y += this.gridLineWidth + this.cellHeight; |
} |
g2.setStroke(new BasicStroke(1)); |
for (GridItem item : this.items) { |
drawItem(g, item); |
} |
if (this.onCreationItem != null) { |
drawItem(g, this.onCreationItem); |
} |
} |
private void drawItem(Graphics g, GridItem item) { |
final boolean isSelected = this.selectedItems.contains(item); |
if (isSelected) { |
g.setColor(SELECTION_COLOR); |
} else { |
g.setColor(item.getColor()); |
} |
int width = item.getW() * (this.gridLineWidth + this.cellWidth); |
int height = item.getH() * (this.gridLineWidth + this.cellHeight); |
final int itemX = item.getX() * (this.gridLineWidth + this.cellWidth); |
final int itemY = item.getY() * (this.gridLineWidth + this.cellHeight); |
g.fillRect(itemX + 1, itemY + 1, width - 2, height - 2); |
if (isSelected) { |
g.setColor(SELECTION_BORDER_COLOR); |
} else { |
g.setColor(item.getBorderColor()); |
} |
g.drawRect(itemX + 1, itemY + 1, width - 2, height - 2); |
g.drawRect(itemX, itemY, width, height); |
} |
public static void main(String[] args) { |
SwingUtilities.invokeLater(new Runnable() { |
@Override |
public void run() { |
try { |
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); |
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) { |
// |
} |
JFrame f = new JFrame(); |
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
final GridPanel contentPane = new GridPanel(24, 4); |
contentPane.add(new GridItem(0, 0, 1, 1)); |
contentPane.add(new GridItem(4, 0, 3, 1)); |
contentPane.add(new GridItem(1, 1, 2, 2)); |
f.setContentPane(contentPane); |
f.pack(); |
f.setLocationRelativeTo(null); |
f.setVisible(true); |
} |
}); |
} |
GridItem getItemAtMouse(int x, int y) { |
int row = getRowFromMouseY(y); |
int col = getColumnFromMouseX(x); |
return getItem(row, col); |
} |
private GridItem getItem(int row, int col) { |
List<GridItem> rItems = this.itemsByRow.get(row); |
if (rItems == null) { |
return null; |
} |
for (GridItem item : rItems) { |
if (item.getX() <= col && (item.getX() + item.getW()) > col) { |
return item; |
} |
} |
return null; |
} |
private int getColumnFromMouseX(int x) { |
return x / (this.gridLineWidth + this.cellWidth); |
} |
private int getRowFromMouseY(int y) { |
return y / (this.gridLineWidth + this.cellHeight); |
} |
public void setEnableEditMode(boolean enable) { |
this.editMode = enable; |
} |
public void setGridListener(GridListener gridListener) { |
this.gridListener = gridListener; |
} |
public List<GridItem> getSelectedItems() { |
return new ArrayList<>(this.selectedItems); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/grid/TwoYearsHeaderPanel.java |
---|
New file |
0,0 → 1,82 |
/* |
* 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.grid; |
import java.awt.Color; |
import java.awt.Dimension; |
import java.awt.Font; |
import java.awt.Graphics; |
import javax.swing.JPanel; |
public class TwoYearsHeaderPanel extends JPanel { |
private int year; |
private String[] months = new String[] { "Janv.", "Fév.", "Mars", "Avr.", "Mai", "Juin", "Juil.", "Août", "Sept.", "Oct.", "Nov.", "Déc." }; |
public TwoYearsHeaderPanel(int year) { |
this.year = year; |
this.setBackground(Color.white); |
} |
@Override |
protected void paintComponent(Graphics g) { |
super.paintComponent(g); |
g.setFont(g.getFont().deriveFont(Font.BOLD)); |
int x1 = this.getWidth() / 4; |
int x2 = (3 * this.getWidth()) / 4; |
String str1 = String.valueOf(this.year); |
int w1 = g.getFontMetrics().stringWidth(str1); |
g.drawString(str1, x1 - w1 / 2, 16); |
String str2 = String.valueOf(this.year + 1); |
int w2 = g.getFontMetrics().stringWidth(str2); |
g.drawString(str2, x2 - w2 / 2, 16); |
int gw = (this.getWidth()) / 24; |
g.setColor(Color.LIGHT_GRAY); |
for (int x = 0; x < this.getWidth(); x += gw * 3) { |
g.drawLine(x, 36, x, this.getHeight()); |
} |
g.setColor(Color.GRAY); |
for (int x = 0; x < this.getWidth(); x += gw * 6) { |
g.drawLine(x, 24, x, this.getHeight()); |
} |
g.setColor(Color.BLACK); |
for (int x = 0; x < this.getWidth(); x += gw * 12) { |
g.drawLine(x, 0, x, this.getHeight()); |
} |
g.setFont(g.getFont().deriveFont(Font.PLAIN)); |
int delta = this.getWidth() / 2; |
for (int i = 0; i < 12; i++) { |
final String str = this.months[i]; |
int w = g.getFontMetrics().stringWidth(str2); |
int x = i * gw + gw / 2 - w / 2; |
g.drawString(str, x, 40); |
x = x + delta; |
g.drawString(str, x, 40); |
} |
} |
@Override |
public Dimension getMinimumSize() { |
return new Dimension(getPreferredSize().width, 48); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/grid/GridListener.java |
---|
New file |
0,0 → 1,27 |
/* |
* 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.grid; |
public interface GridListener { |
public void selectionChanged(GridPanel grid); |
public void triggerPopup(GridPanel grid, int x, int y); |
/** |
* returns true if the newItem is must be added |
*/ |
public boolean add(GridPanel gridPanel, GridItem newItem); |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/grid/DecoratedGridPanel.java |
---|
New file |
0,0 → 1,140 |
/* |
* 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.grid; |
import org.openconcerto.ui.VFlowLayout; |
import java.awt.Color; |
import java.awt.Component; |
import java.awt.Dimension; |
import java.awt.GridBagConstraints; |
import java.awt.GridBagLayout; |
import java.util.ArrayList; |
import java.util.List; |
import javax.swing.JButton; |
import javax.swing.JComponent; |
import javax.swing.JFrame; |
import javax.swing.JPanel; |
import javax.swing.JScrollPane; |
import javax.swing.SwingUtilities; |
import javax.swing.UIManager; |
import javax.swing.UnsupportedLookAndFeelException; |
public class DecoratedGridPanel extends JPanel { |
private GridPanel grid; |
public DecoratedGridPanel(JComponent header, int columnCount, int rowHeight, List<JComponent> rowHeader) { |
this.setBackground(Color.WHITE); |
this.setLayout(new GridBagLayout()); |
JPanel topLeft = new JPanel(); |
this.grid = new GridPanel(columnCount, rowHeader.size(), rowHeight); |
header.setPreferredSize(new Dimension(this.grid.getPreferredSize().width, header.getMinimumSize().height)); |
header.setMaximumSize(new Dimension(this.grid.getPreferredSize().width, header.getMinimumSize().height)); |
header.setMinimumSize(new Dimension(this.grid.getPreferredSize().width, header.getMinimumSize().height)); |
GridBagConstraints c = new GridBagConstraints(); |
c.gridx = 0; |
c.gridy = 0; |
c.weightx = 1; |
c.gridwidth = 1; |
c.fill = GridBagConstraints.BOTH; |
this.add(topLeft, c); |
c.gridx++; |
c.weightx = 0; |
this.add(header, c); |
// |
c.gridwidth = 2; |
c.weightx = 1; |
c.weighty = 1; |
c.gridx = 0; |
c.gridy++; |
JPanel panel = new JPanel(); |
panel.setLayout(new GridBagLayout()); |
GridBagConstraints c2 = new GridBagConstraints(); |
c2.gridx = 0; |
c2.gridy = 0; |
c2.weightx = 1; |
c2.anchor = GridBagConstraints.NORTH; |
c2.fill = GridBagConstraints.BOTH; |
panel.add(createLeft(rowHeader, this.grid.getCellHeight()), c2); |
c2.gridx++; |
c2.weightx = 0; |
c2.weighty = 1; |
panel.add(this.grid, c2); |
final JScrollPane scroll = new JScrollPane(panel); |
scroll.setBorder(null); |
this.add(scroll, c); |
} |
private Component createLeft(List<JComponent> rowHeader, int h) { |
JPanel p = new JPanel(); |
p.setLayout(new VFlowLayout(VFlowLayout.TOP, 1, 1, true)); |
for (JComponent c : rowHeader) { |
c.setMinimumSize(new Dimension(c.getMinimumSize().width, h)); |
c.setPreferredSize(new Dimension(c.getPreferredSize().width, h)); |
p.add(c); |
} |
return p; |
} |
public static void main(String[] args) { |
SwingUtilities.invokeLater(new Runnable() { |
@Override |
public void run() { |
try { |
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); |
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) { |
// |
} |
JFrame f = new JFrame(); |
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
TwoYearsHeaderPanel b = new TwoYearsHeaderPanel(2018); |
List<JComponent> panels = new ArrayList<>(); |
for (int i = 0; i < 5; i++) { |
panels.add(new JButton("line " + i)); |
} |
final DecoratedGridPanel contentPane = new DecoratedGridPanel(b, 24, 40, panels); |
contentPane.add(new GridItem(0, 0, 1, 1)); |
contentPane.add(new GridItem(4, 0, 3, 1)); |
contentPane.add(new GridItem(1, 1, 2, 1)); |
f.setContentPane(contentPane); |
f.pack(); |
f.setLocationRelativeTo(null); |
f.setVisible(true); |
} |
}); |
} |
public void add(GridItem gridItem) { |
this.grid.add(gridItem); |
} |
public void setEnableEditMode(boolean enable) { |
this.grid.setEnableEditMode(enable); |
} |
public void setGridListener(GridListener gridListener) { |
this.grid.setGridListener(gridListener); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/ColorField.java |
---|
New file |
0,0 → 1,62 |
/* |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
* |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved. |
* |
* The contents of this file are subject to the terms of the GNU General Public License Version 3 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific |
* language governing permissions and limitations under the License. |
* |
* When distributing the software, include this License Header Notice in each file. |
*/ |
package org.openconcerto.ui; |
import java.awt.Color; |
import java.awt.Dimension; |
import java.awt.FlowLayout; |
import java.awt.event.MouseAdapter; |
import java.awt.event.MouseEvent; |
import javax.swing.BorderFactory; |
import javax.swing.JColorChooser; |
import javax.swing.JPanel; |
import javax.swing.JTextField; |
public class ColorField extends JPanel { |
private Color color = Color.WHITE; |
private JPanel colorPanel = new JPanel(); |
public ColorField(String chooserTitle) { |
this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); |
int h = new JTextField("O").getPreferredSize().height; |
this.colorPanel.setPreferredSize(new Dimension(h * 2, h)); |
this.colorPanel.setMinimumSize(new Dimension(h, h)); |
this.colorPanel.setMaximumSize(new Dimension(h * 2, h)); |
this.colorPanel.setBackground(this.color); |
this.colorPanel.setOpaque(true); |
this.colorPanel.setBorder(BorderFactory.createLoweredBevelBorder()); |
this.colorPanel.addMouseListener(new MouseAdapter() { |
@Override |
public void mouseReleased(MouseEvent e) { |
final Color c = JColorChooser.showDialog(ColorField.this.colorPanel, chooserTitle, getColor()); |
Color oldValue = getColor(); |
setColor(c); |
firePropertyChange("value", oldValue, c); |
} |
}); |
this.add(this.colorPanel); |
} |
public void setColor(Color c) { |
this.color = c; |
this.colorPanel.setBackground(c); |
} |
public Color getColor() { |
return this.color; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/SearchContent.java |
---|
File deleted |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/SearchSpec.java |
---|
File deleted |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/UserSearchItem.java |
---|
New file |
0,0 → 1,95 |
/* |
* 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.light; |
import org.openconcerto.utils.io.Transferable; |
import net.minidev.json.JSONObject; |
public class UserSearchItem implements Transferable { |
// column id (or subject id of the search) |
private String column; |
// value as text typed by the user |
private String text; |
public static final String TYPE_IS = "is"; |
public static final String TYPE_CONTAINS = "contains"; |
public static final String TYPE_STARTS_WITH = "starts"; |
public static final String TYPE_ENDS_WITH = "ends"; |
public static final String TYPE_EQUALS = "equals"; |
public static final String TYPE_LESS_THAN = "lth"; |
public static final String TYPE_GREATER_THAN = "gth"; |
// type of search (contains,equals,...) |
private String type; |
// operator to apply (and / or) |
private String operator; |
public UserSearchItem(final JSONObject json) { |
this.fromJSON(json); |
} |
public String getColumn() { |
return this.column; |
} |
public String getText() { |
return this.text; |
} |
public String getType() { |
return this.type; |
} |
public String getOperator() { |
return this.operator; |
} |
@Override |
public JSONObject toJSON() { |
final JSONObject json = new JSONObject(); |
json.put("column", this.column); |
json.put("text", this.text); |
json.put("type", this.type); |
json.put("operator", this.operator); |
return json; |
} |
@Override |
public void fromJSON(final JSONObject json) { |
if (!json.containsKey("column") || !(json.get("column") instanceof String)) { |
throw new IllegalArgumentException("value for 'column' not found or invalid"); |
} |
if (!json.containsKey("text") || !(json.get("text") instanceof String)) { |
throw new IllegalArgumentException("value for 'text' not found or invalid"); |
} |
if (!json.containsKey("type") || !(json.get("type") instanceof String)) { |
throw new IllegalArgumentException("value for 'type' not found or invalid"); |
} |
if (json.containsKey("operator")) { |
if (!(json.get("operator") instanceof String)) { |
throw new IllegalArgumentException("value for 'operator' not found or invalid"); |
} else { |
this.operator = (String) json.get("operator"); |
} |
} |
this.column = (String) json.get("column"); |
this.text = (String) json.get("text"); |
this.type = (String) json.get("type"); |
} |
@Override |
public String toString() { |
return super.toString() + " column:" + this.column + " text:" + this.text + " type:" + this.type + " operator:" + this.operator; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIHTMLStrippedPanel.java |
---|
20,6 → 20,9 |
public class LightUIHTMLStrippedPanel extends LightUIPanel implements Transferable, HTMLable { |
public LightUIHTMLStrippedPanel() { |
} |
public LightUIHTMLStrippedPanel(String id) { |
super(id); |
this.setType(LightUIElement.TYPE_RAW_HTML); |
34,11 → 37,6 |
} |
@Override |
public LightUIElement clone() { |
return new LightUIHTMLStrippedPanel(this); |
} |
@Override |
public String getHTML() { |
final StringBuilder b = new StringBuilder(); |
for (int i = 0; i < this.getChildrenCount(); i++) { |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/UserSearch.java |
---|
New file |
0,0 → 1,83 |
/* |
* 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.light; |
import org.openconcerto.utils.io.JSONConverter; |
import org.openconcerto.utils.io.Transferable; |
import java.util.ArrayList; |
import java.util.List; |
import net.minidev.json.JSONArray; |
import net.minidev.json.JSONAware; |
import net.minidev.json.JSONObject; |
public class UserSearch implements Transferable, JSONAware { |
private String tableId; |
private List<UserSearchItem> content = new ArrayList<>(); |
public UserSearch() { |
// Serialization |
} |
public UserSearch(final String tableId) { |
this.tableId = tableId; |
} |
public UserSearch(final JSONObject json) { |
this.fromJSON(json); |
} |
public final String getTableId() { |
return this.tableId; |
} |
public final List<UserSearchItem> getContent() { |
return this.content; |
} |
@Override |
public JSONObject toJSON() { |
final JSONObject json = new JSONObject(); |
json.put("table-id", this.tableId); |
json.put("content", JSONConverter.getJSON(this.content)); |
return json; |
} |
@Override |
public void fromJSON(JSONObject json) { |
this.tableId = JSONConverter.getParameterFromJSON(json, "table-id", String.class); |
final JSONArray jsonContent = JSONConverter.getParameterFromJSON(json, "content", JSONArray.class); |
if (jsonContent != null) { |
this.content = new ArrayList<>(); |
for (final Object o : jsonContent) { |
this.content.add(new UserSearchItem((JSONObject) JSONConverter.getObjectFromJSON(o, JSONObject.class))); |
} |
} |
} |
/* |
* JSONAware pour que le JSONArray.toString() fonctionne quand cet objet est dans un JSONArray |
*/ |
@Override |
public String toJSONString() { |
return toJSON().toJSONString(); |
} |
@Override |
public String toString() { |
return "UserSearch on " + this.tableId + " " + this.content.size() + " items"; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/TableSearchParameter.java |
---|
New file |
0,0 → 1,100 |
/* |
* 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.light; |
import org.openconcerto.utils.io.Transferable; |
import java.util.ArrayList; |
import java.util.List; |
import net.minidev.json.JSONArray; |
import net.minidev.json.JSONObject; |
public class TableSearchParameter implements Transferable { |
private String id; |
private String label; |
private List<TableSearchParameterType> types = new ArrayList<>(); |
public TableSearchParameter() { |
// For serialization |
} |
public String getId() { |
return this.id; |
} |
public String getLabel() { |
return this.label; |
} |
public List<TableSearchParameterType> getTypes() { |
return this.types; |
} |
public TableSearchParameter(String id, String label) { |
this.id = id; |
this.label = label; |
} |
public void add(TableSearchParameterType type) { |
this.types.add(type); |
} |
public void remove(TableSearchParameterType type) { |
this.types.remove(type); |
} |
@Override |
public JSONObject toJSON() { |
if (this.id == null) { |
throw new IllegalStateException("null id"); |
} |
if (this.label == null) { |
throw new IllegalStateException("null label"); |
} |
final JSONObject obj = new JSONObject(); |
obj.put("id", this.id); |
obj.put("label", this.label); |
if (!this.types.isEmpty()) { |
final JSONArray array = new JSONArray(); |
for (TableSearchParameterType type : this.types) { |
array.add(type.toJSON()); |
} |
obj.put("types", array); |
} |
return obj; |
} |
@Override |
public void fromJSON(JSONObject json) { |
this.id = json.getAsString("id"); |
this.label = json.getAsString("label"); |
if (this.id == null) { |
throw new IllegalStateException("null id"); |
} |
if (this.label == null) { |
throw new IllegalStateException("null label"); |
} |
this.types.clear(); |
if (json.containsKey("types")) { |
final JSONArray array = (JSONArray) json.get("types"); |
for (Object object : array) { |
final TableSearchParameterType t = new TableSearchParameterType(); |
t.fromJSON(((JSONObject) object)); |
this.types.add(t); |
} |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUITable.java |
---|
18,10 → 18,6 |
import java.awt.event.ActionEvent; |
import java.awt.event.ActionListener; |
import java.io.Externalizable; |
import java.io.IOException; |
import java.io.ObjectInput; |
import java.io.ObjectOutput; |
import java.util.ArrayList; |
import java.util.List; |
33,7 → 29,7 |
import net.minidev.json.JSONArray; |
import net.minidev.json.JSONObject; |
public class LightUITable extends LightUserControlContainer implements Externalizable { |
public class LightUITable extends LightUserControlContainer { |
public static final int DEFAULT_LINE_HEIGHT = 40; |
49,7 → 45,7 |
private Boolean autoSelectFirstLine = true; |
private TableSpec tableSpec = null; |
private transient List<ActionListener> selectionListeners = new ArrayList<ActionListener>(); |
private transient List<ActionListener> selectionListeners = new ArrayList<>(); |
// Nombre de ligne à afficher par Row |
private int linePerRow = 1; |
81,10 → 77,8 |
final RowSelectionSpec selection = new RowSelectionSpec(this.getId()); |
final ColumnsSpec columnsSpec = new ColumnsSpec(this.getId(), new ArrayList<ColumnSpec>(), new ArrayList<String>(), new ArrayList<String>()); |
final TableSpec tableSpec = new TableSpec(this.getId(), selection, columnsSpec); |
tableSpec.setContent(new TableContent(this.getId())); |
this.setTableSpec(tableSpec); |
this.tableSpec = new TableSpec(this.getId(), selection, columnsSpec); |
this.tableSpec.setContent(new TableContent(this.getId())); |
} |
@Override |
243,7 → 237,7 |
} |
public final List<Row> getSelectedRows() { |
final List<Row> selectedRows = new ArrayList<Row>(); |
final List<Row> selectedRows = new ArrayList<>(); |
if (this.getTableSpec().getSelection() != null) { |
final List<Number> selectedIds = this.getSelectedIds(); |
374,7 → 368,7 |
} |
public <T extends LightUIElement> List<T> findChildren(final Class<T> expectedClass, final boolean recursively) { |
final List<T> result = new ArrayList<T>(); |
final List<T> result = new ArrayList<>(); |
if (this.hasRow()) { |
final int size = this.getRowsCount(); |
382,16 → 376,18 |
final Row row = this.getRow(i); |
final List<Object> rowValues = row.getValues(); |
for (final Object value : rowValues) { |
if (recursively) { |
if (value instanceof LightUIContainer) { |
result.addAll(((LightUIContainer) value).findChildren(expectedClass, recursively)); |
} else if (value instanceof LightUITable) { |
result.addAll(((LightUITable) value).findChildren(expectedClass, recursively)); |
if (value != null) { |
if (recursively) { |
if (value instanceof LightUIContainer) { |
result.addAll(((LightUIContainer) value).findChildren(expectedClass, recursively)); |
} else if (value instanceof LightUITable) { |
result.addAll(((LightUITable) value).findChildren(expectedClass, recursively)); |
} |
} |
if (expectedClass.isAssignableFrom(value.getClass())) { |
result.add(expectedClass.cast(value)); |
} |
} |
if (expectedClass.isAssignableFrom(value.getClass())) { |
result.add(expectedClass.cast(value)); |
} |
} |
} |
} else { |
427,7 → 423,7 |
final Document xmlConf = new Document(); |
final int columnSpecCount = columnsSpec.getColumnCount(); |
final List<String> visibleIds = new ArrayList<String>(); |
final List<String> visibleIds = new ArrayList<>(); |
for (int i = 0; i < columnSpecCount; i++) { |
final ColumnSpec columnSpec = columnsSpec.getColumn(i); |
final Element xmlColumn = this.createXmlColumn(columnSpec.getId(), columnSpec.getMaxWidth(), columnSpec.getMinWidth(), columnSpec.getWidth()); |
494,7 → 490,7 |
final Row row = this.getRow(i); |
final List<Object> values = row.getValues(); |
for (final Object value : values) { |
if (value != null && value instanceof LightUIElement) { |
if (value instanceof LightUIElement) { |
((LightUIElement) value).setReadOnly(readOnly); |
} |
} |
526,9 → 522,9 |
for (int i = 0; i < size; i++) { |
final Row row = this.getRow(i); |
final JSONObject jsonLineContext = (JSONObject) JSONConverter.getObjectFromJSON(jsonContext.get(i), JSONObject.class); |
final JSONObject jsonLineContext = JSONConverter.getObjectFromJSON(jsonContext.get(i), JSONObject.class); |
final Number rowId = JSONConverter.getParameterFromJSON(jsonLineContext, "row.id", Number.class); |
final String rowExtendId = (String) JSONConverter.getParameterFromJSON(jsonLineContext, "row.extend.id", String.class); |
final String rowExtendId = JSONConverter.getParameterFromJSON(jsonLineContext, "row.extend.id", String.class); |
if (NumberUtils.areNumericallyEqual(rowId, row.getId()) && (row.getExtendId() == null || (row.getExtendId() != null && rowExtendId.equals(row.getExtendId())))) { |
if (row.isFillWidth()) { |
if (!row.getValues().isEmpty() && row.getValues().get(0) instanceof LightUserControl) { |
559,7 → 555,7 |
} |
} |
} else { |
final List<Number> ids = new ArrayList<Number>(size); |
final List<Number> ids = new ArrayList<>(size); |
for (int j = 0; j < size; j++) { |
ids.add(this.getRow(j).getId()); |
} |
611,29 → 607,6 |
} |
@Override |
public void writeExternal(ObjectOutput out) throws IOException { |
super.writeExternal(out); |
out.writeBoolean(dynamicLoad); |
out.writeBoolean(allowSelection); |
out.writeBoolean(allowMultiSelection); |
out.writeBoolean(autoSelectFirstLine); |
tableSpec.writeExternal(out); |
} |
@Override |
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { |
super.readExternal(in); |
this.dynamicLoad = in.readBoolean(); |
this.allowSelection = in.readBoolean(); |
this.allowMultiSelection = in.readBoolean(); |
this.autoSelectFirstLine = in.readBoolean(); |
tableSpec = new TableSpec(); |
tableSpec.readExternal(in); |
} |
@Override |
public void destroy() { |
super.destroy(); |
this.selectionListeners.clear(); |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/TableSearchParameterType.java |
---|
New file |
0,0 → 1,89 |
/* |
* 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.light; |
import org.openconcerto.utils.io.Transferable; |
import java.util.Locale; |
import net.minidev.json.JSONObject; |
public class TableSearchParameterType implements Transferable { |
// type from UserSearchItem type |
private String type; |
private String label; |
private String valueType; |
TableSearchParameterType() { |
// For serialization |
} |
public TableSearchParameterType(String type) { |
this.type = type; |
} |
public TableSearchParameterType(String type, String label, String valueType) { |
this.type = type; |
this.label = label; |
this.valueType = valueType; |
} |
public String getType() { |
return this.type; |
} |
public String getLabel() { |
return this.label; |
} |
public String getValueType() { |
return this.valueType; |
} |
@Override |
public JSONObject toJSON() { |
final JSONObject obj = new JSONObject(); |
obj.put("type", this.type); |
obj.put("label", this.label); |
obj.put("value-type", this.valueType); |
return obj; |
} |
@Override |
public void fromJSON(JSONObject json) { |
this.type = json.getAsString("type"); |
this.label = json.getAsString("label"); |
this.valueType = json.getAsString("value-type"); |
} |
public static TableSearchParameterType getContainsStringInstance(Locale locale) { |
if (locale.equals(Locale.FRENCH)) { |
return new TableSearchParameterType(UserSearchItem.TYPE_CONTAINS, "Contient", "string"); |
} |
return new TableSearchParameterType(UserSearchItem.TYPE_CONTAINS, "Contains", "string"); |
} |
public static TableSearchParameterType getIsStringInstance(Locale locale) { |
if (locale.equals(Locale.FRENCH)) { |
return new TableSearchParameterType(UserSearchItem.TYPE_IS, "Est", "string"); |
} |
return new TableSearchParameterType(UserSearchItem.TYPE_IS, "Is", "string"); |
} |
@Override |
public String toString() { |
return super.toString() + "type:" + this.type + " label:" + this.label + " value-type:" + this.valueType; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/TableContent.java |
---|
16,10 → 16,6 |
import org.openconcerto.utils.io.JSONConverter; |
import org.openconcerto.utils.io.Transferable; |
import java.io.Externalizable; |
import java.io.IOException; |
import java.io.ObjectInput; |
import java.io.ObjectOutput; |
import java.util.ArrayList; |
import java.util.List; |
26,7 → 22,7 |
import net.minidev.json.JSONArray; |
import net.minidev.json.JSONObject; |
public class TableContent implements Transferable, Externalizable { |
public class TableContent implements Transferable { |
private static final long serialVersionUID = 3648381615123520834L; |
private String tableId; |
private List<Row> rows; |
100,7 → 96,7 |
* @return a copy of the list |
*/ |
public final synchronized List<Row> getRows() { |
return new ArrayList<Row>(this.rows); |
return new ArrayList<>(this.rows); |
} |
@Override |
122,7 → 118,7 |
this.tableId = JSONConverter.getParameterFromJSON(json, "table-id", String.class); |
final JSONArray jsonRows = JSONConverter.getParameterFromJSON(json, "rows", JSONArray.class); |
if (jsonRows != null) { |
final List<Row> listRows = new ArrayList<Row>(); |
final List<Row> listRows = new ArrayList<>(); |
for (final Object o : jsonRows) { |
listRows.add(new Row(JSONConverter.getObjectFromJSON(o, JSONObject.class))); |
} |
130,27 → 126,4 |
} |
} |
@Override |
public synchronized void writeExternal(ObjectOutput out) throws IOException { |
out.writeUTF(tableId); |
out.writeInt(rows.size()); |
for (Row row : this.rows) { |
row.writeExternal(out); |
} |
} |
@Override |
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { |
tableId = in.readUTF(); |
int size = in.readInt(); |
this.rows = new ArrayList<>(size); |
for (int i = 0; i < size; i++) { |
final Row row = new Row(); |
row.readExternal(in); |
this.rows.add(row); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIStrippedImageLine.java |
---|
42,11 → 42,6 |
} |
@Override |
public LightUIElement clone() { |
return new LightUIStrippedImageLine(this); |
} |
@Override |
protected void copy(LightUIElement element) { |
super.copy(element); |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUITab.java |
---|
54,11 → 54,6 |
} |
@Override |
public LightUIElement clone() { |
return new LightUITab(this); |
} |
@Override |
public void copy(final LightUIElement element) { |
if (!(element instanceof LightUITab)) { |
throw new InvalidClassException(LightUITab.class.getName(), element.getClassName(), element.getId()); |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/RowsBulk.java |
---|
13,6 → 13,9 |
package org.openconcerto.ui.light; |
import org.openconcerto.utils.io.JSONAble; |
import org.openconcerto.utils.io.JSONConverter; |
import java.io.Externalizable; |
import java.io.IOException; |
import java.io.ObjectInput; |
21,8 → 24,6 |
import java.util.Collections; |
import java.util.List; |
import org.openconcerto.utils.io.JSONAble; |
import org.openconcerto.utils.io.JSONConverter; |
import net.minidev.json.JSONArray; |
import net.minidev.json.JSONObject; |
143,7 → 144,7 |
this.total = JSONConverter.getParameterFromJSON(json, "total", Integer.class); |
final JSONArray jsonRows = JSONConverter.getParameterFromJSON(json, "rows", JSONArray.class); |
this.rows = new ArrayList<Row>(); |
this.rows = new ArrayList<>(); |
if (jsonRows != null) { |
for (final Object o : jsonRows) { |
this.rows.add(new Row(JSONConverter.getObjectFromJSON(o, JSONObject.class))); |
153,6 → 154,6 |
@Override |
public String toString() { |
return this.rows.size() + " rows at offset " + offset + " (total:" + total + ") remove:" + this.remove; |
return this.rows.size() + " rows at offset " + this.offset + " (total:" + this.total + ") remove:" + this.remove; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIFileUploadWithSelection.java |
---|
38,11 → 38,6 |
} |
@Override |
public LightUIElement clone() { |
return new LightUIFileUploadWithSelection(this); |
} |
@Override |
protected void copy(LightUIElement element) { |
super.copy(element); |
if (!(element instanceof LightUIFileUploadWithSelection)) { |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIElement.java |
---|
200,7 → 200,7 |
} |
private static long count = 0; |
private static Integer counterLock = new Integer(123456); |
private static Object counterLock = new Object(); |
private String getNextUUID() { |
String result; |
536,7 → 536,11 |
} |
public void setId(final String id) { |
if (id == null) { |
throw new IllegalArgumentException("id cannot be null"); |
} |
this.id = id; |
} |
public String getUUID() { |
809,6 → 813,9 |
if (element == null) { |
throw new IllegalArgumentException("Try to copy attributes of null element in " + this.getId()); |
} |
System.err.println("LightUIElement.copy() " + element); |
this.UUID = getNextUUID(); |
this.id = element.getId(); |
this.fontSize = element.fontSize; |
this.gridHeight = element.gridHeight; |
this.gridWidth = element.gridWidth; |
866,7 → 873,7 |
@Override |
public String toString() { |
if (!destroyed) { |
if (!this.destroyed) { |
return super.toString() + " " + this.id; |
} else { |
return super.toString() + " " + this.id + " DESTROYED"; |
1012,6 → 1019,9 |
if (this.toolTip != null) { |
result.put("tool-tip", this.toolTip); |
} |
if (this.UUID == null) { |
throw new IllegalStateException("null UUID, id: " + this.id); |
} |
result.put("uuid", this.UUID); |
if (this.value != null) { |
result.put("value", this.value); |
1045,6 → 1055,9 |
public void fromJSON(final JSONObject json) { |
this.id = JSONConverter.getParameterFromJSON(json, "id", String.class); |
this.UUID = JSONConverter.getParameterFromJSON(json, "uuid", String.class); |
if (this.UUID == null) { |
throw new IllegalArgumentException("null UUID, id : " + this.id); |
} |
this.displayPrecision = JSONConverter.getParameterFromJSON(json, "display-precision", String.class); |
this.icon = JSONConverter.getParameterFromJSON(json, "icon", String.class); |
this.label = JSONConverter.getParameterFromJSON(json, "label", String.class); |
1109,7 → 1122,7 |
} |
public boolean isDestroyed() { |
return destroyed; |
return this.destroyed; |
} |
@Override |
1120,7 → 1133,7 |
} |
out.writeUTF(this.id); |
if (this.UUID == null) { |
throw new IllegalStateException("UUID"); |
throw new IllegalStateException("null UUID, id : " + this.id); |
} |
out.writeUTF(this.UUID); |
1223,6 → 1236,9 |
this.type = in.readInt(); |
this.id = in.readUTF(); |
this.UUID = in.readUTF(); |
if (this.UUID == null) { |
throw new IllegalStateException("null UUID, id : " + this.id); |
} |
if (in.readBoolean()) { |
this.label = in.readUTF(); |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIFrame.java |
---|
62,10 → 62,16 |
super.destroy(); |
if (this.titlePanel != null) { |
this.titlePanel.destroy(); |
this.titlePanel = null; |
} |
if (this.footerPanel != null) { |
this.footerPanel.destroy(); |
this.footerPanel = null; |
} |
if (this.contentPanel != null) { |
this.contentPanel.destroy(); |
this.contentPanel = null; |
} |
if (this.childrenFrame != null) { |
for (LightUIFrame frame : childrenFrame) { |
frame.destroy(); |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/TableSpec.java |
---|
16,19 → 16,19 |
import org.openconcerto.utils.io.JSONConverter; |
import org.openconcerto.utils.io.Transferable; |
import java.io.Externalizable; |
import java.io.IOException; |
import java.io.ObjectInput; |
import java.io.ObjectOutput; |
import java.util.ArrayList; |
import java.util.List; |
import net.minidev.json.JSONArray; |
import net.minidev.json.JSONObject; |
public class TableSpec implements Transferable, Externalizable { |
public class TableSpec implements Transferable { |
private String id; |
private ColumnsSpec columns; |
private TableContent content; |
private RowSelectionSpec selection; |
private SearchSpec search; |
private List<TableSearchParameter> searchParameters = new ArrayList<>(); |
private UserSearch search; |
private Boolean variableColumnsCount = false; |
public TableSpec() { |
84,11 → 84,11 |
this.selection = selection; |
} |
public SearchSpec getSearch() { |
public UserSearch getSearch() { |
return this.search; |
} |
public void setSearch(final SearchSpec search) { |
public void setSearch(final UserSearch search) { |
this.search = search; |
} |
100,6 → 100,14 |
this.variableColumnsCount = variableColumnsCount; |
} |
public void addSearchParameter(TableSearchParameter p) { |
this.searchParameters.add(p); |
} |
public void removeSearchParameter(TableSearchParameter p) { |
this.searchParameters.remove(p); |
} |
@Override |
public JSONObject toJSON() { |
final JSONObject result = new JSONObject(); |
114,6 → 122,7 |
if (this.selection != null) { |
result.put("selection", JSONConverter.getJSON(this.selection)); |
} |
if (this.search != null) { |
result.put("search", JSONConverter.getJSON(this.search)); |
} |
121,23 → 130,30 |
result.put("variable-columns-count", JSONConverter.getJSON(true)); |
} |
if (!this.searchParameters.isEmpty()) { |
JSONArray a = new JSONArray(); |
for (TableSearchParameter p : this.searchParameters) { |
a.add(p.toJSON()); |
} |
result.put("search-params", a); |
} |
return result; |
} |
@Override |
public void fromJSON(final JSONObject json) { |
this.id = (String) JSONConverter.getParameterFromJSON(json, "id", String.class); |
this.id = json.getAsString("id"); |
final JSONObject jsonColumns = (JSONObject) JSONConverter.getParameterFromJSON(json, "columns", JSONObject.class); |
final JSONObject jsonColumns = JSONConverter.getParameterFromJSON(json, "columns", JSONObject.class); |
if (jsonColumns != null) { |
this.columns = new ColumnsSpec(jsonColumns); |
} |
final JSONObject jsonContent = (JSONObject) JSONConverter.getParameterFromJSON(json, "content", JSONObject.class); |
final JSONObject jsonContent = JSONConverter.getParameterFromJSON(json, "content", JSONObject.class); |
if (jsonContent != null) { |
this.content = new TableContent(jsonContent); |
} |
final JSONObject jsonSelection = (JSONObject) JSONConverter.getParameterFromJSON(json, "selection", JSONObject.class); |
final JSONObject jsonSelection = JSONConverter.getParameterFromJSON(json, "selection", JSONObject.class); |
if (jsonSelection != null) { |
this.selection = new RowSelectionSpec(jsonSelection); |
} else { |
144,39 → 160,22 |
throw new IllegalArgumentException("null selection"); |
} |
final JSONObject jsonSearch = (JSONObject) JSONConverter.getParameterFromJSON(json, "search", JSONObject.class); |
final JSONObject jsonSearch = JSONConverter.getParameterFromJSON(json, "search", JSONObject.class); |
if (jsonSearch != null) { |
this.search = new SearchSpec(jsonSearch); |
this.search = new UserSearch(jsonSearch); |
} |
this.variableColumnsCount = (Boolean) JSONConverter.getParameterFromJSON(json, "variable-columns-count", Boolean.class); |
} |
this.variableColumnsCount = JSONConverter.getParameterFromJSON(json, "variable-columns-count", Boolean.class); |
this.searchParameters.clear(); |
if (json.containsKey("search-params")) { |
final JSONArray array = (JSONArray) json.get("search-params"); |
for (Object o : array) { |
final TableSearchParameter p = new TableSearchParameter(); |
p.fromJSON((JSONObject) o); |
this.searchParameters.add(p); |
} |
} |
@Override |
public void writeExternal(ObjectOutput out) throws IOException { |
out.writeUTF(id); |
this.columns.writeExternal(out); |
this.content.writeExternal(out); |
this.selection.writeExternal(out); |
this.search.writeExternal(out); |
out.writeBoolean(this.variableColumnsCount); |
} |
@Override |
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { |
this.id = in.readUTF(); |
this.columns = new ColumnsSpec(); |
this.columns.readExternal(in); |
this.content = new TableContent(); |
this.content.readExternal(in); |
this.selection = new RowSelectionSpec(); |
this.selection.readExternal(in); |
this.search = new SearchSpec(); |
this.search.readExternal(in); |
this.variableColumnsCount = in.readBoolean(); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/mapping_en.xml |
---|
12,7 → 12,8 |
<FIELD name="ID_USER_RIGHT_COMMON" label="User rights" /> |
<FIELD name="MAIL" label="E-Mail" /> |
<FIELD name="DISABLED" label="Account disabled" /> |
<FIELD name="TEL" label="Phone" titlelabel="Phone" /> |
<FIELD name="TEL" label="Phone" /> |
<FIELD name="COLOR" label="Color" /> |
</element> |
<element refid="sql.right"> |
<name base="right" /> |
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/SavableCustomEditorProvider.java |
---|
File deleted |
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/TableSearchColumnMatcher.java |
---|
New file |
0,0 → 1,76 |
/* |
* 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.ui.light; |
import org.openconcerto.sql.model.FieldPath; |
import org.openconcerto.sql.model.FieldRef; |
import org.openconcerto.sql.model.SQLFunctionField; |
import org.openconcerto.sql.model.SQLFunctionField.SQLFunction; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.view.list.SQLTableModelColumn; |
import org.openconcerto.ui.light.TableSearchParameterType; |
import org.openconcerto.ui.light.UserSearchItem; |
import java.util.ArrayList; |
import java.util.Collections; |
import java.util.List; |
import java.util.Set; |
public class TableSearchColumnMatcher implements TableSearchMatcher { |
private final SQLTableModelColumn col; |
public TableSearchColumnMatcher(SQLTableModelColumn col) { |
this.col = col; |
} |
@Override |
public boolean useMatch() { |
return false; |
} |
@Override |
public boolean match(SQLRowValues r, TableSearchParameterType type, String txt) { |
return true; |
} |
@Override |
public Where getWhere(SQLSelect sel, TableSearchParameterType type, String txt) { |
final Set<FieldPath> fields = this.col.getPaths(); |
final List<Where> wFields = new ArrayList<>(fields.size()); |
for (final FieldPath fpath : fields) { |
if (fpath.getField().getType().getJavaType().equals(String.class)) { |
final FieldRef fieldRef = sel.followFieldPath(fpath); |
if (type.getType().equals(UserSearchItem.TYPE_CONTAINS)) { |
final Where w = new Where(new SQLFunctionField(SQLFunction.LOWER, fieldRef), "LIKE", "%" + txt.toLowerCase() + "%"); |
wFields.add(w); |
} else if (type.getType().equals(UserSearchItem.TYPE_STARTS_WITH)) { |
final Where w = new Where(new SQLFunctionField(SQLFunction.LOWER, fieldRef), "LIKE", txt.toLowerCase() + "%"); |
wFields.add(w); |
} else if (type.getType().equals(UserSearchItem.TYPE_IS)) { |
final Where w = new Where(new SQLFunctionField(SQLFunction.LOWER, fieldRef), "LIKE", txt.toLowerCase()); |
wFields.add(w); |
} |
} |
} |
return Where.or(wFields); |
} |
@Override |
public List<FieldPath> getAdditionnalFieldsToFetch() { |
return Collections.emptyList(); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/SearchInfo.java |
---|
17,8 → 17,8 |
import org.openconcerto.sql.view.search.SearchList; |
import org.openconcerto.sql.view.search.TextSearchSpec; |
import org.openconcerto.sql.view.search.TextSearchSpec.Mode; |
import org.openconcerto.ui.light.SearchContent; |
import org.openconcerto.ui.light.SearchSpec; |
import org.openconcerto.ui.light.UserSearchItem; |
import org.openconcerto.ui.light.UserSearch; |
import java.util.ArrayList; |
import java.util.List; |
28,10 → 28,10 |
private final SearchList list = new SearchList(); |
private final List<String> texts = new ArrayList<String>(); |
public SearchInfo(final SearchSpec params) { |
public SearchInfo(final UserSearch params) { |
int stop = params.getContent().size(); |
for (int i = 0; i < stop; i++) { |
final SearchContent param = params.getContent().get(i); |
final UserSearchItem param = params.getContent().get(i); |
final String col = param.getColumn(); |
final String type = param.getType(); |
final String[] tTexts = param.getText().split(" "); |
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/TableSearchMatcher.java |
---|
New file |
0,0 → 1,51 |
/* |
* 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.ui.light; |
import org.openconcerto.sql.model.FieldPath; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.ui.light.TableSearchParameterType; |
import java.util.List; |
public interface TableSearchMatcher { |
/** |
* Where to add to prefilter the result |
*/ |
public Where getWhere(SQLSelect sel, TableSearchParameterType type, String txt); |
/** |
* Fields to fetch for this matcher. The fields will be accessed in the match method, from the |
* SQLRowValues |
* |
* @return the fields paths |
* @return null or emtpy List is nothing to fetch |
*/ |
public List<FieldPath> getAdditionnalFieldsToFetch(); |
/** |
* @return true is the match method must be used |
*/ |
public boolean useMatch(); |
/** |
* Match the SQLRowValues retrieve from the database (filtered by the Where from getWhere) using |
* the type and the user text |
*/ |
public boolean match(SQLRowValues r, TableSearchParameterType type, String txt); |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/LightUIPanelFiller.java |
---|
15,6 → 15,7 |
import org.openconcerto.sql.Log; |
import org.openconcerto.sql.PropsConfiguration; |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.model.Constraint; |
import org.openconcerto.sql.model.SQLField; |
import org.openconcerto.sql.model.SQLRowAccessor; |
31,6 → 32,9 |
import java.util.Calendar; |
import java.util.Date; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
import java.util.Set; |
/** |
58,11 → 62,17 |
} |
} |
public void fillFromRow(final PropsConfiguration configuration, final SQLRowAccessor row) { |
this.fillFromRow(this.panel, configuration, row); |
public void fillFromRow(final PropsConfiguration configuration, SQLElement element, final SQLRowAccessor row, String sessionSecurityToken) { |
this.fillFromRow(this.panel, configuration, element, row, sessionSecurityToken); |
} |
private void fillFromRow(final LightUIPanel panel, final PropsConfiguration configuration, SQLRowAccessor sqlRow) { |
private void fillFromRow(final LightUIPanel panel, final PropsConfiguration configuration, SQLElement sqlElement, SQLRowAccessor sqlRow, String sessionSecurityToken) { |
List<CustomRowEditor> editors = sqlElement.getCustomRowEditors(configuration, sessionSecurityToken); |
Map<String, CustomRowEditor> mapEditor = new HashMap<>(editors.size()); |
for (CustomRowEditor e : editors) { |
mapEditor.put(e.getItemId(), e); |
} |
final int panelChildCount = panel.getChildrenCount(); |
// Convert as sqlrow if possible to get all values from db |
if (sqlRow.hasID()) { |
73,54 → 83,59 |
final int lineChildCount = panelChild.getChildrenCount(); |
for (int j = 0; j < lineChildCount; j++) { |
final LightUIElement element = panelChild.getChild(j); |
final SQLField sqlField = configuration.getFieldMapper().getSQLFieldForItem(element.getId()); |
if (mapEditor.containsKey(element.getId())) { |
mapEditor.get(element.getId()).fillFrom(element, sqlRow); |
} else { |
SQLRowAccessor sqlRowTmp = this.getSQLRowForField(sqlRow, sqlField); |
if (sqlRowTmp == null) { |
throw new IllegalArgumentException("Impossible to reach the field: " + sqlField.getName() + " from table " + sqlRow.getTable().getName()); |
} |
final SQLField sqlField = configuration.getFieldMapper().getSQLFieldForItem(element.getId()); |
int type = element.getType(); |
if (type == LightUIElement.TYPE_TEXT_FIELD || type == LightUIElement.TYPE_TEXT_AREA) { |
SQLRowAccessor sqlRowTmp = this.getSQLRowForField(sqlRow, sqlField); |
if (sqlRowTmp == null) { |
throw new IllegalArgumentException("Impossible to reach the field: " + sqlField.getName() + " from table " + sqlRow.getTable().getName()); |
} |
if (sqlField == null) { |
Log.get().severe("No field found for text field : " + element.getId()); |
continue; |
} |
element.setValue(sqlRowTmp.getString(sqlField.getName())); |
} else if (sqlField != null && sqlField.isKey() && (type == LightUIElement.TYPE_COMBOBOX || type == LightUIElement.TYPE_AUTOCOMPLETE_COMBOBOX)) { |
// send: id,value |
final LightUIComboBox combo = (LightUIComboBox) element; |
LightUIComboBoxElement value = null; |
final Number foreignID = sqlRowTmp.getForeignIDNumber(sqlField.getName()); |
if (foreignID != null) { |
final SQLTable foreignTable = sqlField.getForeignTable(); |
final ComboSQLRequest req = configuration.getDirectory().getElement(foreignTable).getComboRequest(); |
final IComboSelectionItem comboItem = req.getComboItem(foreignID.intValue()); |
if (comboItem != null) { |
value = new LightUIComboBoxElement(comboItem.getId()); |
value.setValue1(comboItem.getLabel()); |
int type = element.getType(); |
if (type == LightUIElement.TYPE_TEXT_FIELD || type == LightUIElement.TYPE_TEXT_AREA) { |
if (sqlField == null) { |
Log.get().severe("No field found for text field : " + element.getId()); |
continue; |
} |
element.setValue(sqlRowTmp.getString(sqlField.getName())); |
} else if (sqlField != null && sqlField.isKey() && (type == LightUIElement.TYPE_COMBOBOX || type == LightUIElement.TYPE_AUTOCOMPLETE_COMBOBOX)) { |
// send: id,value |
final LightUIComboBox combo = (LightUIComboBox) element; |
LightUIComboBoxElement value = null; |
final Number foreignID = sqlRowTmp.getForeignIDNumber(sqlField.getName()); |
if (foreignID != null) { |
final SQLTable foreignTable = sqlField.getForeignTable(); |
final ComboSQLRequest req = configuration.getDirectory().getElement(foreignTable).getComboRequest(); |
final IComboSelectionItem comboItem = req.getComboItem(foreignID.intValue()); |
if (comboItem != null) { |
value = new LightUIComboBoxElement(comboItem.getId()); |
value.setValue1(comboItem.getLabel()); |
} |
} |
combo.setSelectedValue(value); |
} else if (type == LightUIElement.TYPE_CHECKBOX) { |
if (sqlRowTmp.getObject(sqlField.getName()) != null && sqlRowTmp.getBoolean(sqlField.getName())) { |
element.setValue("true"); |
} else { |
element.setValue("false"); |
} |
} else if (type == LightUIElement.TYPE_DATE) { |
Calendar date = sqlRowTmp.getDate(sqlField.getName()); |
if (date != null) { |
element.setValue(JSONConverter.getJSON(date).toString()); |
} |
} else if (type == LightUIElement.TYPE_PANEL) { |
this.fillFromRow((LightUIPanel) element, configuration, sqlElement, sqlRowTmp, sessionSecurityToken); |
} else if (type == LightUIElement.TYPE_SLIDER) { |
final Integer value = sqlRowTmp.getInt(sqlField.getName()); |
if (value != null) { |
element.setValue(value.toString()); |
} |
} |
combo.setSelectedValue(value); |
} else if (type == LightUIElement.TYPE_CHECKBOX) { |
if (sqlRowTmp.getObject(sqlField.getName()) != null && sqlRowTmp.getBoolean(sqlField.getName())) { |
element.setValue("true"); |
} else { |
element.setValue("false"); |
} |
} else if (type == LightUIElement.TYPE_DATE) { |
Calendar date = sqlRowTmp.getDate(sqlField.getName()); |
if (date != null) { |
element.setValue(JSONConverter.getJSON(date).toString()); |
} |
} else if (type == LightUIElement.TYPE_PANEL) { |
this.fillFromRow((LightUIPanel) element, configuration, sqlRowTmp); |
} else if (type == LightUIElement.TYPE_SLIDER) { |
final Integer value = sqlRowTmp.getInt(sqlField.getName()); |
if (value != null) { |
element.setValue(value.toString()); |
} |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/LightForeignRowValuesTableOffline.java |
---|
16,11 → 16,12 |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.model.SQLField; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.view.list.ITableModel; |
import org.openconcerto.sql.view.list.SQLTableModelLinesSourceOffline; |
import org.openconcerto.ui.light.LightUIElement; |
import org.openconcerto.ui.light.SearchSpec; |
import org.openconcerto.ui.light.TableContent; |
import org.openconcerto.ui.light.UserSearch; |
import java.util.concurrent.Future; |
31,14 → 32,19 |
private SQLField foreignField; |
private Number parentRowId; |
public LightForeignRowValuesTableOffline(final Configuration configuration, final Number userId, final String id, final ITableModel model, final SQLField foreignField, final Number parentRowId) { |
public LightForeignRowValuesTableOffline(final Configuration configuration, final Number userId, final String id, final ITableModel model, final SQLField foreignField) { |
super(configuration, userId, id, model); |
this.foreignField = foreignField; |
this.parentRowId = parentRowId; |
this.init(); |
} |
public void setParentRowId(Number parentRowId) { |
this.parentRowId = parentRowId; |
// FIXME : d'apres Sylvain, on pourrait ne pas a utiliser le ITableMobel car on veut du |
// synchrone |
this.getModel().getReq().getReq().setWhere(new Where(this.foreignField, "=", parentRowId)); |
} |
public LightForeignRowValuesTableOffline(final LightForeignRowValuesTableOffline table) { |
super(table); |
70,7 → 76,7 |
} |
@Override |
public void doSearch(final Configuration configuration, final SearchSpec searchSpec, final int offset) { |
public void doSearch(final Configuration configuration, final UserSearch searchSpec, final int offset) { |
// TODO: Implement search in offline table |
this.getModel().fireTableRowsInserted(0, Integer.MAX_VALUE); |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/GroupToLightUIConvertor.java |
---|
23,7 → 23,6 |
import org.openconcerto.ui.group.Group; |
import org.openconcerto.ui.group.Item; |
import org.openconcerto.ui.group.LayoutHints; |
import org.openconcerto.ui.light.CustomEditorProvider; |
import org.openconcerto.ui.light.LightUIAutoCompleteComboBox; |
import org.openconcerto.ui.light.LightUICheckBox; |
import org.openconcerto.ui.light.LightUIDate; |
43,6 → 42,7 |
import java.sql.Timestamp; |
import java.util.Date; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
public class GroupToLightUIConvertor { |
49,7 → 49,7 |
private final int maxColumnCount; |
private PropsConfiguration configuration; |
private FieldMapper mapper; |
private Map<String, CustomEditorProvider> customEditorProviders = new HashMap<String, CustomEditorProvider>(); |
private Map<String, CustomRowEditor> customRowEditors = new HashMap<>(); |
public GroupToLightUIConvertor(PropsConfiguration conf) { |
this(conf, 4); |
73,6 → 73,15 |
} |
final SQLElement sqlElement = this.configuration.getDirectory().getElement(defaultRow.getTable()); |
if (sqlElement == null) { |
throw new IllegalArgumentException("not SQLElement found for default row table : " + defaultRow.getTable().getName()); |
} |
if (sqlElement.getGroupForCreation() == null) { |
throw new IllegalArgumentException("no group for creation defined in " + sqlElement.getClass().getName()); |
} |
if (sqlElement.getGroupForModification() == null) { |
throw new IllegalArgumentException("no group for creation defined in " + sqlElement.getClass().getName()); |
} |
if (!sqlElement.getGroupForCreation().equals(group) && sqlElement.getGroupForModification().equals(group)) { |
throw new IllegalArgumentException("This group isn't attached to this SQLElement, group ID: " + group.getId() + " element code: " + sqlElement.getCode()); |
} |
313,11 → 322,14 |
} |
private LightUIElement getCustomEditor(final String id) { |
final CustomEditorProvider customEditorProvider = this.customEditorProviders.get(id); |
if (id == null) { |
throw new IllegalArgumentException("null id"); |
} |
final CustomRowEditor customEditorProvider = this.customRowEditors.get(id); |
if (customEditorProvider != null) { |
final LightUIElement element = customEditorProvider.createUIElement(id); |
final LightUIElement element = customEditorProvider.createUIElement(); |
if (element.getId() == null) { |
throw new IllegalStateException("Null id for custom editor for id: " + id); |
throw new IllegalStateException("Null id for custom editor for id: " + id + " element : " + element); |
} |
return element; |
} |
324,11 → 336,12 |
return null; |
} |
public void putCustomEditorProvider(final String id, final CustomEditorProvider provider) { |
this.customEditorProviders.put(id, provider); |
public void putCustomEditorProvider(final CustomRowEditor e) { |
this.customRowEditors.put(e.getItemId(), e); |
} |
public void putAllCustomEditorProvider(final Map<String, CustomEditorProvider> map) { |
this.customEditorProviders.putAll(map); |
public void putAllCustomEditorProvider(final List<CustomRowEditor> editors) { |
for (CustomRowEditor e : editors) |
this.customRowEditors.put(e.getItemId(), e); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/LightRowValuesTable.java |
---|
14,8 → 14,14 |
package org.openconcerto.sql.ui.light; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.model.FieldPath; |
import org.openconcerto.sql.model.FieldRef; |
import org.openconcerto.sql.model.SQLFunctionField; |
import org.openconcerto.sql.model.SQLFunctionField.SQLFunction; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.view.list.ITableModel; |
import org.openconcerto.sql.view.list.ListSQLLine; |
import org.openconcerto.sql.view.list.SQLTableModelColumn; |
26,12 → 32,21 |
import org.openconcerto.ui.light.LightUIElement; |
import org.openconcerto.ui.light.LightUITable; |
import org.openconcerto.ui.light.Row; |
import org.openconcerto.ui.light.SearchSpec; |
import org.openconcerto.ui.light.TableSearchParameter; |
import org.openconcerto.ui.light.TableSearchParameterType; |
import org.openconcerto.ui.light.UserSearch; |
import org.openconcerto.ui.light.UserSearchItem; |
import org.openconcerto.utils.NumberUtils; |
import org.openconcerto.utils.cc.ITransformer; |
import java.util.ArrayList; |
import java.util.Collections; |
import java.util.HashMap; |
import java.util.HashSet; |
import java.util.List; |
import java.util.Locale; |
import java.util.Map; |
import java.util.Set; |
import java.util.concurrent.Callable; |
import javax.swing.SwingUtilities; |
55,8 → 70,10 |
private transient ITransformer<SQLSelect, SQLSelect> orginTransformer; |
private transient List<TableModelListener> tableModelListeners = new ArrayList<TableModelListener>(); |
private transient List<TableModelListener> tableModelListeners = new ArrayList<>(); |
private Map<TableSearchParameter, TableSearchMatcher> searchMap = new HashMap<>(); |
public LightRowValuesTable() { |
// Serialization |
} |
72,6 → 89,74 |
if (model.getReq() instanceof SQLTableModelSourceOnline) { |
final SQLTableModelSourceOnline source = (SQLTableModelSourceOnline) model.getReq(); |
this.orginTransformer = source.getReq().getSelectTransf(); |
List<SQLTableModelColumn> columns = model.getReq().getColumns(); |
// all |
// TODO : traduire |
TableSearchParameter tableSearchParameterAll = new TableSearchParameter("all", "Tous"); |
TableSearchMatcher m = new TableSearchMatcher() { |
@Override |
public boolean useMatch() { |
return false; |
} |
@Override |
public boolean match(SQLRowValues r, TableSearchParameterType type, String txt) { |
return true; |
} |
@Override |
public Where getWhere(SQLSelect sel, TableSearchParameterType type, String txt) { |
final Set<FieldPath> fields = new HashSet<>(); |
for (SQLTableModelColumn col : columns) { |
fields.addAll(col.getPaths()); |
} |
final List<Where> wFields = new ArrayList<>(fields.size()); |
for (final FieldPath fpath : fields) { |
if (fpath.getField().getType().getJavaType().equals(String.class)) { |
final FieldRef fieldRef = sel.followFieldPath(fpath); |
if (type.getType().equals(UserSearchItem.TYPE_CONTAINS)) { |
final Where w = new Where(new SQLFunctionField(SQLFunction.LOWER, fieldRef), "LIKE", "%" + txt.toLowerCase() + "%"); |
wFields.add(w); |
} |
if (type.getType().equals(UserSearchItem.TYPE_STARTS_WITH)) { |
final Where w = new Where(new SQLFunctionField(SQLFunction.LOWER, fieldRef), "LIKE", txt.toLowerCase() + "%"); |
wFields.add(w); |
} |
if (type.getType().equals(UserSearchItem.TYPE_IS)) { |
final Where w = new Where(new SQLFunctionField(SQLFunction.LOWER, fieldRef), "LIKE", txt.toLowerCase()); |
wFields.add(w); |
} |
} |
} |
return Where.or(wFields); |
} |
@Override |
public List<FieldPath> getAdditionnalFieldsToFetch() { |
return Collections.emptyList(); |
} |
}; |
tableSearchParameterAll.add(TableSearchParameterType.getContainsStringInstance(Locale.FRENCH)); |
tableSearchParameterAll.add(TableSearchParameterType.getIsStringInstance(Locale.FRENCH)); |
this.addSearchParameter(tableSearchParameterAll, m); |
// |
for (int i = 0; i < columns.size(); i++) { |
SQLTableModelColumn col = columns.get(i); |
TableSearchParameter tableSearchParameter = new TableSearchParameter("col" + i, col.getName()); |
// FIXME : locale à recuperer depuis le user |
// TODO : mettre d'autres TableSearchParameterType en fonction du type de la colonne |
tableSearchParameter.add(TableSearchParameterType.getContainsStringInstance(Locale.FRENCH)); |
tableSearchParameter.add(TableSearchParameterType.getIsStringInstance(Locale.FRENCH)); |
TableSearchMatcher tableSearchMatcher = new TableSearchColumnMatcher(col); |
this.addSearchParameter(tableSearchParameter, tableSearchMatcher); |
} |
} else { |
this.orginTransformer = null; |
} |
108,7 → 193,13 |
public final void addTableModelListener(final TableModelListener tableModelListener) { |
this.tableModelListeners.add(tableModelListener); |
this.model.addTableModelListener(tableModelListener); |
SwingUtilities.invokeLater(new Runnable() { |
@Override |
public void run() { |
LightRowValuesTable.this.model.addTableModelListener(tableModelListener); |
} |
}); |
} |
public final void removeTableModelListener(final TableModelListener tableModelListener) { |
270,8 → 361,26 |
} |
// TODO: merge with OpenConcerto List search system |
public abstract void doSearch(final Configuration configuration, final SearchSpec searchSpec, final int offset); |
public abstract void doSearch(final Configuration configuration, final UserSearch searchSpec, final int offset); |
public void addSearchParameter(TableSearchParameter tableSearchParameter, TableSearchMatcher tableSearchMatcher) { |
this.searchMap.put(tableSearchParameter, tableSearchMatcher); |
this.getTableSpec().addSearchParameter(tableSearchParameter); |
} |
protected TableSearchMatcher getSearchMatcher(String colId, String searchType) { |
for (TableSearchParameter p : this.searchMap.keySet()) { |
if (p.getId().equals(colId)) { |
for (TableSearchParameterType t : p.getTypes()) { |
if (t.getType().equals(searchType)) { |
return this.searchMap.get(p); |
} |
} |
} |
} |
return null; |
} |
@Override |
public Row getRowById(Number rowId) { |
for (int i = 0; i < this.model.getRowCount(); i++) { |
314,9 → 423,10 |
SwingUtilities.invokeAndWait(new Runnable() { |
@Override |
public void run() { |
final List<TableModelListener> tableModelListeners = LightRowValuesTable.this.tableModelListeners; |
for (int i = tableModelListeners.size() - 1; i > -1; i--) { |
LightRowValuesTable.this.removeTableModelListener(tableModelListeners.get(i)); |
final List<TableModelListener> listeners = LightRowValuesTable.this.tableModelListeners; |
for (int i = listeners.size() - 1; i > -1; i--) { |
LightRowValuesTable.this.removeTableModelListener(listeners.get(i)); |
} |
} |
}); |
325,5 → 435,6 |
} |
this.clearRows(); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/LightEditFrame.java |
---|
41,6 → 41,8 |
import java.sql.SQLException; |
import java.sql.Timestamp; |
import java.util.Date; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
import java.util.concurrent.Future; |
145,19 → 147,18 |
final SQLElement sqlElement = configuration.getDirectory().getElement(this.sqlRow.getTable()); |
final Map<String, CustomEditorProvider> customEditors; |
if (this.editMode.equals(EditMode.CREATION)) { |
customEditors = sqlElement.getCustomEditorProviderForCreation(configuration, sessionSecurityToken); |
} else { |
customEditors = sqlElement.getCustomEditorProviderForModification(configuration, this.sqlRow, sessionSecurityToken); |
final List<CustomRowEditor> customRowEditors = sqlElement.getCustomRowEditors(configuration, sessionSecurityToken); |
final Map<String, CustomRowEditor> customEditors = new HashMap<>(customRowEditors.size()); |
for (CustomRowEditor e : customRowEditors) { |
customEditors.put(e.getItemId(), e); |
} |
this.createRowValues(configuration, sqlElement, fieldMapper, this.group, customEditors); |
this.setMetaData(userId); |
} |
final protected void createRowValues(final Configuration configuration, final SQLElement sqlElement, final FieldMapper fieldMapper, final Group group, |
final Map<String, CustomEditorProvider> customEditors) { |
protected final void createRowValues(final Configuration configuration, final SQLElement sqlElement, final FieldMapper fieldMapper, final Group group, |
final Map<String, CustomRowEditor> customEditors) { |
final int itemCount = group.getSize(); |
for (int i = 0; i < itemCount; i++) { |
final Item item = group.getItem(i); |
176,7 → 177,16 |
this.putValueFromUserControl(configuration, sqlElement, field, uiElement, customEditors); |
} |
} else { |
Log.get().warning("No field attached to " + item.getId()); |
final LightUIElement uiElement = this.findChildByID(item.getId(), LightUIElement.class); |
if (uiElement == null) { |
throw new IllegalArgumentException("Impossible to find UI Element with id: " + item.getId()); |
} |
if (customEditors.containsKey(uiElement.getId())) { |
final CustomRowEditor customEditor = customEditors.get(uiElement.getId()); |
customEditor.store(uiElement, this.sqlRow); |
} else { |
Log.get().warning("No field attached to " + item.getId()); |
} |
} |
} |
} |
183,19 → 193,13 |
} |
protected final void putValueFromUserControl(final Configuration configuration, final SQLElement sqlElement, final SQLField sqlField, final LightUIElement uiElement, |
final Map<String, CustomEditorProvider> customEditors) { |
final Map<String, CustomRowEditor> customEditors) { |
if (!uiElement.isNotSaved()) { |
boolean useElementValue = true; |
final Class<?> fieldType = sqlField.getType().getJavaType(); |
if (customEditors.containsKey(uiElement.getId())) { |
final CustomEditorProvider customEditor = customEditors.get(uiElement.getId()); |
if (customEditor instanceof SavableCustomEditorProvider) { |
((SavableCustomEditorProvider) customEditor).save(this.sqlRow, sqlField, uiElement); |
useElementValue = false; |
} |
} |
if (useElementValue) { |
final CustomRowEditor customEditor = customEditors.get(uiElement.getId()); |
customEditor.store(uiElement, this.sqlRow); |
} else { |
final String fieldName = sqlField.getFieldName(); |
if (sqlField.isKey()) { |
if (!(uiElement instanceof LightUIComboBox)) { |
268,11 → 272,13 |
* @param row Element saved row |
* @param customEditors List of custom editors used in element edit frame |
*/ |
final public void saveReferentRows(final Configuration configuration, final SQLRow parentSqlRow, final Map<String, CustomEditorProvider> customEditors, final String sessionSecurityToken) { |
@Deprecated |
public final void saveReferentRows(final Configuration configuration, final SQLRow parentSqlRow, final Map<String, CustomEditorProvider> customEditors, final String sessionSecurityToken) { |
this.saveReferentRows(configuration, this.group, parentSqlRow, customEditors, sessionSecurityToken); |
} |
final private void saveReferentRows(final Configuration configuration, final Group group, final SQLRow parentSqlRow, final Map<String, CustomEditorProvider> customEditors, |
@Deprecated |
private final void saveReferentRows(final Configuration configuration, final Group group, final SQLRow parentSqlRow, final Map<String, CustomEditorProvider> customEditors, |
final String sessionSecurityToken) { |
for (int i = 0; i < group.getSize(); i++) { |
final Item item = group.getItem(i); |
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/CustomRowEditor.java |
---|
New file |
0,0 → 1,49 |
/* |
* 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.ui.light; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.ui.light.LightUIElement; |
public abstract class CustomRowEditor { |
private final String itemId; |
public CustomRowEditor(String itemId) { |
this.itemId = itemId; |
} |
public String getItemId() { |
return this.itemId; |
} |
/** |
* Create the UI element filled with the row |
* |
*/ |
public abstract LightUIElement createUIElement(); |
public abstract void fillFrom(final LightUIElement uiElement, final SQLRowAccessor row); |
/** |
* Store the values in the row from the UI element |
*/ |
public abstract void store(final LightUIElement uiElement, final SQLRowValues row); |
public void afterCommit(LightUIElement uiElement, SQLRow insertedRow) { |
// nothing |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/LightRowValuesTableOnline.java |
---|
14,29 → 14,23 |
package org.openconcerto.sql.ui.light; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.model.IFieldPath; |
import org.openconcerto.sql.model.SQLFunctionField; |
import org.openconcerto.sql.model.SQLFunctionField.SQLFunction; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.Log; |
import org.openconcerto.sql.model.FieldPath; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.request.ListSQLRequest; |
import org.openconcerto.sql.view.list.ITableModel; |
import org.openconcerto.sql.view.list.SQLTableModelColumn; |
import org.openconcerto.sql.view.list.SQLTableModelSource; |
import org.openconcerto.sql.view.list.SQLTableModelSourceOnline; |
import org.openconcerto.ui.light.SearchSpec; |
import org.openconcerto.ui.light.TableSearchParameterType; |
import org.openconcerto.ui.light.UserSearch; |
import org.openconcerto.ui.light.UserSearchItem; |
import org.openconcerto.utils.cc.ITransformer; |
import java.util.ArrayList; |
import java.util.HashSet; |
import java.util.Arrays; |
import java.util.List; |
import java.util.Set; |
import java.util.concurrent.Callable; |
import java.util.concurrent.FutureTask; |
import javax.swing.SwingUtilities; |
import net.minidev.json.JSONObject; |
public class LightRowValuesTableOnline extends LightRowValuesTable { |
48,7 → 42,6 |
public LightRowValuesTableOnline(final Configuration configuration, final Number userId, final String id, final ITableModel model) { |
super(configuration, userId, id, model); |
this.orginTransformer = ((SQLTableModelSourceOnline) model.getReq()).getReq().getSelectTransf(); |
} |
55,7 → 48,6 |
// Clone constructor |
public LightRowValuesTableOnline(final LightRowValuesTableOnline tableElement) { |
super(tableElement); |
this.orginTransformer = tableElement.orginTransformer; |
} |
66,85 → 58,73 |
} |
@Override |
public void doSearch(final Configuration configuration, final SearchSpec searchSpec, final int offset) { |
public void doSearch(final Configuration configuration, final UserSearch searchSpec, final int offset) { |
this.getTableSpec().setSearch(searchSpec); |
this.setOffset(offset); |
final SQLTableModelSource tableSource = this.getModel().getReq(); |
final SearchInfo sInfo = (searchSpec != null) ? new SearchInfo(searchSpec) : null; |
final ListSQLRequest req = tableSource.getReq(); |
final List<UserSearchItem> content = new ArrayList<>(); |
if (searchSpec != null) { |
content.addAll(searchSpec.getContent()); |
final FutureTask<ListSQLRequest> f = new FutureTask<ListSQLRequest>(new Callable<ListSQLRequest>() { |
@Override |
public ListSQLRequest call() throws Exception { |
final ListSQLRequest req = tableSource.getReq(); |
final List<SQLTableModelColumn> columns = tableSource.getColumns(); |
req.setSelectTransf(new ITransformer<SQLSelect, SQLSelect>() { |
@Override |
public SQLSelect transformChecked(final SQLSelect sel) { |
if (LightRowValuesTableOnline.this.orginTransformer != null) { |
LightRowValuesTableOnline.this.orginTransformer.transformChecked(sel); |
} |
setWhere(sel, sInfo, columns); |
return sel; |
for (UserSearchItem item : content) { |
// ex "col0" |
String colId = item.getColumn(); |
// ex "contains" |
String searchType = item.getType(); |
TableSearchMatcher m = LightRowValuesTableOnline.this.getSearchMatcher(colId, searchType); |
if (m != null && m.getAdditionnalFieldsToFetch() != null) { |
for (FieldPath p : m.getAdditionnalFieldsToFetch()) { |
req.addToGraphToFetch(p.getPath(), Arrays.asList(p.getField().getFieldName())); |
} |
}); |
return req; |
} |
} |
}); |
// TODO: clean swing |
SwingUtilities.invokeLater(f); |
try { |
final ListSQLRequest req = f.get(); |
// get values |
long t4 = System.currentTimeMillis(); |
final List<SQLRowValues> rowValues = req.getValues(); |
final int size = rowValues.size(); |
long t5 = System.currentTimeMillis(); |
System.err.println("DefaultTableContentHandler.handle() getValues() :" + size + " : " + (t5 - t4) + " ms"); |
} catch (final Exception e) { |
throw new IllegalStateException(e); |
} |
} |
req.setSelectTransf(new ITransformer<SQLSelect, SQLSelect>() { |
@Override |
public SQLSelect transformChecked(final SQLSelect sel) { |
if (LightRowValuesTableOnline.this.orginTransformer != null) { |
LightRowValuesTableOnline.this.orginTransformer.transformChecked(sel); |
} |
if (searchSpec != null) { |
// |
final List<Where> wheres = new ArrayList<>(); |
for (UserSearchItem item : content) { |
// ex "col0" |
String colId = item.getColumn(); |
// ex "hello" |
String userText = item.getText(); |
// ex "contains" |
String searchType = item.getType(); |
TableSearchMatcher m = LightRowValuesTableOnline.this.getSearchMatcher(colId, searchType); |
if (m != null) { |
final Where where = m.getWhere(sel, new TableSearchParameterType(searchType), userText); |
if (where != null) { |
wheres.add(where); |
} |
} else { |
Log.get().warning("no TableSearchMatcher for " + item); |
} |
/** |
* Apply filter on ListSQLRequest |
* |
* @param sel - The ListSQLRequest select |
* @param sInfo - Search parameters |
*/ |
private final void setWhere(final SQLSelect sel, final SearchInfo sInfo, final List<SQLTableModelColumn> cols) { |
if (sInfo != null) { |
final Set<IFieldPath> fields = new HashSet<>(cols.size() * 2); |
for (final SQLTableModelColumn sqlTableModelColumn : cols) { |
fields.addAll(sqlTableModelColumn.getPaths()); |
} |
final List<Where> wheres = new ArrayList<>(); |
final List<Where> wFields = new ArrayList<>(); |
} |
final List<String> texts = sInfo.getTexts(); |
for (String string : texts) { |
wFields.clear(); |
for (final IFieldPath fpath : fields) { |
if (fpath.getField().getType().getJavaType().equals(String.class)) { |
final Where w = new Where(new SQLFunctionField(SQLFunction.LOWER, sel.followFieldPath(fpath)), "LIKE", "%" + string.toLowerCase() + "%"); |
wFields.add(w); |
final Where w; |
if (!wheres.isEmpty()) { |
if (sel.getWhere() != null) { |
w = Where.and(sel.getWhere(), Where.and(wheres)); |
} else { |
w = Where.and(wheres); |
} |
sel.setWhere(w); |
} |
} |
wheres.add(Where.or(wFields)); |
return sel; |
} |
}); |
final Where w; |
if (sel.getWhere() != null) { |
w = Where.and(sel.getWhere(), Where.and(wheres)); |
} else { |
w = Where.and(wheres); |
} |
sel.setWhere(w); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/IColorChooser.java |
---|
New file |
0,0 → 1,85 |
/* |
* 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.ui; |
import org.openconcerto.ui.ColorField; |
import org.openconcerto.ui.valuewrapper.ValueWrapper; |
import org.openconcerto.utils.checks.ValidListener; |
import org.openconcerto.utils.checks.ValidState; |
import java.awt.Color; |
import java.beans.PropertyChangeListener; |
import javax.swing.JComponent; |
public class IColorChooser extends ColorField implements ValueWrapper<Integer> { |
public IColorChooser(String title) { |
super(title); |
} |
@Override |
public JComponent getComp() { |
return this; |
} |
@Override |
public ValidState getValidState() { |
return ValidState.getTrueInstance(); |
} |
@Override |
public void setValue(Integer val) { |
if (val == null) { |
val = Color.WHITE.getRGB(); |
} |
setColor(new Color(val)); |
} |
@Override |
public Integer getValue() { |
if (getColor() == null) { |
return null; |
} else { |
return getColor().getRGB(); |
} |
} |
@Override |
public void addValidListener(ValidListener l) { |
// TODO Auto-generated method stub |
} |
@Override |
public void removeValidListener(ValidListener l) { |
// TODO Auto-generated method stub |
} |
@Override |
public void resetValue() { |
this.setColor(null); |
} |
@Override |
public final void addValueListener(final PropertyChangeListener l) { |
this.addPropertyChangeListener("value", l); |
} |
@Override |
public void rmValueListener(final PropertyChangeListener l) { |
this.removePropertyChangeListener("value", l); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/mapping_fr.xml |
---|
2,21 → 2,23 |
<translations> |
<element refid="sql.user"> |
<name base="utilisateur" nounClass="masculine" /> |
<FIELD name="NOM" label="Nom" titlelabel="Nom" /> |
<FIELD name="PRENOM" label="Prénom" titlelabel="Prénom" /> |
<FIELD name="PASSWORD" label="Mot de passe" titlelabel="Mot de passe" /> |
<FIELD name="NOM" label="Nom" /> |
<FIELD name="PRENOM" label="Prénom" /> |
<FIELD name="PASSWORD" label="Mot de passe" /> |
<FIELD name="PASSWORD_CONFIRM" label="Confirmation" /> |
<FIELD name="LOGIN" label="Identifiant" titlelabel="Identifiant" /> |
<FIELD name="SURNOM" label="Surnom" titlelabel="Surnom" /> |
<FIELD name="LOGIN" label="Identifiant" /> |
<FIELD name="SURNOM" label="Surnom" /> |
<FIELD name="ADMIN" label="Administrateur" titlelabel="Admin." /> |
<FIELD name="ID_USER_RIGHT_COMMON" label="Droits utilisateur" titlelabel="Droits utilisateur" /> |
<FIELD name="ID_USER_RIGHT_COMMON" label="Droits utilisateur" /> |
<FIELD name="MAIL" label="E-Mail" titlelabel="E-Mail" /> |
<FIELD name="COMPTE_NUMERO" label="N° compte comptable" /> |
<FIELD name="DISABLED" label="Compte désactivé" /> |
<FIELD name="TEL" label="Téléphone" titlelabel="Téléphone" /> |
<FIELD name="TEL" label="Téléphone" /> |
<FIELD name="COLOR" label="Couleur" /> |
</element> |
<element refid="sql.right"> |
<name base="droit" nounClass="masculine" /> |
<FIELD name="CODE" label="Code" titlelabel="Code" /> |
<FIELD name="CODE" label="Code" /> |
<FIELD name="NOM" label="Nom" titlelabel="Nom du droit" /> |
<FIELD name="DESCRIPTION" label="Description" titlelabel="Desc." /> |
</element> |
/trunk/OpenConcerto/src/org/openconcerto/sql/element/SQLElement.java |
---|
57,10 → 57,10 |
import org.openconcerto.sql.request.SQLCache; |
import org.openconcerto.sql.request.SQLFieldTranslator; |
import org.openconcerto.sql.sqlobject.SQLTextCombo; |
import org.openconcerto.sql.ui.light.CustomRowEditor; |
import org.openconcerto.sql.ui.light.GroupToLightUIConvertor; |
import org.openconcerto.sql.ui.light.LightEditFrame; |
import org.openconcerto.sql.ui.light.LightUIPanelFiller; |
import org.openconcerto.sql.ui.light.SavableCustomEditorProvider; |
import org.openconcerto.sql.users.rights.UserRightsManager; |
import org.openconcerto.sql.utils.SQLUtils; |
import org.openconcerto.sql.utils.SQLUtils.SQLFactory; |
74,7 → 74,6 |
import org.openconcerto.sql.view.list.SQLTableModelSourceOnline; |
import org.openconcerto.ui.group.Group; |
import org.openconcerto.ui.light.ComboValueConvertor; |
import org.openconcerto.ui.light.CustomEditorProvider; |
import org.openconcerto.ui.light.IntValueConvertor; |
import org.openconcerto.ui.light.LightUIComboBox; |
import org.openconcerto.ui.light.LightUIElement; |
337,10 → 336,10 |
editFrame.createTitlePanel(this.getCreationFrameTitle()); |
} else if (editMode.equals(EditMode.MODIFICATION)) { |
editFrame.createTitlePanel(this.getModificationFrameTitle(sqlRow)); |
new LightUIPanelFiller(editFrame.getContentPanel()).fillFromRow(configuration, sqlRow); |
new LightUIPanelFiller(editFrame.getContentPanel()).fillFromRow(configuration, this, sqlRow, sessionSecurityToken); |
} else if (editMode.equals(EditMode.READONLY)) { |
editFrame.createTitlePanel(this.getReadOnlyFrameTitle(sqlRow)); |
new LightUIPanelFiller(editFrame.getContentPanel()).fillFromRow(configuration, sqlRow); |
new LightUIPanelFiller(editFrame.getContentPanel()).fillFromRow(configuration, this, sqlRow, sessionSecurityToken); |
} |
this.setEditFrameModifiers(editFrame, sessionSecurityToken); |
389,11 → 388,12 |
*/ |
public GroupToLightUIConvertor getGroupToLightUIConvertor(final PropsConfiguration configuration, final EditMode editMode, final SQLRowAccessor sqlRow, final String token) { |
final GroupToLightUIConvertor convertor = new GroupToLightUIConvertor(configuration); |
if (editMode.equals(EditMode.CREATION)) { |
convertor.putAllCustomEditorProvider(this.getCustomEditorProviderForCreation(configuration, token)); |
} else { |
convertor.putAllCustomEditorProvider(this.getCustomEditorProviderForModification(configuration, sqlRow, token)); |
} |
// if (editMode.equals(EditMode.CREATION)) { |
convertor.putAllCustomEditorProvider(this.getCustomRowEditors(configuration, token)); |
// } else { |
// convertor.putAllCustomEditorProvider(this.getCustomRowEditors(configuration, sqlRow, |
// token)); |
// } |
return convertor; |
} |
418,76 → 418,55 |
public void setEditFrameModifiers(final LightEditFrame frame, final String sessionToken) { |
} |
public final Map<String, CustomEditorProvider> getCustomEditorProviderForCreation(final Configuration configuration, final String sessionToken) { |
final Map<String, CustomEditorProvider> map = this.getDefaultCustomEditorProvider(configuration, null, sessionToken); |
map.putAll(this._getCustomEditorProviderForCreation(configuration, sessionToken)); |
return map; |
} |
public final Map<String, CustomEditorProvider> getCustomEditorProviderForModification(final Configuration configuration, final SQLRowAccessor sqlRow, final String sessionToken) { |
final Map<String, CustomEditorProvider> map = this.getDefaultCustomEditorProvider(configuration, sqlRow, sessionToken); |
map.putAll(this._getCustomEditorProviderForModification(configuration, sqlRow, sessionToken)); |
return map; |
} |
protected Map<String, CustomEditorProvider> _getCustomEditorProviderForCreation(final Configuration configuration, final String sessionToken) { |
return new HashMap<String, CustomEditorProvider>(); |
} |
protected Map<String, CustomEditorProvider> _getCustomEditorProviderForModification(final Configuration configuration, final SQLRowAccessor sqlRow, final String sessionToken) { |
return new HashMap<String, CustomEditorProvider>(); |
} |
protected Map<String, CustomEditorProvider> _getDefaultCustomEditorProvider(final Configuration configuration, final SQLRowAccessor sqlRow, final String sessionToken) { |
return new HashMap<String, CustomEditorProvider>(); |
} |
private final Map<String, CustomEditorProvider> getDefaultCustomEditorProvider(final Configuration configuration, final SQLRowAccessor sqlRow, final String sessionToken) { |
public List<CustomRowEditor> getCustomRowEditors(final Configuration configuration, final String sessionToken) { |
final Map<String, ComboValueConvertor<?>> comboConvertors = this.getComboConvertors(); |
final Map<String, CustomEditorProvider> result = new HashMap<String, CustomEditorProvider>(); |
final List<CustomRowEditor> result = new ArrayList<>(); |
for (final Entry<String, ComboValueConvertor<?>> entry : comboConvertors.entrySet()) { |
result.put(entry.getKey(), new SavableCustomEditorProvider() { |
final String itemId = entry.getKey(); |
result.add(new CustomRowEditor(itemId) { |
final ComboValueConvertor<?> convertor = entry.getValue(); |
@Override |
public LightUIElement createUIElement(final String elementId) { |
final LightUIComboBox uiCombo = new LightUIComboBox(elementId); |
public LightUIElement createUIElement() { |
final LightUIComboBox uiCombo = new LightUIComboBox(getItemId()); |
this.convertor.fillCombo(uiCombo, null); |
return uiCombo; |
} |
if (sqlRow == null) { |
this.convertor.fillCombo(uiCombo, null); |
} else { |
final SQLField field = configuration.getFieldMapper().getSQLFieldForItem(elementId); |
if (this.convertor instanceof StringValueConvertor) { |
((StringValueConvertor) this.convertor).fillCombo(uiCombo, sqlRow.getString(field.getFieldName())); |
} else if (this.convertor instanceof IntValueConvertor) { |
if (sqlRow.getObject(field.getFieldName()) == null) { |
this.convertor.fillCombo(uiCombo, null); |
} else { |
((IntValueConvertor) this.convertor).fillCombo(uiCombo, sqlRow.getInt(field.getFieldName())); |
} |
@Override |
public void fillFrom(LightUIElement uiElement, SQLRowAccessor sqlRow) { |
final LightUIComboBox uiCombo = (LightUIComboBox) uiElement; |
final SQLField field = configuration.getFieldMapper().getSQLFieldForItem(getItemId()); |
if (this.convertor instanceof StringValueConvertor) { |
((StringValueConvertor) this.convertor).fillCombo(uiCombo, sqlRow.getString(field.getFieldName())); |
} else if (this.convertor instanceof IntValueConvertor) { |
if (sqlRow.getObject(field.getFieldName()) != null) { |
((IntValueConvertor) this.convertor).fillCombo(uiCombo, sqlRow.getInt(field.getFieldName())); |
} |
} |
return uiCombo; |
} |
@Override |
protected void _save(final SQLRowValues sqlRow, final SQLField sqlField, final LightUIElement uiElement) { |
final LightUIComboBox combo = (LightUIComboBox) uiElement; |
if (combo.hasSelectedValue()) { |
public void store(LightUIElement uiElement, SQLRowValues sqlRow) { |
final LightUIComboBox combobox = (LightUIComboBox) uiElement; |
final String fieldName = configuration.getFieldMapper().getSQLFieldForItem(getItemId()).getName(); |
if (combobox.hasSelectedValue()) { |
if (this.convertor instanceof StringValueConvertor) { |
sqlRow.put(sqlField.getName(), ((StringValueConvertor) this.convertor).getIdFromIndex(combo.getSelectedValue().getId())); |
sqlRow.put(fieldName, ((StringValueConvertor) this.convertor).getIdFromIndex(combobox.getSelectedValue().getId())); |
} else if (this.convertor instanceof IntValueConvertor) { |
sqlRow.put(sqlField.getName(), combo.getSelectedValue().getId()); |
sqlRow.put(fieldName, combobox.getSelectedValue().getId()); |
} else { |
throw new IllegalArgumentException("the save is not implemented for the class: " + this.convertor.getClass().getName() + " - ui element id: " + uiElement.getId()); |
throw new IllegalArgumentException("the save is not implemented for the class: " + this.convertor.getClass().getName() + " - ui id: " + getItemId()); |
} |
} else { |
sqlRow.put(sqlField.getName(), null); |
sqlRow.put(fieldName, null); |
} |
} |
}); |
} |
result.putAll(this._getDefaultCustomEditorProvider(configuration, sqlRow, sessionToken)); |
return result; |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/element/BaseSQLComponent.java |
---|
434,7 → 434,13 |
if (!(this instanceof GroupSQLComponent)) { |
for (final Entry<String, JComponent> e : this.getElement().getAdditionalFields().entrySet()) { |
final SpecParser spec = new SpecParser(null, true); |
final SpecParser spec; |
// FIXME Required à spécifier directement depuis le module |
if (this.requiredNames != null && this.requiredNames.contains(e.getKey())) { |
spec = new SpecParser(REQ, true); |
} else { |
spec = new SpecParser(null, true); |
} |
final JComponent comp = e.getValue(); |
if (comp == null) |
// infer component |
726,7 → 732,6 |
return this.getRequest().setLastKnownDBVals(current, this.getRequest().fetchRow(current.getID(), ls)); |
} |
@Override |
public final void select(int id) { |
// TODO in an executor outside of the EDT |
/trunk/OpenConcerto/src/org/openconcerto/sql/element/SQLElementDirectory.java |
---|
202,10 → 202,55 |
* @return the corresponding SQLElement, or <code>null</code> if none can be found. |
* @throws IllegalArgumentException if there's more than one match. |
*/ |
public synchronized final <S extends SQLElement> S getElement(Class<S> clazz) { |
return clazz.cast(this.getElement(getSoleTable(this.byClass, clazz))); |
public final <S extends SQLElement> S getElement(Class<S> clazz) { |
return this.getElementOfClass(clazz, false); |
} |
public final <S extends SQLElement> S getElementOfClass(Class<S> clazz, final boolean allowSubclass) { |
final List<S> res = getElementsOfClass(clazz, allowSubclass); |
if (res.size() > 1) |
throw new IllegalArgumentException(clazz + " is not unique: " + res); |
return res.isEmpty() ? null : res.get(0); |
} |
/** |
* Search for SQLElement whose class is <code>clazz</code>. |
* |
* @param clazz the class. |
* @param allowSubclass <code>true</code> to include {@link Class#isInstance(Object) |
* subclasses}, <code>false</code> to only return exact match. |
* @return the corresponding elements. |
*/ |
public final <S extends SQLElement> List<S> getElementsOfClass(final Class<S> clazz, final boolean allowSubclass) { |
final List<S> res; |
synchronized (this) { |
if (allowSubclass) { |
res = new ArrayList<>(); |
for (final SQLElement elem : this.elements.values()) { |
if (clazz.isInstance(elem)) |
res.add(clazz.cast(elem)); |
} |
} else { |
final Set<SQLTable> tables = this.byClass.get(clazz); |
if (tables != null) { |
res = new ArrayList<>(tables.size()); |
for (final SQLTable t : tables) { |
res.add(clazz.cast(this.getElement(t))); |
} |
} else { |
res = Collections.emptyList(); |
} |
} |
} |
if (res.isEmpty()) { |
return Collections.emptyList(); |
} else if (res.size() == 1) { |
return Collections.singletonList(res.get(0)); |
} else { |
return Collections.unmodifiableList(res); |
} |
} |
public synchronized final SQLElement getElementForCode(String code) { |
return this.getElement(getSoleTable(this.byCode, code)); |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/element/GroupSQLComponent.java |
---|
64,8 → 64,8 |
private final Group group; |
private final int columns = 2; |
private final Map<String, JComponent> labels = new HashMap<String, JComponent>(); |
private final Map<String, JComponent> editors = new HashMap<String, JComponent>(); |
private final Map<String, JComponent> labels = new HashMap<>(); |
private final Map<String, JComponent> editors = new HashMap<>(); |
private String startTabAfter = null; |
private boolean tabGroup; |
private int tabDepth; |
80,6 → 80,12 |
public GroupSQLComponent(final SQLElement element, final Group group) { |
super(element); |
if (element == null) { |
throw new IllegalArgumentException("null SQLElement"); |
} |
if (group == null) { |
throw new IllegalArgumentException("null group (SQLElement : " + element + ")"); |
} |
this.group = group; |
this.hasAdditionnalFields = this.getElement().getAdditionalFields().size() > 0; |
this.additionnalFieldsGroup = getAdditionalFieldsGroup(group.getDescendantGroups()); |
99,7 → 105,7 |
} |
public void startTabGroupAfter(String id) { |
startTabAfter = id; |
this.startTabAfter = id; |
} |
@Override |
155,7 → 161,8 |
c.gridx = 0; |
c.weightx = 1; |
c.gridwidth = 4; |
panel.add(getLabel(id), c); |
JComponent comp = getLabel(id); |
panel.add(comp, c); |
c.gridy++; |
} |
} |
276,13 → 283,13 |
} |
} |
if (id.equals(startTabAfter)) { |
if (tabGroup) { |
if (id.equals(this.startTabAfter)) { |
if (this.tabGroup) { |
throw new IllegalArgumentException("ID " + id + " already set as tab"); |
} |
tabGroup = true; |
tabDepth = level; |
pane = new JTabbedPane(); |
this.tabGroup = true; |
this.tabDepth = level; |
this.pane = new JTabbedPane(); |
c.gridx = 0; |
c.gridy++; |
c.weightx = 1; |
289,7 → 296,7 |
c.weighty = 1; |
c.fill = GridBagConstraints.BOTH; |
c.gridwidth = 4; |
panel.add(pane, c); |
panel.add(this.pane, c); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLTable.java |
---|
122,7 → 122,7 |
}; |
@SuppressWarnings("unchecked") |
private static final Map<String, Number> getUndefIDs(final SQLSchema schema) { |
public static final Map<String, Number> getUndefIDs(final SQLSchema schema) { |
if (!UNDEFINED_IDs.containsKey(schema)) { |
final Map<String, Number> r; |
if (schema.contains(undefTable)) { |
556,7 → 556,10 |
return undef.intValue(); |
} |
} else if ("inDB".equals(policy)) { |
throw new IllegalStateException("Not in " + new SQLName(this.getDBRoot().getName(), undefTable) + " : " + this.getName()); |
return SQLRow.NONEXISTANT_ID; |
// FIXME : BUG A INVESTIGUER DANS LA CREATION DE MODULE throw new |
// throw new IllegalStateException("Not in " + new SQLName(this.getDBRoot().getName(), |
// undefTable) + " : " + this.getName()); |
} else if (policy != null && !"nonexistant".equals(policy)) { |
final int res = Integer.parseInt(policy); |
if (res < SQLRow.MIN_VALID_ID) |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLInjector.java |
---|
166,18 → 166,28 |
rowVals.put(field.getName(), value); |
} |
protected void transfertReference(SQLRowAccessor srcRow, SQLRowValues rowVals, String from, String to) { |
protected void transfertReference(SQLRowAccessor srcRow, SQLRowValues rowVals, final SQLTable tableElementDestination, String refField, String from, String to) { |
String label = rowVals.getString(to); |
if (label != null && label.trim().length() > 0) { |
rowVals.put(to, label + ", " + srcRow.getString(from)); |
} else { |
rowVals.put(to, srcRow.getString(from)); |
SQLPreferences prefs = SQLPreferences.getMemCached(srcRow.getTable().getDBRoot()); |
if (prefs.getBoolean("TransfertRef", true) || !to.equals("NOM")) { |
if (label != null && label.trim().length() > 0) { |
rowVals.put(to, label + ", " + srcRow.getString(from)); |
} else { |
rowVals.put(to, srcRow.getString(from)); |
} |
} else if (prefs.getBoolean("TransfertMultiRef", false)) { |
SQLRowValues rowValsHeader = new SQLRowValues(UndefinedRowValuesCache.getInstance().getDefaultRowValues(tableElementDestination)); |
// TODO taxe may be undefined set it to default |
rowValsHeader.put("NOM", srcRow.getString(from)); |
rowValsHeader.put(refField, rowVals); |
} |
} |
protected void transfertNumberReference(SQLRowAccessor srcRow, SQLRowValues rowVals, final SQLTable tableElementDestination, String refField) { |
SQLPreferences prefs = new SQLPreferences(srcRow.getTable().getDBRoot()); |
SQLPreferences prefs = SQLPreferences.getMemCached(srcRow.getTable().getDBRoot()); |
if (prefs.getBoolean("TransfertRef", true)) { |
String label = rowVals.getString("NOM"); |
412,7 → 422,7 |
* register manually a transfer, use with caution |
* |
* @throws SQLException |
* */ |
*/ |
public void addTransfert(int idFrom, int idTo) throws SQLException { |
final SQLTable tableTransfert = getSource().getTable(getTableTranferName()); |
final SQLRowValues rowTransfer = new SQLRowValues(tableTransfert); |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLUpdate.java |
---|
New file |
0,0 → 1,115 |
/* |
* 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.sql.SQLException; |
import java.util.ArrayList; |
import java.util.List; |
public class SQLUpdate { |
private List<SQLField> fields = new ArrayList<>(); |
private List<Object> values = new ArrayList<>(); |
private SQLTable table; |
private Where where; |
public SQLUpdate(Where where) { |
this.where = where; |
} |
public void add(SQLField field, Object value) { |
if (this.table == null) { |
this.table = field.getTable(); |
} else { |
if (!this.table.equals(field.getTable())) { |
throw new IllegalArgumentException(field + " is not in table " + this.table.toString()); |
} |
} |
this.fields.add(field); |
this.values.add(value); |
} |
public void set(SQLField field, Object value) { |
if (this.table == null) { |
this.table = field.getTable(); |
} else { |
if (!this.table.equals(field.getTable())) { |
throw new IllegalArgumentException(field + " is not in table " + this.table.toString()); |
} |
} |
int index = this.fields.indexOf(field); |
if (index < 0) { |
throw new IllegalArgumentException(field + " not in field list"); |
} |
this.values.set(index, value); |
} |
public boolean contains(SQLField field) { |
return this.fields.indexOf(field) >= 0; |
} |
public Object getValue(SQLField field) { |
int index = this.fields.indexOf(field); |
if (index < 0) { |
throw new IllegalArgumentException(field + " not in field list"); |
} |
return this.values.get(index); |
} |
public String asString() { |
if (this.fields.isEmpty()) { |
throw new IllegalStateException("not fields added"); |
} |
final StringBuilder builder = new StringBuilder(); |
builder.append("UPDATE "); |
builder.append(this.table.getSQLName()); |
builder.append(" SET "); |
// |
int stop = this.fields.size(); |
for (int i = 0; i < stop; i++) { |
final SQLField field = this.fields.get(i); |
builder.append(field.getQuotedName()); |
builder.append("="); |
Object value = this.values.get(i); |
final Class<?> javaType = field.getType().getJavaType(); |
Object str = value; |
if (!javaType.isInstance(value)) { |
str = SQLRowValues.convert(value.getClass(), value, javaType); |
} |
builder.append(field.getType().toString(str)); |
if (i < stop - 1) { |
builder.append(','); |
} |
} |
builder.append(" WHERE "); |
builder.append(this.where.getClause()); |
return builder.toString(); |
} |
/** |
* Update multiple rows with a batch. Rows can be from different tables. |
* |
* Speed : 5000 /s |
*/ |
public static long executeMultipleWithBatch(final DBSystemRoot sysRoot, final List<SQLUpdate> queries) throws SQLException { |
if (queries.isEmpty()) { |
throw new IllegalArgumentException("no updates"); |
} |
final List<String> l = new ArrayList<>(queries.size()); |
for (final SQLUpdate i : queries) |
l.add(i.asString()); |
return sysRoot.getDataSource().executeBatch(l, true).get0(); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLDataSource.java |
---|
16,11 → 16,13 |
import org.openconcerto.sql.Log; |
import org.openconcerto.sql.State; |
import org.openconcerto.sql.request.SQLCache; |
import org.openconcerto.sql.utils.SQLUtils; |
import org.openconcerto.utils.CompareUtils; |
import org.openconcerto.utils.ExceptionHandler; |
import org.openconcerto.utils.ExceptionUtils; |
import org.openconcerto.utils.RTInterruptedException; |
import org.openconcerto.utils.ThreadFactory; |
import org.openconcerto.utils.Tuple2; |
import org.openconcerto.utils.cache.CacheResult; |
import org.openconcerto.utils.cache.ICacheSupport; |
48,6 → 50,8 |
import java.util.concurrent.LinkedBlockingQueue; |
import java.util.concurrent.ThreadPoolExecutor; |
import java.util.concurrent.TimeUnit; |
import java.util.concurrent.atomic.AtomicLong; |
import java.util.concurrent.atomic.AtomicReference; |
import java.util.logging.Level; |
import org.apache.commons.dbcp.AbandonedConfig; |
993,7 → 997,66 |
return res; |
} |
private static final Tuple2<Long, int[]> NO_QUERIES_RES = Tuple2.create(0l, new int[0]); |
/** |
* Execute multiple queries in batch. |
* |
* @param queries what to execute. |
* @param atomic <code>true</code> if all queries should be executed in a transaction. |
* @return the total update count (< 0 if unknown), followed by the individual update counts. |
* @throws SQLException if an error occurs. |
* @see Statement#executeBatch() |
*/ |
public final Tuple2<Long, int[]> executeBatch(final List<String> queries, final boolean atomic) throws SQLException { |
if (queries.isEmpty()) |
return NO_QUERIES_RES; |
final long timeMs = System.currentTimeMillis(); |
final long time = System.nanoTime(); |
final long afterCache = time; |
final AtomicLong afterQueryInfo = new AtomicLong(); |
final AtomicLong afterExecute = new AtomicLong(); |
final AtomicReference<Connection> conn = new AtomicReference<>(); |
final ConnectionHandlerNoSetup<int[], SQLException> handler = new ConnectionHandlerNoSetup<int[], SQLException>() { |
@Override |
public int[] handle(SQLDataSource ds) throws SQLException { |
afterQueryInfo.set(System.nanoTime()); |
conn.set(ds.getConnection()); |
final int[] res; |
try (final Statement stmt = conn.get().createStatement()) { |
for (final String s : queries) { |
stmt.addBatch(s); |
} |
if (Thread.currentThread().isInterrupted()) |
throw new RTInterruptedException("Interrupted before executing : " + queries); |
res = stmt.executeBatch(); |
} |
afterExecute.set(System.nanoTime()); |
return res; |
} |
}; |
final int[] res = atomic ? SQLUtils.executeAtomic(this, handler) : this.useConnection(handler); |
long totalCount = 0; |
int i = 0; |
for (final int count : res) { |
if (count == Statement.SUCCESS_NO_INFO) { |
totalCount = -1; |
break; |
} else { |
if (count < 0) |
throw new SQLException("Invalid count (" + count + ") for query " + i + " : " + queries.get(i)); |
totalCount += count; |
} |
i++; |
} |
if (SQLRequestLog.isEnabled()) { |
final long afterHandle = System.nanoTime(); |
SQLRequestLog.log(queries.toString(), "executeBatch", conn.get(), timeMs, time, afterCache, afterQueryInfo.get(), afterExecute.get(), afterHandle, afterHandle, (int) totalCount); |
} |
return Tuple2.create(totalCount, res); |
} |
/** |
* Try to execute a {@link #getValidationQuery() simple query} on the database server. This |
* method even works when the pool is exhausted. |
* |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLRowListRSH.java |
---|
19,10 → 19,12 |
import java.sql.ResultSet; |
import java.sql.SQLException; |
import java.util.ArrayList; |
import java.util.Collection; |
import java.util.Collections; |
import java.util.HashSet; |
import java.util.List; |
import java.util.Set; |
import java.util.stream.Collectors; |
import org.apache.commons.dbutils.ResultSetHandler; |
37,16 → 39,18 |
// ATTN doesn't check that the types of columns are coherent with the types of the fields |
public RSH(final SQLTable t, final List<String> names) { |
this(Tuple2.create(t, names)); |
if (!t.getFieldsName().containsAll(names)) |
throw new IllegalArgumentException("Not all names are fields of " + t + " : " + names); |
// null are OK (they're ignored) |
final List<String> unknown = names.stream().filter(n -> n != null && !t.getFieldsName().contains(n)).collect(Collectors.toList()); |
if (!unknown.isEmpty()) |
throw new IllegalArgumentException("Not all names are fields of " + t + " : " + unknown); |
} |
private RSH(Tuple2<SQLTable, List<String>> names) { |
private RSH(final Tuple2<SQLTable, List<String>> names) { |
this.names = names; |
} |
@Override |
public List<SQLRow> handle(ResultSet rs) throws SQLException { |
public List<SQLRow> handle(final ResultSet rs) throws SQLException { |
// since the result will be cached, disallow its modification (e.g.avoid |
// ConcurrentModificationException) |
return Collections.unmodifiableList(SQLRow.createListFromRS(this.names.get0(), rs, this.names.get1())); |
58,7 → 62,7 |
} |
@Override |
public boolean equals(Object obj) { |
public boolean equals(final Object obj) { |
if (this == obj) |
return true; |
if (obj == null) |
78,7 → 82,7 |
return t; |
} |
static Tuple2<SQLTable, List<String>> getIndexes(SQLSelect sel, final TableRef passedTable, final boolean findTable) { |
static Tuple2<SQLTable, List<String>> getIndexes(final SQLSelect sel, final TableRef passedTable, final boolean findTable) { |
final List<FieldRef> selectFields = sel.getSelectFields(); |
final int size = selectFields.size(); |
if (size == 0) |
119,11 → 123,12 |
/** |
* Create a handler that don't need metadata. |
* |
* |
* @param sel the select that will produce the result set, must only have one table. |
* @return a handler creating a list of {@link SQLRow}. |
* @deprecated use {@link SQLSelectHandlerBuilder} |
*/ |
@Deprecated |
static public ResultSetHandler createFromSelect(final SQLSelect sel) { |
return create(getIndexes(sel, null, true)); |
} |
131,12 → 136,13 |
/** |
* Create a handler that don't need metadata. Useful since some JDBC drivers perform queries for |
* each metadata. |
* |
* |
* @param sel the select that will produce the result set. |
* @param t the table for which to create rows. |
* @return a handler creating a list of {@link SQLRow}. |
* @deprecated use {@link SQLSelectHandlerBuilder} |
*/ |
@Deprecated |
static public ResultSetHandler createFromSelect(final SQLSelect sel, final TableRef t) { |
return create(getIndexes(sel, t, false)); |
} |
145,10 → 151,24 |
return new RSH(names); |
} |
static public List<SQLRow> fetch(final SQLTable t, final Collection<? extends Number> ids) throws IllegalArgumentException { |
return fetch(t, ids, null); |
} |
static public List<SQLRow> fetch(final SQLTable t, final Collection<? extends Number> ids, final Collection<String> fields) throws IllegalArgumentException { |
final SQLSelect sel = new SQLSelect(); |
if (fields == null) |
sel.addSelectStar(t); |
else |
sel.addAllSelect(t, fields); |
sel.setWhere(new Where(t.getKey(), ids)); |
return execute(sel); |
} |
/** |
* Execute the passed select and return rows. NOTE if there's more than one table in the query |
* {@link #execute(SQLSelect, TableRef)} must be used. |
* |
* |
* @param sel the query to execute. |
* @return rows. |
* @throws IllegalArgumentException if there's more than one table in the query. |
164,7 → 184,7 |
/** |
* Execute the passed select and return rows of <code>t</code>. NOTE if there's only one table |
* in the query {@link #execute(SQLSelect)} should be used. |
* |
* |
* @param sel the query to execute. |
* @param t the table to use. |
* @return rows of <code>t</code>. |
195,17 → 215,18 |
private final SQLTable t; |
private final boolean tableOnly; |
public SQLRowListRSH(SQLTable t) { |
public SQLRowListRSH(final SQLTable t) { |
this(t, false); |
} |
public SQLRowListRSH(SQLTable t, final boolean tableOnly) { |
public SQLRowListRSH(final SQLTable t, final boolean tableOnly) { |
super(); |
this.t = t; |
this.tableOnly = tableOnly; |
} |
public Object handle(ResultSet rs) throws SQLException { |
@Override |
public List<SQLRow> handle(final ResultSet rs) throws SQLException { |
return SQLRow.createListFromRS(this.t, rs, this.tableOnly); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLRequestLog.java |
---|
25,6 → 25,7 |
import java.awt.event.ActionListener; |
import java.awt.event.MouseAdapter; |
import java.awt.event.MouseEvent; |
import java.io.PrintStream; |
import java.sql.Connection; |
import java.sql.PreparedStatement; |
import java.text.DateFormat; |
60,7 → 61,23 |
private static final String ACTIVER_LA_CAPTURE = "Enable monitoring"; |
private static final String DESACTIVER_LA_CAPTURE = "Disable monitoring"; |
private static Vector<SQLRequestLog> list = new Vector<SQLRequestLog>(500); |
@GuardedBy("this") |
private static boolean enabled; |
public static synchronized void setEnabled(boolean enable) { |
enabled = enable; |
} |
public static synchronized boolean toggleEnabled() { |
final boolean newVal = !isEnabled(); |
setEnabled(newVal); |
return newVal; |
} |
public static synchronized boolean isEnabled() { |
return enabled; |
} |
private String query; |
private String comment; |
private long startAsMs; |
85,10 → 102,6 |
return l == 0 ? "" : dformat.format(l / 1000000D) + " ms"; |
} |
public static void setEnabled(boolean enable) { |
enabled = enable; |
} |
public SQLRequestLog(String query, String comment, int connectionId, long starAtMs, String ex, boolean inSwing, long startTime, long afterCache, long afterQueryInfo, long afterExecute, |
long afterHandle, long endTime, int count) { |
this.query = query; |
116,7 → 129,7 |
public static void log(String query, String comment, int connectionId, long starAtMs, long startTime, long afterCache, long afterQueryInfo, long afterExecute, long afterHandle, long endTime, |
int count) { |
if (enabled) { |
if (isEnabled()) { |
if (list.size() < 50000) { |
final String ex = ExceptionUtils.getStackTrace(new Exception()); |
135,7 → 148,7 |
public static void log(PreparedStatement pStmt, String comment, long timeMs, long startTime, long afterCache, long afterQueryInfo, long afterExecute, long afterHandle, long endTime) { |
// only call potentially expensive and/or exceptions throwing methods if necessary |
if (enabled) { |
if (isEnabled()) { |
try { |
log(pStmt.toString(), comment, pStmt.getConnection(), timeMs, startTime, afterCache, afterQueryInfo, afterExecute, afterHandle, endTime, 0); |
} catch (Exception e) { |
433,7 → 446,7 |
JPanel bar = new JPanel(new FlowLayout()); |
final JButton b0 = new JButton(); |
if (enabled) { |
if (isEnabled()) { |
b0.setText(DESACTIVER_LA_CAPTURE); |
} else { |
b0.setText(ACTIVER_LA_CAPTURE); |
440,12 → 453,10 |
} |
b0.addActionListener(new ActionListener() { |
@Override |
public void actionPerformed(ActionEvent e) { |
if (enabled) { |
enabled = false; |
public void actionPerformed(ActionEvent e) { |
if (!toggleEnabled()) { |
b0.setText(ACTIVER_LA_CAPTURE); |
} else { |
enabled = true; |
b0.setText(DESACTIVER_LA_CAPTURE); |
} |
620,4 → 631,15 |
model.fireTableRowsUpdated(0, model.getRowCount() - 1); |
} |
} |
public static void dump(PrintStream out) { |
final DecimalFormat dformat = new DecimalFormat("##0.00"); |
for (SQLRequestLog log : list) { |
out.print(dformat.format(log.getDurationTotalNano() / 1000000D) + " ms "); |
out.print("\t"); |
out.print(log.getQuery()); |
out.println(); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLBackgroundTableCacheItem.java |
---|
28,6 → 28,11 |
public SQLBackgroundTableCacheItem(final SQLTable t, final int second) { |
this.table = t; |
this.timeout = second; |
if (second == -1) { |
reloadFromDB(); |
} |
this.table.addTableModifiedListener(new SQLTableModifiedListener() { |
@Override |
44,17 → 49,21 |
this.enableReloadIfTableModified = enableReloadIfTableModified; |
} |
@SuppressWarnings("unchecked") |
public synchronized void reloadFromDbIfNeeded() { |
final long delta = System.currentTimeMillis() - this.lastReload; |
if (delta / 1000 > this.timeout) { |
final SQLSelect sel = new SQLSelect(); |
sel.addSelectStar(this.table); |
this.rows = Collections.unmodifiableList((List<SQLRow>) this.table.getBase().getDataSource().execute(sel.asString(), SQLRowListRSH.createFromSelect(sel, this.table))); |
this.lastReload = System.currentTimeMillis(); |
if (this.timeout >= 0 && delta / 1000 > this.timeout) { |
reloadFromDB(); |
} |
} |
@SuppressWarnings("unchecked") |
private void reloadFromDB() { |
final SQLSelect sel = new SQLSelect(); |
sel.addSelectStar(this.table); |
this.rows = Collections.unmodifiableList((List<SQLRow>) this.table.getBase().getDataSource().execute(sel.asString(), SQLRowListRSH.createFromSelect(sel, this.table))); |
this.lastReload = System.currentTimeMillis(); |
} |
public synchronized SQLRow getFirstRowContains(final int value, final SQLField field) { |
for (SQLRow r : this.rows) { |
if (r.getInt(field.getName()) == value && !r.isArchived()) { |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLInsert.java |
---|
New file |
0,0 → 1,314 |
/* |
* 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.io.IOException; |
import java.io.StringReader; |
import java.sql.Connection; |
import java.sql.SQLException; |
import java.util.ArrayList; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
import java.util.Map.Entry; |
import org.postgresql.copy.CopyManager; |
import org.postgresql.core.BaseConnection; |
import org.postgresql.jdbc.PgConnection; |
public class SQLInsert { |
private List<SQLField> fields = new ArrayList<>(); |
private List<Object> values = new ArrayList<>(); |
private SQLTable table; |
public void add(SQLField field, Object value) { |
if (this.table == null) { |
this.table = field.getTable(); |
} else { |
if (!this.table.equals(field.getTable())) { |
throw new IllegalArgumentException(field + " is not in table " + this.table.toString()); |
} |
} |
this.fields.add(field); |
this.values.add(value); |
} |
public void set(SQLField field, Object value) { |
if (this.table == null) { |
this.table = field.getTable(); |
} else { |
if (!this.table.equals(field.getTable())) { |
throw new IllegalArgumentException(field + " is not in table " + this.table.toString()); |
} |
} |
int index = this.fields.indexOf(field); |
if (index < 0) { |
throw new IllegalArgumentException(field + " not in field list"); |
} |
this.values.set(index, value); |
} |
public boolean contains(SQLField field) { |
return this.fields.indexOf(field) >= 0; |
} |
public Object getValue(SQLField field) { |
int index = this.fields.indexOf(field); |
if (index < 0) { |
throw new IllegalArgumentException(field + " not in field list"); |
} |
return this.values.get(index); |
} |
public String asString() { |
if (this.fields.isEmpty()) { |
throw new IllegalStateException("not fields added"); |
} |
final StringBuilder builder = new StringBuilder(); |
builder.append("INSERT INTO "); |
builder.append(this.table.getSQLName()); |
builder.append(" ("); |
// |
int stop = this.fields.size(); |
for (int i = 0; i < stop; i++) { |
builder.append(this.fields.get(i).getQuotedName()); |
if (i < stop - 1) { |
builder.append(','); |
} |
} |
builder.append(") VALUES ("); |
for (int i = 0; i < stop; i++) { |
Object value = this.values.get(i); |
final SQLField field = this.fields.get(i); |
final Class<?> javaType = field.getType().getJavaType(); |
Object str = value; |
if (value != null && !javaType.isInstance(value)) { |
str = SQLRowValues.convert(value.getClass(), value, javaType); |
} |
builder.append(field.getType().toString(str)); |
if (i < stop - 1) { |
builder.append(','); |
} |
} |
builder.append(")"); |
return builder.toString(); |
} |
/** |
* Insert multiple rows. Rows can be from different tables. |
* |
* Speed : 19 000 inserts /s on PostgreSQL |
*/ |
public static void executeMultiple(final DBSystemRoot sysRoot, final List<SQLInsert> queries) throws SQLException { |
if (queries.isEmpty()) { |
throw new IllegalArgumentException("no inserts"); |
} |
final Map<SQLTable, List<SQLInsert>> map = new HashMap<>(); |
for (final SQLInsert q : queries) { |
List<SQLInsert> list = map.get(q.table); |
if (list == null) { |
list = new ArrayList<>(); |
map.put(q.table, list); |
} |
list.add(q); |
} |
for (Entry<SQLTable, List<SQLInsert>> entry : map.entrySet()) { |
executeSimilarInserts(sysRoot, entry.getValue(), false); |
} |
} |
/** |
* Insert multiple rows with a batch. Rows can be from different tables. |
* |
* Speed : 8 000 inserts /s on PostgreSQL |
*/ |
public static long executeMultipleWithBatch(final DBSystemRoot sysRoot, final List<SQLInsert> queries) throws SQLException { |
if (queries.isEmpty()) { |
throw new IllegalArgumentException("no inserts"); |
} |
final List<String> l = new ArrayList<>(queries.size()); |
for (final SQLInsert i : queries) |
l.add(i.asString()); |
return sysRoot.getDataSource().executeBatch(l, true).get0(); |
} |
/** |
* Insert multiple rows in the same table, using COPY on PostgreSQL for the maximum speed |
* |
* Speed : 26 000 inserts /s on PostgreSQL |
*/ |
public static long executeSimilarWithCopy(final DBSystemRoot sysRoot, final List<SQLInsert> queries) throws SQLException { |
SQLDataSource dataSource = sysRoot.getDataSource(); |
if (dataSource.getSystem() != SQLSystem.POSTGRESQL) { |
return executeSimilarInserts(sysRoot, queries, true).size(); |
} |
if (queries.isEmpty()) { |
throw new IllegalArgumentException("no inserts"); |
} |
SQLInsert insert0 = queries.get(0); |
final long timeMs = System.currentTimeMillis(); |
final long time = System.nanoTime(); |
final long afterCache = time; |
final String query = insert0 + "..." + queries.size() + " queries"; |
return dataSource.useConnection(new ConnectionHandlerNoSetup<Long, SQLException>() { |
@Override |
public Long handle(SQLDataSource ds) throws SQLException { |
final Connection conn = ds.getConnection().unwrap(PgConnection.class); |
final CopyManager copyManager = new CopyManager((BaseConnection) conn); |
final StringBuilder allValues = new StringBuilder(insert0.fields.size() * 10 * queries.size()); |
final List<String> fi = new ArrayList<>(); |
for (SQLField f : insert0.fields) { |
fi.add(f.getQuotedName()); |
} |
for (final SQLInsert q : queries) { |
if (!q.table.equals(insert0.table)) { |
throw new IllegalArgumentException("table " + q.table.getName() + " is not " + insert0.table.getTable()); |
} |
if (!q.fields.equals(insert0.fields)) { |
throw new IllegalArgumentException("fields" + q.fields + " not equals to " + insert0.fields); |
} |
int stop = q.values.size(); |
for (int i = 0; i < stop; i++) { |
Object value = q.values.get(i); |
final SQLField field = q.fields.get(i); |
final Class<?> javaType = field.getType().getJavaType(); |
Object str = value; |
if (!javaType.isInstance(value)) { |
str = SQLRowValues.convert(value.getClass(), value, javaType); |
} |
// FIXME null, escapes (see SQLSyntaxPG) |
allValues.append(field.getType().toString(str)); |
if (i < stop - 1) { |
allValues.append('\t'); |
} |
} |
allValues.append('\n'); |
} |
final long afterQueryInfo = System.nanoTime(); |
final long afterExecute; |
final long afterHandle; |
final long count; |
try { |
count = copyManager.copyIn("COPY " + insert0.table.getSQLName() + "(" + String.join(",", fi) + ") FROM STDIN WITH (ENCODING 'UTF-8') ", new StringReader(allValues.toString())); |
} catch (IOException e) { |
throw new SQLException(e); |
} |
afterExecute = System.nanoTime(); |
afterHandle = afterExecute; |
SQLRequestLog.log(query, "multiple similar with copy", conn, timeMs, time, afterCache, afterQueryInfo, afterExecute, afterHandle, System.nanoTime(), queries.size()); |
return count; |
} |
}); |
} |
/** |
* Insert multiple rows in the same table |
* |
* Speed : 20 000 inserts /s on PostgreSQL |
*/ |
public static List<Number> executeSimilarInserts(final DBSystemRoot sysRoot, final List<SQLInsert> queries, boolean returnIds) throws SQLException { |
SQLDataSource dataSource = sysRoot.getDataSource(); |
if (queries.isEmpty()) { |
throw new IllegalArgumentException("no inserts"); |
} |
SQLInsert insert0 = queries.get(0); |
final long timeMs = System.currentTimeMillis(); |
final long time = System.nanoTime(); |
final long afterCache = time; |
final String query = insert0 + "..." + queries.size() + " queries"; |
if (sysRoot.getServer().getSQLSystem() != SQLSystem.POSTGRESQL) { |
List<Number> res = new ArrayList<>(); |
for (SQLInsert sqlInsert : queries) { |
res.add((Number) sysRoot.getDataSource().executeScalar(sqlInsert.asString())); |
} |
return res; |
} else { |
return dataSource.useConnection(new ConnectionHandlerNoSetup<List<Number>, SQLException>() { |
@Override |
public List<Number> handle(SQLDataSource ds) throws SQLException { |
final Connection conn = ds.getConnection(); |
final List<String> fi = new ArrayList<>(); |
for (SQLField f : insert0.fields) { |
fi.add(f.getQuotedName()); |
} |
final long afterQueryInfo = System.nanoTime(); |
final long afterExecute; |
final long afterHandle; |
final StringBuilder sql = new StringBuilder(insert0.fields.size() * 10 * (queries.size() + 1)); |
sql.append("(" + String.join(",", fi) + ")"); |
sql.append(" VALUES "); |
int size = queries.size(); |
for (int j = 0; j < size; j++) { |
final SQLInsert q = queries.get(j); |
if (!q.table.equals(insert0.table)) { |
throw new IllegalArgumentException("table " + q.table.getName() + " is not " + insert0.table.getTable()); |
} |
if (!q.fields.equals(insert0.fields)) { |
throw new IllegalArgumentException("fields" + q.fields + " not equals to " + insert0.fields); |
} |
sql.append("("); |
int stop = q.values.size(); |
for (int i = 0; i < stop; i++) { |
Object value = q.values.get(i); |
final SQLField field = q.fields.get(i); |
final Class<?> javaType = field.getType().getJavaType(); |
Object str = value; |
if (!field.isNullable() && value == null) { |
throw new IllegalStateException("null value for " + field); |
} |
if (value != null && !javaType.isInstance(value)) { |
str = SQLRowValues.convert(value.getClass(), value, javaType); |
} |
// FIXME : escape ' (quote) |
sql.append(field.getType().toString(str)); |
if (i < stop - 1) { |
sql.append(','); |
} |
} |
sql.append(")"); |
if (j < size - 1) { |
sql.append(','); |
} |
} |
List<Number> res; |
if (!returnIds) { |
// TODO return count |
SQLRowValues.insertCount(insert0.table, sql.toString()); |
res = null; |
} else { |
res = SQLRowValues.insertIDs(insert0.table, sql.toString()); |
} |
afterExecute = System.nanoTime(); |
afterHandle = afterExecute; |
SQLRequestLog.log(query, "multiple similar insert", conn, timeMs, time, afterCache, afterQueryInfo, afterExecute, afterHandle, System.nanoTime(), queries.size()); |
return res; |
} |
}); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLBackgroundTableCache.java |
---|
19,7 → 19,7 |
public class SQLBackgroundTableCache { |
private static SQLBackgroundTableCache instance; |
private Map<SQLTable, SQLBackgroundTableCacheItem> list = new HashMap<SQLTable, SQLBackgroundTableCacheItem>(); |
private Map<SQLTable, SQLBackgroundTableCacheItem> list = new HashMap<>(); |
/** |
* @param args |
90,7 → 90,8 |
item.reloadFromDbIfNeeded(); |
} else { |
System.err.println("SQLBackgroundTableCache.getCacheForTable() WARNING " + t.getName() + " is not registered (use add to register)"); |
this.add(t, 0); |
// Start cache without autorefresh for Caisse offline |
this.add(t, -1); |
item = this.list.get(t); |
item.reloadFromDbIfNeeded(); |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLRowValues.java |
---|
1006,7 → 1006,7 |
} |
// TODO support java.time.LocalDateTime in Java 8 |
static private <T, U> U convert(final Class<T> source, final Object value, final Class<U> dest) { |
public static <T, U> U convert(final Class<T> source, final Object value, final Class<U> dest) { |
final ValueConvertor<T, U> conv = ValueConvertorFactory.find(source, dest); |
if (conv == null) |
throw new IllegalArgumentException("No convertor to " + dest + " from " + source); |
2447,7 → 2447,6 |
return insert(t, sql, ReturnMode.NO_FIELDS).getCount(); |
} |
// if scalar is null primary keys aren't fetched |
private static final Insertion<?> insert(final SQLTable t, final String sql, final ReturnMode mode) throws SQLException { |
return new Inserter(t).insert(sql, mode, true); |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/utils/SQLUtils.java |
---|
372,9 → 372,8 |
final long afterQueryInfo = System.nanoTime(); |
final long afterExecute, afterHandle; |
final Statement stmt = conn.createStatement(); |
int count = 0; |
try { |
try (final Statement stmt = conn.createStatement()){ |
if (Thread.currentThread().isInterrupted()) |
throw new RTInterruptedException("Interrupted before executing : " + query); |
stmt.execute(query); |
392,8 → 391,6 |
stmt.getMoreResults(); |
} |
afterHandle = System.nanoTime(); |
} finally { |
stmt.close(); |
} |
SQLRequestLog.log(query, "executeMultiple", conn, timeMs, time, afterCache, afterQueryInfo, afterExecute, afterHandle, System.nanoTime(), count); |
return null; |
/trunk/OpenConcerto/src/org/openconcerto/sql/users/UserCommonSQLElement.java |
---|
28,6 → 28,7 |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.request.ComboSQLRequest; |
import org.openconcerto.sql.sqlobject.itemview.SimpleRowItemView; |
import org.openconcerto.sql.ui.IColorChooser; |
import org.openconcerto.sql.ui.Login; |
import org.openconcerto.sql.view.QuickAssignPanel; |
import org.openconcerto.sql.view.list.ITableModel; |
220,8 → 221,7 |
// Login |
c.gridx = 0; |
c.insets = new Insets(2, 2, 1, 2); |
final JLabel labelLogin = new JLabel(getLabelFor("LOGIN")); |
labelLogin.setHorizontalAlignment(SwingConstants.RIGHT); |
final JLabel labelLogin = new JLabel(getLabelFor("LOGIN"), SwingConstants.RIGHT); |
this.add(labelLogin, c); |
final JTextField textLogin = new JTextField(); |
c.gridx++; |
242,8 → 242,7 |
c.gridx = 0; |
c.weightx = 0; |
c.insets = new Insets(2, 2, 1, 2); |
final JLabel labelPass = new JLabel(getLabelFor("PASSWORD")); |
labelPass.setHorizontalAlignment(SwingConstants.RIGHT); |
final JLabel labelPass = new JLabel(getLabelFor("PASSWORD"), SwingConstants.RIGHT); |
this.add(labelPass, c); |
this.passField = new JPasswordField(15); |
c.gridx++; |
254,8 → 253,7 |
// Confirmation password |
c.gridx++; |
c.weightx = 0; |
final JLabel labelConfirmationPass = new JLabel(getLabelFor("PASSWORD_CONFIRM")); |
labelConfirmationPass.setHorizontalAlignment(SwingConstants.RIGHT); |
final JLabel labelConfirmationPass = new JLabel(getLabelFor("PASSWORD_CONFIRM"), SwingConstants.RIGHT); |
this.add(labelConfirmationPass, c); |
this.passFieldConfirm = new JPasswordField(15); |
c.gridx++; |
267,8 → 265,7 |
c.gridx = 0; |
c.gridy++; |
c.weightx = 0; |
final JLabel labelNom = new JLabel(getLabelFor("NOM")); |
labelNom.setHorizontalAlignment(SwingConstants.RIGHT); |
final JLabel labelNom = new JLabel(getLabelFor("NOM"), SwingConstants.RIGHT); |
this.add(labelNom, c); |
final JTextField textNom = new JTextField(); |
c.gridx++; |
278,8 → 275,7 |
// Prenom |
c.gridx++; |
c.weightx = 0; |
final JLabel labelPrenom = new JLabel(getLabelFor("PRENOM")); |
labelPrenom.setHorizontalAlignment(SwingConstants.RIGHT); |
final JLabel labelPrenom = new JLabel(getLabelFor("PRENOM"), SwingConstants.RIGHT); |
this.add(labelPrenom, c); |
final JTextField textPrenom = new JTextField(); |
c.gridx++; |
290,8 → 286,7 |
c.gridx = 0; |
c.gridy++; |
c.weightx = 0; |
final JLabel labelSurnom = new JLabel(getLabelFor("SURNOM")); |
labelSurnom.setHorizontalAlignment(SwingConstants.RIGHT); |
final JLabel labelSurnom = new JLabel(getLabelFor("SURNOM"), SwingConstants.RIGHT); |
this.add(labelSurnom, c); |
final JTextField textSurnom = new JTextField(); |
c.gridx++; |
313,8 → 308,7 |
c.weightx = 0; |
if (getTable().contains("MAIL")) { |
final JLabel labelMail = new JLabel(getLabelFor("MAIL")); |
labelMail.setHorizontalAlignment(SwingConstants.RIGHT); |
final JLabel labelMail = new JLabel(getLabelFor("MAIL"), SwingConstants.RIGHT); |
c.anchor = GridBagConstraints.NORTHWEST; |
this.add(labelMail, c); |
c.gridx++; |
325,6 → 319,7 |
this.add(textMail, c); |
this.addView(textMail, "MAIL"); |
} |
if (getTable().contains("OUT")) { |
c.gridx++; |
final JCheckBox boxOut = new JCheckBox(getLabelFor("OUT")); |
345,9 → 340,24 |
} |
} |
c.gridy++; |
if (getTable().contains("COMPTE_NUMERO")) { |
final JLabel labelMail = new JLabel(getLabelFor("COMPTE_NUMERO")); |
labelMail.setHorizontalAlignment(SwingConstants.RIGHT); |
c.anchor = GridBagConstraints.NORTHWEST; |
this.add(labelMail, c); |
c.gridx++; |
final JTextField textMail = new JTextField(); |
c.gridwidth = 1; |
c.weightx = 1; |
c.gridy++; |
this.add(textMail, c); |
this.addView(textMail, "COMPTE_NUMERO"); |
} |
if (getTable().contains("TEL")) { |
c.gridx = 0; |
final JLabel labelTel = new JLabel(getLabelFor("TEL")); |
final JLabel labelTel = new JLabel(getLabelFor("TEL"), SwingConstants.RIGHT); |
c.gridwidth = 1; |
c.weightx = 0; |
this.add(labelTel, c); |
365,6 → 375,20 |
this.add(boxCalUser, c); |
this.addView(boxCalUser, "CALENDAR_USER"); |
} |
if (getTable().contains("COLOR")) { |
c.gridy++; |
c.gridx = 0; |
final JLabel labelTel = new JLabel(getLabelFor("COLOR"), SwingConstants.RIGHT); |
c.gridwidth = 1; |
c.weightx = 0; |
this.add(labelTel, c); |
final IColorChooser colorChooser = new IColorChooser(getLabelFor("COLOR")); |
c.gridx++; |
c.weightx = 1; |
c.fill = GridBagConstraints.HORIZONTAL; |
this.add(colorChooser, c); |
this.addView(colorChooser, "COLOR"); |
} |
final boolean gestionHoraire = false; |
if (Configuration.getInstance().getAppName().startsWith("OpenConcerto") && gestionHoraire) { |
/trunk/OpenConcerto/src/org/openconcerto/sql/users/User.java |
---|
15,6 → 15,8 |
import org.openconcerto.sql.model.SQLRowAccessor; |
import java.awt.Color; |
import net.jcip.annotations.Immutable; |
@Immutable |
22,6 → 24,7 |
private final int id; |
private final String name, firstName, nickName; |
private final Boolean active; |
private final Color color; |
public User(final SQLRowAccessor r) { |
this.id = r.getID(); |
33,6 → 36,11 |
} else { |
this.active = null; |
} |
if (r.contains("COLOR")) { |
this.color = new Color(r.getInt("COLOR")); |
} else { |
this.color = null; |
} |
} |
public String getName() { |
63,4 → 71,8 |
public boolean isActive() { |
return this.active; |
} |
public Color getColor() { |
return this.color; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/users/rights/SQLTableRightEditor.java |
---|
13,6 → 13,7 |
package org.openconcerto.sql.users.rights; |
import org.openconcerto.sql.Log; |
import org.openconcerto.sql.TM; |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.element.SQLElementDirectory; |
27,7 → 28,6 |
import java.beans.PropertyChangeListener; |
import java.util.ArrayList; |
import java.util.List; |
import java.util.Set; |
import javax.swing.JComponent; |
import javax.swing.JTextField; |
41,15 → 41,12 |
@Override |
public JComponent getRightEditor(final String right, final DBRoot root, final SQLElementDirectory directory, final JTextField fieldObject) { |
final ISearchableCombo<SQLTableComboItem> comboMenu = new ISearchableCombo<SQLTableComboItem>(); |
DefaultIMutableListModel<SQLTableComboItem> comboItems = new DefaultIMutableListModel<SQLTableComboItem>(); |
Set<SQLTable> set = root.getTables(); |
List<SQLTableComboItem> result = new ArrayList<SQLTableComboItem>(set.size()); |
final ISearchableCombo<SQLTableComboItem> comboMenu = new ISearchableCombo<>(); |
final DefaultIMutableListModel<SQLTableComboItem> comboItems = new DefaultIMutableListModel<>(); |
final List<SQLTableComboItem> result = new ArrayList<>(); |
result.add(SQLTableComboItem.createFromTable(null)); |
for (SQLTable table : set) { |
final SQLElement elt = directory.getElement(table); |
result.add(SQLTableComboItem.create(table, elt)); |
for (SQLElement elt : directory.getElements()) { |
result.add(SQLTableComboItem.create(elt.getTable(), elt)); |
} |
comboItems.addAll(result); |
comboMenu.initCache(comboItems); |
57,7 → 54,7 |
@Override |
public void propertyChange(PropertyChangeEvent evt) { |
final SQLTableComboItem selectedItem = (SQLTableComboItem) comboMenu.getSelectedItem(); |
final SQLTableComboItem selectedItem = comboMenu.getSelectedItem(); |
if (selectedItem != null) { |
fieldObject.setText(selectedItem.getValue()); |
} |
72,22 → 69,28 |
RightEditorManager.getInstance().register(code, editor); |
} |
static public class SQLTableComboItem { |
public static class SQLTableComboItem { |
static public SQLTableComboItem create(final SQLTable t, final SQLElement elt) { |
public static SQLTableComboItem create(final SQLTable t, final SQLElement elt) { |
assert elt == null || elt.getTable() == t; |
return elt != null ? createFromElement(elt) : createFromTable(t); |
} |
static public SQLTableComboItem createFromElement(final SQLElement elt) { |
return new SQLTableComboItem(elt.getTable(), elt.getName().getVariant(Grammar.SINGULAR)); |
public static SQLTableComboItem createFromElement(final SQLElement elt) { |
String variant = elt.getName().getVariant(Grammar.SINGULAR); |
if (variant.contains("_")) { |
// quick patch for not translated tables |
Log.get().warning(elt.getName() + " not translated"); |
variant = variant.replace('_', ' ').toLowerCase(); |
} |
return new SQLTableComboItem(elt.getTable(), variant); |
} |
static public SQLTableComboItem createFromTable(final SQLTable t) { |
return new SQLTableComboItem(t, t == null ? TM.tr("rights.allTables") : t.getName()); |
public static SQLTableComboItem createFromTable(final SQLTable t) { |
return new SQLTableComboItem(t, t == null ? TM.tr("rights.allTables") : t.getName().toLowerCase().replace('_', ' ')); |
} |
static public SQLTableComboItem createFromString(final String s, final DBRoot r, final SQLElementDirectory dir) { |
public static SQLTableComboItem createFromString(final String s, final DBRoot r, final SQLElementDirectory dir) { |
if (s == null) |
return createFromTable(null); |
final SQLName n = SQLName.parse(s); |
96,7 → 99,7 |
final SQLTable t = r.findTable(n.getName()); |
if (t == null) |
// allow to use unknown table (e.g. not yet created) |
return new SQLTableComboItem(s, n.getName()); |
return new SQLTableComboItem(s, n.getName().toLowerCase().replace('_', ' ')); |
else |
return create(t, dir.getElement(t)); |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/users/rights/TableAllRights.java |
---|
31,9 → 31,11 |
public static final String ADD_ROW_TABLE = "INSERT_ROW"; |
public static final String VIEW_ROW_TABLE = "SELECT_ROW"; |
public static final String SAVE_ROW_TABLE = "SAVE_ROW"; |
public static final String USER_UI_LOCK_ROW = "LIST_UI_LOCK_ROWS"; |
public static final String USER_UI_UNLOCK_ROW = "LIST_UI_UNLOCK_ROWS"; |
public static final List<String> getCodes() { |
return Arrays.asList(CODE, CODE_MODIF, DELETE_ROW_TABLE, MODIFY_ROW_TABLE, ADD_ROW_TABLE, VIEW_ROW_TABLE, SAVE_ROW_TABLE); |
return Arrays.asList(CODE, CODE_MODIF, DELETE_ROW_TABLE, MODIFY_ROW_TABLE, ADD_ROW_TABLE, VIEW_ROW_TABLE, SAVE_ROW_TABLE, USER_UI_UNLOCK_ROW, USER_UI_LOCK_ROW); |
} |
public static RightTuple createRight(final SQLTable t, final boolean b) { |
119,6 → 121,8 |
res.add(new RightTuple(DELETE_ROW_TABLE, object, haveRight)); |
res.add(new RightTuple(MODIFY_ROW_TABLE, object, haveRight)); |
res.add(new RightTuple(ADD_ROW_TABLE, object, haveRight)); |
res.add(new RightTuple(USER_UI_LOCK_ROW, object, haveRight)); |
res.add(new RightTuple(USER_UI_UNLOCK_ROW, object, haveRight)); |
if (getCode() == CODE) |
res.add(new RightTuple(VIEW_ROW_TABLE, object, haveRight)); |
return res; |
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/KeyTableCellRenderer.java |
---|
20,6 → 20,7 |
import org.openconcerto.sql.model.SQLTableEvent; |
import org.openconcerto.sql.model.SQLTableEvent.Mode; |
import org.openconcerto.sql.model.SQLTableModifiedListener; |
import org.openconcerto.sql.request.ComboSQLRequest; |
import org.openconcerto.sql.sqlobject.IComboSelectionItem; |
import java.awt.Component; |
37,13 → 38,18 |
private Object toSelect; |
private boolean isLoading = false; |
private final SQLElement el; |
private final List<String> fields; |
private JTable t; |
static private final Map<SQLElement, Map<Integer, IComboSelectionItem>> cacheMap = new HashMap<SQLElement, Map<Integer, IComboSelectionItem>>(); |
public KeyTableCellRenderer(final SQLElement el) { |
this(el, null); |
} |
public KeyTableCellRenderer(final SQLElement el, final List<String> fields) { |
super(); |
this.el = el; |
this.fields = fields; |
if (cacheMap.get(this.el) == null) { |
loadCacheAsynchronous(); |
} |
107,7 → 113,9 |
Configuration.getInstance().getNonInteractiveSQLExecutor().execute(new Runnable() { |
public void run() { |
List<IComboSelectionItem> items = KeyTableCellRenderer.this.el.getComboRequest().getComboItems(); |
final ComboSQLRequest comboRequest = KeyTableCellRenderer.this.fields == null || KeyTableCellRenderer.this.fields.isEmpty() ? KeyTableCellRenderer.this.el.getComboRequest() |
: KeyTableCellRenderer.this.el.createComboRequest(KeyTableCellRenderer.this.fields, null); |
List<IComboSelectionItem> items = comboRequest.getComboItems(); |
final Map<Integer, IComboSelectionItem> m = new HashMap<Integer, IComboSelectionItem>(); |
for (IComboSelectionItem comboSelectionItem : items) { |
m.put(comboSelectionItem.getId(), comboSelectionItem); |
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/IListe.java |
---|
30,6 → 30,7 |
import org.openconcerto.sql.request.UpdateBuilder; |
import org.openconcerto.sql.users.User; |
import org.openconcerto.sql.users.UserManager; |
import org.openconcerto.sql.users.rights.TableAllRights; |
import org.openconcerto.sql.view.FileTransfertHandler; |
import org.openconcerto.sql.view.IListener; |
import org.openconcerto.sql.view.list.IListeAction.ButtonsBuilder; |
146,6 → 147,8 |
public final class IListe extends JPanel { |
static private final class LockAction extends RowAction { |
private final boolean lock; |
public LockAction(final boolean lock) { |
super(new AbstractAction(TM.tr(lock ? "ilist.lockRows" : "ilist.unlockRows")) { |
@Override |
167,12 → 170,13 |
t.fireTableModified(fireID.intValue(), update.getFieldsNames()); |
} |
}, false, true); |
this.lock = lock; |
} |
@Override |
public boolean enabledFor(IListeEvent evt) { |
// TODO use right |
return evt.getSelectedRows().size() > 0; |
boolean hasRight = TableAllRights.currentUserHasRight(this.lock ? TableAllRights.USER_UI_LOCK_ROW : TableAllRights.USER_UI_UNLOCK_ROW, evt.getTable()); |
return !evt.getSelectedRows().isEmpty() && hasRight; |
} |
} |
1204,9 → 1208,8 |
try { |
res.add(getRow(i, clazz)); |
} catch (IndexOutOfBoundsException e) { |
throw new IllegalStateException( |
"The selected row at " + i |
+ " is not in the model : it has been changed before Swing could update the selection. E.g. the DB was changed on mousePressed and Swing updated the selection on mouseReleased.", |
throw new IllegalStateException("The selected row at " + i |
+ " is not in the model : it has been changed before Swing could update the selection. E.g. the DB was changed on mousePressed and Swing updated the selection on mouseReleased.", |
e); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/SQLTextComboTableCellEditor.java |
---|
34,6 → 34,7 |
import java.beans.PropertyChangeEvent; |
import java.beans.PropertyChangeListener; |
import java.util.EventObject; |
import java.util.List; |
import javax.swing.AbstractAction; |
import javax.swing.AbstractCellEditor; |
56,7 → 57,7 |
private IListFrame listFrame = null; |
public SQLTextComboTableCellEditor(final SQLElement elt, final boolean addUndefined) { |
this(elt, addUndefined, false); |
this(elt, addUndefined, false,null); |
} |
/** |
66,8 → 67,18 |
* @param chooseInListe possibilité de choisir via une IListe |
*/ |
public SQLTextComboTableCellEditor(final SQLElement elt, final boolean addUndefined, boolean chooseInListe) { |
super(); |
this(elt, addUndefined, chooseInListe, null); |
} |
/** |
* |
* @param elt Element à afficher dans la combo |
* @param addUndefined ajout de l'indéfini |
* @param chooseInListe possibilité de choisir via une IListe |
*/ |
public SQLTextComboTableCellEditor(final SQLElement elt, final boolean addUndefined, boolean chooseInListe, List<String> fieldsInCombo) { |
super(); |
this.addUndefined = addUndefined; |
this.comboBox = new SQLRequestComboBox(addUndefined); |
77,7 → 88,7 |
this.comboBox.setBorder(new LineBorder(Color.black)); |
this.comboBox.getPulseComponents().iterator().next().setBorder(null); |
ComboSQLRequest c = elt.getComboRequest(true); |
ComboSQLRequest c = fieldsInCombo == null || fieldsInCombo.isEmpty() ? elt.getComboRequest(true) : elt.createComboRequest(fieldsInCombo, null); |
this.comboBox.uiInit(c); |
if (chooseInListe) { |
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/RowValuesTableModel.java |
---|
20,6 → 20,7 |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.SQLRowListRSH; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.SQLRowValuesCluster.StoreMode; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.SQLSyntax.ConstraintType; |
import org.openconcerto.sql.model.SQLTable; |
300,7 → 301,7 |
for (int i = 0; i < size; i++) { |
final SQLRowValues r = rowsToCommmit.get(i); |
r.put(r.getTable().getOrderField().getFieldName(), o.add(new BigDecimal(i + 1))); |
final SQLRow row = r.commit(); |
final SQLRow row = r.getGraph().store(StoreMode.COMMIT).getStoredRow(r); |
r.setID(row.getIDNumber()); |
} |
} catch (SQLException e) { |
/trunk/OpenConcerto/src/org/openconcerto/utils/ooxml/XLSXDocument.java |
---|
New file |
0,0 → 1,273 |
/* |
* 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.ooxml; |
import org.openconcerto.utils.StringInputStream; |
import java.io.ByteArrayOutputStream; |
import java.io.File; |
import java.io.IOException; |
import java.io.InputStream; |
import java.nio.charset.StandardCharsets; |
import java.util.ArrayList; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
import java.util.zip.ZipEntry; |
import java.util.zip.ZipFile; |
import javax.xml.XMLConstants; |
import javax.xml.parsers.DocumentBuilder; |
import javax.xml.parsers.DocumentBuilderFactory; |
import javax.xml.parsers.ParserConfigurationException; |
import org.w3c.dom.Document; |
import org.w3c.dom.NamedNodeMap; |
import org.w3c.dom.Node; |
import org.w3c.dom.NodeList; |
import org.xml.sax.SAXException; |
public class XLSXDocument { |
private File file; |
private final List<XLSXSheet> sheets = new ArrayList<>(); |
private final Map<String, String> relationships = new HashMap<>(); |
private final List<String> sharedString = new ArrayList<>(); |
private final Map<Integer, XLSXFormat> mapFormats = new HashMap<>(); |
private final List<XLSXFormat> customFormats = new ArrayList<>(); |
private final List<XLSXStyle> styles = new ArrayList<>(); |
private final DocumentBuilderFactory dbFactory; |
public static XLSXDocument createFromFile(File f) throws IOException { |
XLSXDocument doc = new XLSXDocument(); |
doc.load(f); |
return doc; |
} |
public XLSXDocument() { |
this.mapFormats.put(0, new XLSXFormat(0, "General", false)); |
this.mapFormats.put(1, new XLSXFormat(1, "0", false)); |
this.mapFormats.put(2, new XLSXFormat(2, "0.00", false)); |
this.mapFormats.put(3, new XLSXFormat(3, "#,##0", false)); |
this.mapFormats.put(4, new XLSXFormat(4, "#,##0.00", false)); |
this.mapFormats.put(9, new XLSXFormat(9, "0%", false)); |
this.mapFormats.put(10, new XLSXFormat(10, "0.00%", false)); |
this.mapFormats.put(11, new XLSXFormat(11, "0.00E+00", false)); |
this.mapFormats.put(12, new XLSXFormat(12, "# ?/?", false)); |
this.mapFormats.put(13, new XLSXFormat(13, "# ??/??", false)); |
this.mapFormats.put(14, new XLSXFormat(14, "mm-dd-yy", true)); |
this.mapFormats.put(15, new XLSXFormat(15, "d-mmm-yy", true)); |
this.mapFormats.put(16, new XLSXFormat(16, "d-mmm", true)); |
this.mapFormats.put(17, new XLSXFormat(17, "mmm-yy", true)); |
this.mapFormats.put(18, new XLSXFormat(18, "h:mm AM/PM", false)); |
this.mapFormats.put(19, new XLSXFormat(19, "h:mm:ss AM/PM", false)); |
this.mapFormats.put(20, new XLSXFormat(20, "h:mm", false)); |
this.mapFormats.put(21, new XLSXFormat(21, "h:mm:ss", false)); |
this.mapFormats.put(22, new XLSXFormat(22, "m/d/yy h:mm", true)); |
this.mapFormats.put(27, new XLSXFormat(27, "[$-404]e/m/d", true)); |
this.mapFormats.put(30, new XLSXFormat(30, "m/d/yy", true)); |
this.mapFormats.put(36, new XLSXFormat(36, "[$-404]e/m/d", true)); |
this.mapFormats.put(37, new XLSXFormat(37, "#,##0 ;(#,##0)", false)); |
this.mapFormats.put(38, new XLSXFormat(38, "#,##0 ;[Red](#,##0)", false)); |
this.mapFormats.put(39, new XLSXFormat(39, "#,##0.00;(#,##0.00)", false)); |
this.mapFormats.put(40, new XLSXFormat(40, "#,##0.00;[Red](#,##0.00)", false)); |
this.mapFormats.put(44, new XLSXFormat(44, "_(\"$\"* #,##0.00_);_(\"$\"* (#,##0.00);_(\"$\"* \"-\"??_);_(@_)", false)); |
this.mapFormats.put(45, new XLSXFormat(45, "mm:ss", false)); |
this.mapFormats.put(46, new XLSXFormat(46, "[h]:mm:ss", false)); |
this.mapFormats.put(47, new XLSXFormat(47, "mmss.0", false)); |
this.mapFormats.put(48, new XLSXFormat(48, "##0.0E+0", false)); |
this.mapFormats.put(49, new XLSXFormat(49, "@", false)); |
this.mapFormats.put(50, new XLSXFormat(50, "[$-404]e/m/d", true)); |
this.mapFormats.put(57, new XLSXFormat(57, "[$-404]e/m/d", true)); |
this.mapFormats.put(59, new XLSXFormat(59, "t0", false)); |
this.mapFormats.put(60, new XLSXFormat(60, "t0.00", false)); |
this.mapFormats.put(61, new XLSXFormat(61, "t#,##0", false)); |
this.mapFormats.put(62, new XLSXFormat(62, "t#,##0.00", false)); |
this.mapFormats.put(67, new XLSXFormat(67, "t0%", false)); |
this.mapFormats.put(68, new XLSXFormat(68, "t0.00%", false)); |
this.mapFormats.put(69, new XLSXFormat(69, "t# ?/?", false)); |
this.mapFormats.put(70, new XLSXFormat(70, "t# ??/??", false)); |
this.dbFactory = DocumentBuilderFactory.newInstance(); |
try { |
this.dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); |
} catch (ParserConfigurationException e) { |
throw new IllegalStateException(e); |
} |
try { |
this.dbFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); |
this.dbFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); |
} catch (Exception e) { |
// ignore |
} |
this.dbFactory.setNamespaceAware(true); |
} |
public File getFile() { |
return this.file; |
} |
private void load(File f) throws IOException { |
this.file = f; |
try (ZipFile zipFile = new ZipFile(f)) { |
try { |
parseSharedStrings(zipFile); |
parseStyles(zipFile); |
parseWorkBook(zipFile); |
} catch (ParserConfigurationException | SAXException e) { |
throw new IOException(e); |
} |
} |
} |
private void parseWorkBook(ZipFile zipFile) throws ParserConfigurationException, SAXException, IOException { |
final String relationxXML = getContent(zipFile, "xl/_rels/workbook.xml.rels"); |
final DocumentBuilder dBuilder1 = this.dbFactory.newDocumentBuilder(); |
final Document doc1 = dBuilder1.parse(new StringInputStream(relationxXML, StandardCharsets.UTF_8.name())); |
doc1.getDocumentElement().normalize(); |
final NodeList nList = doc1.getElementsByTagName("Relationship"); |
for (int i = 0; i < nList.getLength(); i++) { |
final NamedNodeMap attributes = nList.item(i).getAttributes(); |
final String rId = attributes.getNamedItem("Id").getNodeValue(); |
final String target = attributes.getNamedItem("Target").getNodeValue(); |
this.relationships.put(rId, target); |
} |
final String workbookXML = getContent(zipFile, "xl/workbook.xml"); |
final DocumentBuilder dBuilder2 = this.dbFactory.newDocumentBuilder(); |
final Document doc2 = dBuilder2.parse(new StringInputStream(workbookXML, StandardCharsets.UTF_8.name())); |
doc2.getDocumentElement().normalize(); |
doc2.getElementsByTagName("sheets"); |
final NodeList nListSheet = doc2.getElementsByTagName("sheet"); |
for (int i = 0; i < nListSheet.getLength(); i++) { |
final NamedNodeMap attributes = nListSheet.item(i).getAttributes(); |
final String sheetId = attributes.getNamedItem("sheetId").getNodeValue(); |
final String name = attributes.getNamedItem("name").getNodeValue(); |
final String rId = attributes.getNamedItemNS("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "id").getNodeValue(); |
final String target = "xl/" + this.relationships.get(rId); |
final String xml = getContent(zipFile, target); |
this.sheets.add(new XLSXSheet(this, sheetId, rId, name, xml)); |
} |
} |
private void parseSharedStrings(ZipFile zipFile) throws ParserConfigurationException, SAXException, IOException { |
final String relationxXML = getContent(zipFile, "xl/sharedStrings.xml"); |
final DocumentBuilder dBuilder1 = this.dbFactory.newDocumentBuilder(); |
final Document doc1 = dBuilder1.parse(new StringInputStream(relationxXML, StandardCharsets.UTF_8.name())); |
doc1.getDocumentElement().normalize(); |
final NodeList nList = doc1.getElementsByTagName("si"); |
for (int i = 0; i < nList.getLength(); i++) { |
final Node siNode = nList.item(i); |
StringBuilder b = new StringBuilder(); |
NodeList list = siNode.getChildNodes(); |
for (int j = 0; j < list.getLength(); j++) { |
Node n = list.item(j); |
if (n.getLocalName().equals("t")) { |
b.append(n.getTextContent()); |
} else { |
NodeList subList = n.getChildNodes(); |
for (int k = 0; k < subList.getLength(); k++) { |
Node nn = subList.item(k); |
if (nn.getLocalName().equals("t")) { |
b.append(nn.getTextContent()); |
} |
} |
} |
} |
this.sharedString.add(b.toString()); |
} |
} |
private void parseStyles(ZipFile zipFile) throws ParserConfigurationException, SAXException, IOException { |
final String relationxXML = getContent(zipFile, "xl/styles.xml"); |
final DocumentBuilder dBuilder1 = this.dbFactory.newDocumentBuilder(); |
final Document doc1 = dBuilder1.parse(new StringInputStream(relationxXML, StandardCharsets.UTF_8.name())); |
doc1.getDocumentElement().normalize(); |
final NodeList nListFormats = doc1.getElementsByTagName("numFmts"); |
for (int i = 0; i < nListFormats.getLength(); i++) { |
final Node siNode = nListFormats.item(i); |
NodeList list = siNode.getChildNodes(); |
for (int j = 0; j < list.getLength(); j++) { |
Node n = list.item(j); |
NamedNodeMap m = n.getAttributes(); |
int id = Integer.parseInt(m.getNamedItem("numFmtId").getNodeValue()); |
String format = m.getNamedItem("formatCode").getNodeValue(); |
final XLSXFormat f = new XLSXFormat(id, format); |
this.mapFormats.put(id, f); |
this.customFormats.add(f); |
} |
} |
final NodeList nListCellXfs = doc1.getElementsByTagName("cellXfs"); |
for (int i = 0; i < nListCellXfs.getLength(); i++) { |
final Node siNode = nListCellXfs.item(i); |
NodeList list = siNode.getChildNodes(); |
for (int j = 0; j < list.getLength(); j++) { |
// xf |
Node n = list.item(j); |
NamedNodeMap m = n.getAttributes(); |
int id = Integer.parseInt(m.getNamedItem("numFmtId").getNodeValue()); |
this.styles.add(new XLSXStyle(id)); |
} |
} |
} |
private String getContent(ZipFile zipFile, String string) throws IOException { |
final ZipEntry entry = zipFile.getEntry(string); |
if (entry == null) { |
throw new IOException("no entry : " + string); |
} |
final InputStream in = zipFile.getInputStream(entry); |
final ByteArrayOutputStream b = new ByteArrayOutputStream(); |
final byte[] bytes = new byte[8192]; |
while (in.available() > 0) { |
final int length = in.read(bytes); |
b.write(bytes, 0, length); |
} |
return b.toString(StandardCharsets.UTF_8.name()); |
} |
public XLSXSheet getSheet(int sheetNumber) { |
return this.sheets.get(sheetNumber); |
} |
public int getSheetCount() { |
return this.sheets.size(); |
} |
public String getSharedString(int index) { |
return this.sharedString.get(index); |
} |
public XLSXFormat getFormatFromStyle(int styleIndex) { |
final XLSXStyle style = this.styles.get(styleIndex); |
if (style == null) { |
return null; |
} |
return this.mapFormats.get(style.getFormatId()); |
} |
public DocumentBuilderFactory getDbFactory() { |
return this.dbFactory; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/ooxml/XLSXStyle.java |
---|
New file |
0,0 → 1,26 |
/* |
* 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.ooxml; |
public class XLSXStyle { |
private final int formatId; |
public XLSXStyle(int formatId) { |
this.formatId = formatId; |
} |
public int getFormatId() { |
return this.formatId; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/ooxml/XLSXFormat.java |
---|
New file |
0,0 → 1,71 |
/* |
* 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.ooxml; |
import java.text.DecimalFormat; |
import java.text.Format; |
import java.text.SimpleDateFormat; |
public class XLSXFormat { |
private final int id; |
private final String format; |
private boolean isDateFormat = false; |
private Format jformat; |
public XLSXFormat(int id, String format) { |
this.id = id; |
this.format = format; |
final String f = format.toLowerCase(); |
if (f.contains("mm") || f.contains("dd") || f.contains("yy")) { |
this.isDateFormat = true; |
} |
} |
public XLSXFormat(int id, String format, boolean date) { |
this.id = id; |
this.format = format; |
this.isDateFormat = date; |
} |
public int getId() { |
return this.id; |
} |
public String getFormat() { |
return this.format; |
} |
public boolean isDateFormat() { |
return this.isDateFormat; |
} |
public String format(String txt) { |
if (this.format.equalsIgnoreCase("general")) { |
return txt; |
} |
if (this.jformat == null) { |
String javaFormat = this.format.replace("YYYY", "yyyy"); |
javaFormat = javaFormat.replace("YY", "yy"); |
javaFormat = javaFormat.replace("mm", "MM"); |
javaFormat = javaFormat.replace("dd", "DD"); |
if (this.isDateFormat) { |
this.jformat = new SimpleDateFormat(javaFormat); |
} else { |
this.jformat = new DecimalFormat(javaFormat); |
} |
} |
return this.jformat.format(txt); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/ooxml/XLSXSheet.java |
---|
New file |
0,0 → 1,261 |
/* |
* 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.ooxml; |
import org.openconcerto.utils.StringInputStream; |
import org.openconcerto.utils.StringUtils; |
import java.awt.Point; |
import java.io.IOException; |
import java.nio.charset.StandardCharsets; |
import java.util.ArrayList; |
import java.util.Calendar; |
import java.util.Date; |
import java.util.List; |
import java.util.regex.Matcher; |
import java.util.regex.Pattern; |
import javax.xml.parsers.DocumentBuilder; |
import javax.xml.parsers.ParserConfigurationException; |
import org.w3c.dom.Document; |
import org.w3c.dom.Node; |
import org.w3c.dom.NodeList; |
import org.xml.sax.SAXException; |
import com.ibm.icu.math.BigDecimal; |
public class XLSXSheet { |
private int columnCount; |
private int startX; |
private int startY; |
private int endX; |
private int endY; |
private static final String MINCELL = "\\$?([A-Z]+)\\$?([0-9]+)"; |
private static final Pattern minCellPattern = Pattern.compile(MINCELL); |
private final List<List<Object>> rows; |
private String id; |
private String rId; |
private String name; |
public XLSXSheet(XLSXDocument document, String id, String rId, String name, String xml) throws IOException, ParserConfigurationException, SAXException { |
this.id = id; |
this.rId = rId; |
this.name = name; |
final DocumentBuilder dBuilder = document.getDbFactory().newDocumentBuilder(); |
final Document doc = dBuilder.parse(new StringInputStream(xml, StandardCharsets.UTF_8.name())); |
doc.getDocumentElement().normalize(); |
final NodeList nList = doc.getElementsByTagName("dimension"); |
final String dimension = nList.item(0).getAttributes().getNamedItem("ref").getNodeValue(); |
final List<String> parts = StringUtils.fastSplit(dimension, ':'); |
final Point start = resolve(parts.get(0)); |
this.startX = start.x; |
this.startY = start.y; |
final Point end = resolve(parts.get(1)); |
this.endX = end.x; |
this.endY = end.y; |
this.rows = new ArrayList<>(end.y - start.y); |
this.columnCount = this.endX - this.startX + 1; |
for (int i = start.y; i <= end.y; i++) { |
List<Object> row = new ArrayList<>(); |
for (int j = 0; j < this.columnCount; j++) { |
row.add(null); |
} |
this.rows.add(row); |
} |
Calendar calendar = Calendar.getInstance(); |
NodeList nListRows = doc.getElementsByTagName("row"); |
int l1 = nListRows.getLength(); |
for (int i = 0; i < l1; i++) { |
Node r = nListRows.item(i); |
NodeList nListCells = r.getChildNodes(); |
int l2 = nListCells.getLength(); |
for (int j = 0; j < l2; j++) { |
Node c = nListCells.item(j); |
final String location = c.getAttributes().getNamedItem("r").getNodeValue(); |
final Point p = resolve(location); |
if (p == null) { |
throw new IllegalStateException("unable to parse location : " + location); |
} |
// The index of this cell's style. Style records are stored in the Styles Part. |
// The possible values for this attribute are defined by the W3C XML Schema |
// unsignedInt datatype. |
int style = 0; |
if (c.getAttributes().getNamedItem("s") != null) { |
style = Integer.parseInt(c.getAttributes().getNamedItem("s").getNodeValue()); |
} |
// An enumeration representing the cell's data type. |
// The possible values for this attribute are defined by the ST_CellType simple type |
// (§18.18.11): |
// "b" boolean |
// "d" ISO 8601 date |
// "n" number |
// "e" error |
// "s" strin |
// "str" formula |
// "inlineStr" the cell value is in the is element rather than the v |
// element in the cell |
String type = "n"; |
if (c.getAttributes().getNamedItem("t") != null) { |
type = c.getAttributes().getNamedItem("t").getNodeValue(); |
} |
NodeList nListCellParts = c.getChildNodes(); |
int l3 = nListCellParts.getLength(); |
for (int k = 0; k < l3; k++) { |
Node part = nListCellParts.item(k); |
if (part.getNodeName().equals("v")) { |
String value = part.getTextContent(); |
Object cellValue = null; |
if (type.equals("n")) { |
final XLSXFormat format = document.getFormatFromStyle(style); |
if (format != null) { |
if (format.isDateFormat()) { |
cellValue = stringToDate(calendar, value); |
} else { |
cellValue = new BigDecimal(value); |
} |
} else { |
cellValue = new BigDecimal(value); |
} |
} else if (type.equals("s")) { |
cellValue = document.getSharedString(Integer.parseInt(value)); |
} |
this.rows.get(p.y - this.startY).set(p.x - this.startX, cellValue); |
} |
} |
} |
} |
} |
public Object getValueAt(int col, int row) { |
return this.rows.get(row).get(col); |
} |
public int getColumnCount() { |
return this.columnCount; |
} |
public int getRowCount() { |
return this.rows.size(); |
} |
/** |
* Convert string coordinates into numeric ones. |
* |
* @param ref the string address, eg "$AA$34" or "AA34". |
* @return the numeric coordinates or <code>null</code> if <code>ref</code> is not valid, eg |
* {26, 33}. |
*/ |
static final Point resolve(String ref) { |
final Matcher matcher = minCellPattern.matcher(ref); |
if (!matcher.matches()) |
return null; |
return resolve(matcher.group(1), matcher.group(2)); |
} |
/** |
* Convert string coordinates into numeric ones. ATTN this method does no checks. |
* |
* @param letters the column, eg "AA". |
* @param digits the row, eg "34". |
* @return the numeric coordinates, eg {26, 33}. |
*/ |
static final Point resolve(final String letters, final String digits) { |
return new Point(toInt(letters), Integer.parseInt(digits) - 1); |
} |
// "AA" => 26 |
static final int toInt(String col) { |
if (col.length() < 1) |
throw new IllegalArgumentException("x cannot be empty"); |
col = col.toUpperCase(); |
int x = 0; |
for (int i = 0; i < col.length(); i++) { |
x = x * 26 + (col.charAt(i) - 'A' + 1); |
} |
// zero based |
return x - 1; |
} |
public static final String toStr(int col) { |
if (col < 0) |
throw new IllegalArgumentException("negative column : " + col); |
// one based (i.e. 0 is A) |
col++; |
final int radix = 26; |
final StringBuilder chars = new StringBuilder(4); |
while (col > 0) { |
chars.append((char) ('A' + ((col - 1) % radix))); |
col = (col - 1) / radix; |
} |
return chars.reverse().toString(); |
} |
/** |
* Convert numeric coordinates into string ones. |
* |
* @param p the numeric coordinates, e.g. {26, 33}. |
* @return the string address, e.g. "AA34". |
*/ |
static final String getAddress(Point p) { |
if (p.x < 0 || p.y < 0) |
throw new IllegalArgumentException("negative coordinates : " + p); |
return toStr(p.x) + (p.y + 1); |
} |
public String getId() { |
return this.id; |
} |
public static Date stringToDate(Calendar c, String d) { |
c.clear(); |
c.set(1900, 0, 0); |
c.add(Calendar.DAY_OF_YEAR, Integer.parseInt(d) - 1); |
return c.getTime(); |
} |
public int getStartX() { |
return this.startX; |
} |
public int getStartY() { |
return this.startY; |
} |
public int getEndX() { |
return this.endX; |
} |
public int getEndY() { |
return this.endY; |
} |
public String getName() { |
return this.name; |
} |
public String getRId() { |
return this.rId; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/TableSorter.java |
---|
348,7 → 348,11 |
* @return the corresponding index in the model. |
*/ |
public int modelIndex(int viewIndex) { |
return getViewToModel()[viewIndex].modelIndex; |
try { |
return getViewToModel()[viewIndex].modelIndex; |
} catch (Exception e) { |
throw new IllegalStateException(this + " couldn't get model index for view index " + viewIndex + " with " + this.getTableModel().getRowCount() + " row(s) in our model", e); |
} |
} |
private int[] getModelToView() { |
430,6 → 434,11 |
this.supp.removePropertyChangeListener(l); |
} |
@Override |
public String toString() { |
return this.getClass().getSimpleName() + " on " + this.getTableModel(); |
} |
// Helper classes |
private class Row implements Comparable<Row> { |
/trunk/OpenConcerto/src/org/openconcerto/utils/FileUtils.java |
---|
695,6 → 695,7 |
* @see StreamUtils#createXMLWriter(java.io.OutputStream) |
*/ |
public static BufferedWriter createXMLWriter(final File f) throws IOException { |
FileUtils.mkParentDirs(f); |
final FileOutputStream outs = new FileOutputStream(f); |
try { |
return StreamUtils.createXMLWriter(outs); |
/trunk/OpenConcerto/src/org/openconcerto/utils/text/CSVReader.java |
---|
29,7 → 29,6 |
import java.io.BufferedReader; |
import java.io.Closeable; |
import java.io.FileReader; |
import java.io.IOException; |
import java.io.Reader; |
import java.util.ArrayList; |
248,11 → 247,4 |
br.close(); |
} |
public static void main(String[] args) throws IOException { |
CSVReader reader = new CSVReader(new FileReader("n:\\Sans nom 1.csv")); |
String[] s = reader.readNext(); |
for (int i = 0; i < s.length; i++) { |
System.err.println("CSVReader.main() :" + i + " : " + s[i]); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/NetUtils.java |
---|
22,11 → 22,17 |
import java.net.ServerSocket; |
import java.net.SocketException; |
import java.net.URL; |
import java.security.KeyManagementException; |
import java.security.NoSuchAlgorithmException; |
import java.security.cert.X509Certificate; |
import java.util.Enumeration; |
import javax.net.ssl.HostnameVerifier; |
import javax.net.ssl.HttpsURLConnection; |
import javax.net.ssl.SSLContext; |
import javax.net.ssl.SSLSession; |
import javax.net.ssl.TrustManager; |
import javax.net.ssl.X509TrustManager; |
public class NetUtils { |
125,6 → 131,10 |
} |
}; |
public static final String getHTTPContent(String address) { |
return getHTTPContent(address, false); |
} |
public static final String getHTTPContent(String address, final boolean dontVerify) { |
String content = ""; |
OutputStream out = null; |
167,4 → 177,23 |
return content; |
} |
// Create a trust manager that does not validate certificate chains |
static private final TrustManager[] TRUSTALL_MANAGERS = new TrustManager[] { new X509TrustManager() { |
public java.security.cert.X509Certificate[] getAcceptedIssuers() { |
return null; |
} |
public void checkClientTrusted(X509Certificate[] certs, String authType) { |
} |
public void checkServerTrusted(X509Certificate[] certs, String authType) { |
} |
} }; |
static public final SSLContext createTrustAllContext() throws KeyManagementException, NoSuchAlgorithmException { |
final SSLContext sc = SSLContext.getInstance("TLS"); |
sc.init(null, TRUSTALL_MANAGERS, new java.security.SecureRandom()); |
return sc; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/ProductInfo.java |
---|
14,6 → 14,9 |
package org.openconcerto.utils; |
import java.io.IOException; |
import java.io.OutputStream; |
import java.nio.file.Files; |
import java.nio.file.Path; |
import java.util.Map; |
import java.util.Properties; |
157,6 → 160,12 |
return this.getProperty(VERSION); |
} |
public final void store(final Path p) throws IOException { |
try (final OutputStream out = Files.newOutputStream(p)) { |
this.getProps().store(out, this.getClass().getName()); |
} |
} |
@Override |
public String toString() { |
return this.getClass().getSimpleName() + " for " + getName() + " " + getVersion(); |
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/CustomEquals.java |
---|
19,7 → 19,10 |
import java.util.Collection; |
import java.util.LinkedHashSet; |
import java.util.List; |
import java.util.ListIterator; |
import java.util.RandomAccess; |
import java.util.Set; |
import java.util.function.BiPredicate; |
/** |
* Allow to create a proxy object which uses a {@link HashingStrategy}. |
103,6 → 106,28 |
return CompareUtils.equals(sA, sB); |
} |
static public final <S, T1 extends S> int indexOf(final List<T1> s1, final S o, final HashingStrategy<S> s) { |
return indexOf(s1, o, s::equals); |
} |
static public final <S, T1 extends S> int indexOf(final List<T1> s1, final S o, final BiPredicate<S, S> s) { |
if (s1 instanceof RandomAccess) { |
final int stop = s1.size(); |
for (int i = 0; i < stop; i++) { |
if (s.test(s1.get(i), o)) |
return i; |
} |
} else { |
final ListIterator<T1> listIter = s1.listIterator(); |
while (listIter.hasNext()) { |
final T1 item = listIter.next(); |
if (s.test(item, o)) |
return listIter.previousIndex(); |
} |
} |
return -1; |
} |
static public class ProxyFull<S, E extends S> implements ProxyItf<E> { |
static public final <S, E extends S> Set<ProxyFull<S, E>> createSet(final HashingStrategy<S> strategy, final Collection<E> coll) { |
192,6 → 217,11 |
else |
return this.strategy.equals(this.getDelegate(), delegate2); |
} |
@Override |
public String toString() { |
return this.getClass().getSimpleName() + " using strategy " + this.getStrategy() + " for " + this.getDelegate(); |
} |
} |
/** |
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/IExnFactory.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 IExnFactory<E, X extends Exception> { |
public abstract E createChecked() throws X; |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/Cookies.java |
---|
New file |
0,0 → 1,216 |
/* |
* 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; |
import java.util.Arrays; |
import java.util.Collection; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
import java.util.Map.Entry; |
import java.util.Objects; |
import java.util.Set; |
import com.google.gson.reflect.TypeToken; |
import net.jcip.annotations.GuardedBy; |
import net.jcip.annotations.ThreadSafe; |
/** |
* Type-safer map (e.g. can store multiple types and collections). |
* |
* @author Sylvain |
*/ |
@ThreadSafe |
public class Cookies { |
@GuardedBy("this") |
private final Map<Object, Object> map; |
@GuardedBy("this") |
private Map<Object, Object> collectionTypes; |
public Cookies() { |
this(8); |
} |
public Cookies(final int initialCapacity) { |
this.map = new HashMap<>(initialCapacity); |
this.collectionTypes = null; |
} |
public Cookies(final Cookies source) { |
synchronized (source) { |
this.map = new HashMap<>(source.map); |
this.collectionTypes = source.collectionTypes == null ? null : new HashMap<>(source.collectionTypes); |
} |
} |
public final void putAll(final Cookies other) { |
if (this == other) |
return; |
final Map<Object, Object> map; |
final Map<Object, Object> collectionTypes; |
synchronized (other) { |
map = new HashMap<>(other.map); |
collectionTypes = other.collectionTypes == null ? null : new HashMap<>(other.collectionTypes); |
} |
synchronized (this) { |
// don't just use putAll() since it won't remove entries from collectionTypes for |
// replaced items |
for (final Entry<Object, Object> e : map.entrySet()) { |
this.put(e.getKey(), e.getValue(), collectionTypes == null ? null : collectionTypes.get(e.getKey())); |
} |
} |
} |
public final Object put(Object k, Object v) { |
return this.put(k, v, null); |
} |
private final Object putCollectionType(Object k, Object v, Object type) { |
if (type == null) |
throw new IllegalArgumentException("Null type"); |
return this.put(k, v, type); |
} |
private final synchronized Object put(Object k, Object v, Object type) { |
if (type != null) { |
if (this.collectionTypes == null) |
this.collectionTypes = new HashMap<>(4); |
this.collectionTypes.put(k, type); |
} else if (this.collectionTypes != null) { |
this.collectionTypes.remove(k); |
} |
return this.map.put(k, v); |
} |
public final <T> Object putCollection(Object k, Collection<T> v, Class<T> clazz) { |
return this.putCollectionType(k, v, clazz); |
} |
public final <K, V> Object putMap(Object k, Map<K, V> v, Class<K> keyClass, Class<V> valueClass) { |
Objects.requireNonNull(keyClass, "Key class"); |
Objects.requireNonNull(valueClass, "value class"); |
return this.putCollectionType(k, v, Arrays.asList(keyClass, valueClass)); |
} |
public final <T> Object putGeneric(Object k, T v, TypeToken<T> clazz) { |
return this.putCollectionType(k, v, clazz); |
} |
public final synchronized boolean containsKey(Object k) { |
return this.map.containsKey(k); |
} |
public final synchronized Object getObject(Object k) { |
return this.map.get(k); |
} |
public final int getInt(Object k) { |
return getObjectAs(k, Number.class).intValue(); |
} |
public final long getLong(Object k) { |
return getObjectAs(k, Number.class).longValue(); |
} |
public final Boolean getBoolean(Object k) { |
return getObjectAs(k, Boolean.class); |
} |
public final boolean getBoolean(Object k, final boolean def) { |
final Boolean res = getBoolean(k); |
return res == null ? def : res.booleanValue(); |
} |
public final String getString(Object k) { |
return getObjectAs(k, String.class); |
} |
public synchronized final <T> T getContainedObjectAs(Object key, Class<T> clazz) { |
if (!this.containsKey(key)) |
throw new IllegalArgumentException(key + " not present in this : " + this.map.keySet()); |
return this.getObjectAs(key, clazz); |
} |
public final <T> T getObjectAs(Object k, Class<T> clazz) { |
return this.getObjectAs(k, clazz, null); |
} |
public final <T> T getObjectAs(Object k, Class<T> clazz, final T defaultVal) { |
return this.getObjectAs(k, clazz, defaultVal, true); |
} |
public synchronized final <T> T getObjectAs(Object k, Class<T> clazz, final T defaultVal, final boolean useDefaultIfNullValue) { |
final Object res = this.getObject(k); |
if (res == null && (useDefaultIfNullValue || !this.containsKey(k))) |
return defaultVal; |
try { |
return clazz.cast(res); |
} catch (ClassCastException e) { |
throw new IllegalArgumentException("Couldn't access " + k + " in " + this + " as " + clazz.getSimpleName(), e); |
} |
} |
public final <T> Object checkType(Object k, Object wantedType, final String needMethodName) { |
final Object object; |
final Object type; |
synchronized (this) { |
object = this.getObject(k); |
type = this.collectionTypes == null ? null : this.collectionTypes.get(k); |
} |
// as getObject() : don't fail on null |
if (object == null) |
return null; |
if (type == null) |
throw new IllegalStateException("Wasn't stored with " + needMethodName + " : " + k); |
if (!type.equals(wantedType)) |
throw new IllegalArgumentException("Wasn't stored with the passed type : " + wantedType + " != " + type); |
return object; |
} |
public final <T> Collection<T> getCollection(Object k, Class<T> clazz) { |
final Object object = checkType(k, clazz, "putCollection()"); |
@SuppressWarnings("unchecked") |
final Collection<T> res = (Collection<T>) object; |
return res; |
} |
public final <T> List<T> getList(Object k, Class<T> clazz) { |
return (List<T>) this.getCollection(k, clazz); |
} |
public final <T> Set<T> getSet(Object k, Class<T> clazz) { |
return (Set<T>) this.getCollection(k, clazz); |
} |
public final <K, V> Map<K, V> getMap(Object k, Class<K> keyClass, Class<V> valueClass) { |
final Object object = checkType(k, Arrays.asList(keyClass, valueClass), "putMap()"); |
@SuppressWarnings("unchecked") |
final Map<K, V> res = (Map<K, V>) object; |
return res; |
} |
public final <T> T getGeneric(Object k, TypeToken<T> clazz) { |
final Object object = checkType(k, clazz, "putGeneric()"); |
@SuppressWarnings("unchecked") |
final T res = (T) object; |
return res; |
} |
@Override |
public synchronized String toString() { |
return this.getClass().getSimpleName() + " of " + this.map.keySet(); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/IFactory.java |
---|
13,8 → 13,9 |
package org.openconcerto.utils.cc; |
public interface IFactory<E> { |
public interface IFactory<E> extends IExnFactory<E, RuntimeException> { |
@Override |
public abstract E createChecked(); |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/CollectionMap2.java |
---|
122,6 → 122,9 |
// ** copy constructors |
// ATTN getDelegate() is not in CollectionMap2Itf, so if one copies an unmodifiableMap() this |
// constructor won't be used and the delegate will be the default HashMap (even if the source |
// used a LinkedHashMap). |
public CollectionMap2(final CollectionMap2<K, C, ? extends V> m) { |
this(CopyUtils.copy(m.getDelegate()), m); |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/CollectionUtils.java |
---|
18,6 → 18,7 |
import org.openconcerto.utils.cc.ITransformer; |
import org.openconcerto.utils.cc.IdentityHashSet; |
import org.openconcerto.utils.cc.IdentitySet; |
import org.openconcerto.utils.cc.LinkedIdentitySet; |
import org.openconcerto.utils.cc.Transformer; |
import java.io.Serializable; |
643,14 → 644,16 |
return collector; |
} |
@SuppressWarnings("unchecked") |
public static <T> Collection<T> subtract(final Collection<T> a, final Collection<? extends T> b) { |
return org.apache.commons.collections.CollectionUtils.subtract(a, b); |
final Collection<T> res = a instanceof IdentitySet ? new LinkedIdentitySet<>(a) : new ArrayList<>(a); |
for (Iterator<? extends T> it = b.iterator(); it.hasNext();) { |
res.remove(it.next()); |
} |
return res; |
} |
@SuppressWarnings("unchecked") |
public static <T> Collection<T> substract(final Collection<T> a, final Collection<? extends T> b) { |
return org.apache.commons.collections.CollectionUtils.subtract(a, b); |
return subtract(a, b); |
} |
public static final <T> T coalesce(T o1, T o2) { |
935,10 → 938,11 |
* @param <K> type of key. |
* @param <V> type of value. |
* @param keys the keys of the map. |
* @return a new map, if <code>keys</code> is a {@link List} it will be ordered. |
* @return a new ordered map. |
*/ |
public static <K, V> Map<K, V> createMap(Collection<? extends K> keys) { |
return fillMap(keys instanceof List ? new LinkedHashMap<K, V>(keys.size()) : new HashMap<K, V>(keys.size()), keys); |
// there's no way to tell if a Collection is ordered, so always use ordered map. |
return fillMap(new LinkedHashMap<K, V>(keys.size()), keys); |
} |
/** |
/trunk/OpenConcerto/src/org/openconcerto/utils/StringUtils.java |
---|
28,6 → 28,7 |
import java.util.List; |
import java.util.Map; |
import java.util.Set; |
import java.util.regex.Matcher; |
import java.util.regex.Pattern; |
/** |
820,4 → 821,13 |
} |
return b.toString(); |
} |
public static final Matcher findFirstContaining(final String s, final Pattern... patterns) { |
for (final Pattern p : patterns) { |
final Matcher matcher = p.matcher(s); |
if (matcher.find()) |
return matcher; |
} |
return null; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/sync/HashWriter.java |
---|
13,6 → 13,8 |
package org.openconcerto.utils.sync; |
import org.openconcerto.utils.MessageDigestUtils; |
import java.io.BufferedInputStream; |
import java.io.BufferedOutputStream; |
import java.io.DataOutputStream; |
38,8 → 40,8 |
} |
final DataOutputStream bOut = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(outputFile))); |
bOut.writeInt((int) this.in.length()); |
final MessageDigest hashSum = MessageDigest.getInstance("SHA-256"); |
final MessageDigest md5 = MessageDigest.getInstance("MD5"); |
final MessageDigest hashSum = MessageDigestUtils.getSHA256(); |
final MessageDigest md5 = MessageDigestUtils.getMD5(); |
fb = new BufferedInputStream(new FileInputStream(in)); |
final RollingChecksum32 r32 = new RollingChecksum32(); |
final byte[] buffer = new byte[BLOCK_SIZE]; |
74,8 → 76,8 |
} |
} |
public static byte[] getHash(File f) throws Exception { |
final MessageDigest hashSum = MessageDigest.getInstance("SHA-256"); |
public static byte[] getHash(File f) throws IOException { |
final MessageDigest hashSum = MessageDigestUtils.getSHA256(); |
FileInputStream fIn = null; |
try { |
fIn = new FileInputStream(f); |
123,4 → 125,15 |
return true; |
} |
private static final char[] hexArray = "0123456789ABCDEF".toCharArray(); |
public static String bytesToHex(byte[] bytes) { |
char[] hexChars = new char[bytes.length * 2]; |
for (int j = 0; j < bytes.length; j++) { |
int v = bytes[j] & 0xFF; |
hexChars[j * 2] = hexArray[v >>> 4]; |
hexChars[j * 2 + 1] = hexArray[v & 0x0F]; |
} |
return new String(hexChars); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/sync/SimpleSyncClient.java |
---|
New file |
0,0 → 1,413 |
/* |
* 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.sync; |
import org.openconcerto.utils.CollectionUtils; |
import org.openconcerto.utils.MessageDigestUtils; |
import org.openconcerto.utils.StreamUtils; |
import java.io.BufferedOutputStream; |
import java.io.File; |
import java.io.IOException; |
import java.io.InputStream; |
import java.io.OutputStream; |
import java.io.UnsupportedEncodingException; |
import java.net.MalformedURLException; |
import java.net.ProtocolException; |
import java.net.URL; |
import java.nio.charset.StandardCharsets; |
import java.nio.file.Files; |
import java.nio.file.Path; |
import java.nio.file.StandardCopyOption; |
import java.nio.file.attribute.FileTime; |
import java.security.DigestOutputStream; |
import java.security.MessageDigest; |
import java.time.Instant; |
import java.util.ArrayList; |
import java.util.Base64; |
import java.util.Collections; |
import java.util.List; |
import java.util.Set; |
import java.util.concurrent.atomic.AtomicBoolean; |
import java.util.function.BiFunction; |
import java.util.function.Predicate; |
import java.util.zip.GZIPInputStream; |
import java.util.zip.GZIPOutputStream; |
import javax.net.ssl.HttpsURLConnection; |
import javax.net.ssl.SSLSocketFactory; |
import net.minidev.json.JSONArray; |
import net.minidev.json.JSONObject; |
import net.minidev.json.parser.JSONParser; |
public final class SimpleSyncClient { |
private static final int MIN_GZIP_SIZE = 64; |
static protected final long getLong(final Object o) { |
return ((Number) o).longValue(); |
} |
static protected final Instant getInstant(final Object o) { |
return Instant.ofEpochMilli(getLong(o)); |
} |
static public class ServerException extends RuntimeException { |
private final int responseCode; |
private final boolean authenticateError; |
protected ServerException(int responseCode, boolean authenticateError) { |
super("Response code was " + responseCode); |
this.responseCode = responseCode; |
this.authenticateError = authenticateError; |
} |
public final int getResponseCode() { |
return this.responseCode; |
} |
public final boolean isAuthenticateError() { |
return this.authenticateError; |
} |
} |
static public final class Response { |
protected final static Response create(HttpsURLConnection con, final Set<Integer> okCodes) throws IOException { |
final boolean success = okCodes == null ? con.getResponseCode() == 200 : okCodes.contains(con.getResponseCode()); |
return new Response(success, con.getResponseCode(), con.getResponseMessage(), con.getContentEncoding(), con.getContentType()); |
} |
private final boolean success; |
private final int code; |
private final String message; |
private final String contentEncoding, contentType; |
protected Response(boolean success, int code, String message, String contentEncoding, String contentType) { |
super(); |
this.success = success; |
this.code = code; |
this.message = message; |
this.contentEncoding = contentEncoding; |
this.contentType = contentType; |
} |
public final int getCode() { |
return this.code; |
} |
public final boolean isSuccess() { |
return this.success; |
} |
public final String getMessage() { |
return this.message; |
} |
public final String getContentEncoding() { |
return this.contentEncoding; |
} |
public final String getContentType() { |
return this.contentType; |
} |
} |
static protected abstract class BaseAttrs { |
private final String path; |
private final String name; |
private final Instant lastModified; |
protected BaseAttrs(final String path, final String name, final Instant lastModified) { |
super(); |
this.path = path; |
this.name = name; |
this.lastModified = lastModified; |
} |
public final String getPath() { |
return this.path; |
} |
public final String getName() { |
return this.name; |
} |
public final Instant getLastModified() { |
return this.lastModified; |
} |
@Override |
public String toString() { |
return this.getClass().getSimpleName() + " '" + this.getName() + "'"; |
} |
} |
static public final class DirAttrs extends BaseAttrs { |
static protected DirAttrs fromJSON(final String path, final JSONArray array) { |
return new DirAttrs(path, (String) array.get(0), getInstant(array.get(1))); |
} |
protected DirAttrs(final String path, String name, Instant lastModified) { |
super(path, name, lastModified); |
} |
} |
static public final class FileAttrs extends BaseAttrs { |
static protected FileAttrs fromJSON(final String path, final JSONArray array) { |
return new FileAttrs(path, (String) array.get(0), getInstant(array.get(2)), getLong(array.get(1)), (String) array.get(3)); |
} |
private final long size; |
private final String sha256; |
protected FileAttrs(final String path, String name, Instant lastModified, long size, String sha256) { |
super(path, name, lastModified); |
this.size = size; |
this.sha256 = sha256; |
} |
public final long getSize() { |
return this.size; |
} |
public final String getSHA256() { |
return this.sha256; |
} |
public final void saveFile(final InputStream in, final Path localFile) throws IOException { |
// Save to temporary file to avoid overwriting old file with a new invalid one. In |
// same folder for the move. |
final Path tmpFile = Files.createTempFile(localFile.getParent(), "partial", null); |
try { |
final MessageDigest md = this.getSHA256() == null ? null : MessageDigestUtils.getSHA256(); |
try (final BufferedOutputStream fileStream = new BufferedOutputStream(Files.newOutputStream(tmpFile)); |
// |
final OutputStream out = md == null ? fileStream : new DigestOutputStream(fileStream, md)) { |
StreamUtils.copy(in, out); |
} |
if (this.getSize() >= 0) { |
final long savedSize = Files.size(tmpFile); |
if (savedSize != this.getSize()) |
throw new IOException("Expected " + this.getSize() + " bytes but saved " + savedSize); |
} |
if (md != null) { |
final String savedHash = MessageDigestUtils.getHashString(md); |
if (!savedHash.equalsIgnoreCase(this.getSHA256())) |
throw new IOException("Expected hash was " + this.getSHA256() + " but saved " + savedHash); |
} |
Files.move(tmpFile, localFile, StandardCopyOption.REPLACE_EXISTING); |
} finally { |
Files.deleteIfExists(tmpFile); |
} |
if (this.getLastModified().compareTo(Instant.EPOCH) > 0) |
Files.setLastModifiedTime(localFile, FileTime.from(this.getLastModified())); |
} |
@Override |
public String toString() { |
return super.toString() + " of size " + getSize(); |
} |
} |
static public final class DirContent { |
private final String path; |
private final JSONObject json; |
protected DirContent(final String path, JSONObject json) { |
super(); |
this.path = path; |
this.json = json; |
} |
public final List<FileAttrs> getFiles() { |
return this.getFiles(null); |
} |
public final List<FileAttrs> getFiles(final Predicate<String> namePredicate) { |
return this.getContent("files", namePredicate, FileAttrs::fromJSON); |
} |
public final List<DirAttrs> getDirs() { |
return this.getDirs(null); |
} |
public final List<DirAttrs> getDirs(final Predicate<String> namePredicate) { |
return this.getContent("dirs", namePredicate, DirAttrs::fromJSON); |
} |
protected final <T extends BaseAttrs> List<T> getContent(final String key, final Predicate<String> namePredicate, final BiFunction<String, JSONArray, T> create) { |
final JSONArray files = (JSONArray) this.json.get(key); |
if (files == null) |
return Collections.emptyList(); |
final List<T> res = new ArrayList<>(); |
for (final Object f : files) { |
final JSONArray array = (JSONArray) f; |
if (namePredicate == null || namePredicate.test((String) array.get(0))) { |
res.add(create.apply(this.path, array)); |
} |
} |
return res; |
} |
} |
private final String url; |
private SSLSocketFactory socketFactory; |
private String token; |
private boolean throwException = true; |
public SimpleSyncClient(final String url) { |
this.url = url; |
} |
public final SSLSocketFactory getSocketFactory() { |
return this.socketFactory; |
} |
public final void setSocketFactory(SSLSocketFactory socketFactory) { |
this.socketFactory = socketFactory; |
} |
public final void setToken(String token) { |
this.token = token; |
} |
public final boolean hasToken() { |
return this.getToken() != null; |
} |
protected final String getToken() { |
return this.token; |
} |
public final void setThrowException(boolean throwException) { |
this.throwException = throwException; |
} |
public final boolean throwsException() { |
return this.throwException; |
} |
protected Response checkResponseCode(final HttpsURLConnection con) throws IOException { |
return checkResponseCode(con, null); |
} |
protected Response checkResponseCode(final HttpsURLConnection con, final Set<Integer> okCodes) throws IOException { |
final Response res = Response.create(con, okCodes); |
if (this.throwsException() && !res.isSuccess()) |
throw new ServerException(res.getCode(), con.getHeaderField("WWW-Authenticate") != null); |
return res; |
} |
private final HttpsURLConnection openConnection(final String path) throws IOException { |
final HttpsURLConnection con = (HttpsURLConnection) new URL(this.url + path).openConnection(); |
con.setRequestProperty("Accept-Encoding", "gzip"); |
if (this.getSocketFactory() != null) |
con.setSSLSocketFactory(this.getSocketFactory()); |
if (getToken() != null) |
con.setRequestProperty("Authorization", "Bearer " + Base64.getEncoder().encodeToString(getToken().getBytes(StandardCharsets.UTF_8))); |
return con; |
} |
private final InputStream getInputStream(final HttpsURLConnection con) throws IOException { |
return "gzip".equals(con.getContentEncoding()) ? new GZIPInputStream(con.getInputStream()) : con.getInputStream(); |
} |
private final HttpsURLConnection send(final HttpsURLConnection con, final String params) throws IOException { |
return this.send(con, params.getBytes(StandardCharsets.UTF_8), false); |
} |
private final HttpsURLConnection send(final HttpsURLConnection con, final byte[] toSend, final boolean allowGzip) throws IOException { |
final boolean useGzip = allowGzip && toSend.length >= MIN_GZIP_SIZE; |
if (useGzip) |
con.setRequestProperty("Content-Encoding", "gzip"); |
con.setRequestMethod("POST"); |
con.setDoOutput(true); |
try (final OutputStream o = useGzip ? new GZIPOutputStream(con.getOutputStream()) : con.getOutputStream()) { |
o.write(toSend); |
} |
return con; |
} |
public DirContent getDir(final String path) throws Exception { |
final HttpsURLConnection con = openConnection("/getDir"); |
final Response res = checkResponseCode(send(con, "rp=" + path + "&type=json")); |
if (!res.isSuccess()) |
return null; |
final JSONParser p = new JSONParser(JSONParser.MODE_STRICTEST); |
try (final InputStream in = getInputStream(con)) { |
return new DirContent(path, (JSONObject) p.parse(in)); |
} |
} |
@FunctionalInterface |
static public interface FileConsumer { |
public void accept(FileAttrs attrs, InputStream fileStream) throws IOException; |
} |
static private final Set<Integer> GETFILE_OK_CODES = CollectionUtils.createSet(200, 404); |
public Response getFile(final String path, final String fileName, final FileConsumer fileConsumer) throws IOException { |
final HttpsURLConnection con = openConnection("/get"); |
send(con, "rn=" + fileName + "&rp=" + path); |
final Response res = checkResponseCode(con, GETFILE_OK_CODES); |
if (res.getCode() == 404) { |
fileConsumer.accept(null, null); |
} else if (res.getCode() == 200) { |
final FileAttrs fileAttrs = new FileAttrs(path, fileName, Instant.ofEpochMilli(con.getLastModified()), -1, con.getHeaderField("X-SHA256")); |
try (final InputStream in = getInputStream(con)) { |
fileConsumer.accept(fileAttrs, in); |
} |
} |
return res; |
} |
// ATTN contrary to other methods, the result isn't if the request was OK : it ignores |
// throwsException() and always throws. The return value is true if the file existed and was |
// saved. |
public boolean saveFile(final String path, final String fileName, final Path localFile) throws IOException { |
final AtomicBoolean missing = new AtomicBoolean(true); |
final Response res = this.getFile(path, fileName, (fileAttrs, in) -> { |
missing.set(fileAttrs == null); |
if (!missing.get()) { |
fileAttrs.saveFile(in, localFile); |
} |
}); |
if (!res.isSuccess()) |
throw new IOException("Couldn't retrieve file " + fileName); |
return !missing.get(); |
} |
public Response deleteFile(final String path, final String fileName) throws MalformedURLException, IOException, ProtocolException, UnsupportedEncodingException { |
final HttpsURLConnection con = openConnection("/delete"); |
return checkResponseCode(send(con, "rn=" + fileName + "&rp=" + path)); |
} |
public Response sendFile(String path, File localFile) throws Exception, MalformedURLException, IOException, ProtocolException { |
byte[] newsha256 = HashWriter.getHash(localFile); |
long size = localFile.length(); |
final HttpsURLConnection con = openConnection("/put"); |
// We use Base64 because headers are not supporting UTF8 |
con.setRequestProperty("X_FILENAME_B64", Base64.getEncoder().encodeToString(localFile.getName().getBytes(StandardCharsets.UTF_8))); |
con.setRequestProperty("X_PATH_B64", Base64.getEncoder().encodeToString(path.getBytes(StandardCharsets.UTF_8))); |
con.setRequestProperty("X_FILESIZE", String.valueOf(size)); |
con.setRequestProperty("X_SHA256", HashWriter.bytesToHex(newsha256)); |
con.setRequestProperty("X-Last-Modified-ms", String.valueOf(localFile.lastModified())); |
return checkResponseCode(send(con, Files.readAllBytes(localFile.toPath()), true)); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/i18n/TranslationManager.java |
---|
25,16 → 25,17 |
import java.util.Map; |
import java.util.ResourceBundle.Control; |
import javax.xml.XMLConstants; |
import javax.xml.parsers.DocumentBuilder; |
import javax.xml.parsers.DocumentBuilderFactory; |
import net.jcip.annotations.GuardedBy; |
import net.jcip.annotations.ThreadSafe; |
import org.w3c.dom.Document; |
import org.w3c.dom.Element; |
import org.w3c.dom.NodeList; |
import net.jcip.annotations.GuardedBy; |
import net.jcip.annotations.ThreadSafe; |
@ThreadSafe |
public class TranslationManager { |
private static final Locale FALLBACK_LOCALE = Locale.ENGLISH; |
64,7 → 65,7 |
@GuardedBy("classes") |
private Locale locale; |
private final Object trMutex = new String("translations mutex"); |
private final Object trMutex = new Object(); |
@GuardedBy("trMutex") |
private Map<String, String> menuTranslation; |
@GuardedBy("trMutex") |
73,7 → 74,7 |
private Map<String, String> actionTranslation; |
private TranslationManager() { |
this.classes = new ArrayList<Class<?>>(); |
this.classes = new ArrayList<>(); |
} |
public void addTranslationStreamFromClass(Class<?> c) { |
164,10 → 165,10 |
private void loadAllTranslation() { |
synchronized (this.trMutex) { |
this.menuTranslation = new HashMap<String, String>(); |
this.itemTranslation = new HashMap<String, String>(); |
this.actionTranslation = new HashMap<String, String>(); |
if (this.classes.size() == 0) { |
this.menuTranslation = new HashMap<>(); |
this.itemTranslation = new HashMap<>(); |
this.actionTranslation = new HashMap<>(); |
if (this.classes.isEmpty()) { |
Log.get().warning("TranslationManager has no resources to load (" + this.getLocale() + ")"); |
} |
for (Class<?> c : this.classes) { |
182,7 → 183,7 |
// return all existing (e.g fr_CA only specify differences with fr) |
private List<InputStream> findStream(final Locale locale, final Class<?> c, final boolean rootLast) { |
final Control cntrl = CONTROL; |
final List<InputStream> res = new ArrayList<InputStream>(); |
final List<InputStream> res = new ArrayList<>(); |
final String baseName = c.getPackage().getName() + "." + BASENAME; |
// test emptiness to not mix languages |
203,7 → 204,7 |
// we want more specific translations to replace general ones, i.e. root Locale first |
for (final InputStream input : findStream(l, c, false)) { |
// create new instances to check if there's no duplicates in each resource |
final Map<String, String> menuTranslation = new HashMap<String, String>(), itemTranslation = new HashMap<String, String>(), actionTranslation = new HashMap<String, String>(); |
final Map<String, String> menuTranslation = new HashMap<>(), itemTranslation = new HashMap<>(), actionTranslation = new HashMap<>(); |
loadTranslation(input, menuTranslation, itemTranslation, actionTranslation); |
// on the other hand, it's OK for one resource to override another |
this.menuTranslation.putAll(menuTranslation); |
214,10 → 215,14 |
return translationLoaded; |
} |
static private void loadTranslation(final InputStream input, final Map<String, String> menuTranslation, final Map<String, String> itemTranslation, final Map<String, String> actionTranslation) { |
private static void loadTranslation(final InputStream input, final Map<String, String> menuTranslation, final Map<String, String> itemTranslation, final Map<String, String> actionTranslation) { |
// FIXME : l'implementation de Java est lente |
// com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl : 60 ms! |
// On pourrait passer à 1ms avec Piccolo... |
final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); |
try { |
dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); |
dbFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); |
final DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); |
final Document doc = dBuilder.parse(input); |
// Menus |
239,7 → 244,7 |
} |
} |
static private void loadTranslation(final Document doc, final String tagName, final Map<String, String> m) { |
private static void loadTranslation(final Document doc, final String tagName, final Map<String, String> m) { |
final NodeList menuChildren = doc.getElementsByTagName(tagName); |
final int size = menuChildren.getLength(); |
for (int i = 0; i < size; i++) { |
/trunk/OpenConcerto/src/org/openconcerto/xml/XMLDecoderJDOM.java |
---|
New file |
0,0 → 1,74 |
/* |
* 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.xml; |
import java.beans.XMLDecoder; |
import java.beans.XMLEncoder; |
import java.util.Iterator; |
import org.jdom2.Element; |
/** |
* To encode and decode using {@link XMLEncoder} and {@link XMLDecoder}. |
* |
* @author Sylvain CUAZ |
*/ |
public final class XMLDecoderJDOM extends AbstractXMLDecoder<Element, RuntimeException> { |
@Override |
protected String getAttributeValue(Element elem, String attrName) { |
return elem.getAttributeValue(attrName); |
} |
@Override |
protected String getLocalName(Element elem) { |
return elem.getName(); |
} |
@Override |
protected String getElementText(Element elem) { |
return elem.getText(); |
} |
@Override |
protected Element getFirstChild(Element elem) { |
return elem.getChildren().get(0); |
} |
@Override |
protected String toString(Element elem) { |
return JDOM2Utils.output(elem); |
} |
@Override |
protected Children<Element> createChildren(final Element elem) { |
return new Children<Element>() { |
private final Iterator<Element> iter = elem.getChildren().iterator(); |
@Override |
public Element getNextChild() { |
if (!this.iter.hasNext()) |
return null; |
final Element res = this.iter.next(); |
assert res != null; |
return res; |
} |
}; |
} |
protected XMLDecoderJDOM() { |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/xml/AbstractXMLDecoder.java |
---|
New file |
0,0 → 1,381 |
/* |
* 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.xml; |
import org.openconcerto.utils.StringUtils; |
import org.openconcerto.utils.cache.CacheResult; |
import org.openconcerto.utils.cache.ICache; |
import org.openconcerto.utils.cc.ExnTransformer; |
import java.beans.XMLDecoder; |
import java.beans.XMLEncoder; |
import java.lang.reflect.Array; |
import java.lang.reflect.Constructor; |
import java.lang.reflect.InvocationTargetException; |
import java.lang.reflect.Method; |
import java.util.ArrayList; |
import java.util.HashMap; |
import java.util.LinkedList; |
import java.util.List; |
import java.util.Map; |
import java.util.Stack; |
/** |
* To decode XML in {@link XMLEncoder} format. |
* |
* @author Sylvain CUAZ |
* @param <S> type of source |
* @param <E> type of exception |
*/ |
public abstract class AbstractXMLDecoder<S, E extends Exception> { |
protected static interface Children<C> { |
C getNextChild(); |
} |
private static final ICache<Object, Method, Object> cache = new ICache<Object, Method, Object>(60, -1, "methods for " + XMLCodecUtils.class); |
private static final ICache<Object, Constructor<?>, Object> cacheCtor = new ICache<Object, Constructor<?>, Object>(60, -1, "constructors for " + XMLCodecUtils.class); |
protected abstract String getLocalName(S elem); |
protected abstract String getAttributeValue(S elem, final String attrName); |
protected abstract String getElementText(S elem) throws E; |
protected abstract S getFirstChild(S elem); |
protected abstract String toString(S elem); |
protected abstract Children<S> createChildren(S elem) throws E; |
public final <K, V> Map<K, V> decodeFromArray(final S elem, final Class<K> keyClass, final Class<V> valueClass) { |
return XMLCodecUtils.decodeFromArray((Object[]) this.decode1(elem), keyClass, valueClass); |
} |
/** |
* Tries to decode an xml element parsed from a string obtained from XMLEncoder. This doesn't |
* use {@link XMLDecoder} as it requires outputting it first to string which is inefficient. |
* NOTE: this decoder supports only a subset of XMLDecoder. |
* |
* @param javaElem a "java" element. |
* @return the decoded object. |
*/ |
public final Object decode1(S javaElem) { |
final S elem = getFirstChild(javaElem); |
try { |
return eval(elem, new Stack<Object>(), new HashMap<String, Object>()); |
} catch (Exception e) { |
throw new IllegalStateException("error decoding " + toString(javaElem), e); |
} |
} |
private final Object eval(S elem, Stack<Object> context, final Map<String, Object> ids) |
throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, E { |
preEval(elem); |
final Object res = this._eval(elem, context, ids); |
postEval(elem, res); |
return res; |
} |
protected void preEval(S elem) throws E { |
} |
protected void nullDecoded(S elem) throws E { |
} |
protected void idRefDecoded(S elem) throws E { |
} |
protected void postEval(S elem, final Object res) throws E { |
} |
private final Object _eval(S elem, Stack<Object> context, final Map<String, Object> ids) |
throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, E { |
final String n = getLocalName(elem); |
// Ordered from real world scenario |
// string : 80k |
// void : 53k |
// int : 18k |
// object : 9k |
// null : 6k |
switch (n) { |
case "string": |
return getElementText(elem); |
case "void": |
case "object": |
final String idref = getAttributeValue(elem, "idref"); |
if (idref != null) { |
if (!ids.containsKey(idref)) |
throw new IllegalStateException("id '" + idref + "' wasn't defined"); |
idRefDecoded(elem); |
return ids.get(idref); |
} |
final String id = getAttributeValue(elem, "id"); |
final String targetClass = getAttributeValue(elem, "class"); |
final Object target = targetClass == null ? context.peek() : Class.forName(targetClass); |
final String propAttr = getAttributeValue(elem, "property"); |
final String indexAttr = getAttributeValue(elem, "index"); |
final String methodAttr = getAttributeValue(elem, "method"); |
// statement or expression |
final Object res = evalContainer(elem, context, ids, new ExnTransformer<List<Object>, Object, Exception>() { |
@Override |
public Object transformChecked(List<Object> args) throws Exception { |
// call the statement |
final Object res; |
if (propAttr != null) { |
final String methodName = (args.size() == 0 ? "get" : "set") + StringUtils.firstUp(propAttr); |
res = invoke(target, methodName, args); |
} else if (indexAttr != null) { |
final String methodName; |
if (target instanceof List) { |
methodName = args.size() == 0 ? "get" : "set"; |
// get(index) or set(index, value) |
args.add(0, Integer.valueOf(indexAttr)); |
res = invoke(target, methodName, args); |
} else if (target.getClass().isArray()) { |
final Class<?> componentType = target.getClass().getComponentType(); |
// in Array there's set(array, int index, Object value) or |
// setPrimitive(array, int index, primitive value) |
methodName = (args.size() == 0 ? "get" : "set") + (componentType.isPrimitive() ? StringUtils.firstUp(componentType.getSimpleName()) : ""); |
args.add(0, target); |
args.add(1, Integer.valueOf(indexAttr)); |
res = invoke(Array.class, methodName, args); |
} else |
throw new IllegalStateException("use index with neither List nor array: " + target); |
} else if (methodAttr != null) { |
res = invoke(target, methodAttr, args); |
} else |
res = getCtor((Class<?>) target, args).newInstance(args.toArray()); |
return res; |
} |
}); |
// not very functional but it works |
if (id != null) |
ids.put(id, res); |
return res; |
case "int": |
return Integer.valueOf(getElementText(elem)); |
case "null": |
nullDecoded(elem); |
return null; |
case "boolean": |
return Boolean.valueOf(getElementText(elem)); |
case "byte": |
return Byte.valueOf(getElementText(elem)); |
case "char": |
return Character.valueOf(getElementText(elem).charAt(0)); |
case "short": |
return Short.valueOf(getElementText(elem)); |
case "long": |
return Long.valueOf(getElementText(elem)); |
case "float": |
return Float.valueOf(getElementText(elem)); |
case "double": |
return Double.valueOf(getElementText(elem)); |
case "array": |
final String classAttr = getAttributeValue(elem, "class"); |
final String lengthAttr = getAttributeValue(elem, "length"); |
final Class<?> componentClass = parseClassName(classAttr); |
if (lengthAttr != null) { |
context.push(Array.newInstance(componentClass, Integer.parseInt(lengthAttr))); |
final Children<S> children = createChildren(elem); |
S child; |
while ((child = children.getNextChild()) != null) { |
eval(child, context, ids); |
} |
return context.pop(); |
} else { |
final List<Object> items = new LinkedList<>(); |
final Children<S> children = createChildren(elem); |
S child; |
while ((child = children.getNextChild()) != null) { |
items.add(eval(child, context, ids)); |
} |
final Object resArray = Array.newInstance(componentClass, items.size()); |
int i = 0; |
for (final Object item : items) |
Array.set(resArray, i++, item); |
return resArray; |
} |
case "class": |
return Class.forName(getElementText(elem)); |
default: |
throw new UnsupportedOperationException("doesn't yet support " + n); |
} |
} |
private final Object evalContainer(final S parent, Stack<Object> context, final Map<String, Object> ids, final ExnTransformer<List<Object>, Object, ? extends Exception> transf) |
throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, E { |
final List<Object> args = new ArrayList<Object>(); |
final Children<S> children = createChildren(parent); |
boolean noVoid = true; |
S child = null; |
while (noVoid && (child = children.getNextChild()) != null) { |
if (getLocalName(child).equals("void")) |
noVoid = false; |
else { |
args.add(eval(child, context, ids)); |
} |
} |
// call the statement |
final Object res = transf.transformCheckedWithExn(args, false, InvocationTargetException.class, InstantiationException.class, IllegalAccessException.class); |
context.push(res); |
// now call the voids |
if (child != null) { |
do { |
eval(child, context, ids); |
} while ((child = children.getNextChild()) != null); |
} |
return context.pop(); |
} |
private static final Object invoke(final Object target, String methodName, final List<Object> args) throws IllegalAccessException, InvocationTargetException { |
// <object class="Cell" method="createEmpty" > |
// for static methods the target is already a class |
final Class clazz = target instanceof Class ? (Class) target : target.getClass(); |
final Method m = getMethod(clazz, methodName, args); |
return m.invoke(target, args.toArray()); |
} |
private static final Method getMethod(Class<?> clazz, String name, List<Object> actualArgs) { |
final List<Class<?>> actualClasses = objectsToClasses(actualArgs); |
final List<Object> key = new ArrayList<Object>(3); |
key.add(clazz); |
key.add(name); |
key.add(actualClasses); |
final CacheResult<Method> cacheRes = cache.check(key); |
if (cacheRes.getState() == CacheResult.State.VALID) |
return cacheRes.getRes(); |
final Method res = findMethod(clazz, name, actualClasses); |
if (res == null) |
throw new IllegalStateException("No matching method " + name + " found in " + clazz); |
cache.put(key, res); |
return res; |
} |
private static final Constructor getCtor(Class<?> clazz, List<Object> actualArgs) { |
final List<Class<?>> actualClasses = objectsToClasses(actualArgs); |
final List<Object> key = new ArrayList<Object>(3); |
key.add(clazz); |
key.add(actualClasses); |
final CacheResult<Constructor<?>> cacheRes = cacheCtor.check(key); |
if (cacheRes.getState() == CacheResult.State.VALID) |
return cacheRes.getRes(); |
final Constructor res = findCtor(clazz, actualClasses); |
cacheCtor.put(key, res); |
return res; |
} |
private static final List<Class<?>> objectsToClasses(List<Object> actualArgs) { |
final List<Class<?>> actualClasses = new ArrayList<Class<?>>(actualArgs.size()); |
for (final Object actualArg : actualArgs) |
actualClasses.add(actualArg == null ? null : actualArg.getClass()); |
return actualClasses; |
} |
// TODO return the most specific matching method instead of the first one |
// (handle both Sub/Superclass and primitive/object type) |
private static final Method findMethod(Class<?> clazz, String name, List<Class<?>> actualArgs) { |
for (final Method m : clazz.getMethods()) { |
if (m.getName().equals(name) && callableWith(m.getParameterTypes(), actualArgs)) { |
return m; |
} |
} |
return null; |
} |
// TODO see findMethod() |
private static final Constructor findCtor(Class<?> clazz, List<Class<?>> actualArgs) { |
for (final Constructor m : clazz.getConstructors()) { |
if (callableWith(m.getParameterTypes(), actualArgs)) { |
return m; |
} |
} |
return null; |
} |
private static final boolean callableWith(Class<?>[] formalArgs, List<Class<?>> actualArgs) { |
if (formalArgs.length != actualArgs.size()) |
return false; |
int i = 0; |
for (final Class<?> argClass : formalArgs) { |
final Class<?> actualArg = actualArgs.get(i); |
// null match everything |
if (actualArg != null && !argClass.isAssignableFrom(actualArg) && argClass != getPrimitive(actualArg)) |
return false; |
i++; |
} |
return true; |
} |
private static Class<?> getPrimitive(Class<?> argClass) { |
if (argClass == Boolean.class) |
return Boolean.TYPE; |
else if (argClass == Character.class) |
return Character.TYPE; |
else if (argClass == Byte.class) |
return Byte.TYPE; |
else if (argClass == Short.class) |
return Short.TYPE; |
else if (argClass == Integer.class) |
return Integer.TYPE; |
else if (argClass == Long.class) |
return Long.TYPE; |
else if (argClass == Float.class) |
return Float.TYPE; |
else if (argClass == Double.class) |
return Double.TYPE; |
else |
return null; |
} |
private static final Map<String, Class> primitiveNames = new HashMap<String, Class>(); |
static { |
primitiveNames.put("boolean", boolean.class); |
primitiveNames.put("byte", byte.class); |
primitiveNames.put("char", char.class); |
primitiveNames.put("short", short.class); |
primitiveNames.put("int", int.class); |
primitiveNames.put("long", long.class); |
primitiveNames.put("float", float.class); |
primitiveNames.put("double", double.class); |
} |
/** |
* Parse class names (including primitive). |
* |
* @param className a class name, eg "java.lang.String" or "int". |
* @return the matching class, eg java.lang.String.class or Integer.TYPE. |
* @throws ClassNotFoundException if the passed name doesn't exist. |
*/ |
private static Class<?> parseClassName(String className) throws ClassNotFoundException { |
final Class<?> primitive = primitiveNames.get(className); |
if (primitive != null) |
return primitive; |
else |
return Class.forName(className); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/xml/XMLCodecUtils.java |
---|
13,11 → 13,6 |
package org.openconcerto.xml; |
import org.openconcerto.utils.StringUtils; |
import org.openconcerto.utils.cache.CacheResult; |
import org.openconcerto.utils.cache.ICache; |
import org.openconcerto.utils.cc.ExnTransformer; |
import java.awt.Dimension; |
import java.awt.Point; |
import java.awt.Rectangle; |
35,11 → 30,8 |
import java.io.ByteArrayOutputStream; |
import java.io.IOException; |
import java.lang.reflect.Array; |
import java.lang.reflect.Constructor; |
import java.lang.reflect.InvocationTargetException; |
import java.lang.reflect.Method; |
import java.nio.charset.Charset; |
import java.util.ArrayList; |
import java.util.Collection; |
import java.util.HashMap; |
import java.util.List; |
47,7 → 39,6 |
import java.util.Map.Entry; |
import java.util.RandomAccess; |
import java.util.Set; |
import java.util.Stack; |
import org.jdom2.Element; |
import org.jdom2.JDOMException; |
62,9 → 53,6 |
private static final String END_DECL = "?>"; |
private static final ICache<Object, Method, Object> cache = new ICache<Object, Method, Object>(60, -1, "methods for " + XMLCodecUtils.class); |
private static final ICache<Object, Constructor<?>, Object> cacheCtor = new ICache<Object, Constructor<?>, Object>(60, -1, "constructors for " + XMLCodecUtils.class); |
// the same as XMLEncoder |
private static final Charset CS = Charset.forName("UTF-8"); |
85,6 → 73,9 |
} |
}; |
public static final XMLDecoderJDOM XML_DECODER_JDOM = new XMLDecoderJDOM(); |
public static final XMLDecoderStAX XML_DECODER_STAX = new XMLDecoderStAX(); |
/** |
* Register a {@link PersistenceDelegate} for the passed class. This method tries to set |
* <code>del</code> as the default for any subsequent {@link Encoder}, but with the current JRE |
130,7 → 121,46 |
return res; |
} |
public static final String encodeAsArray(final Map<?, ?> m) { |
return encodeAsArray(m, new StringBuilder(1024)).toString(); |
} |
/** |
* Encode a map as an array. Useful since parsing an array is faster than parsing a map. |
* |
* @param m the map to encode. |
* @param sb where to encode. |
* @return <code>sb</code>. |
* @see AbstractXMLDecoder#decodeFromArray(Object, Class, Class) |
*/ |
public static final StringBuilder encodeAsArray(final Map<?, ?> m, final StringBuilder sb) { |
final Object[] array = new Object[m.size() * 2]; |
int i = 0; |
for (final Entry<?, ?> e : m.entrySet()) { |
array[i++] = e.getKey(); |
array[i++] = e.getValue(); |
} |
assert i == array.length; |
return encodeSimple(array, sb); |
} |
public static final <K, V> Map<K, V> decodeFromArray(final Object[] array, final Class<K> keyClass, final Class<V> valueClass) { |
return decodeFromArray(array, keyClass, valueClass, null); |
} |
public static final <K, V> Map<K, V> decodeFromArray(final Object[] array, final Class<K> keyClass, final Class<V> valueClass, Map<K, V> m) { |
final int l = array.length; |
if (m == null) |
m = new HashMap<K, V>((int) (l / 2 / 0.8f) + 1, 0.8f); |
for (int i = 0; i < l; i += 2) { |
final K key = keyClass.cast(array[i]); |
final V value = valueClass.cast(array[i + 1]); |
m.put(key, value); |
} |
return m; |
} |
/** |
* Encodes an object using {@link XMLEncoder}, stripping the XML declaration. |
* |
* @param o the object to encode. |
153,10 → 183,14 |
*/ |
public static final String encodeSimple(Object o) { |
final StringBuilder sb = new StringBuilder(256); |
return encodeSimple(o, sb).toString(); |
} |
public static final StringBuilder encodeSimple(final Object o, final StringBuilder sb) { |
sb.append("<java version=\"1.6.0\" class=\"java.beans.XMLDecoder\">"); |
encodeSimpleRec(o, sb); |
sb.append("</java>"); |
return sb.toString(); |
return sb; |
} |
private static final void createElemEscaped(final String elemName, final Object o, final StringBuilder sb) { |
361,287 → 395,9 |
* @return the decoded object. |
*/ |
public static final Object decode1(Element javaElem) { |
final Element elem = (Element) javaElem.getChildren().get(0); |
try { |
return eval(elem, new Stack<Object>(), new HashMap<String, Object>()); |
} catch (Exception e) { |
throw new IllegalStateException("error decoding " + JDOM2Utils.output(javaElem), e); |
} |
return XML_DECODER_JDOM.decode1(javaElem); |
} |
private static final Object eval(Element elem, Stack<Object> context, final Map<String, Object> ids) |
throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException { |
final String n = elem.getName(); |
// Ordered from real world scenario |
// string : 80k |
// void : 53k |
// int : 18k |
// object : 9k |
// null : 6k |
if (n.equals("string")) { |
return elem.getText(); |
} else if (n.equals("void") || n.equals("object")) { |
final String idref = elem.getAttributeValue("idref"); |
if (idref != null) { |
if (!ids.containsKey(idref)) |
throw new IllegalStateException("id '" + idref + "' wasn't defined"); |
return ids.get(idref); |
} |
final String id = elem.getAttributeValue("id"); |
final String targetClass = elem.getAttributeValue("class"); |
final Object target = targetClass == null ? context.peek() : Class.forName(targetClass); |
final String propAttr = elem.getAttributeValue("property"); |
final String indexAttr = elem.getAttributeValue("index"); |
final String methodAttr = elem.getAttributeValue("method"); |
// statement or expression |
final Object res = evalContainer(elem, context, ids, new ExnTransformer<List<Object>, Object, Exception>() { |
@Override |
public Object transformChecked(List<Object> args) throws Exception { |
// call the statement |
final Object res; |
if (propAttr != null) { |
final String methodName = (args.size() == 0 ? "get" : "set") + StringUtils.firstUp(propAttr); |
res = invoke(target, methodName, args); |
} else if (indexAttr != null) { |
final String methodName; |
if (target instanceof List) { |
methodName = args.size() == 0 ? "get" : "set"; |
// get(index) or set(index, value) |
args.add(0, Integer.valueOf(indexAttr)); |
res = invoke(target, methodName, args); |
} else if (target.getClass().isArray()) { |
final Class<?> componentType = target.getClass().getComponentType(); |
// in Array there's set(array, int index, Object value) or |
// setPrimitive(array, int index, primitive value) |
methodName = (args.size() == 0 ? "get" : "set") + (componentType.isPrimitive() ? StringUtils.firstUp(componentType.getSimpleName()) : ""); |
args.add(0, target); |
args.add(1, Integer.valueOf(indexAttr)); |
res = invoke(Array.class, methodName, args); |
} else |
throw new IllegalStateException("use index with neither List nor array: " + target); |
} else if (methodAttr != null) { |
res = invoke(target, methodAttr, args); |
} else |
res = getCtor((Class<?>) target, args).newInstance(args.toArray()); |
return res; |
} |
}); |
// not very functional but it works |
if (id != null) |
ids.put(id, res); |
return res; |
} else if (n.equals("int")) { |
return Integer.valueOf(elem.getText()); |
} else if (n.equals("null")) { |
return null; |
} else if (n.equals("boolean")) { |
return Boolean.valueOf(elem.getText()); |
} else if (n.equals("byte")) { |
return Byte.valueOf(elem.getText()); |
} else if (n.equals("char")) { |
return Character.valueOf(elem.getText().charAt(0)); |
} else if (n.equals("short")) { |
return Short.valueOf(elem.getText()); |
} else if (n.equals("long")) { |
return Long.valueOf(elem.getText()); |
} else if (n.equals("float")) { |
return Float.valueOf(elem.getText()); |
} else if (n.equals("double")) { |
return Double.valueOf(elem.getText()); |
} else if (n.equals("array")) { |
final String classAttr = elem.getAttributeValue("class"); |
final String lengthAttr = elem.getAttributeValue("length"); |
final Class<?> componentClass = parseClassName(classAttr); |
if (lengthAttr != null) { |
context.push(Array.newInstance(componentClass, Integer.parseInt(lengthAttr))); |
for (final Object child : elem.getChildren()) { |
eval((Element) child, context, ids); |
} |
return context.pop(); |
} else { |
return evalContainer(elem, context, ids, new ExnTransformer<List<Object>, Object, RuntimeException>() { |
@Override |
public Object transformChecked(List<Object> args) { |
final Object res = Array.newInstance(componentClass, args.size()); |
for (int j = 0; j < args.size(); j++) { |
Array.set(res, j, args.get(j)); |
} |
return res; |
} |
}); |
} |
} else if (n.equals("class")) { |
return Class.forName(elem.getText()); |
} else |
throw new UnsupportedOperationException("doesn't yet support " + n); |
} |
private static final Object evalContainer(final Element parent, Stack<Object> context, final Map<String, Object> ids, final ExnTransformer<List<Object>, Object, ? extends Exception> transf) |
throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException { |
final List<Object> args = new ArrayList<Object>(); |
final List<?> children = parent.getChildren(); |
int i = 0; |
boolean noVoid = true; |
final int size = children.size(); |
while (i < size && noVoid) { |
final Element child = (Element) children.get(i); |
if (child.getName().equals("void")) |
noVoid = false; |
else { |
args.add(eval(child, context, ids)); |
i++; |
} |
} |
// call the statement |
final Object res = transf.transformCheckedWithExn(args, false, InvocationTargetException.class, InstantiationException.class, IllegalAccessException.class); |
context.push(res); |
// now call the voids |
while (i < children.size()) { |
final Element child = (Element) children.get(i); |
eval(child, context, ids); |
i++; |
} |
return context.pop(); |
} |
private static final Object invoke(final Object target, String methodName, final List<Object> args) throws IllegalAccessException, InvocationTargetException { |
// <object class="Cell" method="createEmpty" > |
// for static methods the target is already a class |
final Class clazz = target instanceof Class ? (Class) target : target.getClass(); |
final Method m = getMethod(clazz, methodName, args); |
return m.invoke(target, args.toArray()); |
} |
private static final Method getMethod(Class<?> clazz, String name, List<Object> actualArgs) { |
final List<Class<?>> actualClasses = objectsToClasses(actualArgs); |
final List<Object> key = new ArrayList<Object>(3); |
key.add(clazz); |
key.add(name); |
key.add(actualClasses); |
final CacheResult<Method> cacheRes = cache.check(key); |
if (cacheRes.getState() == CacheResult.State.VALID) |
return cacheRes.getRes(); |
final Method res = findMethod(clazz, name, actualClasses); |
cache.put(key, res); |
return res; |
} |
private static final Constructor getCtor(Class<?> clazz, List<Object> actualArgs) { |
final List<Class<?>> actualClasses = objectsToClasses(actualArgs); |
final List<Object> key = new ArrayList<Object>(3); |
key.add(clazz); |
key.add(actualClasses); |
final CacheResult<Constructor<?>> cacheRes = cacheCtor.check(key); |
if (cacheRes.getState() == CacheResult.State.VALID) |
return cacheRes.getRes(); |
final Constructor res = findCtor(clazz, actualClasses); |
cacheCtor.put(key, res); |
return res; |
} |
private static final List<Class<?>> objectsToClasses(List<Object> actualArgs) { |
final List<Class<?>> actualClasses = new ArrayList<Class<?>>(actualArgs.size()); |
for (final Object actualArg : actualArgs) |
actualClasses.add(actualArg == null ? null : actualArg.getClass()); |
return actualClasses; |
} |
// TODO return the most specific matching method instead of the first one |
// (handle both Sub/Superclass and primitive/object type) |
private static final Method findMethod(Class<?> clazz, String name, List<Class<?>> actualArgs) { |
for (final Method m : clazz.getMethods()) { |
if (m.getName().equals(name) && callableWith(m.getParameterTypes(), actualArgs)) { |
return m; |
} |
} |
return null; |
} |
// TODO see findMethod() |
private static final Constructor findCtor(Class<?> clazz, List<Class<?>> actualArgs) { |
for (final Constructor m : clazz.getConstructors()) { |
if (callableWith(m.getParameterTypes(), actualArgs)) { |
return m; |
} |
} |
return null; |
} |
private static final boolean callableWith(Class<?>[] formalArgs, List<Class<?>> actualArgs) { |
if (formalArgs.length != actualArgs.size()) |
return false; |
int i = 0; |
for (final Class<?> argClass : formalArgs) { |
final Class<?> actualArg = actualArgs.get(i); |
// null match everything |
if (actualArg != null && !argClass.isAssignableFrom(actualArg) && argClass != getPrimitive(actualArg)) |
return false; |
i++; |
} |
return true; |
} |
private static Class<?> getPrimitive(Class<?> argClass) { |
if (argClass == Boolean.class) |
return Boolean.TYPE; |
else if (argClass == Character.class) |
return Character.TYPE; |
else if (argClass == Byte.class) |
return Byte.TYPE; |
else if (argClass == Short.class) |
return Short.TYPE; |
else if (argClass == Integer.class) |
return Integer.TYPE; |
else if (argClass == Long.class) |
return Long.TYPE; |
else if (argClass == Float.class) |
return Float.TYPE; |
else if (argClass == Double.class) |
return Double.TYPE; |
else |
return null; |
} |
private static final Map<String, Class> primitiveNames = new HashMap<String, Class>(); |
static { |
primitiveNames.put("boolean", boolean.class); |
primitiveNames.put("byte", byte.class); |
primitiveNames.put("char", char.class); |
primitiveNames.put("short", short.class); |
primitiveNames.put("int", int.class); |
primitiveNames.put("long", long.class); |
primitiveNames.put("float", float.class); |
primitiveNames.put("double", double.class); |
} |
/** |
* Parse class names (including primitive). |
* |
* @param className a class name, eg "java.lang.String" or "int". |
* @return the matching class, eg java.lang.String.class or Integer.TYPE. |
* @throws ClassNotFoundException if the passed name doesn't exist. |
*/ |
private static Class<?> parseClassName(String className) throws ClassNotFoundException { |
final Class<?> primitive = primitiveNames.get(className); |
if (primitive != null) |
return primitive; |
else |
return Class.forName(className); |
} |
private XMLCodecUtils() { |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/xml/XMLUtils.java |
---|
New file |
0,0 → 1,133 |
/* |
* 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.xml; |
import javax.xml.stream.XMLStreamConstants; |
import javax.xml.stream.XMLStreamException; |
import javax.xml.stream.XMLStreamReader; |
public class XMLUtils { |
public static final String escapeAttribute(final String value) { |
final int len = value.length(); |
int idx = 0; |
checkloop: while (idx < len) { |
final char ch = value.charAt(idx); |
if (ch == '<' || ch == '>' || ch == '&' || ch == '\r' || ch == '\n' || ch == '"' || ch == '\t') { |
break checkloop; |
} |
idx++; |
} |
if (idx == len) { |
return value; |
} |
final StringBuilder sb = new StringBuilder(len + 5); |
sb.append(value, 0, idx); |
while (idx < len) { |
final char ch = value.charAt(idx++); |
switch (ch) { |
case '<': |
sb.append("<"); |
break; |
case '>': |
sb.append(">"); |
break; |
case '&': |
sb.append("&"); |
break; |
case '\r': |
sb.append("
"); |
break; |
case '"': |
sb.append("""); |
break; |
case '\t': |
sb.append("	"); |
break; |
case '\n': |
sb.append("
"); |
break; |
default: |
sb.append(ch); |
break; |
} |
} |
return sb.toString(); |
} |
public static final String escapeText(final String value) { |
final int right = value.length(); |
int idx = 0; |
checkloop: while (idx < right) { |
final char ch = value.charAt(idx); |
if (ch == '<' || ch == '>' || ch == '&' || ch == '\r' || ch == '\n') { |
break checkloop; |
} |
idx++; |
} |
if (idx == right) { |
// no escape needed. |
return value; |
} |
final StringBuilder sb = new StringBuilder(); |
if (idx > 0) { |
sb.append(value, 0, idx); |
} |
while (idx < right) { |
final char ch = value.charAt(idx++); |
switch (ch) { |
case '<': |
sb.append("<"); |
break; |
case '>': |
sb.append(">"); |
break; |
case '&': |
sb.append("&"); |
break; |
case '\r': |
sb.append("
"); |
break; |
case '\n': |
sb.append('\n'); |
break; |
default: |
sb.append(ch); |
break; |
} |
} |
return sb.toString(); |
} |
public static final void skipToEndElement(final XMLStreamReader reader) throws XMLStreamException { |
if (!reader.isStartElement()) |
throw new IllegalStateException("Not at a start of an element : " + reader.getEventType() + ", " + reader.getLocation()); |
final String name = reader.getLocalName(); |
int depth = 1; |
while (!(depth == 0 && reader.isEndElement() && reader.getLocalName().equals(name))) { |
final int eventType = reader.next(); |
if (eventType == XMLStreamConstants.START_ELEMENT) |
depth++; |
else if (eventType == XMLStreamConstants.END_ELEMENT) |
depth--; |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/xml/XMLDecoderStAX.java |
---|
New file |
0,0 → 1,99 |
/* |
* 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.xml; |
import javax.xml.stream.XMLStreamException; |
import javax.xml.stream.XMLStreamReader; |
/** |
* To decode using {@link XMLStreamReader}. |
* |
* @author Sylvain CUAZ |
*/ |
public final class XMLDecoderStAX extends AbstractXMLDecoder<XMLStreamReader, XMLStreamException> { |
@Override |
protected String getAttributeValue(XMLStreamReader elem, String attrName) { |
return elem.getAttributeValue(null, attrName); |
} |
@Override |
protected String getLocalName(XMLStreamReader elem) { |
return elem.getLocalName(); |
} |
@Override |
protected String getElementText(XMLStreamReader elem) throws XMLStreamException { |
return elem.getElementText(); |
} |
@Override |
protected XMLStreamReader getFirstChild(XMLStreamReader reader) { |
try { |
reader.nextTag(); |
} catch (XMLStreamException e) { |
throw new IllegalStateException("Couldn't advance to first child", e); |
} |
return reader; |
} |
@Override |
protected void preEval(XMLStreamReader reader) throws XMLStreamException { |
assert reader.isStartElement(); |
} |
@Override |
protected void nullDecoded(XMLStreamReader reader) throws XMLStreamException { |
reader.nextTag(); |
} |
@Override |
protected void idRefDecoded(XMLStreamReader reader) throws XMLStreamException { |
reader.nextTag(); |
} |
@Override |
protected void postEval(XMLStreamReader reader, final Object res) throws XMLStreamException { |
assert reader.isEndElement(); |
reader.nextTag(); |
} |
@Override |
protected String toString(XMLStreamReader elem) { |
return elem.getLocation().toString(); |
} |
@Override |
protected Children<XMLStreamReader> createChildren(final XMLStreamReader reader) throws XMLStreamException { |
if (!reader.isStartElement()) |
throw new IllegalStateException("Not at a start of an element : " + reader.getLocation()); |
final String localName = reader.getLocalName(); |
// move from START parent to either : |
// 1. END parent if no children, or |
// 2. START child |
reader.nextTag(); |
return new Children<XMLStreamReader>() { |
@Override |
public XMLStreamReader getNextChild() { |
if (reader.isEndElement() && reader.getLocalName().equals(localName)) { |
return null; |
} |
return reader; |
} |
}; |
} |
protected XMLDecoderStAX() { |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/xml/FastXMLProperties.java |
---|
New file |
0,0 → 1,71 |
/* |
* 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.xml; |
import java.io.BufferedInputStream; |
import java.io.IOException; |
import java.io.InputStream; |
import java.io.OutputStream; |
import java.io.PrintStream; |
import java.util.Properties; |
import org.jdom2.Document; |
import org.jdom2.Element; |
import org.jdom2.input.SAXBuilder; |
import org.jdom2.input.sax.XMLReaderSAX2Factory; |
public class FastXMLProperties { |
public static void load(Properties props, InputStream in) throws IOException { |
final SAXBuilder builder = new SAXBuilder(new XMLReaderSAX2Factory(false, "com.bluecast.xml.Piccolo"), null, null); |
try { |
final Document document = builder.build(new BufferedInputStream(in)); |
for (Element element : document.getRootElement().getChildren()) { |
if (element.getName().equals("entry")) { |
props.setProperty(element.getAttributeValue("key"), element.getText()); |
} |
} |
} catch (Exception e) { |
throw new IOException(e); |
} |
} |
/** |
* Fast alternative (<1ms) for Properties.storeToXML (30ms) |
* |
*/ |
public static void store(Properties props, OutputStream out, String comment) throws IOException { |
PrintStream prt = new PrintStream(out, false, "UTF-8"); |
prt.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n"); |
prt.append("<properties>\\r\n"); |
if (comment != null) { |
prt.append("<comment>"); |
prt.append(comment); |
prt.append("</comment>\\r\n"); |
} |
synchronized (props) { |
for (String k : props.stringPropertyNames()) { |
prt.append("<entry key=\""); |
prt.append(XMLUtils.escapeAttribute(k)); |
prt.append("\">"); |
prt.append(XMLUtils.escapeText(props.getProperty(k))); |
prt.append("</entry>\\r\n"); |
} |
} |
prt.append("</properties>"); |
prt.close(); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/panel/compta/ExportFEC.java |
---|
42,10 → 42,10 |
public class ExportFEC extends AbstractExport { |
private static final char ZONE_SEPARATOR = '\t'; |
private static final char RECORD_SEPARATOR = '\n'; |
public static final char ZONE_SEPARATOR = '\t'; |
public static final char RECORD_SEPARATOR = '\n'; |
private static final char REPLACEMENT = ' '; |
static private final List<String> COLS = Arrays.asList("JournalCode", "JournalLib", "EcritureNum", "EcritureDate", "CompteNum", "CompteLib", "CompAuxNum", "CompAuxLib", "PieceRef", "PieceDate", |
public static final List<String> COLS = Arrays.asList("JournalCode", "JournalLib", "EcritureNum", "EcritureDate", "CompteNum", "CompteLib", "CompAuxNum", "CompAuxLib", "PieceRef", "PieceDate", |
"EcritureLib", "Debit", "Credit", "EcritureLet", "DateLet", "ValidDate", "Montantdevise", "Idevise"); |
private final DecimalFormat format = new DecimalFormat("##0.00", DecimalFormatSymbols.getInstance(Locale.FRANCE)); |
/trunk/OpenConcerto/src/org/openconcerto/erp/panel/compta/ExportPanel.java |
---|
87,6 → 87,12 |
return new ExportSageXimport(root); |
} |
}, |
SAGE_ETENDU("Sage Etendu") { |
@Override |
public AbstractExport createExport(DBRoot root) { |
return new ExportSageEtendu(root); |
} |
}, |
CCMX("Cegid CCMX") { |
@Override |
public AbstractExport createExport(DBRoot root) { |
/trunk/OpenConcerto/src/org/openconcerto/erp/panel/compta/ExportSageEtendu.java |
---|
New file |
0,0 → 1,359 |
/* |
* 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.panel.compta; |
import org.openconcerto.erp.core.finance.payment.element.ModeDeReglementSQLElement; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.SQLRowValuesListFetcher; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.utils.GestionDevise; |
import org.openconcerto.utils.StringUtils; |
import org.openconcerto.utils.cc.ITransformer; |
import java.io.IOException; |
import java.io.OutputStream; |
import java.text.DateFormat; |
import java.text.SimpleDateFormat; |
import java.util.Arrays; |
import java.util.Calendar; |
import java.util.Date; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
import org.apache.poi.hssf.usermodel.HSSFSheet; |
import org.apache.poi.hssf.usermodel.HSSFWorkbook; |
import org.apache.poi.ss.usermodel.Cell; |
import org.apache.poi.ss.usermodel.CellStyle; |
import org.apache.poi.ss.usermodel.CellType; |
import org.apache.poi.ss.usermodel.CreationHelper; |
import org.apache.poi.ss.usermodel.Row; |
public class ExportSageEtendu extends AbstractExport { |
private List<SQLRowValues> data; |
private Map<Integer, SQLRowValues> mapFacture = new HashMap<>(); |
private Map<Integer, SQLRowValues> mapAvoir = new HashMap<>(); |
public ExportSageEtendu(DBRoot rootSociete) { |
super(rootSociete, "Sage Etendu", ".xls"); |
} |
@Override |
protected int fetchData(Date from, Date to, SQLRow selectedJournal, boolean onlyNew) { |
final SQLTable tableEcriture = getEcritureT(); |
// Fetch facture |
final SQLTable tableVF = tableEcriture.getTable("SAISIE_VENTE_FACTURE"); |
SQLRowValues rowValsVF = new SQLRowValues(tableVF); |
rowValsVF.put("ID", null); |
rowValsVF.put("DATE", null); |
rowValsVF.put("NOM", null); |
rowValsVF.put("NUMERO", null); |
SQLRowValues rowValsMdr = rowValsVF.putRowValues("ID_MODE_REGLEMENT"); |
rowValsMdr.putNulls(rowValsMdr.getTable().getFieldsName()); |
rowValsMdr.putRowValues("ID_TYPE_REGLEMENT").putNulls("NOM"); |
if (tableVF.contains("ID_ABONNEMENT")) { |
rowValsVF.putRowValues("ID_ABONNEMENT").putNulls("DATE_DEBUT_FACTURE", "DATE_FIN_FACTURE"); |
} |
SQLRowValuesListFetcher fetcherVF = SQLRowValuesListFetcher.create(rowValsVF); |
List<SQLRowValues> resultVF = fetcherVF.fetch(new Where(tableVF.getField("DATE"), from, to)); |
for (SQLRowValues sqlRowValues : resultVF) { |
this.mapFacture.put(sqlRowValues.getID(), sqlRowValues); |
} |
// Fetch avoirs |
final SQLTable tableAvoir = tableEcriture.getTable("AVOIR_CLIENT"); |
SQLRowValues rowValsAvoir = new SQLRowValues(tableAvoir); |
rowValsAvoir.put("ID", null); |
rowValsAvoir.put("DATE", null); |
rowValsAvoir.put("NOM", null); |
rowValsAvoir.put("NUMERO", null); |
SQLRowValues rowValsMdrAvoir = rowValsAvoir.putRowValues("ID_MODE_REGLEMENT"); |
rowValsMdrAvoir.putNulls(rowValsMdrAvoir.getTable().getFieldsName()); |
rowValsMdrAvoir.putRowValues("ID_TYPE_REGLEMENT").putNulls("NOM"); |
SQLRowValuesListFetcher fetcherAvoir = SQLRowValuesListFetcher.create(rowValsAvoir); |
List<SQLRowValues> resultAvoir = fetcherAvoir.fetch(new Where(tableAvoir.getField("DATE"), from, to)); |
for (SQLRowValues sqlRowValues : resultAvoir) { |
this.mapAvoir.put(sqlRowValues.getID(), sqlRowValues); |
} |
final SQLTable tableCompte = tableEcriture.getForeignTable("ID_COMPTE_PCE"); |
SQLRowValues rowValsFetch = new SQLRowValues(tableEcriture); |
rowValsFetch.putNulls("NOM", "DATE", "DEBIT", "CREDIT"); |
if (tableEcriture.contains("CODE_CLIENT")) { |
rowValsFetch.put("CODE_CLIENT", null); |
} |
rowValsFetch.putRowValues("ID_MOUVEMENT").putNulls("NUMERO", "SOURCE", "IDSOURCE").putRowValues("ID_PIECE").put("NOM", null); |
rowValsFetch.putRowValues("ID_COMPTE_PCE").putNulls("NUMERO", "NOM"); |
rowValsFetch.putRowValues("ID_JOURNAL").putNulls("CODE", "NOM"); |
SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowValsFetch); |
fetcher.addSelTransf(new ITransformer<SQLSelect, SQLSelect>() { |
@Override |
public SQLSelect transformChecked(SQLSelect input) { |
input.setWhere(getWhere(from, to, selectedJournal, onlyNew)); |
input.addFieldOrder(input.getAlias(tableEcriture).getField("ID_MOUVEMENT")); |
input.addFieldOrder(input.getAlias(tableCompte).getField("NUMERO")); |
return input; |
} |
}, 0); |
final List<SQLRowValues> l = fetcher.fetch(); |
this.data = l; |
return l == null ? 0 : l.size(); |
} |
@Override |
protected void export(OutputStream bufOut) throws IOException { |
final List<SQLRowValues> l = this.data; |
final boolean containsCodeClient = getEcritureT().contains("CODE_CLIENT"); |
final int size = l.size(); |
HSSFWorkbook workBook = new HSSFWorkbook(); |
HSSFSheet sheet = workBook.createSheet("Ecritures"); |
Row rowEntete = sheet.createRow(0); |
List<String> colName = Arrays.asList("Date d'écriture", "Code Journal", "Numéro de facture", "Référence", "Compte Général", "Compte Client", "Libellé de l'écriture", "Date d'échéance", |
"Mode de règlement", "Montant débiteur", "Montant Créditeur", "Date de début d'abonnement", "Date de fin d'abonnement"); |
int colIndex = 0; |
for (String string : colName) { |
Cell cell = rowEntete.createCell(colIndex, CellType.STRING); |
cell.setCellValue(string); |
colIndex++; |
} |
CellStyle cellStyle = workBook.createCellStyle(); |
CreationHelper createHelper = workBook.getCreationHelper(); |
cellStyle.setDataFormat(createHelper.createDataFormat().getFormat("m/d/yy")); |
for (int i = 0; i < size; i++) { |
Row row = sheet.createRow(i + 1); |
final SQLRowValues rowLine = l.get(i); |
// Date |
final Date d = rowLine.getDate("DATE").getTime(); |
Cell cellDate = row.createCell(0); |
cellDate.setCellStyle(cellStyle); |
cellDate.setCellValue(d); |
// Jrnl |
SQLRowAccessor rowJrnl = rowLine.getForeign("ID_JOURNAL"); |
Cell cellJrnl = row.createCell(1); |
cellJrnl.setCellValue(StringUtils.toAsciiString(rowJrnl.getString("CODE").trim())); |
SQLRowAccessor rowValsSource = null; |
SQLRowAccessor rowMvt = rowLine.getForeign("ID_MOUVEMENT"); |
if (rowMvt.getString("SOURCE").equals("AVOIR_CLIENT")) { |
rowValsSource = this.mapAvoir.get(rowMvt.getInt("IDSOURCE")); |
} else if (rowMvt.getString("SOURCE").equals("SAISIE_VENTE_FACTURE")) { |
rowValsSource = this.mapFacture.get(rowMvt.getInt("IDSOURCE")); |
} |
// Numero Piece |
Cell cellPiece = row.createCell(2); |
if (rowValsSource != null) { |
cellPiece.setCellValue(StringUtils.toAsciiString(rowValsSource.getString("NUMERO"))); |
} |
// Ref vide |
Cell cellRef = row.createCell(3); |
cellRef.setCellValue(""); |
// N° Compte |
final String cpt = rowLine.getForeign("ID_COMPTE_PCE").getString("NUMERO").trim(); |
Cell cellCpt = row.createCell(4, CellType.STRING); |
cellCpt.setCellValue(getFormattedCompte(cpt)); |
Cell cellCodeClient = row.createCell(5); |
if (containsCodeClient) { |
// Code Client |
String codeClient = ""; |
if (cpt.startsWith("41")) { |
codeClient = rowLine.getString("CODE_CLIENT"); |
} |
cellCodeClient.setCellValue(StringUtils.toAsciiString(codeClient)); |
} |
// Libellé |
Cell cellLib = row.createCell(6); |
cellLib.setCellValue(StringUtils.toAsciiString(rowLine.getString("NOM").trim())); |
Cell cellDateEch = row.createCell(7); |
Cell cellTypeRegl = row.createCell(8); |
if (rowValsSource != null && cpt.startsWith("41")) { |
final SQLRowAccessor foreignMdr = rowValsSource.getForeign("ID_MODE_REGLEMENT"); |
Date ech = ModeDeReglementSQLElement.calculDate(foreignMdr, rowValsSource.getDate("DATE").getTime()); |
cellDateEch.setCellValue(ech); |
cellDateEch.setCellStyle(cellStyle); |
cellTypeRegl.setCellValue(foreignMdr.getForeign("ID_TYPE_REGLEMENT").getString("NOM")); |
} |
// Debit |
Cell cellDebit = row.createCell(9); |
final Long debit = rowLine.getLong("DEBIT"); |
cellDebit.setCellValue(debit / 100.0D); |
// Credit |
final Long credit = rowLine.getLong("CREDIT"); |
Cell cellCredit = row.createCell(10); |
cellCredit.setCellValue(credit / 100.0D); |
Cell cellDebAbo = row.createCell(11); |
Cell cellFinAbo = row.createCell(12); |
if (rowValsSource != null && rowValsSource.contains("ID_ABONNEMENT") && rowValsSource.getTable().getName().equals("ID_SAISIE_VENTE_FACTURE") && cpt.startsWith("41")) { |
SQLRowAccessor rowValsAbo = rowValsSource.getForeign("ID_ABONNEMENT"); |
if (rowValsAbo != null && !rowValsAbo.isUndefined()) { |
final Calendar calDeb = rowValsAbo.getDate("DATE_DEBUT_FACTURE"); |
if (calDeb != null) { |
cellDebAbo.setCellValue(calDeb.getTime()); |
cellDebAbo.setCellStyle(cellStyle); |
} |
final Calendar calFin = rowValsAbo.getDate("DATE_FIN_FACTURE"); |
if (calFin != null) { |
cellFinAbo.setCellValue(calFin.getTime()); |
cellFinAbo.setCellStyle(cellStyle); |
} |
} |
} |
} |
workBook.write(bufOut); |
workBook.close(); |
} |
private void exportTAB(OutputStream bufOut) throws IOException { |
final List<SQLRowValues> l = this.data; |
final boolean containsCodeClient = getEcritureT().contains("CODE_CLIENT"); |
final DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); |
final int size = l.size(); |
for (int i = 0; i < size; i++) { |
// Ligne à insérer dans le fichier |
final StringBuilder line = new StringBuilder(); |
final SQLRowValues rowLine = l.get(i); |
// Date |
final Date d = rowLine.getDate("DATE").getTime(); |
line.append(dateFormat.format(d)); |
line.append('\t'); |
// Jrnl |
SQLRowAccessor rowJrnl = rowLine.getForeign("ID_JOURNAL"); |
line.append(StringUtils.toAsciiString(rowJrnl.getString("CODE").trim())); |
line.append('\t'); |
SQLRowAccessor rowValsSource = null; |
SQLRowAccessor rowMvt = rowLine.getForeign("ID_MOUVEMENT"); |
if (rowMvt.getString("SOURCE").equals("AVOIR_CLIENT")) { |
rowValsSource = this.mapAvoir.get(rowMvt.getInt("IDSOURCE")); |
} else if (rowMvt.getString("SOURCE").equals("SAISIE_VENTE_FACTURE")) { |
rowValsSource = this.mapFacture.get(rowMvt.getInt("IDSOURCE")); |
} |
// Numero Piece |
if (rowValsSource != null) { |
line.append(StringUtils.toAsciiString(rowValsSource.getString("NUMERO"))); |
} |
line.append('\t'); |
// Référence |
// if (rowValsSource != null) { |
// line.append(StringUtils.toAsciiString(rowValsSource.getString("NOM"))); |
// } |
line.append('\t'); |
// N° Compte |
final String cpt = rowLine.getForeign("ID_COMPTE_PCE").getString("NUMERO").trim(); |
line.append(getFormattedCompte(cpt)); |
line.append('\t'); |
if (containsCodeClient) { |
// Code Client |
String codeClient = ""; |
if (cpt.startsWith("41")) { |
codeClient = rowLine.getString("CODE_CLIENT"); |
} |
line.append(StringUtils.toAsciiString(codeClient)); |
line.append('\t'); |
} |
// Libellé |
line.append(StringUtils.toAsciiString(rowLine.getString("NOM").trim())); |
line.append('\t'); |
if (rowValsSource != null && cpt.startsWith("41")) { |
final SQLRowAccessor foreignMdr = rowValsSource.getForeign("ID_MODE_REGLEMENT"); |
Date ech = ModeDeReglementSQLElement.calculDate(foreignMdr, rowValsSource.getDate("DATE").getTime()); |
line.append(dateFormat.format(ech)); |
line.append('\t'); |
line.append(foreignMdr.getForeign("ID_TYPE_REGLEMENT").getString("NOM")); |
line.append('\t'); |
} else { |
line.append('\t'); |
line.append('\t'); |
} |
// Debit |
final Long debit = rowLine.getLong("DEBIT"); |
line.append(GestionDevise.currencyToString(debit.longValue(), false)); |
line.append('\t'); |
// Credit |
final Long credit = rowLine.getLong("CREDIT"); |
line.append(GestionDevise.currencyToString(credit.longValue(), false)); |
line.append('\t'); |
if (rowValsSource != null && rowValsSource.contains("ID_ABONNEMENT") && rowValsSource.getTable().getName().equals("ID_SAISIE_VENTE_FACTURE") && cpt.startsWith("41")) { |
SQLRowAccessor rowValsAbo = rowValsSource.getForeign("ID_ABONNEMENT"); |
if (rowValsAbo != null && !rowValsAbo.isUndefined()) { |
final Calendar calDeb = rowValsAbo.getDate("DATE_DEBUT_FACTURE"); |
if (calDeb != null) { |
line.append(dateFormat.format(calDeb.getTime())); |
} |
line.append('\t'); |
final Calendar calFin = rowValsAbo.getDate("DATE_FIN_FACTURE"); |
if (calFin != null) { |
line.append(dateFormat.format(calFin.getTime())); |
} |
line.append('\t'); |
} |
} else { |
line.append('\t'); |
line.append('\t'); |
} |
line.append('\r'); |
line.append('\n'); |
bufOut.write(line.toString().getBytes(StringUtils.Cp1252)); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/panel/compta/ImportRImport.java |
---|
New file |
0,0 → 1,190 |
/* |
* 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.panel.compta; |
import org.openconcerto.erp.generationEcritures.Ecriture; |
import org.openconcerto.erp.generationEcritures.Exercice; |
import org.openconcerto.erp.generationEcritures.Mouvement; |
import org.openconcerto.erp.generationEcritures.Piece; |
import org.openconcerto.sql.element.SQLElementDirectory; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.users.User; |
import org.openconcerto.utils.StringUtils; |
import java.io.BufferedReader; |
import java.io.File; |
import java.io.FileInputStream; |
import java.io.IOException; |
import java.io.InputStreamReader; |
import java.math.BigDecimal; |
import java.nio.charset.Charset; |
import java.sql.SQLException; |
import java.util.ArrayList; |
import java.util.Calendar; |
import java.util.Date; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
public class ImportRImport { |
private String error = null; |
private final Map<String, Piece> mapPiece = new HashMap<>(); |
private final Map<String, String> mapJournal = new HashMap<>(); |
/** |
* Import format Ciel. |
* |
* Une pièce par journal |
* |
*/ |
public ImportRImport() { |
// |
} |
public void loadFrom(File file) throws IOException { |
this.mapPiece.clear(); |
this.mapJournal.clear(); |
this.error = null; |
parseJournaux(file); |
try (BufferedReader bReader = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.forName("Cp1252")))) { |
String line = bReader.readLine(); |
while (!(line.startsWith("##Section") && line.contains("Mvt"))) { |
line = bReader.readLine(); |
} |
line = bReader.readLine(); |
while (line != null && !line.contains("#Section")) { |
final List<String> parts = StringUtils.fastSplit(line, '\t'); |
final String journalCode = unquote(parts.get(1).trim()); |
final Date ecritureDate = parseDate(unquote(parts.get(2).trim())); |
final String compteNum = unquote(parts.get(3).trim()); |
final String compteLib = unquote(parts.get(4).trim()); |
final BigDecimal m = new BigDecimal(cleanMontant(parts.get(5))); |
BigDecimal debit = BigDecimal.ZERO; |
BigDecimal credit = BigDecimal.ZERO; |
if (parts.get(6).equalsIgnoreCase("D")) { |
debit = m; |
} else { |
credit = m; |
} |
final String valid = parts.get(7); |
Date validDate = null; |
if (valid.equalsIgnoreCase("V")) { |
validDate = ecritureDate; |
} |
final String ecritureLib = unquote(parts.get(8).trim()); |
final String pieceRef = "Import " + journalCode; |
Piece p = this.mapPiece.get(pieceRef); |
Mouvement mouvement; |
if (p == null) { |
p = new Piece(pieceRef); |
mouvement = new Mouvement(); |
p.add(mouvement); |
} else { |
mouvement = p.getMouvements().get(0); |
} |
final Ecriture ecriture = new Ecriture(ecritureDate, debit, credit); |
ecriture.setNom(ecritureLib); |
ecriture.setCompte(compteNum, compteLib); |
final String journal = getJournal(journalCode); |
if (journal == null) { |
this.error = "Pas de journal trouvé pour le code journal : " + journalCode; |
return; |
} |
ecriture.setJournal(journalCode, journal); |
ecriture.setDateValidation(validDate); |
if ("AN".equals(journalCode)) { |
ecriture.setaNouveau(true); |
} |
mouvement.add(ecriture); |
// Next |
line = bReader.readLine(); |
} |
} |
} |
private String unquote(String str) { |
if (str.length() < 3) { |
return str; |
} |
return str.substring(1, str.length() - 1); |
} |
private void parseJournaux(File file) throws IOException { |
try (BufferedReader bReader = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.forName("Cp1252")))) { |
String line = bReader.readLine(); |
while (!(line.startsWith("##Section") && line.contains("Jnl"))) { |
line = bReader.readLine(); |
} |
line = bReader.readLine(); |
while (line != null && !line.contains("#Section")) { |
final List<String> parts = StringUtils.fastSplit(line, '\t'); |
this.mapJournal.put(unquote(parts.get(0)), unquote(parts.get(1))); |
// Next |
line = bReader.readLine(); |
} |
} |
} |
private String getJournal(String journalCode) { |
return this.mapJournal.get(journalCode); |
} |
private String cleanMontant(String str) { |
final int l = str.length(); |
final StringBuilder b = new StringBuilder(l); |
for (int i = 0; i < l; i++) { |
final char c = str.charAt(i); |
if (Character.isDigit(c)) { |
b.append(c); |
} else if (c == ',') { |
b.append('.'); |
} |
} |
return b.toString(); |
} |
private Date parseDate(String str) { |
if (str.length() != 10) { |
return null; |
} |
final Calendar c = Calendar.getInstance(); |
final int day = Integer.parseInt(str.substring(0, 2)); |
final int month = Integer.parseInt(str.substring(3, 5)); |
final int year = Integer.parseInt(str.substring(6, 10)); |
c.set(year, month - 1, day, 0, 0, 0); |
return c.getTime(); |
} |
// return null is no error |
public String getError() { |
return this.error; |
} |
public void importTo(SQLElementDirectory directory, DBRoot rootSociete, User user) throws SQLException { |
Exercice e = new Exercice(); |
e.insert(directory, rootSociete, user, new ArrayList<Piece>(this.mapPiece.values())); |
} |
public static void main(String[] args) throws IOException { |
ImportRImport i = new ImportRImport(); |
i.loadFrom(new File("Y:\\Projets\\OpenConcerto\\ExportCiel\\RImport.txt")); |
System.err.println("ImportRImport.main()" + i.getError()); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/panel/compta/ImportFEC.java |
---|
New file |
0,0 → 1,164 |
/* |
* 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.panel.compta; |
import org.openconcerto.erp.generationEcritures.Ecriture; |
import org.openconcerto.erp.generationEcritures.Exercice; |
import org.openconcerto.erp.generationEcritures.Mouvement; |
import org.openconcerto.erp.generationEcritures.Piece; |
import org.openconcerto.sql.element.SQLElementDirectory; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.users.User; |
import org.openconcerto.utils.StringUtils; |
import java.io.BufferedReader; |
import java.io.File; |
import java.io.FileInputStream; |
import java.io.IOException; |
import java.io.InputStreamReader; |
import java.math.BigDecimal; |
import java.nio.charset.Charset; |
import java.sql.SQLException; |
import java.util.ArrayList; |
import java.util.Calendar; |
import java.util.Date; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
public class ImportFEC { |
private String error = null; |
private Map<String, Piece> mapPiece = new HashMap<>(); |
public ImportFEC() { |
// |
} |
public void loadFrom(File file) throws IOException { |
this.error = null; |
this.mapPiece = null; |
try (BufferedReader bReader = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.forName("Cp1252")))) { |
String line = bReader.readLine(); |
final List<String> headers = StringUtils.fastSplit(line, ExportFEC.ZONE_SEPARATOR); |
for (int i = 0; i < headers.size(); i++) { |
String c1 = headers.get(i); |
String c2 = ExportFEC.COLS.get(i); |
// Typo chez les stars de Ciel : MontantDevise au lieu de Montantdevise |
if (!c1.equalsIgnoreCase(c2)) { |
this.error = "L'entête de la colonne " + (i + 1) + " : " + c1 + " n'est pas " + c2; |
return; |
} |
} |
line = bReader.readLine(); |
while (line != null) { |
final List<String> parts = fastSplit(line, ExportFEC.ZONE_SEPARATOR); |
final String journalCode = parts.get(0).trim(); |
final String journalLib = parts.get(1).trim(); |
// final String ecritureNum = parts.get(2).trim(); |
final Date ecritureDate = parseDate(parts.get(3).trim()); |
final String compteNum = parts.get(4).trim(); |
final String compteLib = parts.get(5).trim(); |
// final String compAuxNum = parts.get(6).trim(); |
// final String compAuxLib = parts.get(7).trim(); |
String pieceRef = parts.get(8).trim(); |
// final String pieceDate = parts.get(9).trim(); |
final String ecritureLib = parts.get(10).trim(); |
final BigDecimal debit = new BigDecimal(parts.get(11).replace(',', '.')); |
final BigDecimal credit = new BigDecimal(parts.get(12).replace(',', '.')); |
final String ecritureLet = parts.get(13).trim(); |
final Date dateLet = parseDate(parts.get(14).trim()); |
final Date validDate = parseDate(parts.get(15).trim()); |
// final String montantdevise = parts.get(16).trim(); |
// final String idevise = parts.get(17).trim(); |
if (pieceRef.isEmpty()) { |
pieceRef = "Import"; |
} |
Piece p = this.mapPiece.get(pieceRef); |
Mouvement mouvement; |
if (p == null) { |
p = new Piece(pieceRef); |
mouvement = new Mouvement(); |
p.add(mouvement); |
} else { |
mouvement = p.getMouvements().get(0); |
} |
final Ecriture ecriture = new Ecriture(ecritureDate, debit, credit); |
ecriture.setNom(ecritureLib); |
ecriture.setCompte(compteNum, compteLib); |
ecriture.setJournal(journalCode, journalLib); |
ecriture.setDateValidation(validDate); |
ecriture.setDateLettrage(dateLet); |
ecriture.setLettrage(ecritureLet); |
if ("AN".equals(journalCode)) { |
ecriture.setaNouveau(true); |
} |
mouvement.add(ecriture); |
// Next |
line = bReader.readLine(); |
} |
} |
} |
private Date parseDate(String str) { |
if (str.length() != 8) { |
return null; |
} |
final Calendar c = Calendar.getInstance(); |
final int year = Integer.parseInt(str.substring(0, 4)); |
final int month = Integer.parseInt(str.substring(4, 6)); |
final int day = Integer.parseInt(str.substring(6, 8)); |
c.set(year, month - 1, day, 0, 0, 0); |
return c.getTime(); |
} |
// return null is no error |
public String getError() { |
return this.error; |
} |
public void importTo(SQLElementDirectory directory, DBRoot rootSociete, User user) throws SQLException { |
final Exercice e = new Exercice(); |
e.insert(directory, rootSociete, user, new ArrayList<Piece>(this.mapPiece.values())); |
} |
public static void main(String[] args) throws IOException { |
final ImportFEC i = new ImportFEC(); |
i.loadFrom(new File("Y:\\Projets\\OpenConcerto\\ExportCiel\\FEC20171231.txt")); |
System.err.println("ImportFEC.main()" + i.getError()); |
} |
public static final List<String> fastSplit(final String string, final char sep) { |
final List<String> l = new ArrayList<>(); |
final int length = string.length(); |
final char[] cars = string.toCharArray(); |
int rfirst = 0; |
for (int i = 0; i < length; i++) { |
if (cars[i] == sep) { |
l.add(new String(cars, rfirst, i - rfirst)); |
rfirst = i + 1; |
} |
} |
if (rfirst <= length) { |
// <= au lieu de < pour Ciel.... |
l.add(new String(cars, rfirst, length - rfirst)); |
} |
return l; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/model/MouseSheetXmlListeListener.java |
---|
14,6 → 14,8 |
package org.openconcerto.erp.model; |
import org.openconcerto.erp.config.ComptaPropsConfiguration; |
import org.openconcerto.erp.core.customerrelationship.mail.EmailTemplate; |
import org.openconcerto.erp.core.customerrelationship.mail.ValueListener; |
import org.openconcerto.erp.generationDoc.AbstractSheetXml; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.model.SQLBase; |
27,6 → 29,7 |
import org.openconcerto.ui.EmailComposer; |
import org.openconcerto.utils.ExceptionHandler; |
import org.openconcerto.utils.ListMap; |
import org.openconcerto.utils.i18n.TranslationManager; |
import java.awt.event.ActionEvent; |
import java.io.File; |
112,13 → 115,13 |
this.showHeader = showHeader; |
} |
protected void sendMail(final AbstractSheetXml sheet, final boolean readOnly) { |
protected void sendMail(EmailTemplate template, final AbstractSheetXml sheet, final boolean readOnly) { |
List<AbstractSheetXml> l = new ArrayList<>(1); |
l.add(sheet); |
sendMail(l, readOnly); |
sendMail(template, l, readOnly); |
} |
protected void sendMail(final List<AbstractSheetXml> sheets, final boolean readOnly) { |
protected void sendMail(EmailTemplate template, final List<AbstractSheetXml> sheets, final boolean readOnly) { |
final Thread t = new Thread() { |
@Override |
public void run() { |
231,6 → 234,10 |
public void run() { |
try { |
String subject = sheets.get(0).getReference(); |
if (template != null) { |
subject = template.getTitle() + " " + sheets.get(0).getReference().trim(); |
} |
subject = subject.trim(); |
if (subject.isEmpty()) { |
final StringJoiner joiner = new StringJoiner(", "); |
for (File f : files) { |
238,7 → 245,14 |
} |
subject = joiner.toString(); |
} |
final String message = getMailObject(sheets.get(0).getSQLRow()); |
String message = getMailObject(sheets.get(0).getSQLRow()); |
if (template != null) { |
if (template.getText().contains("{message}")) { |
message = template.getText().replace("{message}", message); |
} else { |
message += template.getText(); |
} |
} |
EmailComposer.getInstance().compose(mailDest, subject, message, files.toArray(new File[files.size()])); |
} catch (Exception e) { |
ExceptionHandler.handle("Impossible d'envoyer le courriel!", e); |
286,11 → 300,27 |
} |
} else { |
// ODS Viewer |
if (this.previewIsVisible) { |
l.add(new RowAction(new AbstractAction() { |
public void actionPerformed(ActionEvent ev) { |
try { |
createAbstractSheet(IListe.get(ev).fetchSelectedRow()).showPreviewDocument(); |
final AbstractSheetXml sheet = createAbstractSheet(IListe.get(ev).fetchSelectedRow()); |
final SQLTable table = IListe.get(ev).getSource().getPrimaryTable(); |
sheet.showPreviewDocument(TranslationManager.getInstance().getTranslationForAction("email"), new Runnable() { |
@Override |
public void run() { |
EmailTemplate.askTemplate(IListe.get(ev), table.getDBRoot(), new ValueListener() { |
@Override |
public void valueSelected(Object value) { |
sendMail((EmailTemplate) value, sheet, true); |
} |
}); |
} |
}); |
} catch (Exception e) { |
ExceptionHandler.handle("Impossible d'ouvrir le fichier", e); |
} |
388,13 → 418,7 |
public RowAction getSendMail() { |
return new RowAction(new AbstractAction() { |
public void actionPerformed(ActionEvent ev) { |
final List<SQLRowValues> selectedRows = IListe.get(ev).getSelectedRows(); |
final SQLTable table = IListe.get(ev).getSource().getPrimaryTable(); |
final List<SQLRow> rows = new ArrayList<SQLRow>(); |
for (SQLRowValues r : selectedRows) { |
rows.add(table.getRow(r.getID())); |
} |
sendMail(createAbstractSheets(rows), false); |
sendMail(ev, false); |
} |
}, false, "document.send.email") { |
411,17 → 435,7 |
public RowAction getSendMailPDF() { |
return new RowAction(new AbstractAction() { |
public void actionPerformed(ActionEvent ev) { |
try { |
final List<SQLRowValues> selectedRows = IListe.get(ev).getSelectedRows(); |
final SQLTable table = IListe.get(ev).getSource().getPrimaryTable(); |
final List<SQLRow> rows = new ArrayList<SQLRow>(); |
for (SQLRowValues r : selectedRows) { |
rows.add(table.getRow(r.getID())); |
} |
sendMail(createAbstractSheets(rows), true); |
} catch (Exception e) { |
ExceptionHandler.handle("Impossible d'envoyer le(s) fichier(s)", e); |
} |
sendMail(ev, true); |
} |
}, false, "document.pdf.send.email") { |
496,4 → 510,21 |
} |
}; |
} |
private void sendMail(ActionEvent ev, boolean pdf) { |
final List<SQLRowValues> selectedRows = IListe.get(ev).getSelectedRows(); |
final SQLTable table = IListe.get(ev).getSource().getPrimaryTable(); |
final List<SQLRow> rows = new ArrayList<>(); |
for (SQLRowValues r : selectedRows) { |
rows.add(table.getRow(r.getID())); |
} |
EmailTemplate.askTemplate(IListe.get(ev), table.getDBRoot(), new ValueListener() { |
@Override |
public void valueSelected(Object value) { |
sendMail((EmailTemplate) value, createAbstractSheets(rows), pdf); |
} |
}); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/importer/DataImporter.java |
---|
13,17 → 13,15 |
package org.openconcerto.erp.importer; |
import org.openconcerto.erp.config.ComptaPropsConfiguration; |
import org.openconcerto.openoffice.spreadsheet.Sheet; |
import org.openconcerto.openoffice.spreadsheet.SpreadSheet; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.model.SQLBase; |
import org.openconcerto.sql.model.SQLField; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.SQLRowValuesCluster.StoreMode; |
import org.openconcerto.sql.model.SQLRowValuesListFetcher; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.users.UserManager; |
import org.openconcerto.utils.ooxml.XLSXDocument; |
import org.openconcerto.utils.ooxml.XLSXSheet; |
import org.openconcerto.utils.text.CSVReader; |
import org.openconcerto.utils.text.CSVWriter; |
import org.openconcerto.utils.text.CharsetHelper; |
51,6 → 49,7 |
import org.apache.poi.hssf.usermodel.HSSFSheet; |
import org.apache.poi.hssf.usermodel.HSSFWorkbook; |
import org.apache.poi.poifs.filesystem.POIFSFileSystem; |
import org.apache.poi.ss.formula.eval.NotImplementedException; |
import org.apache.poi.ss.usermodel.Cell; |
import org.apache.poi.ss.usermodel.CellValue; |
import org.apache.poi.ss.usermodel.FormulaEvaluator; |
59,13 → 58,13 |
public class DataImporter { |
private boolean skipFirstLine = true; |
private SQLTable table; |
private final Map<Integer, ValueConverter> map = new HashMap<Integer, ValueConverter>(); |
private final Map<SQLField, List<Integer>> fieldMap = new HashMap<SQLField, List<Integer>>(); |
private final Map<Integer, Constraint> constraints = new HashMap<Integer, Constraint>(); |
private List<SQLField> uniqueField = new ArrayList<SQLField>(); |
private List<SQLRowValues> valuesToUpdate = new ArrayList<SQLRowValues>(); |
private List<SQLRowValues> valuesToInsert = new ArrayList<SQLRowValues>(); |
private Map<ValueConverter, SQLField> foreignMap = new HashMap<ValueConverter, SQLField>(); |
private final Map<Integer, ValueConverter> map = new HashMap<>(); |
private final Map<SQLField, List<Integer>> fieldMap = new HashMap<>(); |
private final Map<Integer, Constraint> constraints = new HashMap<>(); |
private List<SQLField> uniqueField = new ArrayList<>(); |
private List<SQLRowValues> valuesToUpdate = new ArrayList<>(); |
private List<SQLRowValues> valuesToInsert = new ArrayList<>(); |
private Map<ValueConverter, SQLField> foreignMap = new HashMap<>(); |
public DataImporter() { |
} |
78,43 → 77,6 |
this.table = table; |
} |
public static void main(String[] args) throws Exception { |
System.setProperty(SQLBase.STRUCTURE_USE_XML, "true"); |
final ComptaPropsConfiguration conf = ComptaPropsConfiguration.create(); |
Configuration.setInstance(conf); |
try { |
conf.getBase(); |
} catch (Exception e) { |
e.printStackTrace(); |
} |
final ComptaPropsConfiguration comptaPropsConfiguration = ((ComptaPropsConfiguration) Configuration.getInstance()); |
comptaPropsConfiguration.setUpSocieteDataBaseConnexion(39); |
UserManager.getInstance().setCurrentUser(2); |
SQLTable table = Configuration.getInstance().getRoot().findTable("ARTICLE"); |
DataImporter importer = new DataImporter(table); |
importer.skipFirstLine = false; |
importer.map(0, table.getField("CODE")); |
importer.map(8, table.getField("ID_FOURNISSEUR")); |
importer.map(4, table.getField("NOM")); |
importer.addContraint(0, new NotEmptyConstraint()); |
importer.addUniqueField(table.getField("CODE")); |
// ArrayTableModel m = importer.createModelFromODS(new File("c:/products-en.ods")); |
// ArrayTableModel m = importer.createModelFromCSV(new File("c:/products-en.csv")); |
// ArrayTableModel m = importer.createModelFromCSV(new File("c:/products-en.scsv.csv")); |
ArrayTableModel m = importer.createModelFromXLS(new File("c:/products-en.xls"), 0); |
m.dump(0, 4); |
m = importer.createConvertedModel(m); |
System.out.println("Dump"); |
m.dump(0, 4); |
importer.importFromModel(m); |
System.out.println(importer.getValuesToInsert().size() + " rows to insert"); |
System.out.println(importer.getValuesToUpdate().size() + " rows to update"); |
// importer.commit(); |
} |
public void commit() throws SQLException { |
for (SQLRowValues row : this.valuesToInsert) { |
row.getGraph().store(StoreMode.INSERT, false); |
126,11 → 88,11 |
} |
public List<SQLRowValues> getValuesToInsert() { |
return valuesToInsert; |
return this.valuesToInsert; |
} |
public List<SQLRowValues> getValuesToUpdate() { |
return valuesToUpdate; |
return this.valuesToUpdate; |
} |
public void addUniqueField(SQLField field) { |
142,7 → 104,7 |
} |
public void addContraint(int columnIndex, Constraint c) { |
constraints.put(Integer.valueOf(columnIndex), c); |
this.constraints.put(Integer.valueOf(columnIndex), c); |
} |
public void map(int columnIndex, SQLField field) { |
156,17 → 118,17 |
public void map(int columnIndex, SQLField field, SQLField foreignField) { |
final ValueConverter converter = new ValueConverter(foreignField); |
map(columnIndex, foreignField, converter); |
foreignMap.put(converter, field); |
this.foreignMap.put(converter, field); |
} |
public void map(int columnIndex, SQLField field, ValueConverter converter) { |
final Integer value = Integer.valueOf(columnIndex); |
map.put(value, converter); |
List<Integer> l = fieldMap.get(field); |
this.map.put(value, converter); |
List<Integer> l = this.fieldMap.get(field); |
if (l == null) { |
l = new ArrayList<Integer>(); |
fieldMap.put(field, l); |
l = new ArrayList<>(); |
this.fieldMap.put(field, l); |
} else if (!field.getType().getJavaType().equals(String.class)) { |
throw new IllegalArgumentException("Mapping multiple column is only supoprted for String values"); |
} |
195,12 → 157,12 |
} |
} |
int start = 0; |
if (skipFirstLine) { |
if (this.skipFirstLine) { |
start = 1; |
} |
final List<List<Object>> rows = new ArrayList<List<Object>>(rowCount - start); |
final List<List<Object>> rows = new ArrayList<>(rowCount - start); |
for (int i = start; i < rowCount; i++) { |
List<Object> row = new ArrayList<Object>(); |
List<Object> row = new ArrayList<>(); |
for (int j = 0; j < columnCount; j++) { |
row.add(sheet.getValueAt(j, i)); |
} |
210,16 → 172,45 |
return new ArrayTableModel(rows); |
} |
public ArrayTableModel createModelFromXLSXGM(File xlsFile, int sheetNumber) throws IOException { |
XLSXDocument doc = XLSXDocument.createFromFile(xlsFile); |
XLSXSheet sheet = doc.getSheet(sheetNumber); |
final int rowCount = sheet.getRowCount(); |
final int columnCount = sheet.getColumnCount(); |
int start = 0; |
if (this.skipFirstLine) { |
start = 1; |
} |
final List<List<Object>> selectedRows = new ArrayList<>(rowCount - start); |
for (int i = start; i < rowCount; i++) { |
List<Object> row = new ArrayList<>(); |
for (int j = 0; j < columnCount; j++) { |
row.add(sheet.getValueAt(j, i)); |
} |
selectedRows.add(row); |
} |
return new ArrayTableModel(selectedRows); |
} |
public ArrayTableModel createModelFromXLS(File xlsFile, int sheetNumber) throws IOException { |
final InputStream inputStream = new FileInputStream(xlsFile); |
final POIFSFileSystem fileSystem = new POIFSFileSystem(new BufferedInputStream(inputStream)); |
final HSSFWorkbook workBook = new HSSFWorkbook(fileSystem); |
final HSSFSheet sheet = workBook.getSheetAt(sheetNumber); |
Iterator<Row> rowsIterator = sheet.rowIterator(); |
final List<List<Object>> rows = createFromExcel(workBook.getCreationHelper().createFormulaEvaluator(), sheet.rowIterator(), sheet.rowIterator()); |
workBook.close(); |
return new ArrayTableModel(rows); |
} |
private List<List<Object>> createFromExcel(FormulaEvaluator evaluator, Iterator<Row> rowsIterator1, Iterator<Row> rowsIterator2) { |
int columnCount = 0; |
int rowCount = 0; |
while (rowsIterator.hasNext()) { |
Row row = rowsIterator.next(); |
while (rowsIterator1.hasNext()) { |
Row row = rowsIterator1.next(); |
int i = row.getPhysicalNumberOfCells(); |
if (i > columnCount) { |
columnCount = i; |
227,18 → 218,16 |
rowCount++; |
} |
// Extract data |
rowsIterator = sheet.rowIterator(); |
int start = 0; |
if (skipFirstLine) { |
if (this.skipFirstLine) { |
start = 1; |
rowsIterator.next(); |
rowsIterator2.next(); |
} |
final List<List<Object>> rows = new ArrayList<List<Object>>(rowCount - start); |
FormulaEvaluator evaluator = workBook.getCreationHelper().createFormulaEvaluator(); |
final List<List<Object>> rows = new ArrayList<>(rowCount - start); |
while (rowsIterator.hasNext()) { |
final Row row = rowsIterator.next(); |
final List<Object> rowData = new ArrayList<Object>(); |
while (rowsIterator2.hasNext()) { |
final Row row = rowsIterator2.next(); |
final List<Object> rowData = new ArrayList<>(); |
for (int i = 0; i < columnCount; i++) { |
final Cell cell = row.getCell(i); |
245,30 → 234,33 |
if (cell == null) { |
rowData.add(""); |
} else { |
CellValue cellValue = evaluator.evaluate(cell); |
CellValue cellValue = null; |
try { |
cellValue = evaluator.evaluate(cell); |
} catch (NotImplementedException exception) { |
exception.printStackTrace(); |
} |
if (cellValue == null) { |
rowData.add(""); |
} else { |
switch (cellValue.getCellType()) { |
case Cell.CELL_TYPE_BOOLEAN: |
switch (cellValue.getCellTypeEnum()) { |
case BOOLEAN: |
rowData.add(Boolean.valueOf(cellValue.getBooleanValue())); |
break; |
case Cell.CELL_TYPE_NUMERIC: |
case NUMERIC: |
if (HSSFDateUtil.isCellDateFormatted(cell)) { |
System.out.println("Row No.: " + row.getRowNum() + " " + cell.getDateCellValue()); |
rowData.add(cell.getDateCellValue()); |
} else { |
rowData.add(Double.valueOf(cellValue.getNumberValue())); |
} |
break; |
case Cell.CELL_TYPE_STRING: |
case STRING: |
rowData.add(cellValue.getStringValue()); |
break; |
case Cell.CELL_TYPE_FORMULA: |
case FORMULA: |
rowData.add(cell.getCellFormula()); |
break; |
case Cell.CELL_TYPE_BLANK: |
case BLANK: |
rowData.add(""); |
break; |
default: |
283,9 → 275,7 |
rows.add(rowData); |
} |
inputStream.close(); |
return new ArrayTableModel(rows); |
return rows; |
} |
public ArrayTableModel createModelFromCSV(File csvFile) throws IOException { |
319,12 → 309,12 |
final int columnCount = lines.get(0).length; |
int start = 0; |
if (skipFirstLine) { |
if (this.skipFirstLine) { |
start = 1; |
} |
final List<List<Object>> rows = new ArrayList<List<Object>>(rowCount - start); |
final List<List<Object>> rows = new ArrayList<>(rowCount - start); |
for (int i = start; i < rowCount; i++) { |
List<Object> row = new ArrayList<Object>(); |
List<Object> row = new ArrayList<>(); |
String[] values = lines.get(i); |
for (int j = 0; j < columnCount; j++) { |
row.add(values[j]); |
347,23 → 337,23 |
public ArrayTableModel createConvertedModel(ArrayTableModel model) { |
final int rowCount = model.getRowCount(); |
final ArrayList<Integer> colsUsed = new ArrayList<Integer>(map.keySet()); |
colsUsed.addAll(constraints.keySet()); |
final ArrayList<Integer> colsUsed = new ArrayList<>(this.map.keySet()); |
colsUsed.addAll(this.constraints.keySet()); |
final int columnCount = 1 + Collections.max(colsUsed); |
final List<List<Object>> rows = new ArrayList<List<Object>>(rowCount); |
final List<List<Object>> rows = new ArrayList<>(rowCount); |
for (int i = 0; i < rowCount; i++) { |
boolean validRow = true; |
final List<Object> row = new ArrayList<Object>(); |
final List<Object> row = new ArrayList<>(); |
for (int j = 0; j < columnCount; j++) { |
Object value = model.getValueAt(i, j); |
ValueConverter converter = map.get(j); |
ValueConverter converter = this.map.get(j); |
if (converter != null) { |
value = converter.convertFrom(value); |
} |
final Constraint constraint = constraints.get(j); |
final Constraint constraint = this.constraints.get(j); |
// Verification de la validité de la valeur à importer |
if (constraint != null && !constraint.isValid(value)) { |
validRow = false; |
380,19 → 370,19 |
} |
protected void customizeRowValuesToFetch(SQLRowValues vals) { |
// Nothing |
} |
public void importFromModel(ArrayTableModel model) throws IOException { |
final int rowCount = model.getRowCount(); |
// Load existing data for duplication check |
final SQLRowValues vals = new SQLRowValues(table); |
final SQLRowValues vals = new SQLRowValues(this.table); |
for (SQLField field : this.fieldMap.keySet()) { |
if (field.getTable().equals(table)) { |
if (field.getTable().equals(this.table)) { |
vals.put(field.getName(), null); |
} else { |
final Set<SQLField> foreignKeys = table.getForeignKeys(field.getTable()); |
final Set<SQLField> foreignKeys = this.table.getForeignKeys(field.getTable()); |
for (SQLField sqlField : foreignKeys) { |
vals.put(sqlField.getName(), null); |
} |
399,17 → 389,15 |
} |
} |
customizeRowValuesToFetch(vals); |
System.out.println("Fetching values"); |
SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(vals); |
List<SQLRowValues> existingRows = fetcher.fetch(); |
System.out.println("Computing cache"); |
final int existingRowsCount = existingRows.size(); |
final ValueConverter[] converters = map.values().toArray(new ValueConverter[map.size()]); |
final ValueConverter[] converters = this.map.values().toArray(new ValueConverter[this.map.size()]); |
// Une map <Object(valeur),SQLRowValues> pour chaque champs unique |
Map<SQLField, Map<Object, SQLRowValues>> cache = new HashMap<SQLField, Map<Object, SQLRowValues>>(); |
Map<SQLField, Map<Object, SQLRowValues>> cache = new HashMap<>(); |
for (SQLField field : this.uniqueField) { |
Map<Object, SQLRowValues> m = new HashMap<Object, SQLRowValues>(); |
Map<Object, SQLRowValues> m = new HashMap<>(); |
cache.put(field, m); |
final String fieldName = field.getName(); |
for (int j = 0; j < existingRowsCount; j++) { |
424,7 → 412,7 |
// Recherche d'existant |
SQLRowValues existingRow = null; |
for (SQLField field : this.uniqueField) { |
List<Integer> cols = fieldMap.get(field); |
List<Integer> cols = this.fieldMap.get(field); |
Object objectToInsert = null; |
for (Integer col : cols) { |
Object v = model.getValueAt(i, col); |
449,7 → 437,7 |
private void updateOrInsert(ArrayTableModel model, final ValueConverter[] converters, int i, SQLRowValues existingRow) { |
final Map<String, Object> newValues = new HashMap<String, Object>(); |
final Map<String, Object> newValues = new HashMap<>(); |
if (existingRow != null) { |
// Préremplissage de la map avec la row existante |
newValues.putAll(existingRow.getAbsolutelyAll()); |
457,7 → 445,7 |
for (int j = 0; j < converters.length; j++) { |
ValueConverter valueConverter = converters[j]; |
List<Integer> cols = fieldMap.get(valueConverter.getField()); |
List<Integer> cols = this.fieldMap.get(valueConverter.getField()); |
Object objectToInsert = null; |
for (Integer col : cols) { |
Object v = model.getValueAt(i, col); |
471,11 → 459,11 |
final String fieldName = valueConverter.getFieldName(); |
if (objectToInsert != null || !valueConverter.isIgnoringEmptyValue()) { |
if (valueConverter.getField().getTable().equals(table)) { |
if (valueConverter.getField().getTable().equals(this.table)) { |
newValues.put(fieldName, objectToInsert); |
} else { |
final SQLField sqlField = foreignMap.get(valueConverter); |
final SQLField sqlField = this.foreignMap.get(valueConverter); |
final Object value = newValues.get(sqlField.getName()); |
if (value == null || value instanceof SQLRowValues) { |
490,26 → 478,21 |
} |
} |
} |
final SQLRowValues rowVals = new SQLRowValues(table, newValues); |
final SQLRowValues rowVals = new SQLRowValues(this.table, newValues); |
patchRowValues(rowVals, model.getLineValuesAt(i), existingRow); |
if (existingRow == null) { |
this.valuesToInsert.add(rowVals); |
} |
// else if (!newValues.equals(existingRow.getAbsolutelyAll())) { |
else { |
} else { |
this.valuesToUpdate.add(rowVals); |
// for (SQLRowValues ref : rowVals.getReferentRows()) { |
// this.valuesToUpdate.add(ref); |
// } |
} |
} |
public void doAfterImport() throws SQLException { |
// Nothing |
} |
protected void patchRowValues(SQLRowValues rowVals, List<Object> lineValues, SQLRowValues existingRow) { |
// Nothing |
} |
public void setSkipFirstLine(boolean skipFirstLine) { |
531,8 → 514,10 |
return createModelFromCSV(file); |
} else if (name.endsWith(".xls")) { |
return createModelFromXLS(file, sheetNumber); |
} else if (name.endsWith(".xlsx") || name.endsWith(".xlsm")) { |
return createModelFromXLSXGM(file, sheetNumber); |
} |
throw new IllegalArgumentException("File format not supported. Please provide an ods, csv or xls file."); |
throw new IllegalArgumentException("File format not supported. Please provide an ods, csv, xls or xlsx file."); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/preferences/MailRelancePreferencePanel.java |
---|
File deleted |
/trunk/OpenConcerto/src/org/openconcerto/erp/preferences/TemplateNXProps.java |
---|
17,7 → 17,6 |
import org.openconcerto.erp.core.customerrelationship.customer.report.FicheClientXmlSheet; |
import org.openconcerto.erp.core.edm.AttachmentSQLElement; |
import org.openconcerto.erp.core.finance.accounting.report.BalanceSheet; |
import org.openconcerto.erp.core.finance.accounting.report.GrandLivreSheet; |
import org.openconcerto.erp.core.finance.accounting.report.GrandLivreSheetXML; |
import org.openconcerto.erp.core.finance.accounting.report.JournauxSheetXML; |
import org.openconcerto.erp.core.humanresources.payroll.report.EtatChargesPayeSheet; |
/trunk/OpenConcerto/src/org/openconcerto/erp/preferences/GestionCommercialeGlobalPreferencePanel.java |
---|
29,11 → 29,13 |
public class GestionCommercialeGlobalPreferencePanel extends JavaPrefPreferencePanel { |
public static String TRANSFERT_REF = "TransfertRef"; |
public static String COMMANDE_FOURNISSEUR_EN_COURS = "CommandeFournisseurEncours"; |
public static String TRANSFERT_MULTI_REF = "TransfertMultiRef"; |
public static String TRANSFERT_NO_REF = "TransfertNoRef"; |
public static String ACOMPTE_DEVIS = "AcompteDevis"; |
public static String ORDER_PACKAGING_MANAGEMENT = "OrderPackagingManagement"; |
public static String ADDRESS_SPEC = "AddressSpec"; |
public static String CATEGORIE_COMPTABLE_SPEC = "CategorieComptableSpec"; |
public static String GESTION_TIMBRE_FISCAL = "GestionTimbreFiscal"; |
public static String TAUX_TIMBRE_FISCAL = "TauxTimbreFiscal"; |
public static String BARCODE_INSERTION = "BarcodeInsertion"; |
69,6 → 71,10 |
orderQuoting.setDefaultValue(Boolean.FALSE); |
this.addView(orderQuoting); |
PrefView<Boolean> cmdEnCours = new PrefView<Boolean>(PrefType.BOOLEAN_TYPE, "Activer la gestion des commandes fournisseurs en cours", COMMANDE_FOURNISSEUR_EN_COURS); |
cmdEnCours.setDefaultValue(Boolean.FALSE); |
this.addView(cmdEnCours); |
PrefView<Boolean> viewAcompteDevis = new PrefView<Boolean>(PrefType.BOOLEAN_TYPE, "Gérer les acomptes sur devis", ACOMPTE_DEVIS); |
viewAcompteDevis.setDefaultValue(Boolean.FALSE); |
this.addView(viewAcompteDevis); |
76,6 → 82,10 |
PrefView<Boolean> addressSpec = new PrefView<Boolean>(PrefType.BOOLEAN_TYPE, "Afficher les sélecteurs d'adresse spécifique", ADDRESS_SPEC); |
addressSpec.setDefaultValue(Boolean.TRUE); |
this.addView(addressSpec); |
PrefView<Boolean> catComptableSpec = new PrefView<Boolean>(PrefType.BOOLEAN_TYPE, "Afficher les sélecteurs de catégorie comptable spécifique", CATEGORIE_COMPTABLE_SPEC); |
catComptableSpec.setDefaultValue(Boolean.FALSE); |
this.addView(catComptableSpec); |
PrefView<Boolean> gestTimbreFisc = new PrefView<Boolean>(PrefType.BOOLEAN_TYPE, "Activer la gestion du timbre fiscal", GESTION_TIMBRE_FISCAL); |
gestTimbreFisc.setDefaultValue(Boolean.FALSE); |
/trunk/OpenConcerto/src/org/openconcerto/erp/config/InstallationPanel.java |
---|
49,6 → 49,7 |
import org.openconcerto.sql.request.Inserter.Insertion; |
import org.openconcerto.sql.request.UpdateBuilder; |
import org.openconcerto.sql.sqlobject.SQLTextCombo; |
import org.openconcerto.sql.users.rights.TableAllRights; |
import org.openconcerto.sql.utils.AlterTable; |
import org.openconcerto.sql.utils.ChangeTable; |
import org.openconcerto.sql.utils.ChangeTable.ClauseType; |
63,6 → 64,7 |
import org.openconcerto.utils.CollectionUtils; |
import org.openconcerto.utils.ExceptionHandler; |
import org.openconcerto.utils.ProductInfo; |
import org.openconcerto.utils.StringUtils; |
import org.openconcerto.utils.cc.ITransformer; |
import java.awt.GridBagConstraints; |
2387,18 → 2389,24 |
} |
root.getTable("ARTICLE").getSchema().updateVersion(); |
// Valeur par défaut des numérotations |
SQLRowValues rNumerotation = root.getTable("NUMEROTATION_AUTO").getRow(2).asRowValues(); |
boolean numerotationFixed = false; |
if (rNumerotation.getString("AVOIR_F_FORMAT").trim().isEmpty()) { |
rNumerotation.put("AVOIR_F_FORMAT", "'AVOIR'yyMM-000"); |
if (root.contains("NUMEROTATION_AUTO")) { |
SQLRow rowNumerotation = root.getTable("NUMEROTATION_AUTO").getRow(2); |
if (rowNumerotation != null) { |
SQLRowValues rNumerotation = rowNumerotation.asRowValues(); |
boolean numerotationFixed = false; |
if (StringUtils.isEmpty(rNumerotation.getString("AVOIR_F_FORMAT"), true)) { |
rNumerotation.put("AVOIR_F_FORMAT", "'AVOIR'yyMM-000"); |
numerotationFixed = true; |
} |
if (StringUtils.isEmpty(rNumerotation.getString("CLIENT_FORMAT"), true)) { |
rNumerotation.put("CLIENT_FORMAT", "'CLI'00000"); |
numerotationFixed = true; |
} |
if (numerotationFixed) { |
rNumerotation.commit(); |
} |
} |
} |
if (rNumerotation.getString("CLIENT_FORMAT").trim().isEmpty()) { |
rNumerotation.put("CLIENT_FORMAT", "'CLI'00000"); |
} |
if (numerotationFixed) { |
rNumerotation.commit(); |
} |
// |
final SQLTable tableCalendarItem = root.getTable("CALENDAR_ITEM"); |
3835,6 → 3843,32 |
rowValsUserRight.commit(); |
} |
if (!codes.contains(TableAllRights.USER_UI_LOCK_ROW)) { |
SQLRowValues rowVals = new SQLRowValues(table); |
rowVals.put("CODE", TableAllRights.USER_UI_LOCK_ROW); |
rowVals.put("NOM", "Autoriser à verrouiller une ligne dans une liste."); |
String desc = "Autorise un utilisateur à verrouiller une ou plusieurs dans les listes où cette fonctionnalité est active."; |
rowVals.put("DESCRIPTION", desc); |
SQLRow row = rowVals.commit(); |
SQLRowValues rowValsUserRight = new SQLRowValues(table.getTable("USER_RIGHT")); |
rowValsUserRight.put("ID_RIGHT", row.getID()); |
rowValsUserRight.put("HAVE_RIGHT", Boolean.TRUE); |
rowValsUserRight.commit(); |
} |
if (!codes.contains(TableAllRights.USER_UI_UNLOCK_ROW)) { |
SQLRowValues rowVals = new SQLRowValues(table); |
rowVals.put("CODE", TableAllRights.USER_UI_UNLOCK_ROW); |
rowVals.put("NOM", "Autoriser à déverrouiller une ligne dans une liste."); |
String desc = "Autorise un utilisateur à déverrouiller une ou plusieurs dans les listes où cette fonctionnalité est active."; |
rowVals.put("DESCRIPTION", desc); |
SQLRow row = rowVals.commit(); |
SQLRowValues rowValsUserRight = new SQLRowValues(table.getTable("USER_RIGHT")); |
rowValsUserRight.put("ID_RIGHT", row.getID()); |
rowValsUserRight.put("HAVE_RIGHT", Boolean.TRUE); |
rowValsUserRight.commit(); |
} |
} |
private void findBadForeignKey(DBRoot root) { |
3975,6 → 4009,15 |
// FK |
new AddFK(root.getDBSystemRoot()).changeAll(root); |
// Couleur |
final SQLTable tableUser = root.getTable("USER_COMMON"); |
if (!tableUser.contains("COLOR")) { |
final AlterTable alter = new AlterTable(tableUser); |
alter.addIntegerColumn("COLOR", 0, false); |
Updater_1_5.exec(alter); |
} |
} |
protected void fixCompletion(DBRoot root) throws SQLException { |
4027,6 → 4070,11 |
alter = true; |
} |
if (!table.getFieldsName().contains("ID_JOURNAL_VALEUR_ENCAISSEMENT")) { |
t.addForeignColumn("ID_JOURNAL_VALEUR_ENCAISSEMENT", root.getTable("JOURNAL")); |
alter = true; |
} |
if (!table.getFieldsName().contains("ID_COMPTE_PCE_PORT_NON_SOUMIS")) { |
t.addForeignColumn("ID_COMPTE_PCE_PORT_NON_SOUMIS", root.getTable("COMPTE_PCE")); |
alter = true; |
4625,7 → 4673,6 |
// at the end to let Updater_1_5 change field types from varchar to text |
fixUnboundedVarchar(root); |
return null; |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/config/translation_fr.xml |
---|
178,8 → 178,9 |
<action id="sales.quote.clone" label="Créer à partir de" /> |
<action id="sales.quote.create.customer.order" label="Transfert vers commande client" /> |
<action id="sales.quote.create.customer.delivery" label="Transfert vers bon de livraison" /> |
<action id="sales.quote.accept.create.customer.order" label="Marquer comme accepté et Transfert en commande client" /> |
<action id="sales.quote.accept.create.customer.order" |
label="Marquer comme accepté et Transfert en commande client" /> |
<!-- Customer --> |
<action id="customerrelationship.customer.label.print" label="Imprimer l'étiquette client" /> |
<action id="customerrelationship.customer.info.create" label="Créer la fiche client" /> |
220,6 → 221,7 |
<action id="supplychain.order.create.purchase" label="Transfert vers saisie achat" /> |
<action id="supplychain.order.valid" label="Marquer comme validée" /> |
<action id="supplychain.order.create.receipt" label="Transfert vers bon de réception" /> |
<action id="supplychain.invoice.clone" label="Créer à partir de" /> |
<!-- Customer order --> |
<action id="sales.order.create.deliverynote" label="Transfert vers bon de livraison" /> |
247,9 → 249,9 |
<item id="customerrelationship.customer.identifier" label="Code" /> |
<item id="customerrelationship.customer.date" label="Date" /> |
<item id="customerrelationship.customer.customproduct" label="Réf. Art. Interne" /> |
<item id="customerrelationship.customer.customtarif" label="Remises client" /> |
<!-- Currency --> |
<item id="currency.USD" label="Dollar américain" /> |
<item id="currency.EUR" label="Euro" /> |
290,7 → 292,7 |
<item id="autres.contributions.ligne" label="Autres contributions dues par l'employeur" /> |
<item id="csg.nonimp.ligne" label="CSG non imposable à l'impôt sur le revenu" /> |
<item id="csg.imp.ligne" label="CSG/CRDS imposable à l'impôt sur le revenu" /> |
<item id="allegement.cotisations.ligne" label="Exonération de cotisations employeur" /> |
<item id="allegement.cotisations.ligne" label="Allégement de cotisation" /> |
<item id="paye.simplifie.ignore" label="Ligne ignorée" /> |
<!-- Groupe Paye Simplifiée --> |
305,6 → 307,6 |
<item id="cotisations.convention" label="COTISATIONS DE CONVENTION COLLECTIVE OU STATUAIRES" /> |
<item id="csg.nonimp" label="CSG/CRDS déductible de l'impôt sur le revenu" /> |
<item id="csg.imp" label="CSG/CRDS non déductible à l'impôt sur le revenu" /> |
<item id="allegement" label="Exonération de cotisations employeur" /> |
<item id="allegement" label="Allégement de cotisation" /> |
<action id="email" label="Email" /> |
</translation> |
/trunk/OpenConcerto/src/org/openconcerto/erp/config/mappingCompta_fr.xml |
---|
1,5 → 1,11 |
<?xml version="1.0" encoding="UTF-8" ?> |
<ROOT> |
<element refid="sales.customer.product.qty.price" nameClass="masculine" name="tarif client"> |
<FIELD name="QUANTITE" label="Quantité" /> |
<FIELD name="ID_ARTICLE" label="Article" /> |
<FIELD name="ID_CLIENT" label="Client" /> |
<FIELD name="POURCENT_REMISE" label="% remise" /> |
</element> |
<element refid="humanresources.payroll.advance" nameClass="masculine" name="acompte"> |
<FIELD name="ID_SALARIE" label="Salarié" /> |
<FIELD name="MONTANT" label="Montant" /> |
241,6 → 247,7 |
<element refid="sales.credit.note" nameClass="feminine" name="facture d'avoir" namePlural="factures d'avoir"> |
<FIELD name="ID_ADRESSE" label="Adresse fact. spéc." /> |
<FIELD name="ID_ADRESSE_LIVRAISON" label="Adresse livr. spéc." /> |
<FIELD name="ID_CATEGORIE_COMPTABLE" label="Cat. comptable spéc." /> |
<FIELD name="ID_CLIENT_DEPARTEMENT" label="Service" /> |
<FIELD name="ID_SECRETAIRE" label="Secrétaire" /> |
<FIELD name="ID_ECHEANCIER_CCI" label="Echeancier CCI" /> |
386,7 → 393,7 |
<FIELD name="DATE_NAISSANCE" label="Date de naissance" /> |
</element> |
<element refid="bank" nameClass="feminine" name="banque"> |
<FIELD name="NOM" label="Nom" /> |
<FIELD name="NOM" label="Banque" /> |
<FIELD name="NUMERO_RUE" label="Numéro de rue" /> |
<FIELD name="VOIE" label="Voie" /> |
<FIELD name="RUE" label="Rue" /> |
473,6 → 480,7 |
<FIELD name="FRAIS_DOCUMENT_HT" label="Frais de document HT" /> |
<FIELD name="ID_ADRESSE" label="Adresse fact. spéc." /> |
<FIELD name="ID_ADRESSE_LIVRAISON" label="Adresse livr. spéc." /> |
<FIELD name="ID_CATEGORIE_COMPTABLE" label="Cat. comptable spéc." /> |
<FIELD name="ID_CLIENT_DEPARTEMENT" label="Service" /> |
<FIELD name="ID_CONTACT" label="Contact" /> |
<FIELD name="ID_TARIF" label="Tarif à appliquer" /> |
834,6 → 842,25 |
<FIELD name="FONCTION" label="Fonction" /> |
<FIELD name="N4DS" label="Contact pour la N4DS" /> |
</element> |
<element refid="CONTACT_SALARIE" nameClass="masculine" name="contact salarié"> |
<FIELD name="PRENOM" label="Prénom du contact" /> |
<FIELD name="NOM" label="Nom du contact" /> |
<FIELD name="ID_TITRE_PERSONNEL" label="Titre" /> |
<FIELD name="TEL_DIRECT" label="Téléphone" /> |
<FIELD name="TEL_PERSONEL" label="Téléphone Personnel" /> |
<FIELD name="TEL_STANDARD" label="Téléphone du standard" /> |
<FIELD name="TEL_MOBILE" label="Portable" /> |
<FIELD name="EMAIL" label="Mail" /> |
<FIELD name="FAX" label="Fax" /> |
<FIELD name="FONCTION" label="Lien de parenté" /> |
<FIELD name="ID_SALARIE" label="Salarié" /> |
<FIELD name="NO_MAILING" label="Pas de mailing" /> |
<FIELD name="TYPE" label="Type" /> |
<FIELD name="SERVICE" label="Service" /> |
<FIELD name="PAYS" label="Pays" /> |
<FIELD name="ID_ADRESSE" label="Adresse" /> |
<FIELD name="DATE_NAISSANCE" label="Date de naissance" /> |
</element> |
<element refid="humanresources.payroll.anticipation.contract" nameClass="masculine" |
name="contrat de prévoyance, mutuelle, formation" namePlural="contrats de prévoyance, mutuelle, formation"> |
<FIELD name="REFERENCE" label="Référence du contrat de Prévoyance (S21.G00.15.001)" /> |
880,6 → 907,7 |
<element refid="humanresources.payroll.contract.employe" nameClass="masculine" name="contrat salarié" |
namePlural="contrats salariés"> |
<FIELD name="NATURE" label="Nature de l'emploi (*)" titlelabel="Nature de l'emploi" /> |
<FIELD name="COMPLEMENT_PCS" label="Code complément PCS-ESE" /> |
<FIELD name="ID_CODE_EMPLOI" label="Catégorie socioprofessionnelle " |
titlelabel="Code Catégorie socioprofessionnelle" /> |
<FIELD name="ID_CODE_CONTRAT_TRAVAIL" label="Contrat de travail" titlelabel="Code contrat" /> |
989,6 → 1017,7 |
<FIELD name="DATE_LIVRAISON_PREV" label="Livraison prévue le" /> |
<FIELD name="ID_ADRESSE" label="Adresse fact. spéc." /> |
<FIELD name="ID_ADRESSE_LIVRAISON" label="Adresse livr. spéc." /> |
<FIELD name="ID_CATEGORIE_COMPTABLE" label="Cat. comptable spéc." /> |
<FIELD name="ID_CLIENT_DEPARTEMENT" label="Service" /> |
<FIELD name="ACOMPTE_COMMANDE" label="Acompte" /> |
<FIELD name="ID_CONTACT" label="Contact" /> |
1276,6 → 1305,7 |
<FIELD name="ID_CLIENT_DEPARTEMENT" label="Service" /> |
<FIELD name="ID_ADRESSE" label="Adresse fact. spéc." /> |
<FIELD name="ID_ADRESSE_LIVRAISON" label="Adresse livr. spéc." /> |
<FIELD name="ID_CATEGORIE_COMPTABLE" label="Cat. comptable spéc." /> |
<FIELD name="CONTACT_MAIL_RAPPORT" label="Email dest. suppl." /> |
<FIELD name="SITE_DIFF" label="Site d'intervention différent du donneur d'ordre" /> |
<FIELD name="DESIGNATION_SITE" label="Désignation du site" /> |
1578,6 → 1608,7 |
</element> |
<element refid="supplychain.order.invoice.purchase" nameClass="feminine" name="facture fournisseur" |
namePlural="factures fournisseur"> |
<FIELD name="TVA_ADJUSTMENT" label="Ajustement de TVA" /> |
<FIELD name="ID_AVOIR_FOURNISSEUR" label="Avoir" /> |
<FIELD name="NET_A_PAYER" label="Net à payer" /> |
<FIELD name="ID_TAXE_PORT" label="Taxe sur port" /> |
1607,6 → 1638,7 |
</element> |
<element refid="supplychain.orderinvoice.purchase.item" nameClass="masculine" name="élément de facture" |
namePlural="éléments de facture"> |
<FIELD name="ID_COMPTE_PCE" label="Compte charge spécifique" /> |
<FIELD name="ID_DEPOT_STOCK" label="Dépôt Stock" /> |
<FIELD name="ID_ECO_CONTRIBUTION" label="Code Eco-Contrib." /> |
<FIELD name="ECO_CONTRIBUTION" label="Dont Eco-Contrib." /> |
1814,6 → 1846,7 |
<FIELD name="DATE_SORTIE" label="Date de sortie" /> |
<FIELD name="CODE_AT" label="Code AT" /> |
<FIELD name="CODE_SECTION_AT" label="Code section AT" /> |
<FIELD name="DUREE_FORFAIT" label="Durée du forfait" /> |
</element> |
<element refid="finance.accounting.book" nameClass="masculine" name="journal"> |
<FIELD name="NOM" label="Journal" /> |
2217,6 → 2250,7 |
<FIELD name="TOTAL_TIMBRE_FISCAL" label="Total timbre" /> |
<FIELD name="ID_CLIENT_DEPARTEMENT" label="Service" /> |
<FIELD name="ID_ADRESSE_LIVRAISON" label="Adresse livr. spéc." /> |
<FIELD name="ID_CATEGORIE_COMPTABLE" label="Cat. comptable spéc." /> |
<FIELD name="ID_COMPTE_PCE_VENTE" label="Compte vente" /> |
<FIELD name="ID_ADRESSE" label="Adresse spécifique" /> |
<FIELD name="T_HA" label="Total achat" /> |
2269,6 → 2303,7 |
</element> |
<element refid="sales.invoice.item" nameClass="masculine" name="article facturé" namePlural="articles facturés"> |
<FIELD name="ID_DEPOT_STOCK" label="Dépôt Stock" /> |
<FIELD name="ID_COMPTE_PCE" label="Compte vente spécifique" /> |
<FIELD name="ID_ECO_CONTRIBUTION" label="Code Eco-Contrib." /> |
<FIELD name="ECO_CONTRIBUTION" label="Dont Eco-Contrib." /> |
<FIELD name="T_ECO_CONTRIBUTION" label="Total Eco-Contrib." /> |
2352,6 → 2387,7 |
<FIELD name="NOM" label="Nom (*)" titlelabel="Nom" /> |
<FIELD name="PRENOM" label="Prénom (*)" titlelabel="Prénom" /> |
<FIELD name="ID_TITRE_PERSONNEL" label="Titre (*)" titlelabel="Titre" /> |
<FIELD name="ID_USER_COMMON" label="Utilisateur associé" titlelabel="Utilisateur associé" /> |
<FIELD name="CODE" label="Code (*)" titlelabel="Code" /> |
<FIELD name="NOM_JEUNE_FILLE" label="Nom de jeune fille" titlelabel="Nom jeune fille" /> |
<FIELD name="ID_ETAT_CIVIL" label="Etat civil" /> |
2496,4 → 2532,12 |
<FIELD name="ControlSum" label="Total des prélèvements" /> |
<FIELD name="XML" label="Message XML" /> |
</element> |
<element refid="customerrelationship.mail.email.template" nameClass="masculine" name="modèle d'email" |
namePlural="modèles d'email"> |
<FIELD name="NOM" label="Nom du modèle" /> |
<FIELD name="TITRE" label="Titre" /> |
<FIELD name="TEXTE" label="Texte" /> |
<FIELD name="FORMAT_DATE" label="Format de date" /> |
<FIELD name="PAR_DEFAUT" label="Par défaut" /> |
</element> |
</ROOT> |
/trunk/OpenConcerto/src/org/openconcerto/erp/config/Gestion.java |
---|
51,6 → 51,7 |
import org.openconcerto.utils.FileUtils; |
import org.openconcerto.utils.ThrowableHandler; |
import org.openconcerto.utils.protocol.Helper; |
import org.openconcerto.xml.FastXMLProperties; |
import java.awt.AWTEvent; |
import java.awt.Component; |
204,6 → 205,9 |
} |
public static void main(String[] args) { |
System.setProperty("org.xml.sax.driver", "com.bluecast.xml.Piccolo"); |
System.setProperty("org.xml.sax.parser", "com.bluecast.xml.Piccolo"); |
System.setProperty("javax.xml.parsers.SAXParserFactory", "com.bluecast.xml.JAXPSAXParserFactory"); |
ComptaPropsConfiguration.checkJava(); |
// Check MacOS Sandbox |
String cwd = new File(getProperty("user.dir")).toURI().toString(); |
410,7 → 414,7 |
if (fTOS.exists()) { |
try { |
pTOS.loadFromXML(new FileInputStream(fTOS)); |
FastXMLProperties.load(pTOS, new FileInputStream(fTOS)); |
} catch (Exception e1) { |
e1.printStackTrace(); |
} |
578,7 → 582,7 |
private static void saveProperties(File fTOS, Properties pTOS) { |
try { |
final FileOutputStream outputStream = new FileOutputStream(fTOS); |
pTOS.storeToXML(outputStream, "tos", "UTF-8"); |
FastXMLProperties.store(pTOS, outputStream, "tos"); |
outputStream.close(); |
} catch (Exception e) { |
e.printStackTrace(); |
593,7 → 597,7 |
public boolean handle(String message, Throwable throwable) { |
if (throwable == null) |
return false; |
throwable.printStackTrace(); |
final ByteArrayOutputStream out = new ByteArrayOutputStream(); |
throwable.printStackTrace(new PrintStream(out)); |
String s = new String(out.toByteArray()); |
634,7 → 638,7 |
return true; |
} |
else if (s.contains("No application is associated with the specified file for this operation")) { |
else if (s.contains("No application is associated with the specified file for this operation") || s.contains("Error message: Package could not be registered")) { |
JOptionPane.showMessageDialog(null, "Merci d'installer LibreOffice ou tout autre application succeptible d'ouvrir ce fichier"); |
return true; |
} else if (s.contains("java.net.SocketTimeoutException: connect timed out")) { |
/trunk/OpenConcerto/src/org/openconcerto/erp/config/translation_pl.xml |
---|
193,6 → 193,7 |
<!-- Supplier order --> |
<action id="supplychain.order.create.purchase" label="Transfer do zakupów" /> |
<action id="supplychain.order.create.receipt" label="Transfer do zamówienia" /> |
<action id="supplychain.invoice.clone" label="Kopiuj z" /> |
<!-- Customer order --> |
<action id="sales.order.create.deliverynote" label="Transfer WZ" /> |
/trunk/OpenConcerto/src/org/openconcerto/erp/config/ComptaPropsConfiguration.java |
---|
27,10 → 27,11 |
import org.openconcerto.erp.core.common.element.StyleSQLElement; |
import org.openconcerto.erp.core.common.element.TitrePersonnelSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.ClientDepartementSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.ComptaContactSQLElement.ContactAdministratifSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.ComptaContactSQLElement.ContactFournisseurSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.ComptaContactSQLElement.ContactSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.ComptaContactSQLElement.ContactSalarieSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.CompteClientTransactionSQLELement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.ContactSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.ContactSQLElement.ContactAdministratifSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.ContactSQLElement.ContactFournisseurSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.CourrierClientSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.CustomerCategorySQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.CustomerSQLElement; |
38,6 → 39,7 |
import org.openconcerto.erp.core.customerrelationship.customer.element.ReferenceClientSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.RelanceSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.TypeLettreRelanceSQLElement; |
import org.openconcerto.erp.core.customerrelationship.mail.EmailTemplateSQLElement; |
import org.openconcerto.erp.core.edm.AttachmentSQLElement; |
import org.openconcerto.erp.core.finance.accounting.element.AssociationAnalytiqueSQLElement; |
import org.openconcerto.erp.core.finance.accounting.element.AssociationCompteAnalytiqueSQLElement; |
172,6 → 174,7 |
import org.openconcerto.erp.core.sales.product.element.ArticleFournisseurSecondaireSQLElement; |
import org.openconcerto.erp.core.sales.product.element.ArticleTarifSQLElement; |
import org.openconcerto.erp.core.sales.product.element.CoutRevientSQLElement; |
import org.openconcerto.erp.core.sales.product.element.CustomerProductQtyPriceSQLElement; |
import org.openconcerto.erp.core.sales.product.element.EcoContributionSQLElement; |
import org.openconcerto.erp.core.sales.product.element.FamilleArticleSQLElement; |
import org.openconcerto.erp.core.sales.product.element.FamilleEcoContributionSQLElement; |
227,6 → 230,7 |
import org.openconcerto.erp.generationDoc.provider.AdresseVilleClientValueProvider; |
import org.openconcerto.erp.generationDoc.provider.AdresseVilleNomClientValueProvider; |
import org.openconcerto.erp.generationDoc.provider.ArticleCodeClientProvider; |
import org.openconcerto.erp.generationDoc.provider.ArticleCodeFournisseurProvider; |
import org.openconcerto.erp.generationDoc.provider.ConditionsReglementDetailsProvider; |
import org.openconcerto.erp.generationDoc.provider.DateBLProvider; |
import org.openconcerto.erp.generationDoc.provider.DateProvider; |
240,6 → 244,7 |
import org.openconcerto.erp.generationDoc.provider.PrixUVProvider; |
import org.openconcerto.erp.generationDoc.provider.PrixUnitaireProvider; |
import org.openconcerto.erp.generationDoc.provider.PrixUnitaireRemiseProvider; |
import org.openconcerto.erp.generationDoc.provider.QteTotalDocProvider; |
import org.openconcerto.erp.generationDoc.provider.QteTotalProvider; |
import org.openconcerto.erp.generationDoc.provider.RecapFactureProvider; |
import org.openconcerto.erp.generationDoc.provider.RefClientValueProvider; |
269,6 → 274,8 |
import org.openconcerto.erp.injector.CommandeCliCommandeSQLInjector; |
import org.openconcerto.erp.injector.CommandeFactureAchatSQLInjector; |
import org.openconcerto.erp.injector.CommandeFactureClientSQLInjector; |
import org.openconcerto.erp.injector.CommandeFactureEltSQLInjector; |
import org.openconcerto.erp.injector.CommandeFactureFournisseurSQLInjector; |
import org.openconcerto.erp.injector.DevisBlEltSQLInjector; |
import org.openconcerto.erp.injector.DevisBlSQLInjector; |
import org.openconcerto.erp.injector.DevisCommandeFournisseurSQLInjector; |
298,7 → 305,6 |
import org.openconcerto.sql.model.DBStructureItemNotFound; |
import org.openconcerto.sql.model.DBSystemRoot; |
import org.openconcerto.sql.model.FieldMapper; |
import org.openconcerto.sql.model.LoadingListener; |
import org.openconcerto.sql.model.SQLDataSource; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLServer; |
338,14 → 344,8 |
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; |
605,6 → 605,7 |
AdresseVilleNomClientValueProvider.register(); |
AdresseFullClientValueProvider.register(); |
QteTotalProvider.register(); |
QteTotalDocProvider.register(); |
StockLocationProvider.register(); |
RefClientValueProvider.register(); |
ModeDeReglementDetailsProvider.register(); |
618,62 → 619,10 |
RecapFactureProvider.register(); |
RestantAReglerProvider.register(); |
SaledTotalNotDiscountedProvider.register(); |
ArticleCodeFournisseurProvider.register(); |
} |
@Override |
protected void initSystemRoot(DBSystemRoot input) { |
super.initSystemRoot(input); |
if (!GraphicsEnvironment.isHeadless()) { |
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) { |
final Thread thread = new Thread(r, "Loading listener thread"); |
thread.setDaemon(true); |
return 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); |
f.dispose(); |
} |
}); |
} 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); |
862,7 → 811,7 |
dir.addSQLElement(AttachmentSQLElement.class); |
dir.addSQLElement(CustomerProductQtyPriceSQLElement.class); |
dir.addSQLElement(EtatStockSQLElement.class); |
dir.addSQLElement(EtatStockItemSQLElement.class); |
dir.addSQLElement(ArticleTarifSQLElement.class); |
882,6 → 831,7 |
dir.addSQLElement(CoefficientPrimeSQLElement.class); |
dir.addSQLElement(ContactFournisseurSQLElement.class); |
dir.addSQLElement(ContactAdministratifSQLElement.class); |
dir.addSQLElement(ContactSalarieSQLElement.class); |
dir.addSQLElement(new TitrePersonnelSQLElement()); |
dir.addSQLElement(new ContactSQLElement()); |
dir.addSQLElement(new SaisieKmItemSQLElement()); |
1065,6 → 1015,7 |
dir.addSQLElement(CalendarItemSQLElement.class); |
dir.addSQLElement(CalendarItemGroupSQLElement.class); |
dir.addSQLElement(DeviseHistoriqueSQLElement.class); |
dir.addSQLElement(EmailTemplateSQLElement.class); |
if (getRootSociete().contains("FWK_LIST_PREFS")) { |
dir.addSQLElement(new FWKListPrefs(getRootSociete())); |
1122,6 → 1073,7 |
public static void setSocieteSQLInjector(final DBRoot rootSociete) { |
new AchatAvoirSQLInjector(rootSociete); |
new CommandeFactureEltSQLInjector(rootSociete); |
new ArticleCommandeEltSQLInjector(rootSociete); |
new CommandeCliCommandeSQLInjector(rootSociete); |
new FactureAvoirSQLInjector(rootSociete); |
1141,6 → 1093,7 |
new CommandeBrSQLInjector(rootSociete); |
new BonReceptionFactureFournisseurSQLInjector(rootSociete); |
new CommandeFactureAchatSQLInjector(rootSociete); |
new CommandeFactureFournisseurSQLInjector(rootSociete); |
new EcheanceEncaisseSQLInjector(rootSociete); |
new EcheanceRegleSQLInjector(rootSociete); |
new BrFactureAchatSQLInjector(rootSociete); |
1181,7 → 1134,7 |
if (getRootSociete().getTable("CLIENT").getFieldsName().contains("LOCALISATION")) { |
showAs.show("CLIENT", "NOM", "LOCALISATION"); |
} else { |
SQLPreferences prefs = new SQLPreferences(root); |
SQLPreferences prefs = SQLPreferences.getMemCached(root); |
if (prefs.getBoolean(GestionClientPreferencePanel.DISPLAY_CLIENT_PCE, false)) { |
showAs.show("CLIENT", "ID_PAYS", "GROUPE", "NOM", "ID_COMPTE_PCE"); |
} else { |
1227,12 → 1180,14 |
final List<String> lEchFact = new ArrayList<String>(); |
lEchFact.add("NUMERO"); |
lEchFact.add("DATE"); |
lEchFact.add("ID_MODE_REGLEMENT"); |
lEchFact.add("ID_COMMERCIAL"); |
SQLTable tableEch = root.getTable("ECHEANCE_CLIENT"); |
showAs.show(tableEch.getField("ID_SAISIE_VENTE_FACTURE"), lEchFact); |
showAs.show("ECHEANCE_FOURNISSEUR", SQLRow.toList("ID_FOURNISSEUR,ID_MOUVEMENT")); |
showAs.show("FICHE_PAYE", SQLRow.toList("ID_MOIS,ANNEE")); |
showAs.show("FICHE_PAYE", SQLRow.toList("ID_MOIS,ANNEE,ID_PROFIL_PAYE")); |
showAs.show("FOURNISSEUR", "NOM"); |
showAs.show("IDCC", "NOM"); |
1305,6 → 1260,16 |
public void setUpSocieteDataBaseConnexion(int base) { |
final String customerName = setUpSocieteStructure(base); |
final DBRoot rootSociete = this.getRootSociete(); |
try { |
// create table if necessary |
SQLPreferences.getPrefTable(rootSociete); |
SQLPreferences.startMemCached(rootSociete); |
} catch (Exception e) { |
// don't die now, we might not need them |
ExceptionHandler.handle("Impossible d'accéder aux préférences", e); |
} |
closeSocieteConnexion(); |
setSocieteDirectory(); |
NumerotationAutoSQLElement.addListeners(); |
1318,15 → 1283,6 |
// Prefetch undefined |
rootSociete.getTables().iterator().next().getUndefinedID(); |
try { |
// create table if necessary |
SQLPreferences.getPrefTable(rootSociete); |
SQLPreferences.startMemCached(rootSociete); |
} catch (Exception e) { |
// don't die now, we might not need them |
ExceptionHandler.handle("Impossible d'accéder aux préférences", e); |
} |
this.getModuleManager().addFactories(Gestion.MODULES_DIR); |
this.getModuleManager().setup(this.getRootSociete(), this); |
} |
1337,9 → 1293,7 |
public void setupBarCodeIfNeeded() { |
final DBRoot rootSociete = this.getRootSociete(); |
// TODO check is the SQLPreferences returned by startMemCached() can be used |
SQLPreferences pref = new SQLPreferences(rootSociete); |
SQLPreferences pref = SQLPreferences.getMemCached(rootSociete); |
if (pref.getBoolean(GestionCommercialeGlobalPreferencePanel.BARCODE_INSERTION, false)) { |
this.barcodeReader = new BarcodeReader(80); |
this.barcodeReader.start(); |
/trunk/OpenConcerto/src/org/openconcerto/erp/config/translation_en.xml |
---|
196,7 → 196,8 |
<!-- Supplier order --> |
<action id="supplychain.order.create.purchase" label="Transfer to purchase" /> |
<action id="supplychain.order.create.receipt" label="Transfer to supplier receipt" /> |
<action id="supplychain.invoice.clone" label="Copy from" /> |
<!-- Customer order --> |
<action id="sales.order.create.deliverynote" label="Transfer to delivey note" /> |
<action id="sales.order.create.invoice" label="Transfer to invoice" /> |
397,5 → 398,5 |
<item id="product.bom.expose" label="Expose BOM" /> |
<item id="product.bom.flat" label="Flat BOM" /> |
<action id="email" label="Email" /> |
</translation> |
/trunk/OpenConcerto/src/org/openconcerto/erp/config/DefaultMenuConfiguration.java |
---|
28,6 → 28,7 |
import org.openconcerto.erp.core.customerrelationship.customer.action.ListeDesDepartementsClientsAction; |
import org.openconcerto.erp.core.customerrelationship.customer.action.NouvelHistoriqueListeClientAction; |
import org.openconcerto.erp.core.customerrelationship.mail.action.ListeDesCourriersClientsAction; |
import org.openconcerto.erp.core.customerrelationship.mail.action.ListeDesModelesEmailAction; |
import org.openconcerto.erp.core.finance.accounting.action.BalanceAgeeAction; |
import org.openconcerto.erp.core.finance.accounting.action.CompteResultatBilanAction; |
import org.openconcerto.erp.core.finance.accounting.action.EtatBalanceAction; |
68,6 → 69,7 |
import org.openconcerto.erp.core.finance.payment.action.NouveauDecaissementChequeAvoirAction; |
import org.openconcerto.erp.core.finance.payment.action.NouveauListeDesChequesADecaisserAction; |
import org.openconcerto.erp.core.finance.payment.action.NouveauListeDesChequesAEncaisserAction; |
import org.openconcerto.erp.core.finance.payment.element.EncaisserMontantSQLElement; |
import org.openconcerto.erp.core.finance.tax.action.ReportingEcoContributionPanel; |
import org.openconcerto.erp.core.finance.tax.action.ReportingTaxeComplementairePanel; |
import org.openconcerto.erp.core.humanresources.ListeDesContactsAdministratif; |
92,6 → 94,7 |
import org.openconcerto.erp.core.reports.stat.action.EvolutionCmdAction; |
import org.openconcerto.erp.core.reports.stat.action.EvolutionCmdCumulAction; |
import org.openconcerto.erp.core.reports.stat.action.EvolutionMargeAction; |
import org.openconcerto.erp.core.reports.stat.action.ReportingCommercialAction; |
import org.openconcerto.erp.core.reports.stat.action.VenteArticleFamilleGraphAction; |
import org.openconcerto.erp.core.reports.stat.action.VenteArticleGraphAction; |
import org.openconcerto.erp.core.reports.stat.action.VenteArticleMargeGraphAction; |
101,6 → 104,7 |
import org.openconcerto.erp.core.sales.invoice.action.GenEtatStockAction; |
import org.openconcerto.erp.core.sales.invoice.action.GenListeVenteAction; |
import org.openconcerto.erp.core.sales.invoice.action.GenReportingVenteAction; |
import org.openconcerto.erp.core.sales.invoice.action.ImportReglementSageAction; |
import org.openconcerto.erp.core.sales.invoice.action.ListeDebiteursAction; |
import org.openconcerto.erp.core.sales.invoice.action.ListeDesElementsFactureAction; |
import org.openconcerto.erp.core.sales.invoice.action.ListeDesFactureItemsAction; |
121,6 → 125,7 |
import org.openconcerto.erp.core.sales.product.action.ListeDesArticlesAction; |
import org.openconcerto.erp.core.sales.product.action.ListeEcoContributionAction; |
import org.openconcerto.erp.core.sales.product.action.ListeHistoCodeClientArticleAction; |
import org.openconcerto.erp.core.sales.product.action.TransfertStockAction; |
import org.openconcerto.erp.core.sales.quote.action.ListeDesDevisAction; |
import org.openconcerto.erp.core.sales.quote.action.ListeDesDevisActionTCP; |
import org.openconcerto.erp.core.sales.quote.action.ListeDesElementsDevisAction; |
294,6 → 299,7 |
supplierGroup.addItem("supplier.credit.create"); |
group.addItem("stock.io.create"); |
} |
group.addItem("product.stock.transfert"); |
return group; |
} |
328,7 → 334,7 |
gUser.addItem("user.task.right"); |
group.add(gUser); |
} |
group.addItem("email.template.list"); |
group.addItem("product.ecotax"); |
group.addItem("office.contact.list"); |
group.addItem("salesman.list"); |
414,6 → 420,7 |
group.addItem("sales.list.reporting"); |
group.addItem("order.list.reporting"); |
group.addItem("sales.list.report"); |
group.addItem("sales.list.salesman.report"); |
group.addItem("sales.product.graph"); |
group.addItem("sales.product.margin.graph"); |
group.addItem("sales.product.family.graph"); |
599,6 → 606,7 |
mManager.putAction(new NouveauSaisieVenteFactureAction(conf), "customer.invoice.create"); |
mManager.putAction(new NouveauAvoirClientAction(conf), "customer.credit.create"); |
mManager.putAction(new TransfertStockAction(conf), "product.stock.transfert"); |
if (rights.haveRight(NXRights.LOCK_MENU_ACHAT.getCode())) { |
mManager.putAction(new NouvelleDemandePrixAction(conf), "supplier.order.ask.create"); |
710,8 → 718,8 |
} |
public void registerStatsMenuActions(final MenuAndActions mManager) { |
final ComptaPropsConfiguration conf = getConfiguration(); |
mManager.putAction(new EvolutionCAAction(), "sales.graph"); |
mManager.putAction(new EvolutionCACumulAction(), "sales.graph.cumulate"); |
718,6 → 726,8 |
mManager.putAction(new EvolutionCmdAction(), "sales.graph.cmd"); |
mManager.putAction(new EvolutionCmdCumulAction(), "sales.graph.cmd.cumulate"); |
mManager.putAction(new ReportingCommercialAction(conf.getRootSociete()), "sales.list.salesman.report"); |
mManager.putAction(new EvolutionMargeAction(), "sales.margin.graph"); |
mManager.putAction(new GenReportingVenteAction(false), "sales.list.reporting"); |
mManager.putAction(new GenReportingVenteAction(true), "order.list.reporting"); |
763,6 → 773,7 |
if (rights.haveRight(NXRights.GESTION_ENCAISSEMENT.getCode())) { |
mManager.putAction(new ListesFacturesClientsImpayeesAction(), "customer.invoice.unpaid.list"); |
mManager.putAction(new ImportReglementSageAction(conf.getDirectory().getElement(EncaisserMontantSQLElement.class)), "customer.invoice.payment.xml.sage.import"); |
mManager.putAction(new ListeDebiteursAction(), "customer.dept.list"); |
mManager.putAction(new AbstractAction("Relevé client") { |
@Override |
839,7 → 850,7 |
mManager.putAction(new GestionDroitsAction(), "user.right.list"); |
mManager.putAction(new TaskAdminAction(), "user.task.right"); |
} |
mManager.putAction(new ListeDesModelesEmailAction(), "email.template.list"); |
mManager.putAction(new ListeDesContactsAdministratif(), "office.contact.list"); |
mManager.putAction(new ListeDesCommerciauxAction(), "salesman.list"); |
mManager.putAction(new ListeDesCaissesTicketAction(), "pos.list"); |
/trunk/OpenConcerto/src/org/openconcerto/erp/config/mapping_fr.xml |
---|
1,5 → 1,15 |
<?xml version="1.0" encoding="UTF-8" ?> |
<ROOT> |
<element refid="sales.customer.product.qty.price" nameClass="masculine" name="tarif client"> |
<FIELD name="QUANTITE" label="Quantité" /> |
<FIELD name="ID_ARTICLE" label="Article" /> |
<FIELD name="ID_CLIENT" label="Client" /> |
<FIELD name="POURCENT_REMISE" label="% remise" /> |
</element> |
<element refid="common.address" nameClass="feminine" name="adresse"> |
<FIELD name="RAISON_SOCIALE" label="Raison sociale" /> |
<FIELD name="RUE" label="Rue" /> |
266,4 → 276,6 |
<FIELD name="FORMULE" label="Formule" /> |
<FIELD name="INFOS" label="Description" /> |
</element> |
</ROOT> |
/trunk/OpenConcerto/src/org/openconcerto/erp/config/update/Updater_1_5.java |
---|
15,6 → 15,7 |
import org.openconcerto.erp.config.InstallationPanel; |
import org.openconcerto.erp.core.common.ui.AbstractVenteArticleItemTable; |
import org.openconcerto.erp.core.customerrelationship.mail.EmailTemplateSQLElement; |
import org.openconcerto.erp.core.finance.payment.element.SDDMessageSQLElement; |
import org.openconcerto.erp.core.finance.payment.element.SEPAMandateSQLElement; |
import org.openconcerto.erp.core.finance.payment.element.TypeReglementSQLElement; |
23,6 → 24,7 |
import org.openconcerto.erp.core.sales.pos.element.TicketCaisseSQLElement; |
import org.openconcerto.erp.core.sales.product.element.ReferenceArticleSQLElement; |
import org.openconcerto.erp.core.sales.quote.element.DevisLogMailSQLElement; |
import org.openconcerto.erp.core.supplychain.stock.element.ComposedItemStockUpdater; |
import org.openconcerto.erp.core.supplychain.stock.element.DepotStockSQLElement; |
import org.openconcerto.erp.core.supplychain.stock.element.StockItem; |
import org.openconcerto.sql.changer.convert.AddMDFields; |
37,6 → 39,7 |
import org.openconcerto.sql.model.SQLSyntax; |
import org.openconcerto.sql.model.SQLSystem; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.model.SQLTable.Index; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.preferences.SQLPreferences; |
import org.openconcerto.sql.request.UpdateBuilder; |
58,6 → 61,7 |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
import java.util.Set; |
import java.util.prefs.BackingStoreException; |
import org.apache.commons.dbutils.handlers.ArrayListHandler; |
1790,6 → 1794,14 |
root.refetchTable("VARIABLE_SALARIE"); |
root.getSchema().updateVersion(); |
} |
SQLTable tableBL = root.getTable("BON_DE_LIVRAISON"); |
if (!tableBL.contains("ID_COMMERCIAL")) { |
final AlterTable alterB = new AlterTable(tableBL); |
alterB.addForeignColumn("ID_COMMERCIAL", root.getTable("COMMERCIAL")); |
root.getBase().getDataSource().execute(alterB.asString()); |
root.refetchTable("BON_DE_LIVRAISON"); |
root.getSchema().updateVersion(); |
} |
// fix stock |
{ |
1857,17 → 1869,151 |
} |
} |
// Tarification client par quantite |
if (root.getTable("TARIF_ARTICLE_CLIENT") == null) { |
final SQLCreateTable createTableQtyTarif = new SQLCreateTable(root, "TARIF_ARTICLE_CLIENT"); |
createTableQtyTarif.addForeignColumn("ID_ARTICLE", root.getTable("ARTICLE")); |
createTableQtyTarif.addForeignColumn("ID_CLIENT", root.getTable("CLIENT")); |
createTableQtyTarif.addDecimalColumn("QUANTITE", 16, 3, BigDecimal.ONE, false); |
createTableQtyTarif.addDecimalColumn("POURCENT_REMISE", 16, 3, null, true); |
// createTableQtyTarif.addDecimalColumn("PRIX_METRIQUE_VT_1", 16, 6, null, true); |
try { |
root.getBase().getDataSource().execute(createTableQtyTarif.asString()); |
InstallationPanel.insertUndef(createTableQtyTarif); |
root.refetchTable("TARIF_ARTICLE_CLIENT"); |
root.getSchema().updateVersion(); |
} catch (SQLException ex) { |
throw new IllegalStateException("Erreur lors de la création de la table " + "TARIF_QUANTITE", ex); |
} |
} |
SQLTable tableTrCmd = root.getTable("TR_COMMANDE"); |
if (!tableTrCmd.contains("ID_FACTURE_FOURNISSEUR")) { |
AlterTable t = new AlterTable(tableTrCmd); |
t.addForeignColumn("ID_FACTURE_FOURNISSEUR", root.getTable("FACTURE_FOURNISSEUR")); |
tableTrCmd.getBase().getDataSource().execute(t.asString()); |
root.refetchTable(tableTrCmd.getName()); |
root.getSchema().updateVersion(); |
} |
SQLTable tableContrat = root.getTable("CONTRAT_SALARIE"); |
if (!tableContrat.contains("COMPLEMENT_PCS")) { |
AlterTable t = new AlterTable(tableContrat); |
t.addVarCharColumn("COMPLEMENT_PCS", 54); |
tableContrat.getBase().getDataSource().execute(t.asString()); |
root.refetchTable(tableContrat.getName()); |
root.getSchema().updateVersion(); |
} |
List<String> tablesCatComptable = Arrays.asList("DEVIS", "COMMANDE_CLIENT", "BON_DE_LIVRAISON", "SAISIE_VENTE_FACTURE", "AVOIR_CLIENT"); |
for (String tableToUp : tablesCatComptable) { |
final SQLTable tableCatComptToAdd = root.getTable(tableToUp); |
if (!tableCatComptToAdd.contains("ID_CATEGORIE_COMPTABLE")) { |
final AlterTable alter = new AlterTable(tableCatComptToAdd); |
alter.addForeignColumn("ID_CATEGORIE_COMPTABLE", root.getTable("CATEGORIE_COMPTABLE")); |
exec(alter); |
root.refetchTable(tableToUp); |
root.getSchema().updateVersion(); |
} |
} |
// Modèles pour les emails |
if (!root.contains(EmailTemplateSQLElement.TABLE_NAME)) { |
final SQLCreateTable createTable = new SQLCreateTable(root, EmailTemplateSQLElement.TABLE_NAME); |
createTable.addVarCharColumn("NOM", 80); |
createTable.addVarCharColumn("TITRE", 80); |
createTable.addVarCharColumn("TEXTE", 4096); |
createTable.addVarCharColumn("FORMAT_DATE", 20); |
createTable.addBooleanColumn("PAR_DEFAUT", Boolean.FALSE, false); |
try { |
root.getBase().getDataSource().execute(createTable.asString()); |
InstallationPanel.insertUndef(createTable); |
root.refetchTable(EmailTemplateSQLElement.TABLE_NAME); |
root.getSchema().updateVersion(); |
} catch (SQLException ex) { |
throw new IllegalStateException("Erreur lors de la création de la table " + EmailTemplateSQLElement.TABLE_NAME, ex); |
} |
} |
// Force undefined policy to inDb |
root.setMetadata(SQLTable.UNDEFINED_ID_POLICY, "inDB"); |
final Map<String, Number> mapTableNameUndefined = SQLTable.getUndefIDs(root.getSchema()); |
final Set<String> tables = root.getSchema().getTableNames(); |
for (String tName : tables) { |
if (!mapTableNameUndefined.containsKey(tName)) { |
System.err.println("Updater_1_5.update() adding undefined in db for " + tName); |
SQLTable.setUndefID(root.getSchema(), tName, null); |
} |
} |
// Création de la table Modéle |
if (!root.contains("CONTACT_SALARIE")) { |
SQLCreateTable createModele = new SQLCreateTable(root, "CONTACT_SALARIE"); |
createModele.addVarCharColumn("NOM", 256); |
createModele.addVarCharColumn("PRENOM", 256); |
createModele.addVarCharColumn("TEL_DIRECT", 256); |
createModele.addVarCharColumn("TEL_MOBILE", 256); |
createModele.addVarCharColumn("EMAIL", 256); |
createModele.addVarCharColumn("FAX", 256); |
createModele.addVarCharColumn("FONCTION", 256); |
createModele.addVarCharColumn("TEL_PERSONEL", 256); |
createModele.addVarCharColumn("TEL_STANDARD", 256); |
createModele.addForeignColumn("ID_TITRE_PERSONNEL", root.findTable("TITRE_PERSONNEL")); |
createModele.addForeignColumn("ID_SALARIE", root.findTable("SALARIE")); |
try { |
root.getBase().getDataSource().execute(createModele.asString()); |
root.refetchTable("CONTACT_SALARIE"); |
SQLRowValues rowVals = new SQLRowValues(root.getTable("CONTACT_SALARIE")); |
SQLRow rowInserted = rowVals.commit(); |
SQLTable.setUndefID(root.getSchema(), "CONTACT_SALARIE", rowInserted.getID()); |
tableDevis.getSchema().updateVersion(); |
} catch (SQLException ex) { |
throw new IllegalStateException("Erreur lors de la création de la table MODELE", ex); |
} |
} |
final SQLTable tableRgltPaye = root.getTable("REGLEMENT_PAYE"); |
if (!tableRgltPaye.contains("IBAN")) { |
final AlterTable alter = new AlterTable(tableRgltPaye); |
alter.addVarCharColumn("IBAN", 128); |
exec(alter); |
root.refetchTable(tableRgltPaye.getName()); |
root.getSchema().updateVersion(); |
} |
if (!tableRgltPaye.contains("BIC")) { |
final AlterTable alter = new AlterTable(tableRgltPaye); |
alter.addVarCharColumn("BIC", 40); |
exec(alter); |
root.refetchTable(tableRgltPaye.getName()); |
root.getSchema().updateVersion(); |
} |
final SQLTable tableSalarie = root.getTable("SALARIE"); |
if (!tableSalarie.contains("ID_USER_COMMON")) { |
final AlterTable alter = new AlterTable(tableSalarie); |
alter.addForeignColumn("ID_USER_COMMON", root.findTable("USER_COMMON")); |
exec(alter); |
root.refetchTable(tableSalarie.getName()); |
root.getSchema().updateVersion(); |
} |
final SQLTable tableInfosSalarie = root.getTable("INFOS_SALARIE_PAYE"); |
if (!tableInfosSalarie.contains("DUREE_FORFAIT")) { |
final AlterTable alter = new AlterTable(tableInfosSalarie); |
alter.addColumn("DUREE_FORFAIT", "real"); |
exec(alter); |
root.refetchTable(tableSalarie.getName()); |
root.getSchema().updateVersion(); |
} |
} |
public static void initStock(SQLRow row) { |
SQLSelect sel = new SQLSelect(); |
sel.addSelectStar(row.getTable().getTable("DEPOT_STOCK")); |
List<SQLRow> rowsDepot = SQLRowListRSH.execute(sel); |
public static void initStock(SQLRow rowArticle, int idDepot) { |
SQLSelect selStock = new SQLSelect(); |
selStock.addSelectStar(row.getTable().getTable("STOCK")); |
selStock.setWhere(new Where(row.getTable().getTable("STOCK").getField("ID_ARTICLE"), "=", row.getID())); |
selStock.addSelectStar(rowArticle.getTable().getTable("STOCK")); |
selStock.setWhere(new Where(rowArticle.getTable().getTable("STOCK").getField("ID_ARTICLE"), "=", rowArticle.getID())); |
List<SQLRow> rowsStock = SQLRowListRSH.execute(selStock); |
Map<Integer, SQLRow> initedDepot = new HashMap<>(); |
for (SQLRow sqlRow : rowsStock) { |
1875,47 → 2021,51 |
} |
List<StockItem> stockItems = new ArrayList<StockItem>(); |
for (SQLRow sqlRow : rowsDepot) { |
try { |
if (!initedDepot.keySet().contains(sqlRow.getID())) { |
SQLRowValues rowVals = new SQLRowValues(row.getTable().getTable("STOCK")); |
rowVals.put("ID_ARTICLE", row.getID()); |
rowVals.put("ID_DEPOT_STOCK", sqlRow.getID()); |
try { |
if (!initedDepot.keySet().contains(idDepot)) { |
SQLRowValues rowVals = new SQLRowValues(rowArticle.getTable().getTable("STOCK")); |
rowVals.put("ID_ARTICLE", rowArticle.getID()); |
rowVals.put("ID_DEPOT_STOCK", idDepot); |
SQLRow rowStock = rowVals.commit(); |
if ((row.getObject("ID_DEPOT_STOCK") == null || row.isForeignEmpty("ID_DEPOT_STOCK")) && sqlRow.getID() == DepotStockSQLElement.DEFAULT_ID) { |
row.createEmptyUpdateRow().put("ID_STOCK", rowStock.getID()).put("ID_DEPOT_STOCK", DepotStockSQLElement.DEFAULT_ID).commit(); |
} else if (sqlRow.getID() == row.getForeignID("ID_DEPOT_STOCK")) { |
row.createEmptyUpdateRow().put("ID_STOCK", rowStock.getID()).commit(); |
} |
stockItems.add(new StockItem(row, rowStock)); |
SQLRow rowStock = rowVals.commit(); |
if ((rowArticle.getObject("ID_DEPOT_STOCK") == null || rowArticle.isForeignEmpty("ID_DEPOT_STOCK")) && idDepot == DepotStockSQLElement.DEFAULT_ID) { |
rowArticle.createEmptyUpdateRow().put("ID_STOCK", rowStock.getID()).put("ID_DEPOT_STOCK", DepotStockSQLElement.DEFAULT_ID).commit(); |
} else if (idDepot == rowArticle.getForeignID("ID_DEPOT_STOCK")) { |
rowArticle.createEmptyUpdateRow().put("ID_STOCK", rowStock.getID()).commit(); |
} |
stockItems.add(new StockItem(rowArticle, rowStock)); |
} else { |
SQLRow rowExisting = initedDepot.get(sqlRow.getID()); |
if ((row.getObject("ID_DEPOT_STOCK") == null || row.isForeignEmpty("ID_DEPOT_STOCK")) && sqlRow.getID() == DepotStockSQLElement.DEFAULT_ID) { |
row.createEmptyUpdateRow().put("ID_STOCK", rowExisting.getID()).put("ID_DEPOT_STOCK", DepotStockSQLElement.DEFAULT_ID).commit(); |
} else if (sqlRow.getID() == row.getForeignID("ID_DEPOT_STOCK")) { |
row.createEmptyUpdateRow().put("ID_STOCK", rowExisting.getID()).commit(); |
} |
stockItems.add(new StockItem(row, rowExisting)); |
} else { |
SQLRow rowExisting = initedDepot.get(idDepot); |
if ((rowArticle.getObject("ID_DEPOT_STOCK") == null || rowArticle.isForeignEmpty("ID_DEPOT_STOCK")) && idDepot == DepotStockSQLElement.DEFAULT_ID) { |
rowArticle.createEmptyUpdateRow().put("ID_STOCK", rowExisting.getID()).put("ID_DEPOT_STOCK", DepotStockSQLElement.DEFAULT_ID).commit(); |
} else if (idDepot == rowArticle.getForeignID("ID_DEPOT_STOCK")) { |
rowArticle.createEmptyUpdateRow().put("ID_STOCK", rowExisting.getID()).commit(); |
} |
stockItems.add(new StockItem(rowArticle, rowExisting)); |
} |
} catch (SQLException e) { |
ExceptionHandler.handle("Erreur lors de l'initialisation du stock de l'article", e); |
} |
if (rowArticle.getReferentRows(rowArticle.getTable().getTable("ARTICLE_ELEMENT").getField("ID_ARTICLE_PARENT")).size() > 0) { |
ComposedItemStockUpdater up = new ComposedItemStockUpdater(rowArticle.getTable().getDBRoot(), stockItems); |
try { |
up.updateNomenclature(stockItems); |
} catch (SQLException e) { |
ExceptionHandler.handle("Erreur lors de l'initialisation du stock de l'article", e); |
ExceptionHandler.handle("Erreur lors de l'actualisation du stock!", e); |
} |
} |
// if |
// (row.getReferentRows(row.getTable().getTable("ARTICLE_ELEMENT").getField("ID_ARTICLE_PARENT")).size() |
// > 0) { |
// ComposedItemStockUpdater up = new ComposedItemStockUpdater(row.getTable().getDBRoot(), |
// stockItems); |
// try { |
// up.updateNomenclature(stockItems); |
// } catch (SQLException e) { |
// ExceptionHandler.handle("Erreur lors de l'actualisation du stock!", e); |
// } |
// } |
} |
public static void initStock(SQLRow row) { |
int foreignID = DepotStockSQLElement.DEFAULT_ID; |
if (row.getObject("ID_DEPOT_STOCK") != null && !row.isForeignEmpty("ID_DEPOT_STOCK")) { |
foreignID = row.getForeignID("ID_DEPOT_STOCK"); |
} |
initStock(row, foreignID); |
} |
public static void exec(final AlterTable alter) throws SQLException { |
alter.getTable().getDBSystemRoot().getDataSource().execute(alter.asString()); |
alter.getTable().getSchema().updateVersion(); |
/trunk/OpenConcerto/src/org/openconcerto/erp/config/translation_es.xml |
---|
200,6 → 200,7 |
<action id="supplychain.order.create.purchase" label="Transferencia hacia introducción de compra" /> |
<action id="supplychain.order.valid" label="Marcar como validada" /> |
<action id="supplychain.order.create.receipt" label="Transferencia hacia álbaran de entrada" /> |
<action id="supplychain.invoice.clone" label="Crear a partir de" /> |
<!-- Customer order --> |
<action id="sales.order.create.deliverynote" label="Transferencia hacia álabaran de salida" /> |
/trunk/OpenConcerto/src/org/openconcerto/erp/action/CreateIListFrameAbstractAction.java |
---|
27,6 → 27,10 |
super(conf, clazz); |
} |
protected CreateIListFrameAbstractAction(final ComptaPropsConfiguration conf, final E elem) { |
super(conf, elem); |
} |
protected SQLTableModelSource createTableSource() { |
return this.getElem().createTableSource(); |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/action/CreateEditFrameAbstractAction.java |
---|
29,7 → 29,11 |
private static final String[] TRANSLATION_KEY_ARRAY = new String[] { TRANSLATION_KEY }; |
protected CreateEditFrameAbstractAction(final PropsConfiguration conf, final Class<? extends E> clazz) { |
super(conf.getDirectory().getElement(clazz)); |
this(conf, conf.getDirectory().getElementOfClass(clazz, true)); |
} |
protected CreateEditFrameAbstractAction(final PropsConfiguration conf, final E elem) { |
super(elem); |
// TODO use conf to find TM |
final NounClass nounClass = this.getElem().getName().getNounClass(); |
final String[] translationKeys = nounClass == null ? TRANSLATION_KEY_ARRAY : new String[] { TRANSLATION_KEY + '.' + nounClass.getName(), TRANSLATION_KEY }; |
/trunk/OpenConcerto/src/org/openconcerto/erp/action/NouvelleConnexionAction.java |
---|
293,6 → 293,11 |
} |
static public void initCache(final ComptaPropsConfiguration comptaConf) { |
initCache(comptaConf, 600); |
} |
static public void initCache(final ComptaPropsConfiguration comptaConf, final int timeout) { |
final SQLBase baseSociete = comptaConf.getSQLBaseSociete(); |
Thread t = new Thread() { |
@Override |
299,7 → 304,7 |
public void run() { |
// laisse le temps au logiciel de demarrer |
try { |
Thread.sleep(1000); |
Thread.sleep(10000); |
} catch (InterruptedException e) { |
e.printStackTrace(); |
} |
310,19 → 315,19 |
Ville.init(new NXDatabaseAccessor(comptaConf), prefs.getBoolean(GestionClientPreferencePanel.LOAD_CITIES, true)); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("TAXE"), 600); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("ETAT_DEVIS"), 600); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("PREFS_COMPTE"), 600); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("COMPTE_PCE"), 600); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("JOURNAL"), 600); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("TAXE"), timeout); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("ETAT_DEVIS"), timeout); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("PREFS_COMPTE"), timeout); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("COMPTE_PCE"), timeout); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("JOURNAL"), timeout); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("COMMERCIAL"), 600); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("PERIODE_VALIDITE"), 1000); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("COMMERCIAL"), timeout); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("PERIODE_VALIDITE"), timeout); |
if (comptaConf.getRootSociete().contains("DEPOT_STOCK")) { |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("DEPOT_STOCK"), 600); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("DEPOT_STOCK"), timeout); |
} |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("TYPE_REGLEMENT"), 1000); |
SQLBackgroundTableCache.getInstance().add(baseSociete.getTable("TYPE_REGLEMENT"), timeout); |
SQLBackgroundTableCache.getInstance().startCacheWatcher(); |
TaxeCache.getCache(); |
/trunk/OpenConcerto/src/org/openconcerto/erp/action/CreateListFrameAbstractAction.java |
---|
61,7 → 61,11 |
private final ComptaPropsConfiguration conf; |
protected CreateListFrameAbstractAction(final ComptaPropsConfiguration conf, final Class<? extends E> clazz) { |
super(conf.getDirectory().getElement(clazz)); |
this(conf, conf.getDirectory().getElementOfClass(clazz, true)); |
} |
protected CreateListFrameAbstractAction(final ComptaPropsConfiguration conf, final E elem) { |
super(elem); |
this.conf = conf; |
// TODO use conf to find TM |
final NounClass nounClass = this.getElem().getName().getNounClass(); |
/trunk/OpenConcerto/src/org/openconcerto/erp/injector/DevisCommandeSQLInjector.java |
---|
68,6 → 68,9 |
map(tableDevis.getField("MONTANT_REMISE"), getDestination().getField("MONTANT_REMISE")); |
map(tableDevis.getField("POURCENT_REMISE"), getDestination().getField("POURCENT_REMISE")); |
} |
if (getSource().getTable().contains("ID_CATEGORIE_COMPTABLE") && getDestination().getTable().contains("ID_CATEGORIE_COMPTABLE")) { |
map(getSource().getField("ID_CATEGORIE_COMPTABLE"), getDestination().getField("ID_CATEGORIE_COMPTABLE")); |
} |
} |
@Override |
78,9 → 81,9 |
final SQLTable tableElementSource = getSource().getTable("DEVIS_ELEMENT"); |
final SQLTable tableElementDestination = getSource().getTable("COMMANDE_CLIENT_ELEMENT"); |
final Collection<? extends SQLRowAccessor> myListItem = srcRow.asRow().getReferentRows(tableElementSource); |
transfertReference(srcRow, rowVals, "OBJET", "NOM"); |
transfertReference(srcRow, rowVals, "INFOS", "INFOS"); |
transfertNumberReference(srcRow, rowVals, tableElementDestination, "ID_COMMANDE_CLIENT"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_COMMANDE_CLIENT", "OBJET", "NOM"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_COMMANDE_CLIENT", "INFOS", "INFOS"); |
if (myListItem.size() != 0) { |
final SQLInjector injector = SQLInjector.getInjector(tableElementSource, tableElementDestination); |
/trunk/OpenConcerto/src/org/openconcerto/erp/injector/DevisFactureSQLInjector.java |
---|
67,6 → 67,9 |
map(tableDevis.getField("MONTANT_REMISE"), tableFacture.getField("MONTANT_REMISE")); |
map(tableDevis.getField("POURCENT_REMISE"), tableFacture.getField("POURCENT_REMISE")); |
} |
if (getSource().getTable().contains("ID_CATEGORIE_COMPTABLE") && getDestination().getTable().contains("ID_CATEGORIE_COMPTABLE")) { |
map(getSource().getField("ID_CATEGORIE_COMPTABLE"), getDestination().getField("ID_CATEGORIE_COMPTABLE")); |
} |
} |
@Override |
78,9 → 81,9 |
final SQLTable tableElementSource = getSource().getTable("DEVIS_ELEMENT"); |
final SQLTable tableElementDestination = getSource().getTable("SAISIE_VENTE_FACTURE_ELEMENT"); |
final Collection<? extends SQLRowAccessor> myListItem = srcRow.asRow().getReferentRows(tableElementSource); |
transfertReference(srcRow, rowVals, "OBJET", "NOM"); |
transfertReference(srcRow, rowVals, "INFOS", "INFOS"); |
transfertNumberReference(srcRow, rowVals, tableElementDestination, "ID_SAISIE_VENTE_FACTURE"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_SAISIE_VENTE_FACTURE", "OBJET", "NOM"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_SAISIE_VENTE_FACTURE", "INFOS", "INFOS"); |
if (getDestination().contains("ID_TAXE_FRAIS_DOCUMENT")) { |
final SQLRowAccessor rowClient = srcRow.getForeign("ID_CLIENT"); |
/trunk/OpenConcerto/src/org/openconcerto/erp/injector/BonFactureSQLInjector.java |
---|
46,6 → 46,9 |
if (getSource().getTable().contains("ID_ADRESSE_LIVRAISON")) { |
map(getSource().getField("ID_ADRESSE_LIVRAISON"), getDestination().getField("ID_ADRESSE_LIVRAISON")); |
} |
if (getSource().getTable().contains("ID_CATEGORIE_COMPTABLE") && getDestination().getTable().contains("ID_CATEGORIE_COMPTABLE")) { |
map(getSource().getField("ID_CATEGORIE_COMPTABLE"), getDestination().getField("ID_CATEGORIE_COMPTABLE")); |
} |
if (tableBon.contains("ID_TAXE_PORT")) { |
map(tableBon.getField("ID_TAXE_PORT"), tableFacture.getField("ID_TAXE_PORT")); |
} |
77,9 → 80,9 |
final SQLTable tableElementSource = getSource().getTable("BON_DE_LIVRAISON_ELEMENT"); |
final SQLTable tableElementDestination = getSource().getTable("SAISIE_VENTE_FACTURE_ELEMENT"); |
final Collection<? extends SQLRowAccessor> myListItem = srcRow.asRow().getReferentRows(tableElementSource); |
transfertReference(srcRow, rowVals, "NOM", "NOM"); |
transfertReference(srcRow, rowVals, "INFOS", "INFOS"); |
transfertNumberReference(srcRow, rowVals, tableElementDestination, "ID_SAISIE_VENTE_FACTURE"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_SAISIE_VENTE_FACTURE", "NOM", "NOM"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_SAISIE_VENTE_FACTURE", "INFOS", "INFOS"); |
if (getDestination().contains("ID_TAXE_FRAIS_DOCUMENT")) { |
final SQLRowAccessor rowClient = srcRow.getForeign("ID_CLIENT"); |
SQLRowAccessor rowFrais = rowClient.getForeign("ID_FRAIS_DOCUMENT"); |
/trunk/OpenConcerto/src/org/openconcerto/erp/injector/DevisBlSQLInjector.java |
---|
45,6 → 45,9 |
if (getSource().getTable().contains("ID_ADRESSE_LIVRAISON")) { |
map(getSource().getField("ID_ADRESSE_LIVRAISON"), getDestination().getField("ID_ADRESSE_LIVRAISON")); |
} |
if (getSource().getTable().contains("ID_CATEGORIE_COMPTABLE") && getDestination().getTable().contains("ID_CATEGORIE_COMPTABLE")) { |
map(getSource().getField("ID_CATEGORIE_COMPTABLE"), getDestination().getField("ID_CATEGORIE_COMPTABLE")); |
} |
} |
@Override |
55,9 → 58,9 |
final SQLTable tableElementSource = getSource().getTable("DEVIS_ELEMENT"); |
final SQLTable tableElementDestination = getSource().getTable("BON_DE_LIVRAISON_ELEMENT"); |
final Collection<? extends SQLRowAccessor> myListItem = srcRow.asRow().getReferentRows(tableElementSource); |
transfertReference(srcRow, rowVals, "NOM", "NOM"); |
transfertReference(srcRow, rowVals, "INFOS", "INFOS"); |
transfertNumberReference(srcRow, rowVals, tableElementDestination, "ID_BON_DE_LIVRAISON"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_BON_DE_LIVRAISON", "NOM", "NOM"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_BON_DE_LIVRAISON", "INFOS", "INFOS"); |
if (myListItem.size() != 0) { |
final SQLInjector injector = SQLInjector.getInjector(tableElementSource, tableElementDestination); |
/trunk/OpenConcerto/src/org/openconcerto/erp/injector/FactureBonSQLInjector.java |
---|
49,9 → 49,9 |
final SQLTable tableElementSource = getSource().getTable("SAISIE_VENTE_FACTURE_ELEMENT"); |
final SQLTable tableElementDestination = getSource().getTable("BON_DE_LIVRAISON_ELEMENT"); |
final Collection<? extends SQLRowAccessor> myListItem = srcRow.asRow().getReferentRows(tableElementSource); |
transfertReference(srcRow, rowVals, "NOM", "NOM"); |
transfertReference(srcRow, rowVals, "INFOS", "INFOS"); |
transfertNumberReference(srcRow, rowVals, tableElementDestination, "ID_BON_DE_LIVRAISON"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_BON_DE_LIVRAISON", "NOM", "NOM"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_BON_DE_LIVRAISON", "INFOS", "INFOS"); |
if (myListItem.size() != 0) { |
final SQLInjector injector = SQLInjector.getInjector(tableElementSource, tableElementDestination); |
/trunk/OpenConcerto/src/org/openconcerto/erp/injector/FactureAvoirSQLInjector.java |
---|
43,7 → 43,9 |
if (getSource().contains("ID_ADRESSE_LIVRAISON") && getDestination().contains("ID_ADRESSE_LIVRAISON")) { |
map(getSource().getField("ID_ADRESSE_LIVRAISON"), getDestination().getField("ID_ADRESSE_LIVRAISON")); |
} |
if (getSource().getTable().contains("ID_CATEGORIE_COMPTABLE") && getDestination().getTable().contains("ID_CATEGORIE_COMPTABLE")) { |
map(getSource().getField("ID_CATEGORIE_COMPTABLE"), getDestination().getField("ID_CATEGORIE_COMPTABLE")); |
} |
if (getSource().getTable().contains("DATE_LIVRAISON") && getDestination().contains("DATE_LIVRAISON")) { |
map(getSource().getField("DATE_LIVRAISON"), getDestination().getField("DATE_LIVRAISON")); |
} |
64,8 → 66,8 |
final SQLTable tableElementSource = getSource().getTable("SAISIE_VENTE_FACTURE_ELEMENT"); |
final SQLTable tableElementDestination = getSource().getTable("AVOIR_CLIENT_ELEMENT"); |
final Collection<? extends SQLRowAccessor> myListItem = srcRow.asRow().getReferentRows(tableElementSource); |
transfertReference(srcRow, rowVals, "NOM", "NOM"); |
transfertNumberReference(srcRow, rowVals, tableElementDestination, "ID_AVOIR_CLIENT"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_AVOIR_CLIENT", "NOM", "NOM"); |
if (myListItem.size() != 0) { |
final SQLInjector injector = SQLInjector.getInjector(tableElementSource, tableElementDestination); |
/trunk/OpenConcerto/src/org/openconcerto/erp/injector/CommandeFactureClientSQLInjector.java |
---|
72,7 → 72,9 |
if (tableFacture.contains("CREATE_VIRTUAL_STOCK")) { |
mapDefaultValues(tableFacture.getField("CREATE_VIRTUAL_STOCK"), Boolean.FALSE); |
} |
if (getSource().getTable().contains("ID_CATEGORIE_COMPTABLE") && getDestination().getTable().contains("ID_CATEGORIE_COMPTABLE")) { |
map(getSource().getField("ID_CATEGORIE_COMPTABLE"), getDestination().getField("ID_CATEGORIE_COMPTABLE")); |
} |
} |
@Override |
83,9 → 85,9 |
final SQLTable tableElementSource = getSource().getTable("COMMANDE_CLIENT_ELEMENT"); |
final SQLTable tableElementDestination = getSource().getTable("SAISIE_VENTE_FACTURE_ELEMENT"); |
final Collection<? extends SQLRowAccessor> myListItem = srcRow.asRow().getReferentRows(tableElementSource); |
transfertReference(srcRow, rowVals, "NOM", "NOM"); |
transfertReference(srcRow, rowVals, "INFOS", "INFOS"); |
transfertNumberReference(srcRow, rowVals, tableElementDestination, "ID_SAISIE_VENTE_FACTURE"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_SAISIE_VENTE_FACTURE", "NOM", "NOM"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_SAISIE_VENTE_FACTURE", "INFOS", "INFOS"); |
if (getDestination().contains("ID_TAXE_FRAIS_DOCUMENT")) { |
final SQLRowAccessor rowClient = srcRow.getForeign("ID_CLIENT"); |
SQLRowAccessor rowFrais = rowClient.getForeign("ID_FRAIS_DOCUMENT"); |
/trunk/OpenConcerto/src/org/openconcerto/erp/injector/CommandeBlSQLInjector.java |
---|
69,6 → 69,9 |
if (getSource().getTable().contains("ID_ADRESSE_LIVRAISON")) { |
map(getSource().getField("ID_ADRESSE_LIVRAISON"), getDestination().getField("ID_ADRESSE_LIVRAISON")); |
} |
if (getSource().getTable().contains("ID_CATEGORIE_COMPTABLE") && getDestination().getTable().contains("ID_CATEGORIE_COMPTABLE")) { |
map(getSource().getField("ID_CATEGORIE_COMPTABLE"), getDestination().getField("ID_CATEGORIE_COMPTABLE")); |
} |
} |
@Override |
80,10 → 83,9 |
final SQLTable tableElementDestination = getSource().getTable("BON_DE_LIVRAISON_ELEMENT"); |
final Collection<? extends SQLRowAccessor> myListItem = srcRow.asRow().getReferentRows(tableElementSource); |
transfertReference(srcRow, rowVals, "NOM", "NOM"); |
transfertReference(srcRow, rowVals, "INFOS", "INFOS"); |
transfertNumberReference(srcRow, rowVals, tableElementDestination, "ID_BON_DE_LIVRAISON"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_BON_DE_LIVRAISON", "NOM", "NOM"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_BON_DE_LIVRAISON", "INFOS", "INFOS"); |
if (myListItem.size() != 0) { |
final SQLInjector injector = SQLInjector.getInjector(tableElementSource, tableElementDestination); |
/trunk/OpenConcerto/src/org/openconcerto/erp/injector/CommandeFactureEltSQLInjector.java |
---|
20,6 → 20,7 |
public CommandeFactureEltSQLInjector(final DBRoot root) { |
super(root, "COMMANDE_CLIENT_ELEMENT", "SAISIE_VENTE_FACTURE_ELEMENT", false); |
createDefaultMap(); |
remove(getSource().getField("QTE_LIVREE"), getDestination().getField("QTE_LIVREE")); |
if (getDestination().contains("ID_COMMANDE_CLIENT_ELEMENT")) { |
map(getSource().getKey(), getDestination().getField("ID_COMMANDE_CLIENT_ELEMENT")); |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/injector/CommandeFactureFournisseurSQLInjector.java |
---|
36,11 → 36,11 |
// Merge elements |
final SQLTable tableElementSource = getSource().getTable("COMMANDE_ELEMENT"); |
final SQLTable tableElementDestination = getSource().getTable("FACTURE_FOUNRISSEUR_ELEMENT"); |
final SQLTable tableElementDestination = getSource().getTable("FACTURE_FOURNISSEUR_ELEMENT"); |
final Collection<? extends SQLRowAccessor> myListItem = srcRow.asRow().getReferentRows(tableElementSource); |
transfertReference(srcRow, rowVals, "NOM", "NOM"); |
transfertReference(srcRow, rowVals, "INFOS", "INFOS"); |
transfertNumberReference(srcRow, rowVals, tableElementDestination, "ID_FACTURE_FOURNISSEUR"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_FACTURE_FOURNISSEUR", "NOM", "NOM"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_FACTURE_FOURNISSEUR", "INFOS", "INFOS"); |
if (myListItem.size() != 0) { |
final SQLInjector injector = SQLInjector.getInjector(tableElementSource, tableElementDestination); |
for (SQLRowAccessor rowElt : myListItem) { |
/trunk/OpenConcerto/src/org/openconcerto/erp/injector/BonReceptionFactureFournisseurSQLInjector.java |
---|
34,6 → 34,12 |
map(getSource().getField("PORT_HT"), getDestination().getField("PORT_HT")); |
map(getSource().getField("ID_TAXE_PORT"), getDestination().getField("ID_TAXE_PORT")); |
} |
if (getSource().contains("ID_AFFAIRE") && getDestination().contains("ID_AFFAIRE")) { |
map(getSource().getField("ID_AFFAIRE"), getDestination().getField("ID_AFFAIRE")); |
} |
if (getSource().contains("ID_POLE_PRODUIT") && getDestination().contains("ID_POLE_PRODUIT")) { |
map(getSource().getField("ID_POLE_PRODUIT"), getDestination().getField("ID_POLE_PRODUIT")); |
} |
} |
@Override |
44,9 → 50,9 |
final SQLTable tableElementSource = getSource().getTable("BON_RECEPTION_ELEMENT"); |
final SQLTable tableElementDestination = getSource().getTable("FACTURE_FOURNISSEUR_ELEMENT"); |
final Collection<? extends SQLRowAccessor> myListItem = srcRow.asRow().getReferentRows(tableElementSource); |
transfertReference(srcRow, rowVals, "NOM", "NOM"); |
transfertReference(srcRow, rowVals, "INFOS", "INFOS"); |
transfertNumberReference(srcRow, rowVals, tableElementDestination, "ID_FACTURE_FOURNISSEUR"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_FACTURE_FOURNISSEUR", "NOM", "NOM"); |
transfertReference(srcRow, rowVals, tableElementDestination, "ID_FACTURE_FOURNISSEUR", "INFOS", "INFOS"); |
if (myListItem.size() != 0) { |
final SQLInjector injector = SQLInjector.getInjector(tableElementSource, tableElementDestination); |
for (SQLRowAccessor rowElt : myListItem) { |
/trunk/OpenConcerto/src/org/openconcerto/erp/injector/CommandeBrSQLInjector.java |
---|
40,6 → 40,9 |
if (tableBr.contains("CREATE_VIRTUAL_STOCK")) { |
mapDefaultValues(tableBr.getField("CREATE_VIRTUAL_STOCK"), Boolean.FALSE); |
} |
if (getSource().contains("ID_AFFAIRE") && getDestination().contains("ID_AFFAIRE")) { |
map(getSource().getField("ID_AFFAIRE"), getDestination().getField("ID_AFFAIRE")); |
} |
} |
@Override |
50,6 → 53,7 |
final SQLTable tableElementSource = getSource().getTable("COMMANDE_ELEMENT"); |
final SQLTable tableElementDestination = getSource().getTable("BON_RECEPTION_ELEMENT"); |
final Collection<? extends SQLRowAccessor> myListItem = srcRow.asRow().getReferentRows(tableElementSource); |
transfertNumberReference(srcRow, rowVals, tableElementDestination, "ID_BON_RECEPTION"); |
if (myListItem.size() != 0) { |
final SQLInjector injector = SQLInjector.getInjector(tableElementSource, tableElementDestination); |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/AbstractJOOReportsSheet.java |
---|
27,6 → 27,7 |
import org.openconcerto.utils.ExceptionHandler; |
import org.openconcerto.utils.FileUtils; |
import java.awt.print.PrinterJob; |
import java.io.BufferedInputStream; |
import java.io.File; |
import java.io.FileNotFoundException; |
245,9 → 246,13 |
return; |
} |
final Component doc = ooConnexion.loadDocument(fileOutOO, true); |
Map<String, Object> map = new HashMap<String, Object>(); |
map.put("Name", printer); |
doc.printDocument(map); |
if (this.printer != null && this.printer.trim().length() > 0) { |
Map<String, Object> map = new HashMap<String, Object>(); |
map.put("Name", this.printer); |
doc.printDocument(map); |
} else { |
doc.printDocument(PrinterJob.getPrinterJob()); |
} |
doc.close(); |
} catch (LinkageError e) { |
JOptionPane.showMessageDialog(new JFrame(), "Merci d'installer OpenOffice ou LibreOffice"); |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/SheetXml.java |
---|
179,19 → 179,23 |
try { |
if (!useODSViewer) { |
final Component doc = ComptaPropsConfiguration.getOOConnexion().loadDocument(generatedFile, !showDocument); |
if (exportToPDF || printDocument) { |
final Component doc = ComptaPropsConfiguration.getOOConnexion().loadDocument(generatedFile, !showDocument); |
if (printDocument) { |
Map<String, Object> map = new HashMap<String, Object>(); |
map.put("Name", this.printer); |
doc.printDocument(map); |
if (printDocument) { |
Map<String, Object> map = new HashMap<String, Object>(); |
map.put("Name", this.printer); |
doc.printDocument(map); |
} |