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/product.properties |
---|
1,5 → 1,5 |
NAME=OpenConcerto |
VERSION=1.6.2 |
VERSION=1.6.3 |
ORGANIZATION_NAME=OpenConcerto |
ORGANIZATION_ID=org.openconcerto |
/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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,6 → 376,7 |
final Row row = this.getRow(i); |
final List<Object> rowValues = row.getValues(); |
for (final Object value : rowValues) { |
if (value != null) { |
if (recursively) { |
if (value instanceof LightUIContainer) { |
result.addAll(((LightUIContainer) value).findChildren(expectedClass, recursively)); |
394,6 → 389,7 |
} |
} |
} |
} |
} else { |
System.out.println("LightUITable.getElementById() - No rows for table: " + this.getId()); |
} |
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/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/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/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); |
@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) { |
this.convertor.fillCombo(uiCombo, null); |
} else { |
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/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); |
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/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/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) |
124,6 → 128,7 |
* @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)); |
} |
137,6 → 142,7 |
* @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,6 → 151,20 |
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. |
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/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/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); |
441,11 → 454,9 |
b0.addActionListener(new ActionListener() { |
@Override |
public void actionPerformed(ActionEvent e) { |
if (enabled) { |
enabled = false; |
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,16 → 49,20 |
this.enableReloadIfTableModified = enableReloadIfTableModified; |
} |
@SuppressWarnings("unchecked") |
public synchronized void reloadFromDbIfNeeded() { |
final long delta = System.currentTimeMillis() - this.lastReload; |
if (delta / 1000 > this.timeout) { |
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) { |
/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/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/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,7 → 36,12 |
} else { |
this.active = null; |
} |
if (r.contains("COLOR")) { |
this.color = new Color(r.getInt("COLOR")); |
} else { |
this.color = null; |
} |
} |
public String getName() { |
return this.name; |
63,4 → 71,8 |
public boolean isActive() { |
return this.active; |
} |
public Color getColor() { |
return this.color; |
} |
} |
/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/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/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/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,8 → 1208,7 |
try { |
res.add(getRow(i, clazz)); |
} catch (IndexOutOfBoundsException e) { |
throw new IllegalStateException( |
"The selected row at " + i |
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,6 → 67,16 |
* @param chooseInListe possibilité de choisir via une IListe |
*/ |
public SQLTextComboTableCellEditor(final SQLElement elt, final boolean addUndefined, boolean chooseInListe) { |
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; |
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/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/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,19 → 58,31 |
} |
@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(); |
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())); |
} |
} |
} |
} |
req.setSelectTransf(new ITransformer<SQLSelect, SQLSelect>() { |
@Override |
public SQLSelect transformChecked(final SQLSelect sel) { |
85,60 → 89,30 |
if (LightRowValuesTableOnline.this.orginTransformer != null) { |
LightRowValuesTableOnline.this.orginTransformer.transformChecked(sel); |
} |
setWhere(sel, sInfo, columns); |
return 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); |
} |
}); |
return req; |
} else { |
Log.get().warning("no TableSearchMatcher for " + item); |
} |
}); |
// 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); |
} |
} |
/** |
* 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); |
} |
} |
wheres.add(Where.or(wFields)); |
} |
final Where w; |
if (!wheres.isEmpty()) { |
if (sel.getWhere() != null) { |
w = Where.and(sel.getWhere(), Where.and(wheres)); |
} else { |
147,4 → 121,10 |
sel.setWhere(w); |
} |
} |
return sel; |
} |
}); |
} |
} |
/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,6 → 83,10 |
final int lineChildCount = panelChild.getChildrenCount(); |
for (int j = 0; j < lineChildCount; j++) { |
final LightUIElement element = panelChild.getChild(j); |
if (mapEditor.containsKey(element.getId())) { |
mapEditor.get(element.getId()).fillFrom(element, sqlRow); |
} else { |
final SQLField sqlField = configuration.getFieldMapper().getSQLFieldForItem(element.getId()); |
SQLRowAccessor sqlRowTmp = this.getSQLRowForField(sqlRow, sqlField); |
115,7 → 129,7 |
element.setValue(JSONConverter.getJSON(date).toString()); |
} |
} else if (type == LightUIElement.TYPE_PANEL) { |
this.fillFromRow((LightUIPanel) element, configuration, sqlRowTmp); |
this.fillFromRow((LightUIPanel) element, configuration, sqlElement, sqlRowTmp, sessionSecurityToken); |
} else if (type == LightUIElement.TYPE_SLIDER) { |
final Integer value = sqlRowTmp.getInt(sqlField.getName()); |
if (value != null) { |
125,6 → 139,7 |
} |
} |
} |
} |
public SQLRowAccessor getSQLRowForField(final SQLRowAccessor sqlRow, final SQLField sqlField) { |
SQLRowAccessor sqlRowResult = sqlRow; |
/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,9 → 193,15 |
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) { |
this.tableModelListeners.remove(tableModelListener); |
this.model.removeTableModelListener(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,26 → 177,29 |
this.putValueFromUserControl(configuration, sqlElement, field, uiElement, customEditors); |
} |
} else { |
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()); |
} |
} |
} |
} |
} |
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/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/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/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/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/TableSorter.java |
---|
348,8 → 348,12 |
* @return the corresponding index in the model. |
*/ |
public int modelIndex(int viewIndex) { |
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() { |
if (!SwingUtilities.isEventDispatchThread()) { |
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/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/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/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,7 → 217,12 |
else |
return this.strategy.equals(this.getDelegate(), delegate2); |
} |
@Override |
public String toString() { |
return this.getClass().getSimpleName() + " using strategy " + this.getStrategy() + " for " + this.getDelegate(); |
} |
} |
/** |
* A proxy object which uses a {@link HashingStrategy}. |
/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/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/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/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/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/generationDoc/SheetXml.java |
---|
179,6 → 179,7 |
try { |
if (!useODSViewer) { |
if (exportToPDF || printDocument) { |
final Component doc = ComptaPropsConfiguration.getOOConnexion().loadDocument(generatedFile, !showDocument); |
if (printDocument) { |
193,6 → 194,9 |
doc.close(); |
} |
} else { |
openDocument(false); |
} |
} else { |
final OpenDocument doc = new OpenDocument(generatedFile); |
if (showDocument) { |
543,9 → 547,13 |
} |
public void showPreviewDocument() throws Exception { |
showPreviewDocument(null, null); |
} |
public void showPreviewDocument(String actionName, Runnable r) throws Exception { |
File f = null; |
f = getOrCreateDocumentFile(); |
PreviewFrame.show(f); |
PreviewFrame.show(f, actionName, r); |
} |
public void printDocument() { |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/OOXMLField.java |
---|
266,6 → 266,9 |
result += stringValue; |
} |
if (suffix != null) { |
if (suffix.contains("#n")) { |
suffix = suffix.replaceAll("#n", "\n"); |
} |
result += suffix; |
} |
if (cellSize != null && cellSize.trim().length() != 0) { |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/provider/ArticleCodeFournisseurProvider.java |
---|
New file |
0,0 → 1,69 |
/* |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
* |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved. |
* |
* The contents of this file are subject to the terms of the GNU General Public License Version 3 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific |
* language governing permissions and limitations under the License. |
* |
* When distributing the software, include this License Header Notice in each file. |
*/ |
package org.openconcerto.erp.generationDoc.provider; |
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueContext; |
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueProvider; |
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueProviderManager; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.SQLRowListRSH; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.model.Where; |
import java.util.List; |
public class ArticleCodeFournisseurProvider implements SpreadSheetCellValueProvider { |
public ArticleCodeFournisseurProvider() { |
} |
public Object getValue(SpreadSheetCellValueContext context) { |
SQLRowAccessor row = context.getRow(); |
String code = row.getString("CODE"); |
if (row.getObject("ID_ARTICLE") != null && !row.isForeignEmpty("ID_ARTICLE")) { |
if (row.getTable().contains("ID_CODE_FOURNISSEUR")) { |
if (row.getObject("ID_CODE_FOURNISSEUR") != null && !row.isForeignEmpty("ID_CODE_FOURNISSEUR")) { |
code = row.getForeign("ID_CODE_FOURNISSEUR").getString("CODE"); |
} else { |
int idFournisseur = row.getForeign("ID_" + row.getTable().getName().replaceAll("_ELEMENT", "")).getForeignID("ID_FOURNISSEUR"); |
SQLSelect sel = new SQLSelect(); |
final SQLTable tableCodeFournisseur = row.getTable().getTable("CODE_FOURNISSEUR"); |
sel.addSelectStar(tableCodeFournisseur); |
Where w = new Where(tableCodeFournisseur.getField("ID_ARTICLE"), "=", row.getForeignID("ID_ARTICLE")); |
w = w.and(new Where(tableCodeFournisseur.getField("ID_FOURNISSEUR"), "=", idFournisseur)); |
sel.setWhere(w); |
List<SQLRow> result = SQLRowListRSH.execute(sel); |
if (!result.isEmpty()) { |
final String val = result.get(0).getString("CODE"); |
if (val.length() > 0) { |
code = val; |
} |
} |
} |
} |
} |
return code; |
} |
public static void register() { |
SpreadSheetCellValueProviderManager.put("supplier.product.code", new ArticleCodeFournisseurProvider()); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/provider/QteTotalDocProvider.java |
---|
New file |
0,0 → 1,68 |
/* |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
* |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved. |
* |
* The contents of this file are subject to the terms of the GNU General Public License Version 3 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific |
* language governing permissions and limitations under the License. |
* |
* When distributing the software, include this License Header Notice in each file. |
*/ |
package org.openconcerto.erp.generationDoc.provider; |
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueContext; |
import org.openconcerto.erp.generationDoc.SpreadSheetCellValueProviderManager; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.SQLTable; |
import java.math.BigDecimal; |
import java.util.Collection; |
public class QteTotalDocProvider extends UserInitialsValueProvider { |
private enum TypeQteTotalDocProvider { |
QTE, COLIS |
}; |
private final TypeQteTotalDocProvider type; |
public QteTotalDocProvider(TypeQteTotalDocProvider t) { |
this.type = t; |
} |
@Override |
public Object getValue(SpreadSheetCellValueContext context) { |
SQLRowAccessor row = context.getRow(); |
final SQLTable table = row.getTable(); |
Collection<? extends SQLRowAccessor> cols = row.getReferentRows(table.getTable(table.getName() + "_ELEMENT")); |
BigDecimal total = BigDecimal.ZERO; |
for (SQLRowAccessor sqlRowAccessor : cols) { |
if (!sqlRowAccessor.getTable().contains("NIVEAU") || sqlRowAccessor.getInt("NIVEAU") == 1) { |
if (this.type == TypeQteTotalDocProvider.QTE) { |
BigDecimal qte = sqlRowAccessor.getBigDecimal("QTE_UNITAIRE").multiply(new BigDecimal(sqlRowAccessor.getInt("QTE"))); |
total = total.add(qte); |
} else { |
if (sqlRowAccessor.getObject("NB_COLIS") != null) { |
total = total.add(new BigDecimal(sqlRowAccessor.getInt("NB_COLIS"))); |
} |
} |
} |
} |
return total; |
} |
public static void register() { |
SpreadSheetCellValueProviderManager.put("sales.qty.total", new QteTotalDocProvider(TypeQteTotalDocProvider.QTE)); |
SpreadSheetCellValueProviderManager.put("sales.package.total", new QteTotalDocProvider(TypeQteTotalDocProvider.COLIS)); |
} |
} |
/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); |
if (this.printer != null && this.printer.trim().length() > 0) { |
Map<String, Object> map = new HashMap<String, Object>(); |
map.put("Name", printer); |
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/gestcomm/EtatVentesXmlSheet.java |
---|
24,6 → 24,8 |
import org.openconcerto.sql.model.AliasedTable; |
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.SQLSelectJoin; |
import org.openconcerto.sql.model.SQLTable; |
62,11 → 64,13 |
private Timestamp du, au; |
public boolean ticketCaisse = false; |
public boolean facture = false; |
public EtatVentesXmlSheet(Date du, Date au, boolean ticketCaisse) { |
public EtatVentesXmlSheet(Date du, Date au, boolean ticketCaisse, boolean facture) { |
super(); |
this.printer = PrinterNXProps.getInstance().getStringProperty("BonPrinter"); |
this.ticketCaisse = ticketCaisse; |
this.facture = facture; |
if (du != null) { |
final Calendar c1 = Calendar.getInstance(); |
c1.setTime(du); |
128,7 → 132,11 |
styleAllSheetValues.put(0, style); |
} |
final ArrayList<Map<String, Object>> listValuesStock = new ArrayList<>(); |
final Map<Integer, String> styleStock = new HashMap<>(); |
// Ventes |
final SQLTable foreignTableArticle = tableFactureElement.getForeignTable("ID_ARTICLE"); |
{ |
final AliasedTable tableModeReglement1 = new AliasedTable(tableModeReglement, MODE1); |
135,6 → 143,17 |
final AliasedTable tableModeReglement2 = new AliasedTable(tableModeReglement, MODE2); |
final AliasedTable tableTicket = new AliasedTable(eltTicketCaisse.getTable(), "ticket"); |
// Stock |
SQLRowValues rowValsArtStock = new SQLRowValues(foreignTableArticle); |
rowValsArtStock.putNulls("ID", "CODE", "NOM"); |
rowValsArtStock.putRowValues("ID_STOCK").putNulls("QTE_REEL", "QTE_TH", "QTE_MIN", "QTE_RECEPT_ATTENTE", "QTE_LIV_ATTENTE"); |
SQLRowValuesListFetcher fetcherStock = SQLRowValuesListFetcher.create(rowValsArtStock); |
List<SQLRowValues> resultStock = fetcherStock.fetch(); |
Map<Integer, SQLRowValues> mapStock = new HashMap<>(); |
for (SQLRowValues sqlRowValues : resultStock) { |
mapStock.put(sqlRowValues.getID(), sqlRowValues); |
} |
// Requete Pour obtenir les quantités pour chaque type de réglement |
SQLSelect sel = new SQLSelect(); |
193,12 → 212,16 |
selQte.addSelect(tableFactureElement.getField("T_PV_TTC"), "SUM"); |
selQte.addSelect(tableFactureElement.getField("ID_TAXE")); |
selQte.addSelect(tableFactureElement.getField("ID_ARTICLE")); |
if (!this.ticketCaisse) { |
if (this.ticketCaisse) { |
selQte.addJoin("LEFT", tableFactureElement.getField("ID_SAISIE_VENTE_FACTURE")).setWhere(Where.FALSE); |
selQte.addJoin("LEFT", tableFactureElement.getField("ID_TICKET_CAISSE"), "ticket").setWhere(w2); |
} else if (this.facture) { |
selQte.addJoin("LEFT", tableFactureElement.getField("ID_SAISIE_VENTE_FACTURE")).setWhere(w); |
selQte.addJoin("LEFT", tableFactureElement.getField("ID_TICKET_CAISSE"), "ticket").setWhere(Where.FALSE); |
} else { |
selQte.addJoin("LEFT", tableFactureElement.getField("ID_SAISIE_VENTE_FACTURE")).setWhere(Where.FALSE); |
selQte.addJoin("LEFT", tableFactureElement.getField("ID_SAISIE_VENTE_FACTURE")).setWhere(w); |
selQte.addJoin("LEFT", tableFactureElement.getField("ID_TICKET_CAISSE"), "ticket").setWhere(w2); |
} |
selQte.addJoin("LEFT", tableFactureElement.getField("ID_TICKET_CAISSE"), "ticket").setWhere(w2); |
SQLSelectJoin joinArt2 = selQte.addJoin("LEFT", tableFactureElement.getField("ID_ARTICLE")); |
SQLSelectJoin joinFamArt2 = selQte.addJoin("LEFT", joinArt2.getJoinedTable().getField("ID_FAMILLE_ARTICLE")); |
selQte.addSelect(joinFamArt2.getJoinedTable().getField("NOM")); |
234,8 → 257,8 |
mapTVAVT.put(tvaID.intValue(), Tuple2.create(t.get0().add((BigDecimal) ht), t.get1().add(ttc))); |
} |
Number articleID = (Number) sqlRow[7]; |
ArticleVendu a = new ArticleVendu(code, nom, qteVendu.intValue(), (BigDecimal) ht, (BigDecimal) ha, ttc, tvaID.intValue(), |
tableFactureElement.getForeignTable("ID_ARTICLE").getRow(articleID.intValue())); |
ArticleVendu a = new ArticleVendu(code, nom, qteVendu.intValue(), (BigDecimal) ht, (BigDecimal) ha, ttc, tvaID.intValue(), foreignTableArticle.getRow(articleID.intValue())); |
map.put(articleID + "##" + code + "##" + nom + "##" + tvaID, a); |
} |
256,6 → 279,8 |
mValues.put("NOM", famille); |
style.put(listValues.size(), "Titre 1"); |
listValues.add(mValues); |
styleStock.put(listValuesStock.size(), "Titre 1"); |
listValuesStock.add(mValues); |
} else if (valueFam != null && !valueFam.toString().equalsIgnoreCase(famille)) { |
famille = valueFam.toString(); |
Map<String, Object> mValues = new HashMap<String, Object>(); |
262,6 → 287,8 |
mValues.put("NOM", famille); |
style.put(listValues.size(), "Titre 1"); |
listValues.add(mValues); |
styleStock.put(listValuesStock.size(), "Titre 1"); |
listValuesStock.add(mValues); |
} |
Map<String, Object> mValues = new HashMap<String, Object>(); |
291,7 → 318,26 |
totalTPVTTC = totalTPVTTC.add(a.ttc); |
style.put(listValues.size(), "Normal"); |
listValues.add(mValues); |
Map<String, Object> mValuesStock = new HashMap<String, Object>(); |
mValuesStock.put("CODE", code); |
mValuesStock.put("NOM", nom); |
mValuesStock.put("QTE", a.qte); |
if (mapStock.containsKey(articleID)) { |
SQLRowValues rowValsArt = mapStock.get(articleID); |
if (rowValsArt.getObject("ID_STOCK") != null && !rowValsArt.isForeignEmpty("ID_STOCK")) { |
SQLRowAccessor rowValsStock = rowValsArt.getForeign("ID_STOCK"); |
mValuesStock.put("QTE_TH", rowValsStock.getObject("QTE_TH")); |
mValuesStock.put("QTE_REEL", rowValsStock.getObject("QTE_REEL")); |
mValuesStock.put("QTE_MIN", rowValsStock.getObject("QTE_MIN")); |
mValuesStock.put("QTE_RECEPT_ATTENTE", rowValsStock.getObject("QTE_RECEPT_ATTENTE")); |
mValuesStock.put("QTE_LIV_ATTENTE", rowValsStock.getObject("QTE_LIV_ATTENTE")); |
} |
styleStock.put(listValuesStock.size(), "Normal"); |
listValuesStock.add(mValuesStock); |
} |
} |
// System.out.println("EtatVentesXmlSheet.createListeValues():" + listValues); |
} |
} |
440,7 → 486,7 |
} |
Number articleID = (Number) sqlRow[7]; |
ArticleVendu a = new ArticleVendu(code, nom, -qteVendu.intValue(), ((BigDecimal) ht).negate(), ((BigDecimal) ha).negate(), ttc.negate(), tvaID.intValue(), |
tableFactureElement.getForeignTable("ID_ARTICLE").getRow(articleID.intValue())); |
foreignTableArticle.getRow(articleID.intValue())); |
map.put(articleID + "##" + code + "##" + nom + "##" + tvaID, a); |
} |
713,6 → 759,10 |
this.listAllSheetValues.put(3, listValuesTVA); |
valuesTVA.put("DATE", periode); |
this.mapAllSheetValues.put(3, valuesTVA); |
this.listAllSheetValues.put(4, listValuesStock); |
this.styleAllSheetValues.put(4, styleStock); |
this.mapAllSheetValues.put(4, values); |
} |
public static SQLRow rowDefaultCptService, rowDefaultCptProduit; |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/OOgenerationXML.java |
---|
195,6 → 195,7 |
} |
} catch (Exception e) { |
ExceptionHandler.handle("Impossible de remplir le document " + templateId + " " + ((rowLanguage == null) ? "" : rowLanguage.getString("CHEMIN")), e); |
e.printStackTrace(); |
return null; |
} |
444,6 → 445,12 |
} |
calc.setRemise(valRemiseHTReel, totalAvtRemise); |
// Fix TVA si nécessaire pour facture fournisseur |
if (row.getTable().contains("TVA_ADJUSTMENT")) { |
BigDecimal tvaFix = row.getBigDecimal("TVA_ADJUSTMENT"); |
calc.addTVAAdjust(tvaFix); |
} |
for (int i = 0; i < rows.size(); i++) { |
SQLRowAccessor sqlRow = rows.get(i); |
calc.addLine(sqlRow, sqlRow.getForeign("ID_ARTICLE"), i, i == rows.size() - 1); |
490,6 → 497,20 |
calc.addLine(rowValsPort, rowValsPort.getForeign("ID_ARTICLE"), 1, false); |
} |
if (row.getTable().contains("FRAIS_DOCUMENT_HT") && row.getTable().contains("ID_TAXE_FRAIS_DOCUMENT")) { |
BigDecimal fraisDoc = BigDecimal.valueOf(row.getLong("FRAIS_DOCUMENT_HT")).movePointLeft(2); |
SQLRowAccessor tvafraisDoc = row.getForeign("ID_TAXE_FRAIS_DOCUMENT"); |
if (tvafraisDoc != null && fraisDoc.signum() != 0 && !tvafraisDoc.isUndefined()) { |
SQLRowValues rowValsfraisDoc = new SQLRowValues(tableElt); |
rowValsfraisDoc.put("T_PV_HT", fraisDoc); |
rowValsfraisDoc.put("QTE", 1); |
rowValsfraisDoc.put("ID_TAXE", tvafraisDoc.getIDNumber()); |
rowValsfraisDoc.put("SERVICE", Boolean.TRUE); |
rowValsfraisDoc.put("ID_FAMILLE_ARTICLE", null); |
calc.addLine(rowValsfraisDoc, null, 1, false); |
} |
} |
calc.checkResult(); |
Map<SQLRowAccessor, Tuple2<BigDecimal, BigDecimal>> taxeCalc = calc.getMapHtTVARowTaux(); |
for (SQLRowAccessor sqlRow : taxeCalc.keySet()) { |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/GenerationMvtDepotChequeClient.java |
---|
93,7 → 93,7 |
List<Integer> pieceIDs = new ArrayList<Integer>(); |
SQLRowValues rowValsDepotElt = new SQLRowValues(depot.getTable().getTable("DEPOT_CHEQUE_ELEMENT")); |
rowValsDepotElt.putNulls("MONTANT", "TIERS"); |
rowValsDepotElt.putNulls("MONTANT", "TIERS", "PIECE"); |
rowValsDepotElt.putRowValues("ID_CLIENT").putNulls("NOM", "ID_COMPTE_PCE"); |
final SQLRowValues rowValuesChq = rowValsDepotElt.putRowValues("ID_CHEQUE_A_ENCAISSER"); |
rowValuesChq.putNulls("SANS_VALEUR_ENCAISSEMENT").putRowValues("ID_MOUVEMENT").putNulls("ID_PIECE"); |
102,7 → 102,7 |
for (SQLRowValues sqlRowAccessor : cheques) { |
final SQLRowAccessor clientRow = sqlRowAccessor.getForeign("ID_CLIENT"); |
// this.nom = this.nom + " " + StringUtils.limitLength(clientRow.getString("NOM"), 20); |
this.putValue("NOM", this.nom + " " + StringUtils.limitLength(clientRow.getString("NOM"), 20)); |
this.putValue("NOM", this.nom + " " + sqlRowAccessor.getString("PIECE") + " " + StringUtils.limitLength(clientRow.getString("NOM"), 20)); |
SQLRowAccessor chequeRow = sqlRowAccessor.getForeign("ID_CHEQUE_A_ENCAISSER"); |
pieceIDs.add(chequeRow.getForeign("ID_MOUVEMENT").getForeignID("ID_PIECE")); |
// compte Clients |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/Piece.java |
---|
New file |
0,0 → 1,58 |
/* |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
* |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved. |
* |
* The contents of this file are subject to the terms of the GNU General Public License Version 3 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific |
* language governing permissions and limitations under the License. |
* |
* When distributing the software, include this License Header Notice in each file. |
*/ |
package org.openconcerto.erp.generationEcritures; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.model.SQLInsert; |
import java.util.ArrayList; |
import java.util.List; |
public class Piece { |
private String nom; |
private List<Mouvement> mouvements = new ArrayList<>(); |
private Number id; |
public Piece(String nom) { |
this.nom = nom; |
} |
public String getNom() { |
return nom; |
} |
public void add(Mouvement mouvement) { |
this.mouvements.add(mouvement); |
mouvement.setPiece(this); |
} |
public List<Mouvement> getMouvements() { |
return mouvements; |
} |
public SQLInsert createInsert(final DBRoot root) { |
final SQLInsert insert = new SQLInsert(); |
insert.add(root.getTable("PIECE").getField("NOM"), this.nom); |
return insert; |
} |
public Number getId() { |
return this.id; |
} |
public void setId(Number id) { |
this.id = id; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/Exercice.java |
---|
New file |
0,0 → 1,517 |
/* |
* 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.generationEcritures; |
import org.openconcerto.sql.element.SQLElementDirectory; |
import org.openconcerto.sql.model.ConnectionHandlerNoSetup; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.model.DBSystemRoot; |
import org.openconcerto.sql.model.SQLDataSource; |
import org.openconcerto.sql.model.SQLField; |
import org.openconcerto.sql.model.SQLInsert; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.model.SQLUpdate; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.users.User; |
import org.openconcerto.sql.utils.SQLUtils; |
import org.openconcerto.utils.CollectionUtils; |
import org.openconcerto.utils.cc.ITransformer; |
import java.sql.ResultSet; |
import java.sql.SQLException; |
import java.util.ArrayList; |
import java.util.Date; |
import java.util.HashMap; |
import java.util.HashSet; |
import java.util.Iterator; |
import java.util.LinkedList; |
import java.util.List; |
import java.util.Map; |
import java.util.Set; |
import java.util.logging.Level; |
import java.util.logging.Logger; |
import org.apache.commons.dbutils.ResultSetHandler; |
public class Exercice { |
private Date debut; |
private Date fin; |
private static final Logger LOGGER = Logger.getLogger(Exercice.class.getName()); |
public Exercice() { |
} |
public Exercice(Date debut, Date fin) { |
if (debut != null && debut.after(fin)) { |
throw new IllegalArgumentException("date de fin invalide"); |
} |
this.debut = debut; |
this.fin = fin; |
} |
public String toString() { |
return "Exercice " + this.debut + " -> " + this.fin; |
} |
public void insert(SQLElementDirectory directory, final DBRoot root, User user, List<Piece> pieces) throws SQLException { |
final DBSystemRoot sysRoot = root.getDBSystemRoot(); |
final List<SQLInsert> insertsPiece = new ArrayList<>(); |
LOGGER.log(Level.INFO, "insertion de {0} pièces comptables", pieces.size()); |
for (Piece p : pieces) { |
// Pièces |
insertsPiece.add(p.createInsert(root)); |
// Vérification des mouvements |
final List<Mouvement> mouvements = p.getMouvements(); |
if (mouvements.isEmpty()) { |
throw new IllegalStateException("Piece vide : " + p); |
} |
for (Mouvement m : mouvements) { |
if (!m.isBalanced()) { |
throw new IllegalStateException("Mouvement non balancé : " + m); |
} |
if (m.isEmpty()) { |
throw new IllegalStateException("Mouvement vide : " + m); |
} |
for (Ecriture e : m.getEcritures()) { |
if (this.debut != null && e.getDate().before(this.debut)) { |
throw new IllegalStateException("Mouvement invalide : " + m + " : une écriture est définie avant la date de début d'exercice : " + e); |
} |
if (e.getNom() == null) { |
throw new IllegalStateException("Ecriture sans nom : " + e); |
} |
} |
if (this.fin != null) { |
for (Ecriture e : m.getEcritures()) { |
if (e.getDate().after(this.fin)) { |
throw new IllegalStateException("Mouvement invalide : " + m + " : une écriture est définie après la date de fin d'exercice : " + e.getDate() + ">" + this.fin); |
} |
} |
} |
} |
} |
SQLUtils.executeAtomic(sysRoot.getDataSource(), new ConnectionHandlerNoSetup<Object, SQLException>() { |
@Override |
public Object handle(SQLDataSource ds) throws SQLException { |
// Insertion des journaux et comptes manquants et remplissage des champs journaux et |
// comptes des |
// écritures depuis les ids |
final Set<Journal> journauxACreerOuFetcher = new HashSet<>(); |
final Set<Number> journauxAresoudre = new HashSet<>(); |
final Set<Compte> comptesACreerOuFetcher = new HashSet<>(); |
final Set<Number> comptesAresoudre = new HashSet<>(); |
final List<Ecriture> ecrituresSansJournalID = new LinkedList<>(); |
final List<Ecriture> ecrituresSansCompteID = new LinkedList<>(); |
for (Piece p : pieces) { |
for (Mouvement m : p.getMouvements()) { |
for (Ecriture e : m.getEcritures()) { |
if (e.getJournalID() == null) { |
// Journal à creer |
journauxACreerOuFetcher.add(new Journal(null, e.getJournalCode(), e.getJournalNom())); |
ecrituresSansJournalID.add(e); |
} else { |
journauxAresoudre.add(e.getJournalID()); |
} |
if (e.getCompteID() == null) { |
// Compte à creer |
comptesACreerOuFetcher.add(new Compte(null, e.getCompteNumero(), e.getCompteNom())); |
ecrituresSansCompteID.add(e); |
} else { |
comptesAresoudre.add(e.getJournalID()); |
} |
} |
} |
} |
final Map<Long, Journal> mapJournaux = new HashMap<>(); |
if (!journauxACreerOuFetcher.isEmpty()) { |
if (LOGGER.isLoggable(Level.FINE)) { |
LOGGER.fine(journauxACreerOuFetcher.size() + " journaux à créer : " + journauxACreerOuFetcher); |
} |
// On récupère tous les journaux car il y en a peu |
final Map<String, Journal> codesDesJournauxExistants = getCodesJournaux(root); |
final List<SQLInsert> insertsJournaux = new ArrayList<>(); |
final List<Journal> list = new ArrayList<>(); |
for (Journal journal : journauxACreerOuFetcher) { |
// journal non déjà existant |
if (codesDesJournauxExistants.get(journal.getCode().toLowerCase()) == null) { |
list.add(journal); |
insertsJournaux.add(journal.createInsert(root)); |
} |
} |
final List<Number> journauxIds = new ArrayList<>(); |
if (!insertsJournaux.isEmpty()) { |
journauxIds.addAll(SQLInsert.executeSimilarInserts(sysRoot, insertsJournaux, true)); |
journauxAresoudre.addAll(journauxIds); |
} |
// Mise à jour de l'ID du journal pour les écritures dont le journal vient |
// d'être créé |
final int size = list.size(); |
for (int i = 0; i < size; i++) { |
final String journalCode = list.get(i).getCode(); |
final Number journalID = journauxIds.get(i); |
final Iterator<Ecriture> it = ecrituresSansJournalID.iterator(); |
while (it.hasNext()) { |
final Ecriture e = it.next(); |
if (e.getJournalCode().equalsIgnoreCase(journalCode)) { |
e.setJournalID(journalID); |
it.remove(); |
} |
} |
} |
final Iterator<Ecriture> it = ecrituresSansJournalID.iterator(); |
while (it.hasNext()) { |
final Ecriture e = it.next(); |
final Journal journal = codesDesJournauxExistants.get(e.getJournalCode().toLowerCase()); |
e.setJournalID(journal.getId()); |
it.remove(); |
} |
for (Journal journal : codesDesJournauxExistants.values()) { |
mapJournaux.put(journal.getId(), journal); |
} |
} |
final Map<Long, Compte> mapComptes = new HashMap<>(); |
if (!comptesACreerOuFetcher.isEmpty()) { |
if (LOGGER.isLoggable(Level.FINE)) { |
LOGGER.fine(comptesACreerOuFetcher.size() + " comptes à créer ou fetcher: " + comptesACreerOuFetcher); |
} |
final Map<String, Compte> numerosDesComptesExistants = getNumeroDesComptes(root, pieces); |
final List<SQLInsert> insertsComptes = new ArrayList<>(); |
final List<Compte> list = new ArrayList<>(); |
for (Compte c : comptesACreerOuFetcher) { |
if (numerosDesComptesExistants.get(c.getNumero().toLowerCase()) == null) { |
if (LOGGER.isLoggable(Level.FINE)) { |
LOGGER.fine("création du compte : " + c.getNumero().toLowerCase()); |
} |
list.add(c); |
insertsComptes.add(c.createInsert(root)); |
} |
} |
List<Number> comptesIds = new ArrayList<>(); |
if (!insertsComptes.isEmpty()) { |
final List<Number> insertedIDs = SQLInsert.executeSimilarInserts(sysRoot, insertsComptes, true); |
comptesIds.addAll(insertedIDs); |
if (LOGGER.isLoggable(Level.FINE)) { |
LOGGER.fine("IDs des comptes créés : " + comptesIds); |
} |
comptesAresoudre.addAll(comptesIds); |
} |
// Mise à jour de l'ID du compte pour les écritures dont le compte vient |
// d'être créé |
final int size = list.size(); |
for (int i = 0; i < size; i++) { |
final String compteCode = list.get(i).getNumero(); |
final Number compteID = comptesIds.get(i); |
final Iterator<Ecriture> it = ecrituresSansCompteID.iterator(); |
while (it.hasNext()) { |
final Ecriture e = it.next(); |
if (e.getCompteNumero().equalsIgnoreCase(compteCode)) { |
if (LOGGER.isLoggable(Level.FINEST)) { |
LOGGER.finest("mise à jour de l'écriture " + e + " avec le compte d'ID " + compteID); |
} |
e.setCompteID(compteID); |
it.remove(); |
} |
} |
} |
final Iterator<Ecriture> it = ecrituresSansCompteID.iterator(); |
while (it.hasNext()) { |
final Ecriture e = it.next(); |
Compte compte = numerosDesComptesExistants.get(e.getCompteNumero().toLowerCase()); |
if (compte != null) { |
e.setCompteID(compte.getId()); |
it.remove(); |
} |
} |
for (Compte compte : numerosDesComptesExistants.values()) { |
mapComptes.put(compte.getId(), compte); |
} |
} |
// fetch journaux et comptes, update des code/numéro et nom |
final List<String> queries = new ArrayList<>(); |
final List<ResultSetHandler> handlers = new ArrayList<>(); |
if (!comptesAresoudre.isEmpty()) { |
if (LOGGER.isLoggable(Level.FINE)) { |
LOGGER.fine(comptesAresoudre.size() + " comptes à résoudre : ids " + comptesAresoudre); |
} |
final SQLTable tableCompte = root.getTable("COMPTE_PCE"); |
final SQLSelect selCompte = new SQLSelect(); |
selCompte.addSelect(tableCompte.getKey()); |
selCompte.addSelect(tableCompte.getField("NUMERO")); |
selCompte.addSelect(tableCompte.getField("NOM")); |
selCompte.setWhere(new Where(tableCompte.getKey(), comptesAresoudre)); |
queries.add(selCompte.asString()); |
handlers.add(new ResultSetHandler() { |
@Override |
public Object handle(ResultSet rs) throws SQLException { |
while (rs.next()) { |
final Long id = rs.getLong(1); |
final String numero = rs.getString(2); |
final String nom = rs.getString(3); |
mapComptes.put(id, new Compte(id, numero, nom)); |
} |
return null; |
} |
}); |
} |
if (!journauxAresoudre.isEmpty()) { |
if (LOGGER.isLoggable(Level.FINE)) { |
LOGGER.fine(journauxAresoudre.size() + " journaux à résoudre ids : " + journauxAresoudre); |
} |
final SQLTable tableJournal = root.getTable("JOURNAL"); |
final SQLSelect selJournal = new SQLSelect(); |
selJournal.addSelect(tableJournal.getKey()); |
selJournal.addSelect(tableJournal.getField("CODE")); |
selJournal.addSelect(tableJournal.getField("NOM")); |
selJournal.setWhere(new Where(tableJournal.getKey(), journauxAresoudre)); |
queries.add(selJournal.asString()); |
handlers.add(new ResultSetHandler() { |
@Override |
public Object handle(ResultSet rs) throws SQLException { |
while (rs.next()) { |
final Long id = rs.getLong(1); |
final String code = rs.getString(2); |
final String nom = rs.getString(3); |
mapJournaux.put(id, new Journal(id, code, nom)); |
} |
return null; |
} |
}); |
} |
SQLUtils.executeMultiple(sysRoot, queries, handlers); |
for (Piece p : pieces) { |
for (Mouvement m : p.getMouvements()) { |
for (Ecriture e : m.getEcritures()) { |
Number compteID = e.getCompteID(); |
if (compteID == null) { |
throw new IllegalStateException("pas d'ID compte dans l'écriture " + e); |
} |
final Long idCompte = compteID.longValue(); |
final Compte c = mapComptes.get(idCompte); |
if (c == null) { |
throw new IllegalStateException("pas de compte d'ID " + idCompte + " dans la map " + mapComptes.keySet()); |
} |
e.setCompte(c.getNumero(), c.getNom()); |
final Long idJournal = e.getJournalID().longValue(); |
final Journal j = mapJournaux.get(idJournal); |
if (j == null) { |
throw new IllegalStateException("pas de journal d'ID " + idJournal + " dans la map " + mapJournaux.keySet()); |
} |
e.setJournal(j.getCode(), j.getNom()); |
} |
} |
} |
// Insertion des pieces |
final List<Number> idsPieces = SQLInsert.executeSimilarInserts(sysRoot, insertsPiece, true); |
// Creation des inserts des mouvements |
final List<SQLInsert> insertsMouvement = new ArrayList<>(insertsPiece.size() * 3); |
final List<Mouvement> listMvtWithoutIDs = new ArrayList<>(insertsPiece.size() * 3); |
for (int i = 0; i < pieces.size(); i++) { |
Piece piece = pieces.get(i); |
piece.setId(idsPieces.get(i)); |
for (Mouvement m : piece.getMouvements()) { |
listMvtWithoutIDs.add(m); |
insertsMouvement.add(m.createInsert(root)); |
} |
} |
// Insertion des mouvements |
final List<Number> idsMouvements = SQLInsert.executeSimilarInserts(sysRoot, insertsMouvement, true); |
// Mise à jour des numeros de mouvements |
SQLSelect sel = new SQLSelect(); |
final SQLTable tableMvt = root.getTable("MOUVEMENT"); |
sel.addSelect(tableMvt.getField("NUMERO"), "MAX"); |
Number maxMvtNumber = (Number) sysRoot.getDataSource().executeScalar(sel.asString()); |
int maxMvt = 1; |
if (maxMvtNumber != null) { |
maxMvt = maxMvtNumber.intValue(); |
} |
List<SQLUpdate> mvtUpdate = new ArrayList<>(); |
for (int i = 0; i < idsMouvements.size(); i++) { |
Number mvtId = idsMouvements.get(i); |
SQLUpdate update = new SQLUpdate(new Where(tableMvt.getKey(), "=", mvtId)); |
update.add(tableMvt.getField("NUMERO"), maxMvt); |
mvtUpdate.add(update); |
maxMvt++; |
listMvtWithoutIDs.get(i).setId(mvtId); |
} |
SQLUpdate.executeMultipleWithBatch(sysRoot, mvtUpdate); |
// Creation des inserts des écritures sans analytique |
final List<SQLInsert> insertsEcrituresSansAnalytique = new ArrayList<>(insertsMouvement.size() * 2); |
final List<SQLInsert> insertsEcrituresAvecAnalytique = new ArrayList<>(insertsMouvement.size() * 2); |
final List<Ecriture> ecrituresAvecAnalytique = new ArrayList<>(insertsEcrituresAvecAnalytique.size()); |
for (Piece p : pieces) { |
final List<Mouvement> mouvements = p.getMouvements(); |
final int stop = mouvements.size(); |
for (int i = 0; i < stop; i++) { |
final Mouvement m = mouvements.get(i); |
for (Ecriture e : m.getEcritures()) { |
if (e.hasAnalytique()) { |
insertsEcrituresAvecAnalytique.add(e.createInsert(root, user)); |
ecrituresAvecAnalytique.add(e); |
} else { |
insertsEcrituresSansAnalytique.add(e.createInsert(root, user)); |
} |
} |
} |
} |
// Insertions des écritures des mouvements |
SQLInsert.executeSimilarInserts(sysRoot, insertsEcrituresSansAnalytique, false); |
// Insertions des écritures avec analytique |
if (!ecrituresAvecAnalytique.isEmpty()) { |
final List<Number> idsEcritues = SQLInsert.executeSimilarInserts(sysRoot, insertsEcrituresAvecAnalytique, true); |
// Analytique |
final List<SQLInsert> insertsAssociationAnalytique = new ArrayList<>(insertsEcrituresAvecAnalytique.size()); |
final int size = ecrituresAvecAnalytique.size(); |
for (int i = 0; i < size; i++) { |
final Ecriture e = ecrituresAvecAnalytique.get(i); |
e.setId(idsEcritues.get(i)); |
for (AssociationAnalytique a : e.getAssociationsAnalytiques()) { |
insertsAssociationAnalytique.add(a.createInsert(root, user)); |
} |
} |
SQLInsert.executeSimilarInserts(sysRoot, insertsAssociationAnalytique, false); |
} |
for (Piece p : pieces) { |
final List<Mouvement> mouvements = p.getMouvements(); |
for (Mouvement m : mouvements) { |
if (m.getPostInsertionAction() != null) { |
m.getPostInsertionAction().afterInsert(m); |
} |
} |
} |
return null; |
} |
}); |
} |
/** |
* Map des numero de compte en minuscule <-> Compte |
* |
* @param pieces pièces servant à déterminer sur quels numéros de compte on limite la requête |
*/ |
protected Map<String, Compte> getNumeroDesComptes(DBRoot root, List<Piece> pieces) { |
// tous les comptes dont le numero |
// est parmis celles des écritures des pièces |
final Set<String> numerosDesComptes = new HashSet<>(); |
for (Piece p : pieces) { |
final List<Mouvement> mouvements = p.getMouvements(); |
for (Mouvement m : mouvements) { |
for (Ecriture e : m.getEcritures()) { |
numerosDesComptes.add(e.getCompteNumero().toLowerCase()); |
} |
} |
} |
final Map<String, Compte> result = new HashMap<>(); |
final SQLTable tableCompte = root.getTable("COMPTE_PCE"); |
final SQLSelect selCompte = new SQLSelect(); |
selCompte.addSelect(tableCompte.getKey()); |
final SQLField fNumero = tableCompte.getField("NUMERO"); |
selCompte.addSelect(fNumero); |
selCompte.addSelect(tableCompte.getField("NOM")); |
String numeros = CollectionUtils.join(numerosDesComptes, ",", new ITransformer<Object, String>() { |
@Override |
public String transformChecked(final Object input) { |
return fNumero.getField().getType().toString(input); |
} |
}); |
final Where w = Where.createRaw("lower(" + fNumero.getFieldRef() + ") in (" + numeros + ")", fNumero); |
selCompte.setWhere(w); |
final ResultSetHandler resultSetHandler = new ResultSetHandler() { |
@Override |
public Object handle(ResultSet rs) throws SQLException { |
while (rs.next()) { |
final Long id = rs.getLong(1); |
final String numero = rs.getString(2); |
final String nom = rs.getString(3); |
result.put(numero.toLowerCase(), new Compte(id, numero, nom)); |
} |
return null; |
} |
}; |
root.getDBSystemRoot().getDataSource().execute(selCompte.asString(), resultSetHandler); |
return result; |
} |
/** |
* Map des codes en minuscule <-> Journal |
*/ |
protected Map<String, Journal> getCodesJournaux(DBRoot root) { |
final Map<String, Journal> result = new HashMap<>(); |
final SQLTable tableJournal = root.getTable("JOURNAL"); |
final SQLSelect selJournal = new SQLSelect(); |
selJournal.addSelect(tableJournal.getKey()); |
selJournal.addSelect(tableJournal.getField("CODE")); |
selJournal.addSelect(tableJournal.getField("NOM")); |
final ResultSetHandler resultSetHandler = new ResultSetHandler() { |
@Override |
public Object handle(ResultSet rs) throws SQLException { |
while (rs.next()) { |
final Long id = rs.getLong(1); |
final String code = rs.getString(2); |
final String nom = rs.getString(3); |
result.put(code.toLowerCase(), new Journal(id, code, nom)); |
} |
return null; |
} |
}; |
root.getDBSystemRoot().getDataSource().execute(selJournal.asString(), resultSetHandler); |
return result; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/Compte.java |
---|
New file |
0,0 → 1,69 |
/* |
* 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.generationEcritures; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.model.SQLInsert; |
import org.openconcerto.sql.model.SQLTable; |
public class Compte { |
private final Long id; |
private String numero; |
private String nom; |
public Compte(Long id, String numero, String nom) { |
this.id = id; |
this.numero = numero; |
this.nom = nom; |
} |
public Long getId() { |
return this.id; |
} |
public String getNumero() { |
return this.numero; |
} |
public String getNom() { |
return this.nom; |
} |
@Override |
public int hashCode() { |
return this.numero.hashCode(); |
} |
@Override |
public boolean equals(Object obj) { |
if (obj == null) |
return false; |
if (this.getClass() != obj.getClass()) |
return false; |
return ((Compte) obj).numero.equalsIgnoreCase(this.numero); |
} |
SQLInsert createInsert(DBRoot root) { |
final SQLInsert insert = new SQLInsert(); |
final SQLTable table = root.getTable("COMPTE_PCE"); |
insert.add(table.getField("NUMERO"), this.numero); |
insert.add(table.getField("NOM"), this.nom); |
return insert; |
} |
@Override |
public String toString() { |
return "Compte numero:" + this.numero + " " + this.nom + " (id:" + this.id + ")"; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/AssociationAnalytique.java |
---|
New file |
0,0 → 1,67 |
/* |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
* |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved. |
* |
* The contents of this file are subject to the terms of the GNU General Public License Version 3 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific |
* language governing permissions and limitations under the License. |
* |
* When distributing the software, include this License Header Notice in each file. |
*/ |
package org.openconcerto.erp.generationEcritures; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.model.SQLInsert; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.users.User; |
import java.math.BigDecimal; |
public class AssociationAnalytique { |
private final int idPosteAnalytique; |
private int idSaisieKmElement = 1; |
private BigDecimal pourcentage; |
private long montant; // centimes |
private boolean gestionAuto = false; |
private Ecriture ecriture; |
public AssociationAnalytique(int idPosteAnalytique) { |
this.idPosteAnalytique = idPosteAnalytique; |
} |
public void setIdSaisieKmElement(int idSaisieKmElement) { |
this.idSaisieKmElement = idSaisieKmElement; |
} |
public void setPourcentage(BigDecimal pourcentage) { |
this.pourcentage = pourcentage; |
} |
public void setMontant(long montant) { |
this.montant = montant; |
} |
public void setGestionAuto(boolean gestionAuto) { |
this.gestionAuto = gestionAuto; |
} |
public void setEcriture(Ecriture ecriture) { |
this.ecriture = ecriture; |
} |
public SQLInsert createInsert(DBRoot root, User user) { |
final SQLInsert insert = new SQLInsert(); |
final SQLTable table = root.getTable("ASSOCIATION_ANALYTIQUE"); |
insert.add(table.getField("ID_ECRITURE"), this.ecriture.getId().intValue()); |
insert.add(table.getField("ID_SAISIE_KM_ELEMENT"), this.idSaisieKmElement); |
insert.add(table.getField("ID_POSTE_ANALYTIQUE"), this.idPosteAnalytique); |
insert.add(table.getField("POURCENT"), this.pourcentage); |
insert.add(table.getField("MONTANT"), this.montant); |
insert.add(table.getField("GESTION_AUTO"), this.gestionAuto); |
return insert; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/Journal.java |
---|
New file |
0,0 → 1,69 |
/* |
* 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.generationEcritures; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.model.SQLInsert; |
import org.openconcerto.sql.model.SQLTable; |
public class Journal { |
private final Long id; |
private final String code; |
private final String nom; |
public Journal(Long id, final String code, final String nom) { |
this.id = id; |
this.code = code; |
this.nom = nom; |
} |
public Long getId() { |
return this.id; |
} |
public String getNom() { |
return this.nom; |
} |
public String getCode() { |
return this.code; |
} |
@Override |
public int hashCode() { |
return this.code.hashCode(); |
} |
@Override |
public boolean equals(Object obj) { |
if (obj == null) |
return false; |
if (this.getClass() != obj.getClass()) |
return false; |
return ((Journal) obj).code.equalsIgnoreCase(this.code); |
} |
SQLInsert createInsert(DBRoot root) { |
final SQLInsert insert = new SQLInsert(); |
final SQLTable table = root.getTable("JOURNAL"); |
insert.add(table.getField("CODE"), this.code); |
insert.add(table.getField("NOM"), this.nom); |
return insert; |
} |
@Override |
public String toString() { |
return "Journal code:" + this.code + " " + this.nom + " (id:" + this.id + ")"; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/MouvementPostInsertionAction.java |
---|
New file |
0,0 → 1,22 |
/* |
* 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.generationEcritures; |
import java.sql.SQLException; |
public interface MouvementPostInsertionAction { |
public void afterInsert(Mouvement m) throws SQLException; |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/Mouvement.java |
---|
New file |
0,0 → 1,114 |
/* |
* 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.generationEcritures; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.model.SQLInsert; |
import org.openconcerto.sql.model.SQLTable; |
import java.math.BigDecimal; |
import java.util.ArrayList; |
import java.util.List; |
public class Mouvement { |
private String numero; |
private List<Ecriture> ecritures = new ArrayList<>(); |
private Number id; |
private BigDecimal debit = BigDecimal.ZERO; |
private BigDecimal credit = BigDecimal.ZERO; |
private Piece piece; |
// Source |
private Number idSource; |
private String source; |
private Mouvement pere; |
private MouvementPostInsertionAction postInsertionAction; |
public Mouvement() { |
} |
public void setSource(Number idSource, String source) { |
this.idSource = idSource; |
this.source = source; |
} |
public void add(Ecriture e) { |
this.ecritures.add(e); |
this.debit = this.debit.add(e.getDebit()); |
this.credit = this.credit.add(e.getCredit()); |
e.setMouvement(this); |
} |
List<Ecriture> getEcritures() { |
return this.ecritures; |
} |
void setId(Number id) { |
this.id = id; |
} |
public Number getId() { |
return this.id; |
} |
SQLInsert createInsert(DBRoot root) { |
final SQLInsert insert = new SQLInsert(); |
final SQLTable table = root.getTable("MOUVEMENT"); |
// FIXME le numero doit être généré en auto |
// Thread.dumpStack(); |
// NUMERO = SELECT (MAX) ? |
// insert.add(table.getField("NUMERO"), this.numero); |
// select for update max(numero) |
if (this.idSource != null) { |
insert.add(table.getField("IDSOURCE"), this.idSource); |
insert.add(table.getField("SOURCE"), this.source); |
} |
insert.add(table.getField("ID_PIECE"), this.piece.getId().intValue()); |
if (this.pere != null) { |
insert.add(table.getField("ID_MOUVEMENT_PERE"), this.pere.getId().intValue()); |
} |
// TODO CREATION_DATE MODIFICATION_DATE |
return insert; |
} |
public boolean isBalanced() { |
BigDecimal d = BigDecimal.ZERO; |
BigDecimal c = BigDecimal.ZERO; |
for (Ecriture e : this.ecritures) { |
d = d.add(e.getDebit()); |
c = c.add(e.getCredit()); |
} |
return d.compareTo(c) == 0; |
} |
public Piece getPiece() { |
return this.piece; |
} |
public void setPiece(Piece piece) { |
this.piece = piece; |
} |
public boolean isEmpty() { |
return this.ecritures.isEmpty(); |
} |
public MouvementPostInsertionAction getPostInsertionAction() { |
return this.postInsertionAction; |
} |
public void setAfterInsert(MouvementPostInsertionAction insertionAction) { |
this.postInsertionAction = insertionAction; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/GenerationEcritures.java |
---|
396,6 → 396,10 |
if (tiers.getObject("ID_CATEGORIE_COMPTABLE") != null && !tiers.isForeignEmpty("ID_CATEGORIE_COMPTABLE")) { |
rowCatCompta = tiers.getForeign("ID_CATEGORIE_COMPTABLE"); |
} |
if (row.getTable().contains("ID_CATEGORIE_COMPTABLE") && row.getObject("ID_CATEGORIE_COMPTABLE") != null && !row.isForeignEmpty("ID_CATEGORIE_COMPTABLE")) { |
rowCatCompta = row.getForeign("ID_CATEGORIE_COMPTABLE"); |
} |
TotalCalculator calc = new TotalCalculator("T_PA_HT", fieldTotalHT, null, achat, defaultCompte, rowCatCompta); |
calc.setIntraComm(intra); |
436,6 → 440,7 |
calc.addEchantillon((BigDecimal) sqlRow.getObject("T_PV_HT"), sqlRow.getForeign("ID_TAXE")); |
} |
} |
calc.checkResult(); |
totalAvtRemise = calc.getTotalHT(); |
} |
514,6 → 519,12 |
calc.addLine(rowValsFraisDoc, null, 1, false); |
} |
// Fix TVA si nécessaire pour facture fournisseur |
if (row.getTable().contains("TVA_ADJUSTMENT")) { |
BigDecimal tvaFix = row.getBigDecimal("TVA_ADJUSTMENT"); |
calc.addTVAAdjust(tvaFix); |
} |
calc.checkResult(); |
return calc; |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/Ecriture.java |
---|
New file |
0,0 → 1,237 |
/* |
* 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.generationEcritures; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.model.SQLInsert; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.users.User; |
import java.math.BigDecimal; |
import java.util.ArrayList; |
import java.util.Date; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
public class Ecriture { |
private Date date; |
private BigDecimal debit; |
private BigDecimal credit; |
private Mouvement mouvement; |
private String nom; |
private String compteNumero; |
private String compteNom; |
private Number compteID; |
private String journalNom; |
private String journalCode; |
private Number journalID; |
private List<AssociationAnalytique> associations; |
private Number id; |
private Map<String, Object> cookies; |
private boolean cloture; |
private boolean aNouveau; |
private Date dateValidation; |
private Date dateLettrage; |
private String lettrage; |
public Ecriture(Date date, BigDecimal debit, BigDecimal credit) { |
this.date = date; |
this.debit = debit; |
this.credit = credit; |
} |
public SQLInsert createInsert(DBRoot root, User user) { |
final SQLInsert insert = new SQLInsert(); |
final SQLTable table = root.getTable("ECRITURE"); |
insert.add(table.getField("DATE"), this.date); |
insert.add(table.getField("ID_MOUVEMENT"), this.mouvement.getId().intValue()); |
insert.add(table.getField("DEBIT"), this.debit.multiply(new BigDecimal(100)).longValue()); |
insert.add(table.getField("CREDIT"), this.credit.multiply(new BigDecimal(100)).longValue()); |
insert.add(table.getField("NOM"), this.nom); |
if (this.compteNom == null) { |
throw new IllegalStateException("nom du compte manquant"); |
} |
if (this.compteNumero == null || this.compteNumero.isEmpty()) { |
throw new IllegalStateException("numéro du compte manquant"); |
} |
insert.add(table.getField("ID_COMPTE_PCE"), this.compteID); |
insert.add(table.getField("COMPTE_NUMERO"), this.compteNumero); |
insert.add(table.getField("COMPTE_NOM"), this.compteNom); |
if (this.journalNom == null) { |
throw new IllegalStateException("nom du journal manquant"); |
} |
if (this.journalCode == null || this.journalCode.isEmpty()) { |
throw new IllegalStateException("code du journal manquant"); |
} |
insert.add(table.getField("ID_JOURNAL"), this.journalID); |
insert.add(table.getField("JOURNAL_NOM"), this.journalNom); |
insert.add(table.getField("JOURNAL_CODE"), this.journalCode); |
insert.add(table.getField("NOM_PIECE"), this.mouvement.getPiece().getNom()); |
insert.add(table.getField("ID_USER_COMMON_CREATE"), user.getId()); |
insert.add(table.getField("ID_USER_COMMON_MODIFY"), user.getId()); |
insert.add(table.getField("CLOTURE"), this.cloture); |
insert.add(table.getField("RAN"), this.aNouveau); |
if (this.dateValidation != null) { |
insert.add(table.getField("DATE_VALIDE"), this.dateValidation); |
insert.add(table.getField("VALIDE"), Boolean.TRUE); |
} else { |
insert.add(table.getField("DATE_VALIDE"), null); |
insert.add(table.getField("VALIDE"), Boolean.FALSE); |
} |
insert.add(table.getField("DATE_LETTRAGE"), this.dateLettrage); |
insert.add(table.getField("LETTRAGE"), this.lettrage == null || this.lettrage.isEmpty() ? " " : this.lettrage); |
return insert; |
} |
public void setDateValidation(Date dateValidation) { |
this.dateValidation = dateValidation; |
} |
public void setDateLettrage(Date dateLettrage) { |
this.dateLettrage = dateLettrage; |
} |
public void setLettrage(String lettrage) { |
this.lettrage = lettrage; |
} |
public void setCloture(boolean cloture) { |
this.cloture = cloture; |
} |
public void setaNouveau(boolean aNouveau) { |
this.aNouveau = aNouveau; |
} |
public String getNom() { |
return this.nom; |
} |
public void setNom(String nom) { |
this.nom = nom; |
} |
void setId(Number id) { |
this.id = id; |
} |
public Number getId() { |
return this.id; |
} |
public Number getCompteID() { |
return this.compteID; |
} |
public void setCompteID(Number compteID) { |
this.compteID = compteID; |
} |
public void setCompte(String numero, String nom) { |
this.compteNumero = numero; |
this.compteNom = nom; |
} |
public String getCompteNumero() { |
return this.compteNumero; |
} |
public String getCompteNom() { |
return this.compteNom; |
} |
public Number getJournalID() { |
return this.journalID; |
} |
public void setJournalID(Number journalID) { |
this.journalID = journalID; |
} |
public void setJournal(String code, String nom) { |
this.journalCode = code; |
this.journalNom = nom; |
} |
public String getJournalCode() { |
return this.journalCode; |
} |
public String getJournalNom() { |
return this.journalNom; |
} |
public BigDecimal getDebit() { |
return this.debit; |
} |
public BigDecimal getCredit() { |
return this.credit; |
} |
public Date getDate() { |
return this.date; |
} |
public void setMouvement(Mouvement mouvement) { |
this.mouvement = mouvement; |
} |
public List<AssociationAnalytique> getAssociationsAnalytiques() { |
return this.associations; |
} |
public void addAssociationAnalytique(AssociationAnalytique a) { |
if (this.associations == null) { |
this.associations = new ArrayList<>(); |
} |
a.setEcriture(this); |
this.associations.add(a); |
} |
public void removeAssociationAnalytique(AssociationAnalytique a) { |
if (this.associations == null) { |
a.setEcriture(null); |
return; |
} |
this.associations.remove(a); |
a.setEcriture(null); |
if (this.associations.isEmpty()) { |
this.associations = null; |
} |
} |
public boolean hasAnalytique() { |
return this.associations != null; |
} |
public void putCookie(String key, Object value) { |
if (this.cookies == null) { |
this.cookies = new HashMap<>(); |
} |
this.cookies.put(key, value); |
} |
public Object getCookie(String key) { |
return this.cookies.get(key); |
} |
@Override |
public String toString() { |
return "Ecriture : " + this.nom + ", Compte (id:" + this.compteID + ") " + this.compteNumero + " " + this.compteNom + ", Débit : " + this.debit + ", Crédit:" + this.credit; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/GenerationReglementVenteNG.java |
---|
392,7 → 392,12 |
} |
} |
this.putValue("ID_JOURNAL", JournalSQLElement.BANQUES); |
int idJournal = JournalSQLElement.BANQUES; |
if (rowPrefsCompte.getObject("ID_JOURNAL_VALEUR_ENCAISSEMENT") != null && !rowPrefsCompte.isForeignEmpty("ID_JOURNAL_VALEUR_ENCAISSEMENT")) { |
idJournal = rowPrefsCompte.getForeignID("ID_JOURNAL_VALEUR_ENCAISSEMENT"); |
} |
this.putValue("ID_JOURNAL", idJournal); |
this.putValue("ID_COMPTE_PCE", idCompteClient); |
this.putValue("DEBIT", Long.valueOf(0)); |
this.putValue("CREDIT", Long.valueOf(ttc.getLongValue())); |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/GenerationMvtFactureFournisseur.java |
---|
166,6 → 166,10 |
} |
} |
this.putValue("ID_COMPTE_PCE", new Integer(idCompteFourn)); |
if (rowFournisseur.getTable().getTable("ECRITURE").contains("CODE_CLIENT")) { |
this.putValue("CODE_CLIENT", rowFournisseur.getString("CODE")); |
} |
this.putValue("DEBIT", new Long(0)); |
if (rowFournisseur.getBoolean("UE")) { |
this.putValue("CREDIT", new Long(htLongValue)); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/element/ContactSQLElement.java |
---|
File deleted |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/element/CustomerSQLComponent.java |
---|
17,6 → 17,7 |
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.ui.AdresseClientItemTable; |
import org.openconcerto.erp.core.sales.product.element.ClientCodeArticleTable; |
import org.openconcerto.erp.core.sales.product.ui.CustomerProductQtyPriceListTable; |
import org.openconcerto.erp.preferences.ModeReglementDefautPrefPanel; |
import org.openconcerto.erp.utils.TM; |
import org.openconcerto.sql.Configuration; |
75,6 → 76,7 |
private ContactItemTable table; |
private ClientCodeArticleTable tableCustomProduct; |
private AdresseClientItemTable adresseTable = new AdresseClientItemTable(); |
private SQLTable contactTable = Configuration.getInstance().getDirectory().getElement("CONTACT").getTable(); |
private final SQLTable tableNum = getTable().getBase().getTable("NUMEROTATION_AUTO"); |
private final JUniqueTextField code = new JUniqueTextField(20) { |
88,6 → 90,7 |
} |
}; |
private CustomerProductQtyPriceListTable clienTarifTable = new CustomerProductQtyPriceListTable(); |
private SQLRowValues defaultContactRowVals = new SQLRowValues(UndefinedRowValuesCache.getInstance().getDefaultRowValues(this.contactTable)); |
private JCheckBox checkAdrLivraison, checkAdrFacturation; |
167,6 → 170,8 |
return this.table; |
} else if (id.equals("customerrelationship.customer.customproduct")) { |
return this.tableCustomProduct; |
} else if (id.equals("customerrelationship.customer.customtarif")) { |
return this.clienTarifTable; |
} else if (id.equals("customerrelationship.customer.addresses")) { |
return createAdressesComponent(); |
} else if (id.equals("NOM")) { |
243,6 → 248,7 |
super.update(); |
final int selectedID = getSelectedID(); |
this.table.updateField("ID_CLIENT", selectedID); |
this.clienTarifTable.updateField("ID_CLIENT", selectedID); |
this.tableCustomProduct.updateField("ID_CLIENT", selectedID); |
this.adresseTable.updateField("ID_CLIENT", selectedID); |
} |
254,6 → 260,7 |
this.checkAdrFacturation.setSelected(r == null || !r.getFields().contains("ID_ADRESSE_F") || r.isForeignEmpty("ID_ADRESSE_F")); |
if (r != null) { |
this.table.insertFrom("ID_CLIENT", r.asRowValues()); |
this.clienTarifTable.insertFrom("ID_CLIENT", r.asRowValues()); |
this.tableCustomProduct.insertFrom("ID_CLIENT", r.asRowValues()); |
this.adresseTable.insertFrom("ID_CLIENT", r.asRowValues()); |
} |
294,6 → 301,7 |
id = super.insert(order); |
this.table.updateField("ID_CLIENT", id); |
this.tableCustomProduct.updateField("ID_CLIENT", id); |
this.clienTarifTable.updateField("ID_CLIENT", id); |
this.adresseTable.updateField("ID_CLIENT", id); |
if (NumerotationAutoSQLElement.getNextNumero(getElement().getClass()).equalsIgnoreCase(this.code.getText().trim())) { |
SQLRowValues rowVals = new SQLRowValues(this.tableNum); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/element/CustomerGroup.java |
---|
94,6 → 94,9 |
final Group gCustomProduct = new Group("customerrelationship.customer.customproduct", LayoutHints.DEFAULT_SEPARATED_GROUP_HINTS); |
gCustomProduct.addItem("customerrelationship.customer.customproduct", new LayoutHints(true, true, true, true, true, true, true, true)); |
this.add(gCustomProduct); |
final Group gCustomRemiseProduct = new Group("customerrelationship.customer.customtarif", LayoutHints.DEFAULT_SEPARATED_GROUP_HINTS); |
gCustomRemiseProduct.addItem("customerrelationship.customer.customtarif", new LayoutHints(true, true, true, true, true, true, true, true)); |
this.add(gCustomRemiseProduct); |
this.add(gState); |
final Group gInfo = new Group("customerrelationship.customer.info", LayoutHints.DEFAULT_SEPARATED_GROUP_HINTS); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/element/ClientNormalSQLElement.java |
---|
22,14 → 22,19 |
import org.openconcerto.ql.QLPrinter; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.element.SQLComponent; |
import org.openconcerto.sql.model.FieldPath; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.graph.Path; |
import org.openconcerto.sql.preferences.SQLPreferences; |
import org.openconcerto.sql.request.ListSQLRequest; |
import org.openconcerto.sql.view.list.BaseSQLTableModelColumn; |
import org.openconcerto.sql.view.list.IListe; |
import org.openconcerto.sql.view.list.IListeAction.IListeEvent; |
import org.openconcerto.sql.view.list.RowAction.PredicateRowAction; |
import org.openconcerto.sql.view.list.SQLTableModelSource; |
import org.openconcerto.ui.EmailComposer; |
import org.openconcerto.utils.CollectionUtils; |
import org.openconcerto.utils.ExceptionHandler; |
import java.awt.Font; |
37,6 → 42,7 |
import java.util.ArrayList; |
import java.util.Arrays; |
import java.util.List; |
import java.util.Set; |
import javax.swing.AbstractAction; |
180,6 → 186,28 |
return l; |
} |
@Override |
protected void _initTableSource(SQLTableModelSource res) { |
super._initTableSource(res); |
res.getColumns().add(new BaseSQLTableModelColumn(getDirectory().getTranslator().getLabelFor(getTable().getField("CATEGORIES")), String.class) { |
@Override |
protected Object show_(SQLRowAccessor r) { |
return r.getString("CATEGORIES"); |
} |
@Override |
public Set<FieldPath> getPaths() { |
Path p = new Path(getTable()); |
return CollectionUtils.createSet(new FieldPath(p, "CATEGORIES")); |
} |
}); |
} |
/* |
* (non-Javadoc) |
* |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/element/ComptaContactSQLElement.java |
---|
New file |
0,0 → 1,63 |
/* |
* 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.core.customerrelationship.customer.element; |
import org.openconcerto.sql.view.list.IListe; |
import org.openconcerto.sql.view.list.IListeAction.IListeEvent; |
import org.openconcerto.sql.view.list.RowAction.PredicateRowAction; |
import java.awt.event.ActionEvent; |
import javax.swing.AbstractAction; |
public abstract class ComptaContactSQLElement extends ContactSQLElementBase { |
static public class ContactFournisseurSQLElement extends ComptaContactSQLElement { |
public ContactFournisseurSQLElement() { |
super("CONTACT_FOURNISSEUR"); |
} |
} |
static public class ContactSalarieSQLElement extends ComptaContactSQLElement { |
public ContactSalarieSQLElement() { |
super("CONTACT_SALARIE"); |
} |
} |
static public class ContactAdministratifSQLElement extends ComptaContactSQLElement { |
public ContactAdministratifSQLElement() { |
super("CONTACT_ADMINISTRATIF"); |
} |
} |
static public class ContactSQLElement extends ComptaContactSQLElement { |
public ContactSQLElement() { |
super("CONTACT"); |
} |
} |
protected ComptaContactSQLElement(String tableName) { |
super(tableName); |
PredicateRowAction action = new PredicateRowAction(new AbstractAction() { |
@Override |
public void actionPerformed(ActionEvent e) { |
sendMail(IListe.get(e).getSelectedRows()); |
} |
}, true, "customerrelationship.customer.email.send"); |
action.setPredicate(IListeEvent.getNonEmptySelectionPredicate()); |
getRowActions().add(action); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/report/ReportingCommercialPDF.java |
---|
New file |
0,0 → 1,177 |
/* |
* 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.core.customerrelationship.customer.report; |
import java.awt.Color; |
import java.awt.Desktop; |
import java.io.File; |
import java.io.FileOutputStream; |
import java.io.IOException; |
import java.math.BigDecimal; |
import java.text.DecimalFormat; |
import java.text.DecimalFormatSymbols; |
import java.util.ArrayList; |
import java.util.Calendar; |
import java.util.Collections; |
import java.util.Comparator; |
import java.util.Date; |
import java.util.List; |
import com.ibm.icu.text.SimpleDateFormat; |
import com.lowagie.text.Document; |
import com.lowagie.text.Element; |
import com.lowagie.text.Font; |
import com.lowagie.text.PageSize; |
import com.lowagie.text.Paragraph; |
import com.lowagie.text.Phrase; |
import com.lowagie.text.Rectangle; |
import com.lowagie.text.pdf.PdfPCell; |
import com.lowagie.text.pdf.PdfPTable; |
import com.lowagie.text.pdf.PdfWriter; |
public class ReportingCommercialPDF { |
private final List<ReportingCommercial> items; |
public ReportingCommercialPDF(List<ReportingCommercial> items) { |
this.items = new ArrayList<>(items); |
Collections.sort(this.items, new Comparator<ReportingCommercial>() { |
@Override |
public int compare(ReportingCommercial o1, ReportingCommercial o2) { |
return o2.getTotal().compareTo(o1.getTotal()); |
} |
}); |
} |
public static void main(String[] args) throws IOException { |
final List<ReportingCommercial> list = new ArrayList<>(); |
final Calendar c = Calendar.getInstance(); |
final Date d1 = c.getTime(); |
c.add(Calendar.MONTH, 50); |
final Date d2 = c.getTime(); |
for (int i = 0; i < 5; i++) { |
ReportingCommercial r = new ReportingCommercial("commercial " + i, d1, d2); |
for (int j = 0; j < i * 5; j++) { |
final ReportingCommercialItem item = new ReportingCommercialItem("client " + j); |
item.addCA(BigDecimal.valueOf(j * 12345.78f)); |
r.add(item); |
} |
list.add(r); |
} |
final File file = new File("out.pdf"); |
final ReportingCommercialPDF pdf = new ReportingCommercialPDF(list); |
pdf.export(file); |
Desktop.getDesktop().open(file); |
} |
public void export(File file) throws IOException { |
try { |
final Document document = new Document(PageSize.A4); |
PdfWriter.getInstance(document, new FileOutputStream(file)); |
document.open(); |
// Formats |
final SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy"); |
final DecimalFormat decimalFormat = new DecimalFormat("###,###,##0.00"); |
final DecimalFormatSymbols formatSymbols = decimalFormat.getDecimalFormatSymbols(); |
formatSymbols.setGroupingSeparator(' '); |
formatSymbols.setDecimalSeparator(','); |
decimalFormat.setDecimalFormatSymbols(formatSymbols); |
// Fonts |
final Font fontHeader = new Font(Font.HELVETICA, 11f, Font.BOLD); |
fontHeader.setColor(Color.WHITE); |
final Font normal = new Font(Font.HELVETICA, 10f, Font.NORMAL); |
final Font fontTitle = new Font(Font.HELVETICA, 18f, Font.BOLD); |
final Font fontInfo = new Font(Font.HELVETICA, 11f, Font.NORMAL); |
// Colors |
final Color backgroundColor = new Color(57, 115, 157); |
final Color cellBackgroundColor = new Color(225, 236, 244); |
for (ReportingCommercial reporting : this.items) { |
final List<ReportingCommercialItem> rItems = new ArrayList<ReportingCommercialItem>(reporting.getItems()); |
Collections.sort(rItems, new Comparator<ReportingCommercialItem>() { |
@Override |
public int compare(ReportingCommercialItem o1, ReportingCommercialItem o2) { |
return o2.getCa().compareTo(o1.getCa()); |
} |
}); |
document.add(new Paragraph("Chiffre d'affaires", fontTitle)); |
document.add(new Paragraph("Commercial : " + reporting.getCommercial(), fontInfo)); |
document.add(new Paragraph("Période : du " + df.format(reporting.getDebut()) + " au " + df.format(reporting.getFin()), fontInfo)); |
if (rItems.isEmpty()) { |
document.add(new Paragraph("\n")); |
document.add(new Paragraph("\n")); |
final Font fontInfo2 = new Font(Font.HELVETICA, 13f, Font.ITALIC); |
fontInfo2.setColor(Color.GRAY); |
document.add(new Paragraph("Aucune donnée.", fontInfo2)); |
} else { |
document.add(new Paragraph("Total : " + decimalFormat.format(reporting.getTotal()) + " € HT", fontInfo)); |
document.add(new Paragraph("\n")); |
final PdfPTable table = new PdfPTable(2); |
table.setWidthPercentage(100); |
table.setWidths(new float[] { 800f, 160f }); |
final PdfPCell c1 = new PdfPCell(new Phrase("Clients", fontHeader)); |
c1.setBackgroundColor(backgroundColor); |
c1.setBorder(Rectangle.NO_BORDER); |
c1.setHorizontalAlignment(Element.ALIGN_LEFT); |
c1.setVerticalAlignment(Element.ALIGN_MIDDLE); |
c1.setPaddingBottom(7); |
c1.setPaddingLeft(6); |
table.addCell(c1); |
final PdfPCell c2 = new PdfPCell(new Phrase("C.A. H.T.", fontHeader)); |
c2.setBackgroundColor(backgroundColor); |
c2.setBorder(Rectangle.NO_BORDER); |
c2.setHorizontalAlignment(Element.ALIGN_CENTER); |
c2.setVerticalAlignment(Element.ALIGN_MIDDLE); |
c2.setPaddingBottom(7); |
c2.setPaddingLeft(6); |
table.addCell(c2); |
table.setHeaderRows(1); |
boolean pair = true; |
for (ReportingCommercialItem rItem : rItems) { |
final PdfPCell col1 = new PdfPCell(new Phrase(rItem.getClient(), normal)); |
col1.setBorder(Rectangle.NO_BORDER); |
col1.setHorizontalAlignment(Element.ALIGN_LEFT); |
col1.setVerticalAlignment(Element.ALIGN_CENTER); |
col1.setPaddingBottom(5); |
col1.setPaddingLeft(6); |
final PdfPCell col2 = new PdfPCell(new Phrase(decimalFormat.format(rItem.getCa()), normal)); |
col2.setHorizontalAlignment(Element.ALIGN_RIGHT); |
col2.setBorder(Rectangle.NO_BORDER); |
// Alternance couleur |
if (pair) { |
col1.setBackgroundColor(cellBackgroundColor); |
col2.setBackgroundColor(cellBackgroundColor); |
} |
table.addCell(col1); |
table.addCell(col2); |
pair = !pair; |
} |
document.add(table); |
} |
document.newPage(); |
} |
document.close(); |
} catch (Exception e) { |
throw new IOException(e); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/report/ReportingCommercialItem.java |
---|
New file |
0,0 → 1,39 |
/* |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
* |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved. |
* |
* The contents of this file are subject to the terms of the GNU General Public License Version 3 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific |
* language governing permissions and limitations under the License. |
* |
* When distributing the software, include this License Header Notice in each file. |
*/ |
package org.openconcerto.erp.core.customerrelationship.customer.report; |
import java.math.BigDecimal; |
public class ReportingCommercialItem { |
private String client; |
private BigDecimal ca; |
public ReportingCommercialItem(String client) { |
this.client = client; |
this.ca = BigDecimal.ZERO; |
} |
public void addCA(BigDecimal c) { |
this.ca = this.ca.add(c); |
} |
public String getClient() { |
return this.client; |
} |
public BigDecimal getCa() { |
return this.ca; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/report/ReportingCommercial.java |
---|
New file |
0,0 → 1,73 |
/* |
* 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.core.customerrelationship.customer.report; |
import java.math.BigDecimal; |
import java.util.Collection; |
import java.util.Date; |
import java.util.HashMap; |
import java.util.Map; |
public class ReportingCommercial { |
private String commercial; |
private Date debut; |
private Date fin; |
private Map<String, ReportingCommercialItem> items = new HashMap<>(); |
public ReportingCommercial(String commercial, Date debut, Date fin) { |
this.commercial = commercial; |
this.debut = debut; |
this.fin = fin; |
} |
public BigDecimal getTotal() { |
BigDecimal total = BigDecimal.ZERO; |
for (ReportingCommercialItem item : this.items.values()) { |
total = total.add(item.getCa()); |
} |
return total; |
} |
public void add(ReportingCommercialItem item) { |
this.items.put(item.getClient(), item); |
} |
public void add(String client, BigDecimal ht) { |
if (this.items.containsKey(client)) { |
this.items.get(client).addCA(ht); |
} else { |
ReportingCommercialItem reportingCommercialItem = new ReportingCommercialItem(client); |
reportingCommercialItem.addCA(ht); |
this.items.put(client, reportingCommercialItem); |
} |
} |
public Collection<ReportingCommercialItem> getItems() { |
return this.items.values(); |
} |
public String getCommercial() { |
return this.commercial; |
} |
public Date getDebut() { |
return this.debut; |
} |
public Date getFin() { |
return this.fin; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/report/ReportingCommercialCreator.java |
---|
New file |
0,0 → 1,111 |
/* |
* 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.core.customerrelationship.customer.report; |
import org.openconcerto.sql.model.DBRoot; |
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.cc.ITransformer; |
import java.math.BigDecimal; |
import java.util.Collection; |
import java.util.Date; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
public class ReportingCommercialCreator { |
final private Date deb, fin; |
final private DBRoot root; |
public ReportingCommercialCreator(Date deb, Date fin, DBRoot root) { |
this.deb = deb; |
this.fin = fin; |
this.root = root; |
} |
public Collection<ReportingCommercial> getValues() { |
// Facture |
final SQLTable tableFacture = this.root.getTable("SAISIE_VENTE_FACTURE"); |
SQLRowValues rowValues = new SQLRowValues(tableFacture); |
rowValues.putRowValues("ID_COMMERCIAL").putNulls("PRENOM", "NOM"); |
rowValues.putRowValues("ID_CLIENT").putNulls("CODE", "NOM"); |
rowValues.putNulls("T_HT", "T_TTC"); |
SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowValues); |
fetcher.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() { |
@Override |
public SQLSelect transformChecked(SQLSelect input) { |
Where w = new Where(tableFacture.getField("DATE"), deb, fin); |
input.setWhere(w); |
return input; |
} |
}); |
Map<Integer, ReportingCommercial> mapCommercial = new HashMap<>(); |
List<SQLRowValues> result = fetcher.fetch(); |
for (SQLRowValues sqlRowValues : result) { |
int commercialID = sqlRowValues.getForeignID("ID_COMMERCIAL"); |
if (!mapCommercial.containsKey(commercialID)) { |
SQLRowAccessor commercialRow = sqlRowValues.getForeign("ID_COMMERCIAL"); |
mapCommercial.put(commercialID, new ReportingCommercial(commercialRow.getString("PRENOM") + " " + commercialRow.getString("NOM"), deb, fin)); |
} |
ReportingCommercial r = mapCommercial.get(commercialID); |
BigDecimal bigDecimal = new BigDecimal(sqlRowValues.getLong("T_HT")).movePointLeft(2); |
r.add(sqlRowValues.getForeign("ID_CLIENT").getString("NOM"), bigDecimal); |
} |
// Avoir |
final SQLTable tableAvoir = this.root.getTable("AVOIR_CLIENT"); |
SQLRowValues rowValuesAvoir = new SQLRowValues(tableAvoir); |
rowValuesAvoir.putRowValues("ID_COMMERCIAL").putNulls("PRENOM", "NOM"); |
rowValuesAvoir.putRowValues("ID_CLIENT").putNulls("CODE", "NOM"); |
rowValuesAvoir.putNulls("MONTANT_HT", "MONTANT_TTC"); |
SQLRowValuesListFetcher fetcherAvoir = SQLRowValuesListFetcher.create(rowValuesAvoir); |
fetcherAvoir.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() { |
@Override |
public SQLSelect transformChecked(SQLSelect input) { |
Where w = new Where(tableAvoir.getField("DATE"), deb, fin); |
input.setWhere(w); |
return input; |
} |
}); |
List<SQLRowValues> resultA = fetcherAvoir.fetch(); |
for (SQLRowValues sqlRowValues : resultA) { |
int commercialID = sqlRowValues.getForeignID("ID_COMMERCIAL"); |
if (!mapCommercial.containsKey(commercialID)) { |
SQLRowAccessor commercialRow = sqlRowValues.getForeign("ID_COMMERCIAL"); |
mapCommercial.put(commercialID, new ReportingCommercial(commercialRow.getString("PRENOM") + " " + commercialRow.getString("NOM"), deb, fin)); |
} |
ReportingCommercial r = mapCommercial.get(commercialID); |
BigDecimal bigDecimal = new BigDecimal(sqlRowValues.getLong("MONTANT_HT")).movePointLeft(2).negate(); |
r.add(sqlRowValues.getForeign("ID_CLIENT").getString("NOM"), bigDecimal); |
} |
return mapCommercial.values(); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/report/ReportingCommercialPanel.java |
---|
New file |
0,0 → 1,125 |
/* |
* 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. |
*/ |
/* |
* Créé le 23 avr. 2012 |
*/ |
package org.openconcerto.erp.core.customerrelationship.customer.report; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.ui.DefaultGridBagConstraints; |
import org.openconcerto.ui.JDate; |
import org.openconcerto.utils.ExceptionHandler; |
import java.awt.Desktop; |
import java.awt.Frame; |
import java.awt.GridBagConstraints; |
import java.awt.GridBagLayout; |
import java.awt.event.ActionEvent; |
import java.beans.PropertyChangeEvent; |
import java.beans.PropertyChangeListener; |
import java.io.File; |
import java.io.IOException; |
import java.util.ArrayList; |
import java.util.Calendar; |
import java.util.List; |
import javax.swing.AbstractAction; |
import javax.swing.JButton; |
import javax.swing.JLabel; |
import javax.swing.JPanel; |
import javax.swing.SwingUtilities; |
public class ReportingCommercialPanel extends JPanel { |
public ReportingCommercialPanel(final DBRoot root) { |
super(new GridBagLayout()); |
JLabel labelCom = new JLabel("Période du "); |
GridBagConstraints c = new DefaultGridBagConstraints(); |
this.add(labelCom, c); |
c.gridx++; |
final JDate dateDeb = new JDate(); |
this.add(dateDeb, c); |
c.gridx++; |
JLabel labelYear = new JLabel("au"); |
final JDate dateFin = new JDate(); |
Calendar cal = Calendar.getInstance(); |
cal.set(Calendar.MONTH, Calendar.JANUARY); |
cal.set(Calendar.DAY_OF_MONTH, 1); |
dateDeb.setValue(cal.getTime()); |
this.add(labelYear, c); |
c.gridx++; |
this.add(dateFin, c); |
cal.set(Calendar.MONTH, Calendar.DECEMBER); |
cal.set(Calendar.DAY_OF_MONTH, 31); |
dateFin.setValue(cal.getTime()); |
final JButton buttonValid = new JButton(new AbstractAction("Valider") { |
@Override |
public void actionPerformed(ActionEvent e) { |
new Thread() { |
public void run() { |
ReportingCommercialCreator creator = new ReportingCommercialCreator(dateDeb.getValue(), dateFin.getValue(), root); |
List<ReportingCommercial> list = new ArrayList<>(creator.getValues()); |
ReportingCommercialPDF reporting = new ReportingCommercialPDF(list); |
File file; |
try { |
file = File.createTempFile("ReportingCommerical", ".pdf"); |
reporting.export(file); |
Desktop.getDesktop().open(file); |
} catch (IOException e) { |
ExceptionHandler.handle("Erreur lors de la cration du fichier", e); |
} |
SwingUtilities.invokeLater(new Runnable() { |
@Override |
public void run() { |
Frame frame = (Frame) SwingUtilities.getRoot(ReportingCommercialPanel.this); |
if (frame != null) { |
frame.dispose(); |
} |
} |
}); |
}; |
}.start(); |
} |
}); |
c.gridx++; |
// buttonValid.setEnabled(false); |
this.add(buttonValid, c); |
dateDeb.addValueListener(new PropertyChangeListener() { |
@Override |
public void propertyChange(PropertyChangeEvent evt) { |
buttonValid.setEnabled(dateDeb.getValue() != null && dateFin.getValue() != null); |
} |
}); |
dateFin.addValueListener(new PropertyChangeListener() { |
@Override |
public void propertyChange(PropertyChangeEvent evt) { |
buttonValid.setEnabled(dateDeb.getValue() != null && dateFin.getValue() != null); |
} |
}); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/action/ListeDesContactsAction.java |
---|
15,7 → 15,7 |
import org.openconcerto.erp.action.CreateIListFrameAbstractAction; |
import org.openconcerto.erp.config.ComptaPropsConfiguration; |
import org.openconcerto.erp.core.customerrelationship.customer.element.ContactSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.ComptaContactSQLElement.ContactSQLElement; |
public class ListeDesContactsAction extends CreateIListFrameAbstractAction<ContactSQLElement> { |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/action/ListeDesClientsAction.java |
---|
15,9 → 15,8 |
import org.openconcerto.erp.action.CreateIListFrameAbstractAction; |
import org.openconcerto.erp.config.ComptaPropsConfiguration; |
import org.openconcerto.erp.core.customerrelationship.customer.element.ClientNormalSQLElement; |
import org.openconcerto.erp.core.customerrelationship.customer.element.CustomerSQLElement; |
import org.openconcerto.erp.core.sales.invoice.ui.EcheanceRenderer; |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.model.SQLField; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.view.IListFrame; |
26,10 → 25,12 |
import javax.swing.JTable; |
public class ListeDesClientsAction extends CreateIListFrameAbstractAction<ClientNormalSQLElement> { |
public class ListeDesClientsAction extends CreateIListFrameAbstractAction<SQLElement> { |
public ListeDesClientsAction(final ComptaPropsConfiguration conf) { |
super(conf, CustomerSQLElement.class); |
// handle CustomerSQLElement/ClientSocieteSQLElement (or even a module replacing the |
// default element) |
super(conf, conf.getDirectory().getElement(conf.getRootSociete().getTable("CLIENT"))); |
} |
@Override |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/ui/CategorieComptableChoiceUI.java |
---|
New file |
0,0 → 1,67 |
/* |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
* |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved. |
* |
* The contents of this file are subject to the terms of the GNU General Public License Version 3 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific |
* language governing permissions and limitations under the License. |
* |
* When distributing the software, include this License Header Notice in each file. |
*/ |
package org.openconcerto.erp.core.customerrelationship.customer.ui; |
import org.openconcerto.sql.element.BaseSQLComponent; |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.sqlobject.ElementComboBox; |
import org.openconcerto.ui.DefaultGridBagConstraints; |
import java.awt.GridBagConstraints; |
import javax.swing.JLabel; |
import javax.swing.SwingConstants; |
public class CategorieComptableChoiceUI { |
private ElementComboBox comboCatCompt; |
public CategorieComptableChoiceUI() { |
// TODO Auto-generated constructor stub |
} |
public void addToUI(BaseSQLComponent comp, GridBagConstraints c) { |
// Adresse Facturation |
c.gridx = 0; |
c.gridy++; |
c.gridwidth = 1; |
final JLabel labelCat = new JLabel(comp.getLabelFor("ID_CATEGORIE_COMPTABLE")); |
labelCat.setHorizontalAlignment(SwingConstants.RIGHT); |
c.weightx = 0; |
c.gridwidth = 1; |
c.fill = GridBagConstraints.HORIZONTAL; |
comp.add(labelCat, c); |
this.comboCatCompt = new ElementComboBox(); |
this.comboCatCompt.setButtonsVisible(false); |
c.gridx++; |
c.gridwidth = 1; |
c.weightx = 0; |
c.weighty = 0; |
c.fill = GridBagConstraints.NONE; |
comp.add(this.comboCatCompt, c); |
final SQLElement catComptableElement = comp.getElement().getForeignElement("ID_CATEGORIE_COMPTABLE"); |
this.comboCatCompt.init(catComptableElement, catComptableElement.getComboRequest(true)); |
DefaultGridBagConstraints.lockMinimumSize(this.comboCatCompt); |
comp.addView(this.comboCatCompt, "ID_CATEGORIE_COMPTABLE"); |
this.comboCatCompt.setAddIconVisible(false); |
} |
public ElementComboBox getCombo() { |
return this.comboCatCompt; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/mail/EmailTemplateGroup.java |
---|
New file |
0,0 → 1,30 |
/* |
* 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.core.customerrelationship.mail; |
import org.openconcerto.ui.group.Group; |
import org.openconcerto.ui.group.LayoutHints; |
public class EmailTemplateGroup extends Group { |
public static final String ID = "customerrelationship.mail.email.template"; |
public EmailTemplateGroup() { |
super(ID); |
addItem("NOM"); |
addItem("TITRE", LayoutHints.DEFAULT_LARGE_FIELD_HINTS); |
addItem("TEXTE", new LayoutHints(true, true, true, true, true, true, true)); |
addItem("FORMAT_DATE", new LayoutHints(false, false, true, true, false, false)); |
addItem("PAR_DEFAUT"); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/mail/ValueListener.java |
---|
New file |
0,0 → 1,18 |
/* |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
* |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved. |
* |
* The contents of this file are subject to the terms of the GNU General Public License Version 3 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific |
* language governing permissions and limitations under the License. |
* |
* When distributing the software, include this License Header Notice in each file. |
*/ |
package org.openconcerto.erp.core.customerrelationship.mail; |
public interface ValueListener { |
public void valueSelected(Object value); |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/mail/EmailTemplate.java |
---|
New file |
0,0 → 1,170 |
/* |
* 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.core.customerrelationship.mail; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowListRSH; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.SQLTable; |
import java.awt.BorderLayout; |
import java.awt.Component; |
import java.awt.Container; |
import java.awt.Dimension; |
import java.awt.FlowLayout; |
import java.awt.Frame; |
import java.awt.event.ActionEvent; |
import java.awt.event.ActionListener; |
import java.util.ArrayList; |
import java.util.Collections; |
import java.util.Comparator; |
import java.util.List; |
import javax.swing.DefaultListCellRenderer; |
import javax.swing.JButton; |
import javax.swing.JComponent; |
import javax.swing.JDialog; |
import javax.swing.JLabel; |
import javax.swing.JList; |
import javax.swing.JPanel; |
import javax.swing.ListSelectionModel; |
import javax.swing.SwingUtilities; |
import com.lowagie.text.Font; |
public class EmailTemplate { |
private String name; |
private String title; |
private String text; |
private boolean isDefault; |
private String dateFormat; |
public EmailTemplate(String name, String title, String text, Boolean isDefault, String dateFormat) { |
this.name = name; |
this.title = title; |
this.text = text; |
this.isDefault = isDefault; |
this.dateFormat = dateFormat; |
} |
public static List<EmailTemplate> getAll(DBRoot root) { |
final List<EmailTemplate> result = new ArrayList<>(); |
final SQLSelect selF = new SQLSelect(); |
final SQLTable tFamilleArticle = root.getTable(EmailTemplateSQLElement.TABLE_NAME); |
selF.addSelect(tFamilleArticle.getKey()); |
selF.addSelect(tFamilleArticle.getField("NOM")); |
selF.addSelect(tFamilleArticle.getField("TITRE")); |
selF.addSelect(tFamilleArticle.getField("TEXTE")); |
selF.addSelect(tFamilleArticle.getField("PAR_DEFAUT")); |
selF.addSelect(tFamilleArticle.getField("FORMAT_DATE")); |
final List<SQLRow> lF = SQLRowListRSH.execute(selF); |
for (SQLRow sqlRow : lF) { |
result.add(new EmailTemplate(sqlRow.getString("NOM"), sqlRow.getString("TITRE"), sqlRow.getString("TEXTE"), sqlRow.getBoolean("PAR_DEFAUT"), sqlRow.getString("FORMAT_DATE"))); |
} |
return result; |
} |
public String getName() { |
return this.name; |
} |
public String getTitle() { |
return this.title; |
} |
public String getText() { |
return this.text; |
} |
public boolean isDefault() { |
return this.isDefault; |
} |
public String getDateFormat() { |
return this.dateFormat; |
} |
public static void askTemplate(JComponent parent, DBRoot root, ValueListener listener) { |
if (!SwingUtilities.isEventDispatchThread()) { |
throw new IllegalStateException("must be called from EDT"); |
} |
List<EmailTemplate> templates = getAll(root); |
if (templates.isEmpty()) { |
listener.valueSelected(null); |
return; |
} |
if (templates.size() == 1) { |
listener.valueSelected(templates.get(0)); |
return; |
} |
Collections.sort(templates, new Comparator<EmailTemplate>() { |
@Override |
public int compare(EmailTemplate o1, EmailTemplate o2) { |
return o1.getName().compareToIgnoreCase(o2.getName()); |
} |
}); |
final JDialog dialog = new JDialog((Frame) SwingUtilities.getWindowAncestor(parent), "Modèle à utiliser", true); |
final JList<EmailTemplate> list = new JList<>(templates.toArray(new EmailTemplate[0])); |
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); |
for (int i = 0; i < templates.size(); i++) { |
final EmailTemplate t = templates.get(i); |
if (t.isDefault) { |
list.setSelectedIndex(i); |
break; |
} |
} |
list.setFixedCellHeight((int) (new JLabel("t").getPreferredSize().height * 1.5)); |
list.setCellRenderer(new DefaultListCellRenderer() { |
@Override |
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { |
EmailTemplate t = (EmailTemplate) value; |
final JLabel l = (JLabel) super.getListCellRendererComponent(list, t.getName(), index, isSelected, cellHasFocus); |
if (t.isDefault) { |
l.setFont(l.getFont().deriveFont(Font.BOLD)); |
} else { |
l.setFont(l.getFont().deriveFont(Font.NORMAL)); |
} |
return l; |
} |
}); |
list.setMinimumSize(new Dimension(300, 200)); |
list.setPreferredSize(new Dimension(300, 200)); |
final Container contentPane = dialog.getContentPane(); |
contentPane.setLayout(new BorderLayout()); |
contentPane.add(list, BorderLayout.CENTER); |
JPanel p = new JPanel(); |
p.setLayout(new FlowLayout(FlowLayout.RIGHT)); |
final JButton button = new JButton("Valider"); |
button.addActionListener(new ActionListener() { |
@Override |
public void actionPerformed(ActionEvent e) { |
listener.valueSelected(list.getSelectedValue()); |
dialog.dispose(); |
} |
}); |
p.add(button); |
contentPane.add(p, BorderLayout.SOUTH); |
dialog.pack(); |
dialog.setLocationRelativeTo(parent); |
dialog.setVisible(true); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/mail/EmailTemplateSQLComponent.java |
---|
New file |
0,0 → 1,32 |
/* |
* 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.core.customerrelationship.mail; |
import org.openconcerto.sql.element.GroupSQLComponent; |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.model.SQLRowValues; |
public class EmailTemplateSQLComponent extends GroupSQLComponent { |
public EmailTemplateSQLComponent(SQLElement element) { |
super(element); |
} |
@Override |
protected SQLRowValues createDefaults() { |
final SQLRowValues defaultValues = super.createDefaults(); |
defaultValues.put("FORMAT_DATE", "dd/MM/yyyy"); |
return defaultValues; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/mail/EmailTemplateSQLElement.java |
---|
New file |
0,0 → 1,52 |
/* |
* 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.core.customerrelationship.mail; |
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement; |
import org.openconcerto.sql.element.GlobalMapper; |
import org.openconcerto.sql.element.SQLComponent; |
import java.util.Arrays; |
import java.util.List; |
public class EmailTemplateSQLElement extends ComptaSQLConfElement { |
public static final String TABLE_NAME = "MODELE_EMAIL"; |
public EmailTemplateSQLElement() { |
super(TABLE_NAME, "un modèle d'email", "modèles d'emails"); |
final EmailTemplateGroup group = new EmailTemplateGroup(); |
GlobalMapper.getInstance().map(EmailTemplateGroup.ID, group); |
setDefaultGroup(group); |
} |
@Override |
protected List<String> getListFields() { |
return Arrays.asList("NOM", "PAR_DEFAUT"); |
} |
@Override |
protected List<String> getComboFields() { |
return Arrays.asList("NOM"); |
} |
@Override |
protected SQLComponent createComponent() { |
return new EmailTemplateSQLComponent(this); |
} |
@Override |
protected String createCode() { |
return "customerrelationship.mail.email.template"; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/mail/action/ListeDesModelesEmailAction.java |
---|
New file |
0,0 → 1,35 |
/* |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
* |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved. |
* |
* The contents of this file are subject to the terms of the GNU General Public License Version 3 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific |
* language governing permissions and limitations under the License. |
* |
* When distributing the software, include this License Header Notice in each file. |
*/ |
package org.openconcerto.erp.core.customerrelationship.mail.action; |
import org.openconcerto.erp.action.CreateFrameAbstractAction; |
import org.openconcerto.erp.core.customerrelationship.mail.EmailTemplateSQLElement; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.view.IListFrame; |
import org.openconcerto.sql.view.ListeAddPanel; |
import javax.swing.Action; |
import javax.swing.JFrame; |
public class ListeDesModelesEmailAction extends CreateFrameAbstractAction { |
public ListeDesModelesEmailAction() { |
super(); |
this.putValue(Action.NAME, "Liste des modèles d'email"); |
} |
public JFrame createFrame() { |
return new IListFrame(new ListeAddPanel(Configuration.getInstance().getDirectory().getElement(EmailTemplateSQLElement.TABLE_NAME))); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/element/AssociationAnalytiqueSQLElement.java |
---|
16,6 → 16,8 |
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement; |
import org.openconcerto.sql.element.BaseSQLComponent; |
import org.openconcerto.sql.element.SQLComponent; |
import org.openconcerto.sql.element.SQLElementLink.LinkType; |
import org.openconcerto.sql.element.SQLElementLinksSetup; |
import org.openconcerto.sql.model.FieldPath; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.graph.Path; |
44,6 → 46,14 |
this.setAction("ID_SAISIE_KM_ELEMENT", ReferenceAction.CASCADE); |
} |
@Override |
protected void setupLinks(SQLElementLinksSetup links) { |
super.setupLinks(links); |
if (getTable().contains("ID_ECRITURE")) { |
links.get("ID_ECRITURE").setType(LinkType.ASSOCIATION); |
} |
} |
protected List<String> getListFields() { |
final List<String> list = new ArrayList<String>(2); |
list.add("ID_ECRITURE"); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/element/EcritureSQLElement.java |
---|
65,8 → 65,6 |
import java.awt.event.ActionEvent; |
import java.awt.event.KeyAdapter; |
import java.awt.event.KeyEvent; |
import java.awt.event.MouseAdapter; |
import java.awt.event.MouseEvent; |
import java.math.BigDecimal; |
import java.math.BigInteger; |
import java.sql.SQLException; |
80,7 → 78,6 |
import javax.swing.JFrame; |
import javax.swing.JLabel; |
import javax.swing.JOptionPane; |
import javax.swing.JPopupMenu; |
import javax.swing.JTextField; |
import javax.swing.SwingUtilities; |
153,6 → 150,11 |
return "ID_MOUVEMENT"; |
} |
@Override |
public boolean isPrivate() { |
return false; |
} |
// Impossible de modifier si validée |
// FIXME impossible de saisir une écriture avant la date de debut d'exercice --> de saisir de |
// document de gest comm |
196,67 → 198,9 |
} |
public void consultationCompte(SQLRowAccessor rowCpt) { |
final ConsultationCompteFrame f = new ConsultationCompteFrame(new ListeDesEcrituresPanel(), "Consultation compte n°" + rowCpt.getString("NUMERO") + " " + rowCpt.getString("NOM")); |
final ListeDesEcrituresPanel panel = new ListeDesEcrituresPanel(); |
final ConsultationCompteFrame f = new ConsultationCompteFrame(panel, rowCpt); |
f.getPanel().getListe().getJTable().addMouseListener(new MouseAdapter() { |
public void mousePressed(final MouseEvent mE) { |
if (mE.getButton() == MouseEvent.BUTTON3) { |
JPopupMenu menuDroit = new JPopupMenu(); |
menuDroit.add(new AbstractAction("Voir les ecritures du journal") { |
public void actionPerformed(ActionEvent e) { |
int id = f.getPanel().getListe().idFromIndex(f.getPanel().getListe().getJTable().rowAtPoint(mE.getPoint())); |
// int id = f.getPanel().getListe().getSelectedId(); |
SQLTable ecrTable = getTable().getTable("ECRITURE"); |
System.err.println("Ecritures ID ::: " + id); |
SQLRow rowEcr = ecrTable.getRow(id); |
System.err.println("Ecritures ID ::: " + id + " --> ID_JOURNAL = " + rowEcr.getInt("ID_JOURNAL")); |
ConsultationCompteFrame f2 = new ConsultationCompteFrame(new ListeDesEcrituresPanel(), |
"Consultation du journal " + getTable().getTable("JOURNAL").getRow(rowEcr.getInt("ID_JOURNAL")).getString("NOM")); |
Where w = new Where(ecrTable.getField("ID_JOURNAL"), "=", rowEcr.getInt("ID_JOURNAL")); |
f2.getPanel().getListe().getRequest().setWhere(w); |
f2.getPanel().getListe().setModificationAllowed(false); |
f2.pack(); |
f2.setVisible(true); |
} |
}); |
menuDroit.add(new AbstractAction("Voir la source") { |
public void actionPerformed(ActionEvent e) { |
// int id = f.getPanel().getListe().getSelectedId(); |
int id = f.getPanel().getListe().idFromIndex(f.getPanel().getListe().getJTable().rowAtPoint(mE.getPoint())); |
System.err.println("ID COMPTE SELECTED " + id); |
SQLRow rowEcr = getTable().getTable("ECRITURE").getRow(id); |
System.out.println("MOUVEMENT VALIDE ------------->>>>>>>>>>>>>> " + MouvementSQLElement.isEditable(rowEcr.getInt("ID_MOUVEMENT"))); |
MouvementSQLElement.showSource(rowEcr.getInt("ID_MOUVEMENT")); |
System.out.println("Mouvement Numero : " + rowEcr.getInt("ID_MOUVEMENT")); |
} |
}); |
menuDroit.show(mE.getComponent(), mE.getX(), mE.getY()); |
} |
} |
}); |
SQLTable ecrTable = getTable().getTable("ECRITURE"); |
Where w = new Where(ecrTable.getField("ID_COMPTE_PCE"), "=", rowCpt.getID()); |
f.getPanel().getListe().getRequest().setWhere(w); |
f.getPanel().getListe().setModificationAllowed(false); |
f.pack(); |
f.setVisible(true); |
696,7 → 640,9 |
// on archive le mouvement |
if (dropMvt) { |
SQLElement elt = Configuration.getInstance().getDirectory().getElement(tableMvt); |
SQLElement elt = getDirectory().getElement(tableMvt); |
try { |
elt.archive(idMvt); |
} catch (SQLException e) { |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/report/GrandLivreSheetXML.java |
---|
179,47 → 179,8 |
@Override |
public SQLSelect transformChecked(SQLSelect sel) { |
Where w = (new Where(tableEcriture.getField("DATE"), GrandLivreSheetXML.this.dateDu, GrandLivreSheetXML.this.dateAu)); |
Where w = getWhere(lCompteSolde); |
if (GrandLivreSheetXML.this.compteDeb.equals(GrandLivreSheetXML.this.compteEnd)) { |
w = w.and(new Where(tableEcriture.getField("COMPTE_NUMERO"), "=", GrandLivreSheetXML.this.compteDeb)); |
} else { |
w = w.and(new Where(tableEcriture.getField("COMPTE_NUMERO"), (Object) GrandLivreSheetXML.this.compteDeb, (Object) GrandLivreSheetXML.this.compteEnd)); |
} |
w = w.and(new Where(tableEcriture.getField("ID_JOURNAL"), "!=", idJrnlExclude)); |
w = w.and(new Where(tableEcriture.getField("ID_MOUVEMENT"), "=", tableMvt.getField("ID"))); |
if (GrandLivreSheetXML.this.lettrage == GrandLivreSheet.MODELETTREE) { |
Object o = null; |
w = w.and(new Where(tableEcriture.getField("LETTRAGE"), "<>", o)); |
w = w.and(new Where(tableEcriture.getField("LETTRAGE"), "!=", "")); |
w = w.and(new Where(tableEcriture.getField("DATE_LETTRAGE"), "<=", GrandLivreSheetXML.this.dateAu)); |
} else if (GrandLivreSheetXML.this.lettrage == GrandLivreSheet.MODENONLETTREE_PERIODE) { |
Object o = null; |
Where w2 = new Where(tableEcriture.getField("LETTRAGE"), "=", o); |
Where wSTTC = new Where(tableEcriture.getField("DATE_LETTRAGE"), "<>", o); |
wSTTC = wSTTC.and(new Where(tableEcriture.getField("DATE_LETTRAGE"), ">", GrandLivreSheetXML.this.dateAu)); |
w2 = w2.or(wSTTC); |
w = w.and(w2.or(new Where(tableEcriture.getField("LETTRAGE"), "=", ""))); |
} else if (GrandLivreSheetXML.this.lettrage == GrandLivreSheet.MODENONLETTREE_ALL) { |
Object o = null; |
Where w2 = new Where(tableEcriture.getField("LETTRAGE"), "=", o); |
w = w.and(w2.or(new Where(tableEcriture.getField("LETTRAGE"), "=", ""))); |
} |
if (GrandLivreSheetXML.this.excludeCompteSolde) { |
System.err.println("Exclude compte"); |
w = w.and(new Where(tableEcriture.getField("ID_COMPTE_PCE"), lCompteSolde).not()); |
} |
w = w.and(new Where(tableEcriture.getField("NOM"), "NOT LIKE", "Fermeture du compte%")); |
if (!UserRightsManager.getCurrentUserRights().haveRight(ComptaUserRight.ACCES_NOT_RESCTRICTED_TO_411)) { |
// TODO Show Restricted acces in UI |
w = w.and(new Where(tableEcriture.getField("COMPTE_NUMERO"), "LIKE", "411%")); |
} |
sel.setWhere(w); |
sel.addFieldOrder(tableEcriture.getField("COMPTE_NUMERO")); |
sel.addFieldOrder(tableEcriture.getField("DATE")); |
567,36 → 528,8 |
sel.addSelect(tableEcriture.getField("DEBIT"), "SUM"); |
sel.addSelect(tableEcriture.getField("CREDIT"), "SUM"); |
Where w; |
if (this.compteDeb.equals(this.compteEnd)) { |
w = new Where(tableCompte.getField("NUMERO"), "=", this.compteDeb); |
} else { |
w = new Where(tableCompte.getField("NUMERO"), (Object) this.compteDeb, (Object) this.compteEnd); |
} |
Where w = getWhere(null); |
w = w.and(new Where(tableEcriture.getField("ID_COMPTE_PCE"), "=", tableCompte.getField("ID"))); |
if (this.cumul) { |
w = w.and(new Where(tableEcriture.getField("DATE"), "<=", this.dateAu)); |
} else { |
w = w.and(new Where(tableEcriture.getField("DATE"), this.dateDu, this.dateAu)); |
} |
w = w.and(new Where(tableEcriture.getField("ID_JOURNAL"), "!=", idJrnlExclude)); |
if (this.lettrage == GrandLivreSheet.MODELETTREE) { |
Object o = null; |
w = w.and(new Where(tableEcriture.getField("LETTRAGE"), "<>", o)); |
w = w.and(new Where(tableEcriture.getField("LETTRAGE"), "!=", "")); |
} else if (this.lettrage == GrandLivreSheet.MODENONLETTREE_ALL) { |
Object o = null; |
Where w2 = new Where(tableEcriture.getField("LETTRAGE"), "=", o); |
w = w.and(w2.or(new Where(tableEcriture.getField("LETTRAGE"), "=", ""))); |
} else if (this.lettrage == GrandLivreSheet.MODENONLETTREE_PERIODE) { |
Object o = null; |
Where w2 = new Where(tableEcriture.getField("LETTRAGE"), "=", o); |
w = w.and(w2.or(new Where(tableEcriture.getField("LETTRAGE"), "=", ""))); |
} |
sel.setWhere(w); |
String req = sel.asString() + " GROUP BY \"COMPTE_PCE\".\"ID\""; |
623,6 → 556,52 |
return list; |
} |
private Where getWhere(final List<Integer> lCompteSolde) { |
Where w = (new Where(tableEcriture.getField("DATE"), GrandLivreSheetXML.this.dateDu, GrandLivreSheetXML.this.dateAu)); |
if (GrandLivreSheetXML.this.compteDeb.equals(GrandLivreSheetXML.this.compteEnd)) { |
w = w.and(new Where(tableEcriture.getField("COMPTE_NUMERO"), "=", GrandLivreSheetXML.this.compteDeb)); |
} else { |
w = w.and(new Where(tableEcriture.getField("COMPTE_NUMERO"), (Object) GrandLivreSheetXML.this.compteDeb, (Object) GrandLivreSheetXML.this.compteEnd)); |
} |
w = w.and(new Where(tableEcriture.getField("ID_JOURNAL"), "!=", idJrnlExclude)); |
w = w.and(new Where(tableEcriture.getField("ID_MOUVEMENT"), "=", tableMvt.getField("ID"))); |
if (GrandLivreSheetXML.this.lettrage == GrandLivreSheet.MODELETTREE) { |
Object o = null; |
w = w.and(new Where(tableEcriture.getField("LETTRAGE"), "<>", o)); |
w = w.and(new Where(tableEcriture.getField("LETTRAGE"), "!=", "")); |
w = w.and(new Where(tableEcriture.getField("DATE_LETTRAGE"), "<=", GrandLivreSheetXML.this.dateAu)); |
} else if (GrandLivreSheetXML.this.lettrage == GrandLivreSheet.MODENONLETTREE_PERIODE) { |
Object o = null; |
Where w2 = new Where(tableEcriture.getField("LETTRAGE"), "=", o); |
Where wSTTC = new Where(tableEcriture.getField("DATE_LETTRAGE"), "<>", o); |
wSTTC = wSTTC.and(new Where(tableEcriture.getField("DATE_LETTRAGE"), ">", GrandLivreSheetXML.this.dateAu)); |
w2 = w2.or(wSTTC); |
w = w.and(w2.or(new Where(tableEcriture.getField("LETTRAGE"), "=", ""))); |
} else if (GrandLivreSheetXML.this.lettrage == GrandLivreSheet.MODENONLETTREE_ALL) { |
Object o = null; |
Where w2 = new Where(tableEcriture.getField("LETTRAGE"), "=", o); |
w = w.and(w2.or(new Where(tableEcriture.getField("LETTRAGE"), "=", ""))); |
} |
if (GrandLivreSheetXML.this.excludeCompteSolde) { |
System.err.println("Exclude compte"); |
if (lCompteSolde != null) { |
w = w.and(new Where(tableEcriture.getField("ID_COMPTE_PCE"), lCompteSolde).not()); |
} |
} |
w = w.and(new Where(tableEcriture.getField("NOM"), "NOT LIKE", "Fermeture du compte%")); |
if (!UserRightsManager.getCurrentUserRights().haveRight(ComptaUserRight.ACCES_NOT_RESCTRICTED_TO_411)) { |
// TODO Show Restricted acces in UI |
w = w.and(new Where(tableEcriture.getField("COMPTE_NUMERO"), "LIKE", "411%")); |
} |
return w; |
} |
/** |
* @param d date limite des cumuls |
* @return Map<Integer id compte, Long solde(debit-credit)> |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/report/Map2033A.java |
---|
499,9 → 499,9 |
// 120 -SommeSolde( 100, 103* )-SommeSolde( 108, 109* ) |
// Racine = "101, 104, 108" |
// S120=-10...101-108-104 |
long v120 = -this.sommeCompte.sommeCompteFils("101", this.dateDebut, this.dateFin) - this.sommeCompte.sommeCompteFils("103", this.dateDebut, this.dateFin) |
- this.sommeCompte.sommeCompteFils("108", this.dateDebut, this.dateFin) - this.sommeCompte.sommeCompteFils("104", this.dateDebut, this.dateFin) |
+ this.sommeCompte.soldeCompteCrediteur(109, 109, true, this.dateDebut, this.dateFin); |
long v120 = -this.sommeCompte.sommeCompteFils("101", this.dateDebut, this.dateFin) - this.sommeCompte.sommeCompteFils("102", this.dateDebut, this.dateFin) |
- this.sommeCompte.sommeCompteFils("103", this.dateDebut, this.dateFin) - this.sommeCompte.sommeCompteFils("108", this.dateDebut, this.dateFin) |
- this.sommeCompte.sommeCompteFils("104", this.dateDebut, this.dateFin) + this.sommeCompte.soldeCompteCrediteur(109, 109, true, this.dateDebut, this.dateFin); |
this.m.put("PASSIF3.15", GestionDevise.currencyToString(v120, false)); |
// 121 |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/report/Map2033B.java |
---|
215,7 → 215,7 |
* VARIATION DE STOCK |
******************************************************************************************/ |
// 240 SommeSolde( 6030, 6036* ) |
long v240 = this.sommeCompte.soldeCompte(6031, 6032, true, this.dateDeb, this.dateFin); |
long v240 = this.sommeCompte.soldeCompte(6031, 6036, true, this.dateDeb, this.dateFin); |
this.m.put("CHARGES3.11", GestionDevise.currencyToString(v240, false)); |
// 213 |
264,7 → 264,7 |
******************************************************************************************/ |
// 250 SommeSolde( 640, 644* )+SommeSolde( 648, 649* ) |
long v250 = this.sommeCompte.soldeCompte(644, 644, true, this.dateDeb, this.dateFin) + this.sommeCompte.soldeCompte(648, 649, true, this.dateDeb, this.dateFin) |
+ this.sommeCompte.soldeCompte(641, 641, true, this.dateDeb, this.dateFin); |
+ this.sommeCompte.soldeCompte(641, 641, true, this.dateDeb, this.dateFin)+ this.sommeCompte.soldeCompte(642, 642, true, this.dateDeb, this.dateFin); |
this.m.put("CHARGES3.14", GestionDevise.currencyToString(v250, false)); |
// 220 |
352,7 → 352,7 |
* PRODUITS FINANCIERS |
******************************************************************************************/ |
// 280 -SommeSolde( 760, 769* )-SommeSolde( 786, 786* )-SommeSolde( 796, 796* ) |
long v280 = -this.sommeCompte.soldeCompte(761, 768, true, this.dateDeb, this.dateFin) - this.sommeCompte.soldeCompte(786, 786, true, this.dateDeb, this.dateFin) |
long v280 = -this.sommeCompte.soldeCompte(760, 768, true, this.dateDeb, this.dateFin) - this.sommeCompte.soldeCompte(786, 786, true, this.dateDeb, this.dateFin) |
- this.sommeCompte.soldeCompte(796, 796, true, this.dateDeb, this.dateFin); |
this.m.put("PCHARGES3.21", GestionDevise.currencyToString(v280, false)); |
369,7 → 369,7 |
* PRODUITS EXCEPTIONNELS |
******************************************************************************************/ |
// 290 -SommeSolde( 77, 77* )-SommeSolde( 787, 789* )-SommeSolde( 797, 799* ) |
long v290 = -this.sommeCompte.soldeCompte(771, 772, true, this.dateDeb, this.dateFin) - this.sommeCompte.soldeCompte(775, 778, true, this.dateDeb, this.dateFin) |
long v290 = -this.sommeCompte.soldeCompte(770, 772, true, this.dateDeb, this.dateFin) - this.sommeCompte.soldeCompte(775, 778, true, this.dateDeb, this.dateFin) |
- this.sommeCompte.soldeCompte(787, 787, true, this.dateDeb, this.dateFin) - this.sommeCompte.soldeCompte(797, 797, true, this.dateDeb, this.dateFin); |
this.m.put("PCHARGES3.22", GestionDevise.currencyToString(v290, false)); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/EcritureGrandLivreRenderer.java |
---|
40,23 → 40,16 |
} |
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { |
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); |
TableCellRendererUtils.setBackgroundColor(this, table, isSelected); |
if (!isSelected) { |
Ecriture ecrTmp = ((ConsultCompteModel) this.model.getTableModel()).getEcritures().get(this.model.viewIndex(row)); |
if (!ecrTmp.getValide()) { |
// this.setForeground(couleurEcritureValide); |
Date dateEcr = ecrTmp.getDate(); |
Date dateToDay = new Date(); |
if ((dateEcr.getDate() == dateToDay.getDate()) && (dateEcr.getMonth() == dateToDay.getMonth()) && (dateEcr.getYear() == dateToDay.getYear())) { |
// System.out.println("ToDay :: " + dateToDay + " Ecr ::: " + dateEcr); |
this.setBackground(couleurEcritureToDay); |
} else { |
this.setBackground(couleurEcritureValide); |
63,14 → 56,13 |
} |
} |
} |
if (value != null) { |
if (value instanceof Date) { |
this.setText(dateFormat.format((Date) value)); |
} |
if (value.getClass() == Long.class) { |
} else if (value.getClass() == Long.class) { |
this.setText(GestionDevise.currencyToString(((Long) value).longValue())); |
} |
} |
return this; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/SaisieJournalItemTable.java |
---|
21,6 → 21,7 |
import org.openconcerto.erp.generationEcritures.GenerationMvtSaisieKm; |
import org.openconcerto.erp.preferences.DefaultNXProps; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.TM; |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowAccessor; |
36,6 → 37,7 |
import org.openconcerto.sql.view.list.TextTableCellEditorWithCompletion; |
import org.openconcerto.sql.view.list.ValidStateChecker; |
import org.openconcerto.ui.DefaultGridBagConstraints; |
import org.openconcerto.ui.JComponentUtils; |
import org.openconcerto.ui.RangedIntegerTableCellEditor; |
import org.openconcerto.utils.DecimalUtils; |
import org.openconcerto.utils.GestionDevise; |
45,6 → 47,7 |
import java.awt.GridBagConstraints; |
import java.awt.GridBagLayout; |
import java.awt.event.ActionEvent; |
import java.awt.event.ActionListener; |
import java.awt.event.KeyEvent; |
import java.awt.event.KeyListener; |
import java.awt.event.MouseEvent; |
54,6 → 57,7 |
import java.math.BigDecimal; |
import java.math.RoundingMode; |
import java.sql.SQLException; |
import java.util.Arrays; |
import java.util.Calendar; |
import java.util.Collection; |
import java.util.Date; |
62,6 → 66,7 |
import javax.swing.AbstractAction; |
import javax.swing.BorderFactory; |
import javax.swing.JButton; |
import javax.swing.JCheckBox; |
import javax.swing.JLabel; |
import javax.swing.JOptionPane; |
295,10 → 300,21 |
TextTableCellEditorWithCompletion t = (TextTableCellEditorWithCompletion) this.tableElementNumeroCompte.getTableCellEditor(this.table); |
this.controlPanel = new RowValuesTableControlPanel(this.table); |
controlPanel.setButtonAjouterEnabled(false); |
this.add(controlPanel, c); |
JButton buttonClone = new JButton(TM.tr("duplicateLine")); |
buttonClone.addActionListener(new ActionListener() { |
public void actionPerformed(ActionEvent event) { |
cloneLine(table.getSelectedRow()); |
} |
}); |
buttonClone.setEnabled(false); |
c.gridx++; |
JComponentUtils.setMinimumWidth(buttonClone, 95); |
this.controlPanel = new RowValuesTableControlPanel(this.table, Arrays.asList(buttonClone)); |
this.controlPanel.setVisibleButtonClone(false); |
this.controlPanel.setButtonAjouterEnabled(false); |
this.add(this.controlPanel, c); |
c.gridy++; |
c.fill = GridBagConstraints.BOTH; |
c.weightx = 1; |
688,4 → 704,26 |
public void mouseExited(final MouseEvent e) { |
} |
private void cloneLine(int row) { |
if (row < 0) { |
System.err.println("RowValuesTableControlPanel.cloneLine() wrong selected line, index = " + row); |
Thread.dumpStack(); |
return; |
} |
SQLRowValues rowVals = this.table.getRowValuesTableModel().getRowValuesAt(row); |
SQLRowValues rowValsBis = rowVals.deepCopy(); |
rowValsBis.clearPrimaryKeys(); |
rowValsBis.put(rowValsBis.getTable().getOrderField().getName(), null); |
this.table.getRowValuesTableModel().getSQLElement().clearPrivateFields(rowValsBis); |
rowValsBis.putEmptyLink("ID_ECRITURE"); |
for (String elt : this.table.getClearCloneTableElement()) { |
if (rowValsBis.getTable().getFieldsName().contains(elt)) { |
rowValsBis.putEmptyLink(elt); |
} |
} |
this.table.getRowValuesTableModel().addRow(rowValsBis); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/SaisieKmItemTable.java |
---|
20,6 → 20,7 |
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement; |
import org.openconcerto.erp.preferences.DefaultNXProps; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.TM; |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.model.SQLBase; |
import org.openconcerto.sql.model.SQLRow; |
38,13 → 39,16 |
import org.openconcerto.sql.view.list.TextTableCellEditorWithCompletion; |
import org.openconcerto.sql.view.list.ValidStateChecker; |
import org.openconcerto.ui.DefaultGridBagConstraints; |
import org.openconcerto.ui.JComponentUtils; |
import org.openconcerto.utils.checks.ValidState; |
import java.awt.GridBagConstraints; |
import java.awt.GridBagLayout; |
import java.awt.event.ActionEvent; |
import java.awt.event.ActionListener; |
import java.awt.event.MouseEvent; |
import java.awt.event.MouseListener; |
import java.util.Arrays; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
51,6 → 55,7 |
import java.util.Vector; |
import javax.swing.AbstractAction; |
import javax.swing.JButton; |
import javax.swing.JPanel; |
import javax.swing.JPopupMenu; |
import javax.swing.JScrollPane; |
143,7 → 148,7 |
@Override |
public ValidState getValidState(Object o) { |
if (o != null) { |
return elt.getCompteNumeroValidState(o.toString()); |
return this.elt.getCompteNumeroValidState(o.toString()); |
} |
return super.getValidState(o); |
} |
161,8 → 166,19 |
m2.setWhere(w); |
TextTableCellEditorWithCompletion t = (TextTableCellEditorWithCompletion) this.tableElementNumeroCompte.getTableCellEditor(this.table); |
JButton buttonClone = new JButton(TM.tr("duplicateLine")); |
buttonClone.addActionListener(new ActionListener() { |
public void actionPerformed(ActionEvent event) { |
cloneLine(table.getSelectedRow()); |
} |
}); |
buttonClone.setEnabled(false); |
c.gridx++; |
JComponentUtils.setMinimumWidth(buttonC |