Dépôt officiel du code source de l'ERP OpenConcerto
/trunk/OpenConcerto/src/org/openconcerto/ql/QLPrinter.java |
---|
23,10 → 23,12 |
import java.net.InetAddress; |
import java.net.Socket; |
import java.net.UnknownHostException; |
import java.nio.charset.StandardCharsets; |
import javax.imageio.ImageIO; |
public class QLPrinter { |
private static final int ESC = 0x1B; |
private String host; |
private boolean highQuality; |
private boolean paperCutAuto; |
49,7 → 51,7 |
/** |
* Set print width (in milimeters) |
* */ |
*/ |
public void setPrintWidth(int mm) { |
this.printWidth = mm; |
} |
77,16 → 79,18 |
for (int i = 0; i < 200; i++) { |
out.write(0x00); |
} |
// Init 0x1B 0x40 |
out.write(0x1B); |
out.write(0x40); |
// ?? : 0x1B 0x69 0x61 0x01 |
out.write(0x1B); |
// Select ESCP/P Mode : 0x1B 0x69 0x61 0x01 |
out.write(ESC); |
out.write(0x69); |
out.write(0x61); |
out.write(0x01); |
// Init 0x1B 0x40 |
out.write(ESC); |
out.write(0x40); |
// Page Length |
out.write(0x1B); |
out.write(ESC); |
out.write(0x69); |
out.write(0x7A); |
101,8 → 105,8 |
out.write(0); |
out.write(0); |
out.write(0); |
// Paper Cut |
out.write(0x1B); |
// Paper Cut : ESC i |
out.write(ESC); |
out.write(0x69); |
out.write(0x4D); |
if (this.paperCutAuto) { |
111,13 → 115,13 |
out.write(0x00); |
} |
// ?? : 0x1B 0x69 0x41 0x01 |
out.write(0x1B); |
// ?? : 0x1B 0x69 0x41 0x01 :ESC i A |
out.write(ESC); |
out.write(0x69); |
out.write(0x41); |
out.write(0x01); |
// Set Mode |
out.write(0x1B); |
// Set Mode : ESC i K |
out.write(ESC); |
out.write(0x69); |
out.write(0x4B); |
if (!this.highQuality) { |
126,7 → 130,7 |
out.write(0x48); |
} |
// Set Margin |
out.write(0x1B); |
out.write(ESC); |
out.write(0x69); |
out.write(0x64); |
out.write(0x00); |
332,6 → 336,7 |
out.close(); |
in.close(); |
socket.close(); |
System.out.println("QLPrinter.print() done"); |
} |
} |
346,4 → 351,92 |
return cfA; |
} |
/** |
* Print 2D barcode (DataMatrix) |
* |
* @param dotsPerCell (3 - 10) |
* @param barcode : barcode (ascii) |
* @throws IOException |
* |
*/ |
public void printDataMatrixBarCode2D(int dotsPerCell, String barcode) throws IOException { |
if (barcode.length() > (144 * 144)) { |
throw new IllegalArgumentException("barcode too long (max : 144x144:20736)"); |
} |
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
{ |
// Header: 0x00 : 200 fois |
for (int i = 0; i < 200; i++) { |
out.write(0x00); |
} |
} |
// Select ESCP/P Mode : 0x1B 0x69 0x61 0x00 |
out.write(ESC); |
out.write(0x69); |
out.write(0x61); |
out.write(0x00); // mode ESC/P standard |
// Init 0x1B 0x40 |
out.write(ESC); |
out.write(0x40); |
// ESC i D |
out.write(ESC); |
out.write(0x69); |
out.write(0x44); |
// |
out.write(dotsPerCell); |
out.write(0); // square |
out.write(0); // vertical size : auto |
out.write(0); // horizontal size : auto |
for (int i = 0; i < 5; i++) { |
out.write(0); // reserved |
} |
// data |
out.write(barcode.getBytes(StandardCharsets.US_ASCII)); |
out.write('\\'); |
out.write('\\'); |
out.write('\\'); |
// Page feed |
out.write(0x0C); |
out.flush(); |
final byte[] byteArray = out.toByteArray(); |
print(byteArray); |
} |
public void print(String string) throws IOException { |
ByteArrayOutputStream bOut = new ByteArrayOutputStream(); |
// Select ESCP/P Mode : 0x1B 0x69 0x61 0x00 |
bOut.write(ESC); |
bOut.write(0x69); |
bOut.write(0x61); |
bOut.write(0x0); // mode ESC/P standard |
// Init 0x1B 0x40 |
bOut.write(ESC); |
bOut.write(0x40); |
// Init |
bOut.write(ESC); |
bOut.write(0x40); |
// French characters |
bOut.write(ESC); |
bOut.write(0x52); |
bOut.write(0x01); |
// Normal |
bOut.write(ESC); |
bOut.write(0x21); |
bOut.write(0);// Default |
bOut.write(string.getBytes(StandardCharsets.US_ASCII)); |
bOut.write(0x0A);// Retour a la ligne |
// Page feed |
bOut.write(0x0C); |
print(bOut.toByteArray()); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ql/QLPrinterExample.java |
---|
18,15 → 18,19 |
public class QLPrinterExample { |
public static void main(String[] args) { |
QLPrinter prt = new QLPrinter("192.168.1.103"); |
QLPrinter prt = new QLPrinter("192.168.168.53"); |
prt.setHighQuality(true); |
try { |
prt.print(new File("Hello_720x300.png")); |
String code = "123456789"; |
prt.printDataMatrixBarCode2D(10, code); |
prt.print("Hello"); |
} catch (IOException e) { |
e.printStackTrace(); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/generation/ReportGeneration.java |
---|
39,13 → 39,14 |
import java.util.Map.Entry; |
import java.util.Stack; |
import java.util.concurrent.Callable; |
import java.util.concurrent.ExecutionException; |
import java.util.concurrent.FutureTask; |
import java.util.concurrent.TimeoutException; |
import org.jdom.Element; |
import org.jdom.JDOMException; |
import org.jdom.filter.Filter; |
import net.jcip.annotations.GuardedBy; |
import ognl.Ognl; |
import ognl.OgnlException; |
import ognl.OgnlRuntime; |
87,9 → 88,11 |
// Inheritable to allow generators to spawn threads |
private final InheritableThreadLocal<ReportPart> currentParts; |
private final InheritableThreadLocal<DocumentGenerator> currentGenerator; |
@GuardedBy("this") |
private Throwable interruptCause; |
// tous les générateurs s'exécuter dans ce groupe |
private final ThreadGroup thg; |
@GuardedBy("this") |
private List<Thread> thg; |
private final List<PropertyChangeListener> taskListeners; |
private final PropertyChangeListener taskListener; |
private Map<String, Object> commonData; |
109,11 → 112,7 |
this.currentParts = new InheritableThreadLocal<ReportPart>(); |
this.currentGenerator = new InheritableThreadLocal<DocumentGenerator>(); |
this.interruptCause = null; |
this.thg = new ThreadGroup("Generateurs") { |
public void uncaughtException(Thread t, Throwable e) { |
ReportGeneration.this.interrupt(e); |
} |
}; |
this.thg = null; |
this.taskListeners = new ArrayList<PropertyChangeListener>(); |
this.taskListener = new PropertyChangeListener() { |
198,6 → 197,7 |
public final Map<String, ODSingleXMLDocument> generateMulti() throws Throwable { |
synchronized (this) { |
this.interruptCause = null; |
this.thg = new ArrayList<>(); |
} |
Map<String, ODSingleXMLDocument> f = null; |
206,17 → 206,34 |
return createDocument(); |
} |
}); |
final Thread thr = new Thread(this.thg, future); |
// Don't pass a ThreadGroup, since every thread created, including "cache timeout", JDBC |
// threads will be in it. But these threads must out-live this generation. |
final Thread thr = new Thread(null, future); |
this.registerThread(thr); |
thr.start(); |
try { |
thr.join(); |
f = future.get(); |
} catch (Exception e) { |
if (isInterruptedExn(e) || (e instanceof ExecutionException && isInterruptedExn(e.getCause()))) |
f = null; |
else |
assert f == null; |
// If one thread was interrupted (or failed), interrupt the others |
this.interrupt(e); |
} finally { |
// Make sure all threads are stopped and don't prevent this from being garbage |
// collected. |
final List<Thread> toJoin; |
synchronized (this) { |
toJoin = this.thg; |
this.thg = null; |
} |
for (final Thread t : toJoin) { |
// If no exception occurred, then should already be finished but if there was one in |
// a thread, another thread might be stuck on some I/O for a while before it can |
// process the interrupt. |
t.join(4500); |
if (t.isAlive()) |
throw new TimeoutException("Thread still not terminated : " + t); |
} |
} |
final Map<String, ODSingleXMLDocument> res; |
synchronized (this) { |
236,14 → 253,20 |
return res; |
} |
public final synchronized void registerThread(final Thread thr) { |
this.thg.add(thr); |
} |
protected final void interrupt(Throwable cause) { |
synchronized (this) { |
if (this.interruptCause == null) { |
this.interruptCause = cause; |
this.thg.interrupt(); |
for (final Thread thr : this.thg) { |
thr.interrupt(); |
} |
} |
} |
} |
private Map<String, ODSingleXMLDocument> createDocument() throws IOException, OgnlException, InterruptedException { |
// recompute common data for each run |
276,6 → 299,7 |
if (part instanceof ForkReportPart) { |
GenThread thread = new GenThread(part.getName(), ((ForkReportPart) part).getChildren()); |
forked.put(part.getName(), thread); |
this.registerThread(thread); |
thread.start(); |
} else if (part instanceof SubReportPart) { |
final SubReportPart subReportPart = (SubReportPart) part; |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/generation/view/BaseGenerationRapport.java |
---|
59,9 → 59,12 |
import javax.swing.JPanel; |
import javax.swing.JScrollPane; |
import javax.swing.SwingUtilities; |
import javax.swing.SwingWorker; |
import org.jdom.JDOMException; |
import net.jcip.annotations.GuardedBy; |
/** |
* A panel to choose a ReportType, see the tasks of the generation, and optionnaly open the |
* document. NOTE: you have to call {@link #enableGeneration(boolean)} before being able to |
95,11 → 98,11 |
private JList<GenerationTask> tasksView; |
private final JLabel status; |
// le groupe dans lequel doivent être toutes les thread de la génération |
private final ThreadGroup thg; |
@GuardedBy("EDT") |
private SwingWorker<Void, Void> generationWorker; |
public BaseGenerationRapport() throws JDOMException, IOException { |
this.thg = new ThreadGroup(this + " thread group"); |
this.generationWorker = null; |
this.status = new JLabel(); |
this.setStatus("Inactif"); |
} |
234,7 → 237,8 |
*/ |
public final void interrupt() { |
// pas de threads active, quand pas génération |
this.thg.interrupt(); |
if (this.generationWorker != null) |
this.generationWorker.cancel(true); |
} |
class GenerateAction implements ActionListener { |
246,21 → 250,22 |
enableGeneration(false); |
final FileAction sel = (FileAction) BaseGenerationRapport.this.fileActionCombo.getSelectedItem(); |
// "génération..." |
new Thread(BaseGenerationRapport.this.thg, new Runnable() { |
BaseGenerationRapport.this.generationWorker = new SwingWorker<Void, Void>() { |
@Override |
public void run() { |
protected Void doInBackground() throws Exception { |
generate(sel); |
return null; |
} |
@Override |
protected void done() { |
// toujours le faire, même si interrompu |
SwingUtilities.invokeLater(new Runnable() { |
@Override |
public void run() { |
enableGeneration(true); |
} |
}); |
}; |
BaseGenerationRapport.this.generationWorker.execute(); |
} |
}).start(); |
} |
} |
protected final void enableGeneration(final boolean b) { |
this.fileActionCombo.setEnabled(b); |
267,7 → 272,6 |
this.genererButton.setEnabled(b); |
} |
// doit s'exécuter dans this.thg |
protected final void generate(final FileAction sel) { |
final ReportType type = (ReportType) this.typeRapportComboSelection.getSelectedItem(); |
final R rg = this.createGeneration(type); |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/ODFrame.java |
---|
13,6 → 13,7 |
package org.openconcerto.openoffice; |
import org.openconcerto.openoffice.spreadsheet.BytesProducer; |
import org.openconcerto.openoffice.text.TextNode; |
import java.math.BigDecimal; |
28,6 → 29,20 |
*/ |
public class ODFrame<D extends ODDocument> extends ImmutableDocStyledNode<GraphicStyle, D> { |
static public Element createEmpty(XMLVersion ns, final Number w, final Number h, final LengthUnit unit) { |
return createEmpty(ns, BigDecimal.ZERO, BigDecimal.ZERO, w, h, unit); |
} |
static public Element createEmpty(XMLVersion ns, final Number x, final Number y, final Number w, final Number h, final LengthUnit unit) { |
final Namespace svgNS = ns.getNS("svg"); |
final Element res = new Element("frame", ns.getNS("draw")); |
res.setAttribute("x", unit.format(x), svgNS); |
res.setAttribute("y", unit.format(y), svgNS); |
res.setAttribute("width", unit.format(w), svgNS); |
res.setAttribute("height", unit.format(h), svgNS); |
return res; |
} |
/** |
* Parse SVG and OD length. |
* |
120,4 → 135,36 |
public final LengthUnit getUnit() { |
return LengthUnit.MM; |
} |
public final void addImage(final String name, final BytesProducer data) { |
final Element imageElem = new Element("image", getElement().getNamespace("draw")); |
this.getElement().addContent(imageElem); |
this.putImage(imageElem, name, data); |
} |
private final void putImage(final Element imageElem, final String name, final BytesProducer data) { |
final String imgPath = "Pictures/" + name + (data.getFormat() != null ? "." + data.getFormat() : ""); |
imageElem.setAttribute("href", imgPath, this.getODDocument().getVersion().getNS("xlink")); |
this.getODDocument().getPackage().putFile(imgPath, data.getBytes(this)); |
} |
public final void setImage(final String name, final BytesProducer data, final boolean allowAdd) { |
final Element imageElem = this.getElement().getChild("image", getElement().getNamespace("draw")); |
if (imageElem != null) { |
final String oldPath = imageElem.getAttributeValue("href", this.getODDocument().getVersion().getNS("xlink")); |
this.getODDocument().getPackage().putFile(oldPath, null); |
imageElem.removeChild("binary-data", this.getODDocument().getVersion().getOFFICE()); |
if (data == null) { |
imageElem.detach(); |
} else { |
this.putImage(imageElem, name, data); |
} |
} else if (data != null) { |
if (allowAdd) |
this.addImage(name, data); |
else |
throw new IllegalStateException("No image in " + this); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/ODEpoch.java |
---|
14,6 → 14,8 |
package org.openconcerto.openoffice; |
import org.openconcerto.utils.TimeUtils; |
import org.openconcerto.utils.cache.LRUMap; |
import org.openconcerto.utils.cc.CachedTransformer; |
import java.math.BigDecimal; |
import java.math.BigInteger; |
22,8 → 24,6 |
import java.text.ParseException; |
import java.text.SimpleDateFormat; |
import java.util.Calendar; |
import java.util.LinkedHashMap; |
import java.util.Map; |
import java.util.TimeZone; |
import javax.xml.datatype.DatatypeConstants; |
43,12 → 43,7 |
static private final DateFormat DATE_FORMAT; |
static private final ODEpoch DEFAULT_EPOCH; |
@GuardedBy("cache") |
static private final Map<String, ODEpoch> cache = new LinkedHashMap<String, ODEpoch>(4, 0.75f, true) { |
@Override |
protected boolean removeEldestEntry(Map.Entry<String, ODEpoch> eldest) { |
return this.size() > 16; |
} |
}; |
static private final CachedTransformer<String, ODEpoch, ParseException> cache = new CachedTransformer<>(new LRUMap<>(16, 4), ODEpoch::new); |
static { |
DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); |
70,16 → 65,19 |
return DEFAULT_EPOCH; |
} else { |
synchronized (cache) { |
ODEpoch res = cache.get(date); |
if (res == null) { |
res = new ODEpoch(date); |
cache.put(date, res); |
return cache.transformChecked(date); |
} |
return res; |
} |
} |
public static final BigDecimal getDays(final java.time.Duration d) { |
return getDays(d.toMillis()); |
} |
public static final BigDecimal getDays(final long millis) { |
return BigDecimal.valueOf(millis).divide(MS_PER_DAY, MathContext.DECIMAL128); |
} |
static private final Calendar parse(final String date) throws ParseException { |
synchronized (DATE_FORMAT) { |
final Calendar cal = (Calendar) DATE_FORMAT.getCalendar().clone(); |
139,7 → 137,7 |
// can't use Duration.normalizeWith() since it doesn't handle DST, i.e. going from winter to |
// summer at midnight will miss a day |
final long diff = TimeUtils.normalizeLocalTime(cal) - this.epochUTC.getTimeInMillis(); |
return BigDecimal.valueOf(diff).divide(MS_PER_DAY, MathContext.DECIMAL128); |
return getDays(diff); |
} |
public final Calendar getDate(final BigDecimal days) { |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/spreadsheet/CellStyle.java |
---|
132,10 → 132,11 |
super(pkg, tableColElem); |
} |
private final DataStyle getDataStyle(final Attribute name) { |
final DataStyle getDataStyle(final Attribute name) { |
return (DataStyle) Style.getReferencedStyle(getPackage(), name); |
} |
// see MutableCell#getDataStyle() |
final DataStyle getDataStyle() { |
return getDataStyle(this.getElement().getAttribute("data-style-name", this.getSTYLE())); |
} |
160,13 → 161,13 |
} |
} |
final List<?> styleMaps = res.getElement().getChildren("map", getSTYLE()); |
final List<Element> styleMaps = res.getMapChildren(); |
if (styleMaps.size() > 0) { |
final Object converted = convertForCondition(returnCellValue, res); |
// we can't compare() so don't try |
if (converted != null) { |
for (Object child : styleMaps) { |
final Element styleMap = (Element) child; |
for (Element child : styleMaps) { |
final Element styleMap = child; |
final Matcher matcher = conditionPatrn.matcher(styleMap.getAttributeValue("condition", getSTYLE()).trim()); |
if (!matcher.matches()) |
throw new IllegalStateException("Cannot parse " + JDOMUtils.output(styleMap)); |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/spreadsheet/Lines.java |
---|
97,7 → 97,7 |
public Lines(final ODDocument doc, final String text) { |
super(); |
this.doc = doc; |
this.xml = OOXML.get(doc.getFormatVersion(), false); |
this.xml = doc.getFormatVersion().getXML(); |
this.lines = new LinkedList<String>(); |
this.separators = new LinkedList<Sep>(); |
this.parse(text, isCalc()); |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/spreadsheet/MutableCell.java |
---|
13,9 → 13,14 |
package org.openconcerto.openoffice.spreadsheet; |
import static org.openconcerto.utils.TimeUtils.SECONDS_PER_HOUR; |
import static org.openconcerto.utils.TimeUtils.SECONDS_PER_MINUTE; |
import org.openconcerto.openoffice.LengthUnit; |
import org.openconcerto.openoffice.Log; |
import org.openconcerto.openoffice.ODDocument; |
import org.openconcerto.openoffice.ODFrame; |
import org.openconcerto.openoffice.ODPackage; |
import org.openconcerto.openoffice.ODValueType; |
import org.openconcerto.openoffice.StyleDesc; |
import org.openconcerto.openoffice.XMLVersion; |
29,6 → 34,8 |
import org.openconcerto.utils.TimeUtils.DurationNullsChanger; |
import org.openconcerto.utils.Tuple2; |
import org.openconcerto.utils.Tuple3; |
import org.openconcerto.utils.cache.LRUMap; |
import org.openconcerto.utils.cc.CachedTransformer; |
import java.awt.Color; |
import java.awt.Image; |
35,8 → 42,10 |
import java.awt.Point; |
import java.io.File; |
import java.io.IOException; |
import java.math.BigDecimal; |
import java.text.DateFormat; |
import java.text.DecimalFormat; |
import java.text.DecimalFormatSymbols; |
import java.text.NumberFormat; |
import java.util.Calendar; |
import java.util.Date; |
59,10 → 68,40 |
*/ |
public class MutableCell<D extends ODDocument> extends Cell<D> { |
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 CachedTransformer<Locale, DateFormat, RuntimeException> TextPDateFormat = new CachedTransformer<>(new LRUMap<>(20), (l) -> DateFormat.getDateInstance(DateFormat.DEFAULT, l), |
false); |
static private final CachedTransformer<Locale, DateFormat, RuntimeException> TextPTimeFormat = new CachedTransformer<>(new LRUMap<>(20), (l) -> DateFormat.getTimeInstance(DateFormat.DEFAULT, l), |
false); |
static private final CachedTransformer<Locale, NumberFormat, RuntimeException> TextPMinuteSecondFormat = new CachedTransformer<>(new LRUMap<>(20), |
(l) -> new DecimalFormat("00.###", DecimalFormatSymbols.getInstance(l)), false); |
static private final char TEXTP_SEP = ':'; |
// HH:mm:ss.SSS |
static String textPDuration(final long hours, final int minutes, final BigDecimal secsAndNanos, final Locale locale) { |
final StringBuilder res = new StringBuilder(16); |
res.append(hours); |
res.append(TEXTP_SEP); |
res.append(TextPMinuteSecondFormat.get(locale).format(minutes)); |
res.append(TEXTP_SEP); |
res.append(TextPMinuteSecondFormat.get(locale).format(secsAndNanos)); |
return res.toString(); |
} |
static String textPDuration(final java.time.Duration d, final Locale locale) { |
// -1H is treated as 23:00 in LO |
if (d.isNegative()) |
throw new UnsupportedOperationException("Negative duration"); |
final long seconds = d.getSeconds(); |
// from Duration.toString() |
final long hours = seconds / SECONDS_PER_HOUR; |
final int minutes = (int) ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE); |
final int secs = (int) (seconds % SECONDS_PER_MINUTE); |
final BigDecimal secsAndNanos = BigDecimal.valueOf(secs).add(BigDecimal.valueOf(d.getNano()).movePointLeft(9)); |
return textPDuration(hours, minutes, secsAndNanos, locale); |
} |
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(); |
139,8 → 178,8 |
// Like LO, do not generate string-value |
if (type != null && type != ODValueType.STRING) { |
// LO cells don't support the full syntax of a duration (user meta fields do) |
// instead it support only values without nYnMnD |
if (type == ODValueType.TIME && getTimeValueMode()) { |
// instead it support only values without nYnMnD (as does java.time.Duration) |
if (type == ODValueType.TIME && getTimeValueMode() && !(val instanceof java.time.Duration)) { |
final Duration d = val instanceof Duration ? (Duration) val : TimeUtils.timePartToDuration((Calendar) val); |
val = TIME_NULLS.apply(getODDocument().getEpoch().normalizeToHours(d)); |
} |
214,13 → 253,15 |
if (formatted.get0() != null) { |
text = formatted.get0(); |
} else { |
// either there were no format or formatting failed |
// either there were no format, formatting failed or wasn't attempted because the data |
// style cannot format vt |
if (vt == ODValueType.FLOAT) { |
text = getODDocument().getPackage().formatNumber((Number) obj, getDefaultStyle()); |
text = ODPackage.formatNumber((Number) obj, getDataLocale(), getDefaultStyle()); |
} else if (vt == ODValueType.PERCENTAGE) { |
text = getODDocument().getPackage().formatPercent((Number) obj, getDefaultStyle()); |
text = ODPackage.formatPercent((Number) obj, getDataLocale(), getDefaultStyle()); |
} else if (vt == ODValueType.CURRENCY) { |
text = getODDocument().getPackage().formatCurrency((Number) obj, getDefaultStyle()); |
text = ODPackage.formatCurrency((Number) obj, getDataLocale(), getDefaultStyle()); |
} else if (vt == ODValueType.DATE) { |
final Date d; |
if (obj instanceof Calendar) { |
228,25 → 269,18 |
} else { |
d = (Date) obj; |
} |
text = TextPDateFormat.format(d); |
text = TextPDateFormat.get(getDataLocale()).format(d); |
} else if (vt == ODValueType.TIME) { |
if (obj instanceof Duration) { |
final Duration normalized = getODDocument().getEpoch().normalizeToHours((Duration) obj); |
text = "" + normalized.getHours() + ':' + TextPMinuteSecondFormat.format(normalized.getMinutes()) + ':' + TextPMinuteSecondFormat.format(TimeUtils.getSeconds(normalized)); |
text = textPDuration(normalized.getHours(), normalized.getMinutes(), TimeUtils.getSeconds(normalized), getDataLocale()); |
} else if (obj instanceof java.time.Duration) { |
text = textPDuration((java.time.Duration) obj, getDataLocale()); |
} else { |
text = TextPTimeFormat.format(((Calendar) obj).getTime()); |
text = TextPTimeFormat.get(getDataLocale()).format(((Calendar) obj).getTime()); |
} |
} else if (vt == ODValueType.BOOLEAN) { |
Locale l = null; |
final CellStyle s = getStyle(); |
if (s != null) { |
final DataStyle ds = s.getDataStyle(); |
if (ds != null) |
l = ds.getLocale(); |
} |
if (l == null) |
l = getODDocument().getPackage().getLocale(); |
text = BooleanStyle.toString((Boolean) obj, l, lenient); |
text = BooleanStyle.toString((Boolean) obj, getDataLocale(), lenient); |
} else if (vt == ODValueType.STRING) { |
text = obj.toString(); |
} else { |
256,6 → 290,54 |
this.setValue(vt, obj, text); |
} |
/** |
* The locale of the data style. NOTE this doesn't evaluate the map elements with the current |
* cell value. |
* |
* @return the locale of the data style, or if none, the ODPackage locale. |
*/ |
public final Locale getDataLocale() { |
return this.getDataLocale(false); |
} |
public final Locale getDataLocale(final boolean local) { |
Locale res = null; |
final CellStyle s = getStyle(); |
if (s != null) { |
final DataStyle ds = s.getDataStyle(); |
if (ds != null) |
res = ds.getLocale(local); |
} |
if (local || res != null) |
return res; |
return getODDocument().getPackage().getLocale(); |
} |
/** |
* Set the locale for the data style. This is different from the locale of the |
* {@link CellStyle#getTextProperties() text properties}. Like LibreOffice, this set the |
* attributes of the main {@link DataStyle}, and all {@link #getDataStyle() mapped} ones. |
* |
* @param locale the new locale, <code>null</code> to remove attributes. |
* @throws IllegalStateException if there's no {@link DataStyle}. |
*/ |
public final void setDataLocale(final Locale locale) throws IllegalStateException { |
final CellStyle s = getStyle(); |
if (s != null) { |
final DataStyle ds = s.getDataStyle(); |
if (ds != null) { |
ds.setLocale(locale); |
// LO does this, and this avoids the need for mapped styles to have a reference to |
// their parent. |
for (final Element mapElem : ds.getMapChildren()) { |
s.getDataStyle(mapElem.getAttribute("apply-style-name", mapElem.getNamespace())).setLocale(locale); |
} |
return; |
} |
} |
throw new IllegalStateException("No data style for " + this); |
} |
// return null String if no data style exists, or if one exists but we couldn't use it |
private Tuple3<String, ODValueType, Object> format(Object obj, ODValueType valueType, boolean onlyCast, boolean lenient) { |
String res = null; |
452,6 → 534,12 |
return this.getRow().getSheet().getTableCellPropertiesAt(this.getX(), this.getY()); |
} |
public final ODFrame<D> addFrame(final Number x, final Number y, final Number w, final Number h, final LengthUnit unit) { |
final Element elem = ODFrame.createEmpty(getNS(), x, y, w, h, unit); |
this.getElement().addContent(elem); |
return new ODFrame<>(getODDocument(), elem); |
} |
public void setImage(final File pic) throws IOException { |
this.setImage(pic, false); |
} |
467,20 → 555,11 |
private void setImage(final String name, final BytesProducer data) { |
final Namespace draw = this.getNS().getNS("draw"); |
final Element frame = this.getElement().getChild("frame", draw); |
final Element imageElem = frame == null ? null : frame.getChild("image", draw); |
if (imageElem != null) { |
final Attribute refAttr = imageElem.getAttribute("href", this.getNS().getNS("xlink")); |
this.getODDocument().getPackage().putFile(refAttr.getValue(), null); |
if (data == null) |
frame.detach(); |
else { |
refAttr.setValue("Pictures/" + name + (data.getFormat() != null ? "." + data.getFormat() : "")); |
this.getODDocument().getPackage().putFile(refAttr.getValue(), data.getBytes(new ODFrame<D>(getODDocument(), frame))); |
} |
if (frame != null) { |
new ODFrame<>(getODDocument(), frame).setImage(name, data, false); |
} else if (data != null) |
throw new IllegalStateException("this cell doesn't contain an image: " + this); |
throw new IllegalStateException("this cell doesn't contain a frame: " + this); |
} |
public final void setBackgroundColor(final Color color) { |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/spreadsheet/BytesProducer.java |
---|
28,7 → 28,7 |
import org.jdom.Element; |
abstract class BytesProducer { |
public abstract class BytesProducer { |
/** |
* The data of an image to put in <code>frame</code>. |
36,7 → 36,7 |
* @param frame the frame where this image will be put. |
* @return the corresponding bytes. |
*/ |
abstract byte[] getBytes(ODFrame<?> frame); |
public abstract byte[] getBytes(ODFrame<?> frame); |
/** |
* The format of the data returned by {@link #getBytes(Element)}. |
43,12 → 43,12 |
* |
* @return the name of the format, <code>null</code> if unknown, eg "png". |
*/ |
abstract String getFormat(); |
public abstract String getFormat(); |
// *** concrete subclasses |
// a no-op Producer |
static final class ByteArrayProducer extends BytesProducer { |
static public final class ByteArrayProducer extends BytesProducer { |
private final byte[] data; |
private final boolean keepRatio; |
104,7 → 104,7 |
} |
// will generate a new png image (and can also keep ratio) |
static final class ImageProducer extends BytesProducer { |
static public final class ImageProducer extends BytesProducer { |
private final Image img; |
private final boolean keepRatio; |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/Grep.java |
---|
72,6 → 72,10 |
this.pattern = Pattern.compile(pattern); |
} |
public final Pattern getPattern() { |
return this.pattern; |
} |
public final void grep(final File dir) { |
FileUtils.walk(dir, new IClosure<File>() { |
@Override |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/OOUtils.java |
---|
20,8 → 20,10 |
import java.io.File; |
import java.io.IOException; |
import java.io.StringReader; |
import java.util.Locale; |
import org.jdom.Document; |
import org.jdom.Element; |
import org.jdom.JDOMException; |
import org.jdom.Namespace; |
import org.jdom.input.SAXBuilder; |
120,4 → 122,33 |
public static Color decodeRGB(String color) { |
return color == null ? null : Color.decode(color.trim()); |
} |
public static final Locale getElementLocale(final Element elem) { |
return getElementLocale(elem, elem.getNamespace()); |
} |
public static final Locale getElementLocale(final Element elem, final Namespace ns) { |
final Locale res; |
final String country = elem.getAttributeValue("country", ns); |
final String lang = elem.getAttributeValue("language", ns); |
if (lang != null) { |
res = new Locale.Builder().setLanguage(lang).setRegion(country).build(); |
} else { |
res = null; |
} |
return res; |
} |
public static final void setElementLocale(final Element elem, final Namespace ns, final Locale l) { |
if (l == null) |
elem.removeAttribute("country", ns); |
else |
elem.setAttribute("country", l.getCountry(), ns); |
final String lang = l == null ? null : l.getLanguage(); |
if (lang == null || lang.isEmpty()) |
elem.removeAttribute("language", ns); |
else |
elem.setAttribute("language", lang, ns); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/OOXML.java |
---|
41,10 → 41,6 |
import javax.xml.validation.Schema; |
import javax.xml.validation.SchemaFactory; |
import net.jcip.annotations.GuardedBy; |
import net.jcip.annotations.Immutable; |
import net.jcip.annotations.ThreadSafe; |
import org.jdom.Content; |
import org.jdom.DocType; |
import org.jdom.Document; |
56,6 → 52,10 |
import org.jdom.xpath.XPath; |
import org.xml.sax.SAXException; |
import net.jcip.annotations.GuardedBy; |
import net.jcip.annotations.Immutable; |
import net.jcip.annotations.ThreadSafe; |
/** |
* Various bits of OpenDocument XML. |
* |
69,6 → 69,7 |
* never return <code>null</code>, allowing to support unknown versions. |
*/ |
public static final String LAST_FOR_UNKNOWN_PROP = OOXML.class.getPackage().getName() + ".lastOOXMLForUnknownVersion"; |
private static final boolean LAST_FOR_UNKNOWN = Boolean.getBoolean(LAST_FOR_UNKNOWN_PROP); |
private static final XML_OO instanceOO = new XML_OO(); |
@GuardedBy("OOXML") |
private static final SortedMap<String, XML_OD> instancesODByDate = new TreeMap<String, XML_OD>(); |
83,6 → 84,7 |
register(new XML_OD_1_0()); |
register(new XML_OD_1_1()); |
register(new XML_OD_1_2()); |
register(new XML_OD_1_3()); |
final List<OOXML> tmp = new ArrayList<OOXML>(instancesODByDate.size() + 1); |
tmp.add(instanceOO); |
106,7 → 108,7 |
* @see #LAST_FOR_UNKNOWN_PROP |
*/ |
public static OOXML get(XMLFormatVersion version) { |
return get(version, Boolean.getBoolean(LAST_FOR_UNKNOWN_PROP)); |
return get(version, LAST_FOR_UNKNOWN); |
} |
public static synchronized OOXML get(XMLFormatVersion version, final boolean lastForUnknown) { |
741,11 → 743,17 |
} |
} |
private static final class XML_OD_1_2 extends XML_OD { |
private static final class XML_OD_1_2 extends XML_OD_1_2plus { |
public XML_OD_1_2() { |
super("20110317", "1.2", "OpenDocument-v1.2-schema.rng", "OpenDocument-v1.2-manifest-schema.rng"); |
} |
} |
private static abstract class XML_OD_1_2plus extends XML_OD { |
protected XML_OD_1_2plus(final String dateString, final String versionString, final String schemaFile, final String manifestSchemaFile) { |
super(dateString, versionString, schemaFile, manifestSchemaFile); |
} |
@Override |
public Document createManifestDoc() { |
final Document res = super.createManifestDoc(); |
753,4 → 761,13 |
return res; |
} |
} |
// https://issues.oasis-open.org/issues/?jql=project%20%3D%20OFFICE%20AND%20resolution%20%3D%20Fixed%20AND%20fixVersion%20%3D%20%22ODF%201.3%22 |
// - https://issues.oasis-open.org/browse/OFFICE-3860 : New attributes "min-decimal-places" and |
// "forced-exponent-sign" parsed in DataStyle.formatNumberOrScientificNumber() |
private static final class XML_OD_1_3 extends XML_OD_1_2plus { |
public XML_OD_1_3() { |
super("20191225", "1.3", "OpenDocument-schema-v1.3.rng", "OpenDocument-manifest-schema-v1.3.rng"); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/ODValueType.java |
---|
85,6 → 85,7 |
return FLOAT.parse(s); |
} |
}, |
// TODO support LocalDateTime |
DATE("date-value", Date.class, Calendar.class) { |
@Override |
106,12 → 107,15 |
} |
}, |
TIME("time-value", Duration.class, Calendar.class) { |
TIME("time-value", Duration.class, java.time.Duration.class, Calendar.class) { |
@Override |
public String format(Object o) { |
if (o instanceof Duration) { |
return o.toString(); |
} else if (o instanceof java.time.Duration) { |
// w/o days or larger : PTnHnMnS |
return o.toString(); |
} else { |
final Calendar cal = (Calendar) o; |
return TimeUtils.timePartToDuration(cal).toString(); |
218,7 → 222,7 |
return BOOLEAN; |
else if (o instanceof String) |
return STRING; |
else if (o instanceof Duration) |
else if (o instanceof Duration || o instanceof java.time.Duration) |
return TIME; |
else if (DATE.canFormat(o.getClass())) |
return DATE; |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/text/TextNode.java |
---|
158,7 → 158,7 |
static private final String getCharacterContent(final List<Content> pElem, final XMLFormatVersion vers, final boolean ooMode, final boolean useSeparator, final Option option) { |
if (pElem.isEmpty()) |
return ""; |
final OOXML xml = OOXML.get(vers, false); |
final OOXML xml = vers.getXML(); |
final StringBuilder sb = new StringBuilder(); |
final Namespace textNS = xml.getVersion().getTEXT(); |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/ODPackage.java |
---|
268,11 → 268,8 |
} |
public static ODPackage createFromFile(final File f) throws IOException { |
final FileInputStream ins = new FileInputStream(f); |
try { |
try (final FileInputStream ins = new FileInputStream(f)) { |
return create(f, ins, f.getName()); |
} finally { |
ins.close(); |
} |
} |
600,19 → 597,19 |
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 static final String formatNumber(Number n, final Locale locale, final CellStyle defaultStyle) { |
return formatNumber(NumberFormat.getNumberInstance(locale), n, defaultStyle); |
} |
public final String formatPercent(Number n, final CellStyle defaultStyle) { |
return formatNumber(NumberFormat.getPercentInstance(getLocale()), n, defaultStyle); |
public static final String formatPercent(Number n, final Locale locale, final CellStyle defaultStyle) { |
return formatNumber(NumberFormat.getPercentInstance(locale), n, defaultStyle); |
} |
public final String formatCurrency(Number n, final CellStyle defaultStyle) { |
return formatNumber(NumberFormat.getCurrencyInstance(getLocale()), n, defaultStyle); |
public static final String formatCurrency(Number n, final Locale locale, final CellStyle defaultStyle) { |
return formatNumber(NumberFormat.getCurrencyInstance(locale), n, defaultStyle); |
} |
private final String formatNumber(NumberFormat format, Number n, final CellStyle defaultStyle) { |
private static final String formatNumber(NumberFormat format, Number n, final CellStyle defaultStyle) { |
synchronized (format) { |
final int decPlaces = DataStyle.getDecimalPlaces(defaultStyle); |
format.setMinimumFractionDigits(0); |
1183,13 → 1180,13 |
final Object val = entry.getData(); |
if (val != null) { |
if (val instanceof ODXMLDocument) { |
final OutputStream o = z.createEntry(name); |
try (final OutputStream o = z.createEntryStream(name)) { |
outputter.output(((ODXMLDocument) val).getDocument(), o); |
o.close(); |
} |
} else if (val instanceof Document) { |
final OutputStream o = z.createEntry(name); |
try (final OutputStream o = z.createEntryStream(name)) { |
outputter.output((Document) val, o); |
o.close(); |
} |
} else { |
z.zip(name, (byte[]) val, entry.isCompressed()); |
} |
1245,8 → 1242,7 |
if (pageCount != null && getContentType() != null && ContentType.TEXT.equals(getContentType().getType())) |
this.getMeta().getMetaChild("document-statistic").setAttribute("page-count", pageCount, getVersion().getMETA()); |
final Zip z = new Zip(out); |
try (final Zip z = new Zip(out)) { |
// magic number, see section 17.4 |
z.zipNonCompressed(MIMETYPE_ENTRY, this.getMimeType().getBytes(MIMETYPE_ENC)); |
1253,8 → 1249,8 |
final Manifest manifest = createManifest(z); |
z.zip(Manifest.ENTRY_NAME, new StringInputStream(manifest.asString())); |
z.close(); |
} |
} |
/** |
* Save the content of this package to our file, overwriting it if it exists. |
1272,12 → 1268,8 |
f.getParentFile().mkdirs(); |
// ATTN at this point, we must have read all the content of this file |
// otherwise we could save to File.createTempFile("oofd", null).deleteOnExit(); |
final FileOutputStream out = new FileOutputStream(f); |
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(out, 512 * 1024); |
try { |
try (final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(f), 512 * 1024);) { |
this.save(bufferedOutputStream); |
} finally { |
bufferedOutputStream.close(); |
} |
return f; |
} |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/NumberStyle.java |
---|
44,6 → 44,8 |
res = (Number) value; |
} else if (value instanceof Boolean) { |
res = ((Boolean) value).booleanValue() ? 1 : 0; |
} else if (value instanceof java.time.Duration) { |
res = ODEpoch.getDays((java.time.Duration) value); |
} else if ((value instanceof Duration || value instanceof Date || value instanceof Calendar)) { |
if (value instanceof Duration) { |
res = epoch.getDays((Duration) value); |
84,11 → 86,11 |
if (elem.getName().equals("text")) { |
sb.append(elem.getText()); |
} else if (elem.getName().equals("number") || elem.getName().equals("scientific-number")) { |
sb.append(formatNumberOrScientificNumber(elem, n, defaultStyle)); |
sb.append(formatNumberOrScientificNumber(elem, n, defaultStyle, lenient)); |
} else if (elem.getName().equals("fraction")) { |
// TODO fractions |
reportError("Fractions not supported", lenient); |
sb.append(getPackage().formatNumber(n, defaultStyle)); |
sb.append(ODPackage.formatNumber(n, getLocale(), defaultStyle)); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/DataStyle.java |
---|
17,6 → 17,7 |
import org.openconcerto.openoffice.ODEpoch; |
import org.openconcerto.openoffice.ODPackage; |
import org.openconcerto.openoffice.ODValueType; |
import org.openconcerto.openoffice.OOUtils; |
import org.openconcerto.openoffice.Style; |
import org.openconcerto.openoffice.StyleDesc; |
import org.openconcerto.openoffice.StyleProperties; |
51,18 → 52,29 |
/** |
* 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")); |
public static final int DEFAULT_DECIMAL_PLACES; |
private static final Pattern QUOTE_PATRN = Pattern.compile("'", Pattern.LITERAL); |
private static final Pattern EXP_PATTERN = Pattern.compile("E(\\d+)$"); |
public static int getDecimalPlaces(final CellStyle defaultStyle) { |
if (defaultStyle != null) { |
return defaultStyle.getTableCellProperties(null).getDecimalPlaces(); |
final int res = defaultStyle.getTableCellProperties(null).getDecimalPlaces(); |
// Ignore invalid value |
return res < 0 ? DEFAULT_DECIMAL_PLACES : res; |
} else { |
return DEFAULT_DECIMAL_PLACES; |
} |
} |
protected static final int parsePositive(final String attr, final boolean lenient) { |
final int res = Integer.parseInt(attr); |
if (res < 0) { |
reportError("Negative value for " + attr, lenient); |
return 0; |
} |
return res; |
} |
public static void addStringLiteral(final StringBuilder formatSB, final String s) { |
formatSB.append('\''); |
formatSB.append(QUOTE_PATRN.matcher(s).replaceAll("''")); |
83,6 → 95,12 |
l.add(BooleanStyle.class); |
DATA_STYLES = Collections.unmodifiableSet(l); |
assert DATA_STYLES_DESCS.length == DATA_STYLES.size() : "Discrepancy between classes and descs"; |
final String decPlacesProp = System.getProperty("openDocument.defaultDecimalPlaces"); |
final int decPlacesParsed = decPlacesProp == null ? -1 : Integer.parseInt(decPlacesProp); |
// Ignore invalid value |
DEFAULT_DECIMAL_PLACES = decPlacesParsed < 0 ? 15 : decPlacesParsed; |
assert DEFAULT_DECIMAL_PLACES >= 0; |
} |
public static abstract class DataStyleDesc<S extends DataStyle> extends StyleDesc<S> { |
182,19 → 200,32 |
} |
public final Locale getLocale() { |
return this.getLocale(this.getElement()); |
return this.getLocale(false); |
} |
protected final Locale getLocale(final Element elem) { |
final Locale res = DateStyle.getElementLocale(elem); |
return res != null ? res : this.getPackage().getLocale(); |
public final Locale getLocale(final boolean local) { |
return this.getLocale(this.getElement(), local); |
} |
protected final String formatNumberOrScientificNumber(final Element elem, final Number n, CellStyle defaultStyle) { |
return this.formatNumberOrScientificNumber(elem, n, 1, defaultStyle); |
protected final Locale getLocale(final Element elem, final boolean local) { |
final Locale res = OOUtils.getElementLocale(elem); |
return local || res != null ? res : this.getPackage().getLocale(); |
} |
protected final String formatNumberOrScientificNumber(final Element elem, final Number n, final int multiplier, CellStyle defaultStyle) { |
public final void setLocale(final Locale l) { |
OOUtils.setElementLocale(this.getElement(), this.getElement().getNamespace(), l); |
} |
@SuppressWarnings("unchecked") |
public final List<Element> getMapChildren() { |
return this.getElement().getChildren("map", getSTYLE()); |
} |
protected final String formatNumberOrScientificNumber(final Element elem, final Number n, CellStyle defaultStyle, final boolean lenient) { |
return this.formatNumberOrScientificNumber(elem, n, 1, defaultStyle, lenient); |
} |
protected final String formatNumberOrScientificNumber(final Element elem, final Number n, final int multiplier, CellStyle defaultStyle, final boolean lenient) { |
final Namespace numberNS = this.getElement().getNamespace(); |
final StringBuilder numberSB = new StringBuilder(); |
221,9 → 252,10 |
} |
// e.g. if it's "--", 12,3 is displayed "12,3" and 12 is displayed "12,--" |
final String decReplacement = elem.getAttributeValue("decimal-replacement", numberNS); |
// From v1.3 §19.356.2 decimal-replacement can be empty |
final String decReplacement = elem.getAttributeValue("decimal-replacement", numberNS, ""); |
final boolean decSeparatorAlwaysShown; |
if (decReplacement != null && !NumberUtils.hasFractionalPart(n)) { |
if (!decReplacement.isEmpty() && !NumberUtils.hasFractionalPart(n)) { |
decSeparatorAlwaysShown = true; |
numberSB.append('.'); |
// escape quote in replacement |
231,30 → 263,47 |
} else { |
decSeparatorAlwaysShown = false; |
// see 19.343.2 |
final Attribute decPlacesAttr = elem.getAttribute("decimal-places", numberNS); |
final int decPlaces; |
final char decChar; |
if (decPlacesAttr != null) { |
decChar = '0'; |
decPlaces = Integer.parseInt(decPlacesAttr.getValue()); |
final String decPlacesAttr = elem.getAttributeValue("decimal-places", numberNS, ""); |
final String minDecPlacesAttr = elem.getAttributeValue("min-decimal-places", numberNS, ""); |
final int forcedPlaces, nonZeroPlaces; |
if (!decPlacesAttr.isEmpty()) { |
final int decPlaces = parsePositive(decPlacesAttr, lenient); |
if (minDecPlacesAttr.isEmpty()) { |
forcedPlaces = decPlaces; |
nonZeroPlaces = 0; |
} else { |
forcedPlaces = parsePositive(minDecPlacesAttr, lenient); |
if (forcedPlaces > decPlaces) { |
DataStyle.reportError("min-decimal-places greater than decimal-places : " + minDecPlacesAttr + " > " + decPlacesAttr, lenient); |
nonZeroPlaces = 0; |
} else { |
nonZeroPlaces = decPlaces - forcedPlaces; |
} |
} |
} else { |
// default style specifies the maximum |
decChar = '#'; |
decPlaces = getDecimalPlaces(defaultStyle); |
forcedPlaces = 0; |
nonZeroPlaces = getDecimalPlaces(defaultStyle); |
} |
if (decPlaces > 0) { |
if (forcedPlaces + nonZeroPlaces > 0) { |
numberSB.append('.'); |
for (int i = 0; i < decPlaces; i++) |
numberSB.append(decChar); |
for (int i = 0; i < forcedPlaces; i++) |
numberSB.append('0'); |
for (int i = 0; i < nonZeroPlaces; i++) |
numberSB.append('#'); |
} |
} |
final Attribute minExpAttr = elem.getAttribute("min-exponent-digits", numberNS); |
final boolean forcedExpSign; |
if (minExpAttr != null) { |
forcedExpSign = Boolean.parseBoolean(elem.getAttributeValue("forced-exponent-sign", numberNS, "true")); |
numberSB.append('E'); |
for (int i = 0; i < Integer.parseInt(minExpAttr.getValue()); i++) |
numberSB.append('0'); |
} else { |
forcedExpSign = false; |
} |
final DecimalFormatSymbols symbols = new DecimalFormatSymbols(this.getLocale()); |
267,8 → 316,8 |
decFormat.setGroupingSize(DEFAULT_GROUPING_SIZE); |
decFormat.setDecimalSeparatorAlwaysShown(decSeparatorAlwaysShown); |
String res = decFormat.format(NumberUtils.divide(n, factor)); |
// java only puts the minus sign, OO also puts the plus sign |
if (minExpAttr != null) { |
// There's no way to force the plus sign in DecimalFormat |
if (forcedExpSign) { |
final Matcher m = EXP_PATTERN.matcher(res); |
if (m.find()) |
res = res.substring(0, m.start()) + "E+" + m.group(1); |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/CurrencyStyle.java |
---|
58,12 → 58,12 |
// ATTN OpenOffice Fix (it generates <text>-</text>, so we have to use the |
// absolute value) |
final int multiplier = n.doubleValue() > 0 ? 1 : -1; |
sb.append(formatNumberOrScientificNumber(elem, n, multiplier, defaultStyle)); |
sb.append(formatNumberOrScientificNumber(elem, n, multiplier, defaultStyle, lenient)); |
} else if (elem.getName().equals("currency-symbol")) { |
if (elem.getTextTrim().length() > 0) { |
sb.append(elem.getText()); |
} else { |
sb.append(new DecimalFormatSymbols(this.getLocale(elem)).getCurrencySymbol()); |
sb.append(new DecimalFormatSymbols(this.getLocale(elem, false)).getCurrencySymbol()); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/DateStyle.java |
---|
54,18 → 54,6 |
return !"long".equals(elem.getAttributeValue("style", elem.getNamespace("number"))); |
} |
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()); |
if (lang != null) { |
res = new Locale(lang, country == null ? "" : country); |
} else { |
res = null; |
} |
return res; |
} |
private static final Calendar getCalendar(final Element elem, Calendar defaultCal) { |
final Calendar res; |
final String cal = elem.getAttributeValue("calendar", elem.getNamespace()); |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/OD 1.3.fods |
---|
New file |
0,0 → 1,51 |
<?xml version="1.0" encoding="UTF-8"?> |
<office:document xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:ooo="http://openoffice.org/2004/office" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta: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:rpt="http://openoffice.org/2005/report" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.spreadsheet"> |
<office:styles> |
<style:default-style style:family="table-cell"> |
<style:paragraph-properties style:tab-stop-distance="1.25cm"/> |
<style:text-properties style:font-name="Liberation Sans" fo:language="fr" fo:country="FR" style:font-name-asian="Noto Sans CJK SC" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="FreeSans" style:language-complex="hi" style:country-complex="IN"/> |
</style:default-style> |
<number:number-style style:name="N108"> |
<number:number number:decimal-places="2" number:min-decimal-places="1" number:min-integer-digits="1" number:decimal-replacement="" number:grouping="true"/> |
</number:number-style> |
<style:style style:name="Default" style:family="table-cell"/> |
</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="2.258cm"/> |
</style:style> |
<style:style style:name="ro1" style:family="table-row"> |
<style:table-row-properties style:row-height="0.452cm" 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> |
<style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N108"/> |
</office:automatic-styles> |
<office:body> |
<office:spreadsheet> |
<table:calculation-settings table:automatic-find-labels="false" table:use-regular-expressions="false" table:use-wildcards="true"/> |
<table:table table:name="Feuille1" table:style-name="ta1"> |
<table:table-column table:style-name="co1" table:default-cell-style-name="ce1"/> |
<table:table-row table:style-name="ro1"> |
<table:table-cell office:value-type="float" office:value="1.236" calcext:value-type="float"> |
<text:p>1,24</text:p> |
</table:table-cell> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell office:value-type="float" office:value="1" calcext:value-type="float"> |
<text:p>1,0</text:p> |
</table:table-cell> |
</table:table-row> |
<table:table-row table:style-name="ro1" table:number-rows-repeated="1048571"> |
<table:table-cell/> |
</table:table-row> |
<table:table-row table:style-name="ro1"> |
<table:table-cell/> |
</table:table-row> |
</table:table> |
<table:named-expressions/> |
</office:spreadsheet> |
</office:body> |
</office:document> |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/TimeStyle.java |
---|
65,7 → 65,13 |
@Override |
public String format(Object o, CellStyle defaultStyle, boolean lenient) { |
final Duration d = o instanceof Calendar ? TimeUtils.timePartToDuration((Calendar) o) : (Duration) o; |
final Duration d; |
if (o instanceof Calendar) |
d = TimeUtils.timePartToDuration((Calendar) o); |
else if (o instanceof java.time.Duration) |
d = TimeUtils.getTypeFactory().newDurationDayTime(o.toString()); |
else |
d = (Duration) o; |
final Namespace numberNS = this.getElement().getNamespace(); |
final StringBuilder sb = new StringBuilder(); |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/style/data/PercentStyle.java |
---|
54,7 → 54,7 |
if (elem.getName().equals("text")) { |
sb.append(elem.getText()); |
} else if (elem.getName().equals("number")) { |
sb.append(formatNumberOrScientificNumber(elem, n, 100, defaultStyle)); |
sb.append(formatNumberOrScientificNumber(elem, n, 100, defaultStyle, lenient)); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/ODXMLDocument.java |
---|
17,6 → 17,7 |
package org.openconcerto.openoffice; |
import org.openconcerto.openoffice.ODPackage.RootElement; |
import org.openconcerto.utils.cache.LRUMap; |
import org.openconcerto.utils.cc.IFactory; |
import org.openconcerto.xml.JDOMUtils; |
import org.openconcerto.xml.Validator; |
26,7 → 27,6 |
import java.util.Collections; |
import java.util.HashMap; |
import java.util.Iterator; |
import java.util.LinkedHashMap; |
import java.util.List; |
import java.util.Map; |
import java.util.Set; |
113,13 → 113,8 |
this.content = content; |
this.version = version; |
this.childCreator = new ChildCreator(this.content.getRootElement(), ELEMS_ORDER.get(this.getVersion())); |
this.styleNamesLast = new LinkedHashMap<String, Integer>(4, 0.75f, true) { |
@Override |
protected boolean removeEldestEntry(java.util.Map.Entry<String, Integer> eldest) { |
return this.size() > 15; |
this.styleNamesLast = new LRUMap<>(15, 4); |
} |
}; |
} |
public ODXMLDocument(Document content) { |
this(content, XMLFormatVersion.get(content.getRootElement())); |
/trunk/OpenConcerto/src/org/openconcerto/openoffice/ODSingleXMLDocument.java |
---|
14,6 → 14,11 |
package org.openconcerto.openoffice; |
import static org.openconcerto.openoffice.ODPackage.RootElement.CONTENT; |
import static org.openconcerto.xml.Step.createAttributeStep; |
import static org.openconcerto.xml.Step.createAttributeStepFromQualifiedName; |
import static org.openconcerto.xml.Step.createElementStep; |
import static org.openconcerto.xml.Step.createElementStepFromQualifiedName; |
import org.openconcerto.openoffice.ODPackage.RootElement; |
import org.openconcerto.openoffice.style.data.DataStyle; |
import org.openconcerto.utils.Base64; |
28,6 → 33,7 |
import java.awt.Point; |
import java.io.File; |
import java.io.FileOutputStream; |
import java.io.IOException; |
import java.io.InputStream; |
import java.io.OutputStream; |
46,7 → 52,6 |
import java.util.Map.Entry; |
import java.util.Set; |
import org.apache.commons.collections.Transformer; |
import org.jdom.Attribute; |
import org.jdom.Content; |
import org.jdom.DocType; |
1042,12 → 1047,8 |
*/ |
protected final void detachDuplicate(Element elem) throws JDOMException { |
final String singularName = elem.getName().substring(0, elem.getName().length() - 1); |
final List thisNames = getXPath("./text:" + singularName + "s/text:" + singularName + "/@text:name").selectNodes(getChild("body")); |
org.apache.commons.collections.CollectionUtils.transform(thisNames, new Transformer() { |
public Object transform(Object obj) { |
return ((Attribute) obj).getValue(); |
} |
}); |
final SimpleXMLPath<Attribute> simplePath = SimpleXMLPath.create(createElementStep(singularName + "s", "text"), createElementStep(singularName, "text"), createAttributeStep("name", "text")); |
final List<String> thisNames = simplePath.selectValues(getChild("body")); |
final Iterator iter = elem.getChildren().iterator(); |
while (iter.hasNext()) { |
1202,24 → 1203,19 |
} |
private List<String> mergeUnique(ODXMLDocument doc, String topElem, String elemToMerge, String attrFQName, ElementTransformer addTransf) throws JDOMException { |
final Element other = doc.getChild(topElem); |
if (other == null) |
return Collections.emptyList(); |
List<String> added = new ArrayList<String>(); |
Element thisParent = this.getChild(topElem, true); |
XPath xp = this.getXPath("./" + elemToMerge + "/@" + attrFQName); |
final SimpleXMLPath<Attribute> simplePath = SimpleXMLPath.create(createElementStepFromQualifiedName(elemToMerge), createAttributeStepFromQualifiedName(attrFQName)); |
// les styles de ce document |
List thisElemNames = xp.selectNodes(thisParent); |
// on transforme la liste d'attributs en liste de String |
org.apache.commons.collections.CollectionUtils.transform(thisElemNames, new Transformer() { |
public Object transform(Object obj) { |
return ((Attribute) obj).getValue(); |
} |
}); |
final List<String> thisElemNames = simplePath.selectValues(thisParent); |
// pour chaque style de l'autre document |
Iterator otherElemNames = xp.selectNodes(doc.getChild(topElem)).iterator(); |
while (otherElemNames.hasNext()) { |
Attribute attr = (Attribute) otherElemNames.next(); |
for (final Attribute attr : simplePath.selectNodes(other)) { |
// on l'ajoute si non déjà dedans |
if (!thisElemNames.contains(attr.getValue())) { |
thisParent.addContent(addTransf.transform((Element) attr.getParent().clone())); |
1409,7 → 1405,7 |
throw new IllegalStateException("Cannot convert to binary data element : " + hrefParent); |
final Element binaryData = new Element("binary-data", getPackage().getVersion().getOFFICE()); |
binaryData.setText(Base64.encodeBytes(getPackage().getBinaryFile(href))); |
binaryData.setText(Base64.encodeBytesBreakLines(getPackage().getBinaryFile(href))); |
hrefParent.addContent(binaryData); |
// If this element is present, an xlink:href attribute in its parent element |
// shall be ignored. But LO doesn't respect that |
1418,7 → 1414,11 |
} |
final File f = this.getPackage().getContentType().addExt(fNoExt, true); |
FileUtils.write(ODPackage.createOutputter().outputString(doc), f); |
try (final FileOutputStream outs = new FileOutputStream(f)) { |
// Use OutputStream parameter so that the encoding used for the Writer matches the |
// XML declaration. |
ODPackage.createOutputter().output(doc, outs); |
} |
return f; |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/component/InteractionMode.java |
---|
76,6 → 76,10 |
return comp; |
} |
public final InteractionMode and(InteractionMode m) { |
return from(this.isEnabled() && m.isEnabled(), this.isEditable() && m.isEditable()); |
} |
/** |
* Try to infer the mode of the passed component. This method has special cases for known |
* component (.e.g {@link JTextComponent}) otherwise generic components are presumed to not have |
/trunk/OpenConcerto/src/org/openconcerto/ui/WindowUtils.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.ui; |
import org.openconcerto.utils.Platform; |
import java.awt.Toolkit; |
import java.lang.reflect.Field; |
import java.util.Objects; |
import java.util.function.Supplier; |
public class WindowUtils { |
private WindowUtils() { |
} |
/** |
* Allow to set WM_CLASS for X11 windows. |
* |
* @param nameSupplier which name to use. |
* @param pidSuffix <code>true</code> if the name should be suffixed by the PID of the VM. That |
* way, there is one group of windows per launch. |
*/ |
static public void setWMClass(final Supplier<String> nameSupplier, final boolean pidSuffix) { |
// Set WM_CLASS to have a meaningful name and avoid grouping together all windows of all VMs |
final Class<?> xtoolkit = Toolkit.getDefaultToolkit().getClass(); |
// https://bugs.openjdk.java.net/browse/JDK-6528430 |
// need system property to override default WM_CLASS |
// #183739 - provide proper app name on Linux |
// org/netbeans/core/windows/view/ui/MainWindow.java |
if (xtoolkit.getName().equals("sun.awt.X11.XToolkit")) { |
try { |
final Field awtAppClassName = xtoolkit.getDeclaredField("awtAppClassName"); |
awtAppClassName.setAccessible(true); |
String pid = null; |
// use PID to have one group of windows per launch |
if (pidSuffix) { |
try { |
final Platform p = Platform.getInstance(); |
if (p.supportsPID()) |
pid = p.getPID(); |
} catch (Exception e1) { |
e1.printStackTrace(); |
} |
} |
final String suppliedName = Objects.requireNonNull(nameSupplier.get(), "Null name").trim(); |
if (suppliedName.isEmpty()) |
throw new IllegalArgumentException("Empty name"); |
final String name = suppliedName + (pid == null ? "" : " [" + pid + "]"); |
awtAppClassName.set(null, name); |
} catch (Exception x) { |
x.printStackTrace(); |
} |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/DefaultGridBagConstraints.java |
---|
13,11 → 13,11 |
package org.openconcerto.ui; |
import java.awt.Component; |
import java.awt.Dimension; |
import java.awt.GridBagConstraints; |
import java.awt.Insets; |
import javax.swing.JComponent; |
import javax.swing.UIManager; |
public class DefaultGridBagConstraints extends GridBagConstraints { |
43,11 → 43,11 |
return new Insets(2, 3, 2, 2); |
} |
public static void lockMinimumSize(JComponent c) { |
public static void lockMinimumSize(Component c) { |
c.setMinimumSize(new Dimension(c.getPreferredSize())); |
} |
public static void lockMaximumSize(JComponent c) { |
public static void lockMaximumSize(Component c) { |
c.setMaximumSize(new Dimension(c.getPreferredSize())); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/WrapLayout.java |
---|
New file |
0,0 → 1,184 |
/* |
* 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.Component; |
import java.awt.Container; |
import java.awt.Dimension; |
import java.awt.FlowLayout; |
import java.awt.Insets; |
import javax.swing.JScrollPane; |
import javax.swing.SwingUtilities; |
/** |
* FlowLayout subclass that fully supports wrapping of components. |
*/ |
public class WrapLayout extends FlowLayout { |
/** |
* Constructs a new <code>WrapLayout</code> with a left alignment and a default 5-unit |
* horizontal and vertical gap. |
*/ |
public WrapLayout() { |
super(FlowLayout.LEFT); |
} |
/** |
* Constructs a new <code>FlowLayout</code> with the specified alignment and a default 5-unit |
* horizontal and vertical gap. The value of the alignment argument must be one of |
* <code>WrapLayout</code>, <code>WrapLayout</code>, or <code>WrapLayout</code>. |
* |
* @param align the alignment value |
*/ |
public WrapLayout(int align) { |
super(align); |
} |
/** |
* Creates a new flow layout manager with the indicated alignment and the indicated horizontal |
* and vertical gaps. |
* <p> |
* The value of the alignment argument must be one of <code>WrapLayout</code>, |
* <code>WrapLayout</code>, or <code>WrapLayout</code>. |
* |
* @param align the alignment value |
* @param hgap the horizontal gap between components |
* @param vgap the vertical gap between components |
*/ |
public WrapLayout(int align, int hgap, int vgap) { |
super(align, hgap, vgap); |
} |
/** |
* Returns the preferred dimensions for this layout given the <i>visible</i> components in the |
* specified target container. |
* |
* @param target the component which needs to be laid out |
* @return the preferred dimensions to lay out the subcomponents of the specified container |
*/ |
@Override |
public Dimension preferredLayoutSize(Container target) { |
return layoutSize(target, true); |
} |
/** |
* Returns the minimum dimensions needed to layout the <i>visible</i> components contained in |
* the specified target container. |
* |
* @param target the component which needs to be laid out |
* @return the minimum dimensions to lay out the subcomponents of the specified container |
*/ |
@Override |
public Dimension minimumLayoutSize(Container target) { |
Dimension minimum = layoutSize(target, false); |
minimum.width -= (getHgap() + 1); |
return minimum; |
} |
/** |
* Returns the minimum or preferred dimension needed to layout the target container. |
* |
* @param target target to get layout size for |
* @param preferred should preferred size be calculated |
* @return the dimension to layout the target container |
*/ |
private Dimension layoutSize(Container target, boolean preferred) { |
synchronized (target.getTreeLock()) { |
// Each row must fit with the width allocated to the containter. |
// When the container width = 0, the preferred width of the container |
// has not yet been calculated so lets ask for the maximum. |
Container container = target; |
while (container.getSize().width == 0 && container.getParent() != null) { |
container = container.getParent(); |
} |
int targetWidth = container.getSize().width; |
if (targetWidth == 0) { |
targetWidth = Integer.MAX_VALUE; |
} |
int hgap = getHgap(); |
int vgap = getVgap(); |
Insets insets = target.getInsets(); |
int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2); |
int maxWidth = targetWidth - horizontalInsetsAndGap; |
// Fit components into the allowed width |
Dimension dim = new Dimension(0, 0); |
int rowWidth = 0; |
int rowHeight = 0; |
final int nmembers = target.getComponentCount(); |
for (int i = 0; i < nmembers; i++) { |
Component m = target.getComponent(i); |
if (m.isVisible()) { |
Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize(); |
// Can't add the component to current row. Start a new row. |
if (rowWidth + d.width > maxWidth) { |
addRow(dim, rowWidth, rowHeight); |
rowWidth = 0; |
rowHeight = 0; |
} |
// Add a horizontal gap for all components after the first |
if (rowWidth != 0) { |
rowWidth += hgap; |
} |
rowWidth += d.width; |
rowHeight = Math.max(rowHeight, d.height); |
} |
} |
addRow(dim, rowWidth, rowHeight); |
dim.width += horizontalInsetsAndGap; |
dim.height += insets.top + insets.bottom + vgap * 2; |
// When using a scroll pane or the DecoratedLookAndFeel we need to |
// make sure the preferred size is less than the size of the |
// target containter so shrinking the container size works |
// correctly. Removing the horizontal gap is an easy way to do this. |
final Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target); |
if (scrollPane != null && target.isValid()) { |
dim.width -= (hgap + 1); |
} |
return dim; |
} |
} |
/* |
* A new row has been completed. Use the dimensions of this row to update the preferred size for |
* the container. |
* |
* @param dim update the width and height when appropriate |
* |
* @param rowWidth the width of the row to add |
* |
* @param rowHeight the height of the row to add |
*/ |
private void addRow(Dimension dim, int rowWidth, int rowHeight) { |
dim.width = Math.max(dim.width, rowWidth); |
if (dim.height > 0) { |
dim.height += getVgap(); |
} |
dim.height += rowHeight; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUITable.java |
---|
517,7 → 517,7 |
if (this.hasRow()) { |
final int size = this.getRowsCount(); |
if (jsonContext.size() != size) { |
System.err.println("LightUITable.setValueFromContext() - Incorrect line count in JSON"); |
throw new IllegalStateException("LightUITable.setValueFromContext() - Incorrect line count in JSON, row count:" + size + " context:" + jsonContext.size() + " (" + value + ")"); |
} else { |
for (int i = 0; i < size; i++) { |
/trunk/OpenConcerto/src/org/openconcerto/ui/FormLayouter.java |
---|
146,9 → 146,9 |
} |
/** |
* Ajout un composant sur une ligne Si comp est null, un titre est créé. |
* Ajout un composant sur une ligne. |
* |
* @param desc le label du champ. |
* @param desc le label du champ, <code>null</code> if <code>comp</<code> should use its area. |
* @param comp le composant graphique d'edition. |
* @param w la largeur, entre 1 et la largeur de ce layout, ou 0 pour toute la largeur. |
* @return the created label. |
158,11 → 158,20 |
public JLabel add(String desc, Component comp, int w) { |
w = this.checkArgs(comp, w); |
final int realWidth = this.getRealFieldWidth(w); |
int realWidth = this.getRealFieldWidth(w); |
final JLabel lab; |
final int fieldX; |
if (desc == null) { |
lab = null; |
fieldX = this.getLabelX(); |
realWidth += this.getFieldX() - fieldX; |
} else { |
lab = new JLabel(desc); |
// Guillaume : right alignment like the Mac |
final JLabel lab = new JLabel(desc); |
this.co.add(lab, this.constraints.xy(this.getLabelX(), this.getY(), CellConstraints.RIGHT, this.getRowAlign())); |
this.co.add(comp, this.constraints.xyw(this.getFieldX(), this.getY(), realWidth, CellConstraints.DEFAULT, this.getRowAlign())); |
fieldX = this.getFieldX(); |
} |
this.co.add(comp, this.constraints.xyw(fieldX, this.getY(), realWidth, CellConstraints.DEFAULT, this.getRowAlign())); |
this.x += w; |
return lab; |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/group/LayoutHints.java |
---|
17,7 → 17,7 |
@Immutable |
public class LayoutHints { |
private final boolean visible; |
private boolean visible; |
private final boolean largeWidth; |
private final boolean largeHeight; |
private boolean foldable = false; |
39,6 → 39,7 |
public static final LayoutHints DEFAULT_GROUP_HINTS = new LayoutHints(true, false, false, false, true, true); |
public static final LayoutHints DEFAULT_SEPARATED_GROUP_HINTS = new LayoutHints(true, false, true, true, true, true); |
public static final LayoutHints DEFAULT_NOLABEL_SEPARATED_GROUP_HINTS = new LayoutHints(true, false, false, true, true, true); |
public static final LayoutHints DEFAULT_SEPARATED_VERY_LARGE_HINTS = new LayoutHints(false, false, true, true, true, false, false, true); |
public LayoutHints(boolean largeWidth, boolean largeHeight, boolean showLabel) { |
this(largeWidth, largeHeight, showLabel, false, false, false); |
157,9 → 158,13 |
} |
public boolean isVisible() { |
return visible; |
return this.visible; |
} |
public void setVisible(boolean b) { |
this.visible = b; |
} |
@Override |
public int hashCode() { |
final int prime = 31; |
187,4 → 192,5 |
return this.fillHeight == other.fillHeight && this.fillWidth == other.fillWidth && this.largeHeight == other.largeHeight && this.largeWidth == other.largeWidth |
&& this.separated == other.separated && this.showLabel == other.showLabel && this.split == other.split && this.visible == other.visible; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/group/Group.java |
---|
21,6 → 21,11 |
import java.util.Comparator; |
import java.util.List; |
/** |
* Allow to customize UI layout. |
* |
* @author guillaume |
*/ |
public class Group extends Item { |
public static Group copy(final Group g, final Group newParent) { |
63,11 → 68,33 |
} |
} |
public final Group toImmutable() { |
return this.toImmutable(true); |
} |
public final Group toImmutable(final boolean onlyDesc) { |
if (this.isFrozen()) |
return this; |
final Group res; |
if (onlyDesc) { |
res = copy(this, null); |
res.freeze(); |
} else { |
final List<String> p = this.getAbsolutePath(); |
final Group copy = copy(this.getRoot(), null); |
copy.freeze(); |
res = copy.followPath(p, false); |
} |
assert res.isFrozen(); |
return res; |
} |
@Override |
public synchronized void freeze() { |
super.freeze(); |
protected synchronized void _freeze() { |
super._freeze(); |
for (final Tuple2<Item, Integer> child : this.list) { |
child.get0().freeze(); |
child.get0()._freeze(); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/ui/group/Item.java |
---|
15,6 → 15,10 |
import java.util.Collection; |
import java.util.Collections; |
import java.util.LinkedList; |
import java.util.List; |
import java.util.concurrent.atomic.AtomicReference; |
import java.util.function.Consumer; |
import net.jcip.annotations.GuardedBy; |
66,7 → 70,13 |
throw new IllegalStateException("Frozen cannot " + op); |
} |
public synchronized void freeze() { |
public synchronized final void freeze() { |
if (this.getParent() != null) |
throw new IllegalStateException("Can only freeze from the root down"); |
this._freeze(); |
} |
protected synchronized void _freeze() { |
this.frozen = true; |
} |
113,14 → 123,26 |
this.localHint = new LayoutHints(localHint == null ? LayoutHints.DEFAULT_FIELD_HINTS : localHint); |
} |
public final Group getRoot() { |
public final void applyUntilRoot(final Consumer<Item> cons) { |
Item current = this; |
while (current.getParent() != null) { |
while (current != null) { |
cons.accept(current); |
current = current.getParent(); |
} |
return current instanceof Group ? (Group) current : null; |
} |
public final List<String> getAbsolutePath() { |
final LinkedList<String> res = new LinkedList<>(); |
this.applyUntilRoot((item) -> res.addFirst(item.getId())); |
return res; |
} |
public final Group getRoot() { |
final AtomicReference<Item> current = new AtomicReference<>(); |
this.applyUntilRoot((item) -> current.set(item)); |
return current.get() instanceof Group ? (Group) current.get() : null; |
} |
protected void printTree(final StringBuilder builder, final int localOrder, final int level) { |
for (int i = 0; i < level - 1; i++) { |
builder.append(" "); |
/trunk/OpenConcerto/src/org/openconcerto/odtemplate/TemplateGenerator.java |
---|
80,7 → 80,9 |
try { |
this.transform(pkg.toSingle()); |
// MAYBE fireStatusChange with the number of tag done out of the total |
return new Template(pkg).createDocument(new OGNLDataModel(data)); |
try (final Template template = new Template(pkg)) { |
return template.createDocument(new OGNLDataModel(data)); |
} |
} catch (Exception exn) { |
throw ExceptionUtils.createExn(IOException.class, "generation error in " + this, exn); |
} |
/trunk/OpenConcerto/src/org/openconcerto/odtemplate/engine/Parsed.java |
---|
114,4 → 114,9 |
} |
return new Processor<E>(this, data).process().getWhole(); |
} |
public void destroy() { |
for (final Statement st : this.statements.values()) |
st.destroy(); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/odtemplate/statements/Include.java |
---|
36,7 → 36,10 |
private static final String PREFIX = "[IOD"; |
// Cache whole file to avoid disk access since there can be a lot of sections in a single file |
private final ICache<File, ODSingleXMLDocument, File> cache; |
// Cache the Parsed of just one section in the above file |
// { filePath#sectionName -> Parsed } |
private final ICache<String, Parsed<ODSingleXMLDocument>, File> parsedCache; |
public Include() { |
45,6 → 48,13 |
this.parsedCache = new ICache<String, Parsed<ODSingleXMLDocument>, File>(180); |
} |
@Override |
public void destroy() { |
this.cache.getSupp().die(); |
this.parsedCache.getSupp().die(); |
super.destroy(); |
} |
public boolean matches(Element elem) { |
if (!elem.getQualifiedName().equals("text:a")) |
return false; |
129,9 → 139,10 |
private Parsed<ODSingleXMLDocument> createParsed(final File ref, final String sectionName, final Parsed<?> parsed) throws JDOMException, IOException, TemplateException { |
final ODSingleXMLDocument docToAdd = getXMLDocument(ref).clone(); |
// replace the body with just sectionName |
final XPath sectionXP = docToAdd.getXPath("//text:section[@text:name = '" + sectionName + "']"); |
final Element section = (Element) sectionXP.selectSingleNode(docToAdd.getDocument()); |
// ajouter la section car souvent des if s'y réfèrent. |
// ajouter la section elle-même car souvent des if s'y réfèrent. |
docToAdd.getBody().setContent(section.detach()); |
final Material<ODSingleXMLDocument> from = Material.from(docToAdd); |
/trunk/OpenConcerto/src/org/openconcerto/odtemplate/statements/Statement.java |
---|
72,6 → 72,9 |
*/ |
public abstract void execute(Processor<?> processor, Element elem, DataModel model) throws TemplateException; |
public void destroy() { |
} |
@Override |
public String toString() { |
return this.getClass().getSimpleName() + " " + this.getName(); |
/trunk/OpenConcerto/src/org/openconcerto/odtemplate/Template.java |
---|
37,7 → 37,7 |
* template.createDocument(vars, new FileOutputStream("document.sxw")); |
* </pre> |
*/ |
public class Template { |
public class Template implements AutoCloseable { |
protected final Parsed<ODPackage> contentTemplate; |
62,6 → 62,11 |
this.contentTemplate = new Parsed<ODPackage>(Material.from(contents)); |
} |
@Override |
public void close() throws Exception { |
this.contentTemplate.destroy(); |
} |
/** |
* Generates a document merging template and data. |
* |
/trunk/OpenConcerto/src/org/openconcerto/sql/request/RSTransformer.java |
---|
File deleted |
/trunk/OpenConcerto/src/org/openconcerto/sql/element/SQLElement.java |
---|
56,6 → 56,7 |
import org.openconcerto.sql.request.ListSQLRequest; |
import org.openconcerto.sql.request.SQLCache; |
import org.openconcerto.sql.request.SQLFieldTranslator; |
import org.openconcerto.sql.sqlobject.SQLRequestComboBox; |
import org.openconcerto.sql.sqlobject.SQLTextCombo; |
import org.openconcerto.sql.ui.light.CustomRowEditor; |
import org.openconcerto.sql.ui.light.GroupToLightUIConvertor; |
127,6 → 128,7 |
import java.util.SortedMap; |
import java.util.concurrent.atomic.AtomicReference; |
import java.util.logging.Level; |
import java.util.function.Supplier; |
import javax.swing.JComponent; |
import javax.swing.JOptionPane; |
202,7 → 204,7 |
@GuardedBy("this") |
private SQLCache<SQLRow, Object> modelCache; |
private final Map<String, JComponent> additionalFields; |
private final Map<String, Supplier<? extends JComponent>> additionalFields; |
private final List<SQLTableModelColumn> additionalListCols; |
@GuardedBy("this") |
private List<String> mdPath; |
242,7 → 244,7 |
this.modelCache = null; |
// the components should always be in the same order |
this.additionalFields = new LinkedHashMap<String, JComponent>(); |
this.additionalFields = new LinkedHashMap<>(); |
this.additionalListCols = new ArrayList<SQLTableModelColumn>(); |
this.mdPath = Collections.emptyList(); |
} |
3014,19 → 3016,23 |
* @return <code>true</code> if no view existed. |
*/ |
public final boolean putAdditionalField(final String field) { |
return this.putAdditionalField(field, (JComponent) null); |
return this.putAdditionalField(field, null); |
} |
public final boolean putAdditionalField(final String field, final JTextComponent comp) { |
return this.putAdditionalField(field, (JComponent) comp); |
public final boolean putAdditionalTextField(final String field, final Supplier<? extends JTextComponent> comp) { |
return this.putAdditionalField(field, comp); |
} |
public final boolean putAdditionalField(final String field, final SQLTextCombo comp) { |
return this.putAdditionalField(field, (JComponent) comp); |
public final boolean putAdditionalTextCombo(final String field, final Supplier<? extends SQLTextCombo> comp) { |
return this.putAdditionalField(field, comp); |
} |
public final boolean putAdditionalCombo(final String field, final Supplier<? extends SQLRequestComboBox> comp) { |
return this.putAdditionalField(field, comp); |
} |
// private as only a few JComponent are OK |
private final boolean putAdditionalField(final String field, final JComponent comp) { |
private final boolean putAdditionalField(final String field, final Supplier<? extends JComponent> comp) { |
if (this.additionalFields.containsKey(field)) { |
return false; |
} else { |
3035,7 → 3041,7 |
} |
} |
public final Map<String, JComponent> getAdditionalFields() { |
public final Map<String, Supplier<? extends JComponent>> getAdditionalFields() { |
return Collections.unmodifiableMap(this.additionalFields); |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/element/BaseSQLComponent.java |
---|
84,6 → 84,7 |
import java.util.Map; |
import java.util.Map.Entry; |
import java.util.Set; |
import java.util.function.Supplier; |
import javax.swing.JCheckBox; |
import javax.swing.JComponent; |
429,11 → 430,11 |
|| (this.getMode() != Mode.INSERTION && CollectionUtils.containsAny(this.getElement().getInsertOnlyFields(), fieldsNames)); |
} |
@Override |
protected final void inited() { |
super.inited(); |
if (!(this instanceof GroupSQLComponent)) { |
for (final Entry<String, JComponent> e : this.getElement().getAdditionalFields().entrySet()) { |
for (final Entry<String, Supplier<? extends JComponent>> e : this.getElement().getAdditionalFields().entrySet()) { |
final SpecParser spec; |
// FIXME Required à spécifier directement depuis le module |
if (this.requiredNames != null && this.requiredNames.contains(e.getKey())) { |
441,14 → 442,16 |
} else { |
spec = new SpecParser(null, true); |
} |
final JComponent comp = e.getValue(); |
if (comp == null) |
final Supplier<? extends JComponent> comp = e.getValue(); |
if (comp == null) { |
// infer component |
this.addViewJComponent(e.getKey(), spec); |
else |
this.addView(comp, e.getKey(), spec); |
} else { |
// create component |
this.addView(comp.get(), e.getKey(), spec); |
} |
} |
} |
// assure that added views are consistent with our editable status |
this.updateChildrenEditable(); |
for (final SQLRowItemView v : this.getRequest().getViews()) { |
/trunk/OpenConcerto/src/org/openconcerto/sql/element/SQLElementDirectory.java |
---|
195,15 → 195,17 |
} |
/** |
* Search for an SQLElement whose class is <code>clazz</code>. |
* Search for an SQLElement which is an {@link Class#isInstance(Object) instance of} |
* <code>clazz</code>. |
* |
* @param <S> type of SQLElement |
* @param clazz the class. |
* @return the corresponding SQLElement, or <code>null</code> if none can be found. |
* @throws IllegalArgumentException if there's more than one match. |
* @see #getElementsOfClass(Class, boolean) |
*/ |
public final <S extends SQLElement> S getElement(Class<S> clazz) { |
return this.getElementOfClass(clazz, false); |
return this.getElementOfClass(clazz, true); |
} |
public final <S extends SQLElement> S getElementOfClass(Class<S> clazz, final boolean allowSubclass) { |
/trunk/OpenConcerto/src/org/openconcerto/sql/element/GroupSQLComponent.java |
---|
168,8 → 168,7 |
} |
if (this.hasAdditionnalFields) { |
if ((currentGroup == this.group && this.additionnalFieldsGroup == null) || (currentGroup == this.additionnalFieldsGroup)) { |
final Map<String, JComponent> additionalFields = this.getElement().getAdditionalFields(); |
for (String field : additionalFields.keySet()) { |
for (String field : this.getElement().getAdditionalFields().keySet()) { |
Item item = new Item(field, new LayoutHints(false, false, true, false, true, false)); |
int fill = c.fill; |
double weightx = c.weightx; |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLInjector.java |
---|
169,6 → 169,24 |
rowVals.put(field.getName(), value); |
} |
private String cleanRef(String value) { |
List<String> l = StringUtils.fastSplit(value, ','); |
Set<String> s = new HashSet<>(l); |
String nom = ""; |
if (s.size() > 1) { |
Set<String> refAdded = new HashSet<>(); |
for (String string : s) { |
if (string.trim().length() > 0 && !refAdded.contains(string.trim())) { |
nom += string + ","; |
refAdded.add(string.trim()); |
} |
} |
} else if (s.size() == 1) { |
nom = s.iterator().next(); |
} |
return nom; |
} |
protected void transfertReference(SQLRowAccessor srcRow, SQLRowValues rowVals, final SQLTable tableElementDestination, String refField, String from, String to) { |
String label = rowVals.getString(to); |
176,7 → 194,7 |
if (prefs.getBoolean("TransfertRef", true) || !to.equals("NOM")) { |
if (label != null && label.trim().length() > 0) { |
rowVals.put(to, label + ", " + srcRow.getString(from)); |
rowVals.put(to, cleanRef(label + ", " + srcRow.getString(from))); |
} else { |
rowVals.put(to, srcRow.getString(from)); |
} |
198,17 → 216,7 |
String label = rowVals.getString("NOM"); |
if (label != null && label.trim().length() > 0) { |
final String value = label + ", " + srcRow.getString("NUMERO"); |
List<String> l = StringUtils.fastSplit(value, ','); |
Set<String> s = new HashSet<>(l); |
String nom = ""; |
if (s.size() > 1) { |
for (String string : s) { |
nom += string + ","; |
} |
} else if (s.size() == 1) { |
nom = s.iterator().next(); |
} |
rowVals.put("NOM", nom); |
rowVals.put("NOM", cleanRef(value)); |
} else { |
rowVals.put("NOM", srcRow.getString("NUMERO")); |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLSyntaxMS.java |
---|
23,7 → 23,6 |
import org.openconcerto.utils.FileUtils; |
import org.openconcerto.utils.ListMap; |
import org.openconcerto.utils.ProcessStreams; |
import org.openconcerto.utils.ProcessStreams.Action; |
import org.openconcerto.utils.RTInterruptedException; |
import org.openconcerto.utils.StringUtils; |
import org.openconcerto.utils.Tuple2; |
395,8 → 394,7 |
pb.command().add("-E"); |
} |
final Process p = pb.start(); |
ProcessStreams.handle(p, Action.REDIRECT); |
final Process p = ProcessStreams.redirect(pb).start(); |
try { |
final int returnCode = p.waitFor(); |
if (returnCode != 0) |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLSyntax.java |
---|
673,8 → 673,8 |
/** |
* Get the default clause. |
* |
* @param def the default, e.g. "0". |
* @return the default clause, e.g. "DEFAULT 0". |
* @param def the default, e.g. "0" or <code>null</code>. |
* @return the default clause, e.g. " DEFAULT 0" or " ". |
*/ |
public final String getDefaultClause(final String def) { |
if (def == null) |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLResultSet.java |
---|
13,6 → 13,8 |
package org.openconcerto.sql.model; |
import org.openconcerto.utils.cc.CachedTransformer; |
import java.io.InputStream; |
import java.io.Reader; |
import java.math.BigDecimal; |
36,9 → 38,6 |
import java.util.HashMap; |
import java.util.Map; |
import org.apache.commons.collections.Transformer; |
import org.apache.commons.collections.map.LazyMap; |
/** |
* A resultSet that wraps onto another one, caching name to index translation, and using a |
* ResultSetFullnameHelper. |
120,23 → 119,14 |
private final ResultSet delegate; |
private final ResultSetFullnameHelper helper; |
private final Map indexes; |
private final CachedTransformer<String, Integer, SQLException> indexes; |
private int rowProcessedCount; |
public SQLResultSet(ResultSet delegate) { |
this.delegate = delegate; |
this.helper = new ResultSetFullnameHelper(this); |
this.indexes = LazyMap.decorate(new HashMap(), new Transformer() { |
public Object transform(Object input) { |
final String colName = (String) input; |
try { |
return new Integer(doFindColumn(colName)); |
} catch (SQLException e) { |
return e; |
this.indexes = new CachedTransformer<>(new HashMap<>(), this::doFindColumn); |
} |
} |
}); |
} |
private ResultSet getDelegate() { |
return this.delegate; |
171,17 → 161,12 |
} |
public int findColumn(String columnName) throws SQLException { |
final Object res = this.indexes.get(columnName); |
if (res instanceof SQLException) |
throw (SQLException) res; |
else { |
final int index = ((Number) res).intValue(); |
final int index = this.indexes.get(columnName).intValue(); |
if (index < 1) |
throw new SQLException(columnName + " not found"); |
else |
return index; |
} |
} |
private int doFindColumn(String columnName) throws SQLException { |
try { |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLRowMode.java |
---|
14,11 → 14,7 |
package org.openconcerto.sql.model; |
import org.openconcerto.sql.model.SQLSelect.ArchiveMode; |
import org.openconcerto.utils.CollectionUtils; |
import org.openconcerto.utils.cc.IPredicate; |
import java.util.Collection; |
/** |
* Allow to specify which rows we're interested in. |
* |
92,14 → 88,4 |
public SQLRow filter(SQLRow r) { |
return this.check(r) ? r : null; |
} |
public void filter(Collection<SQLRow> rows) { |
CollectionUtils.filter(rows, new IPredicate<SQLRow>() { |
@Override |
public boolean evaluateChecked(SQLRow r) { |
return check(r); |
} |
}); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/model/ResultSetFullnameHelper.java |
---|
19,9 → 19,6 |
import java.util.HashMap; |
import java.util.Map; |
import org.apache.commons.collections.Factory; |
import org.apache.commons.collections.map.LazyMap; |
/** |
* A class to help find fields by their fullname in resultset. Some jdbc drivers only accept the |
* short name of fields, eg you execute "select B.DESIGNATION from BATIMENT B" but you can only |
33,15 → 30,11 |
public final class ResultSetFullnameHelper { |
private final ResultSet delegate; |
private ResultSetMetaData rsMD; |
private final Map tablesMap; |
private final Map<String, Map<String, Integer>> tablesMap; |
public ResultSetFullnameHelper(ResultSet rs) { |
this.delegate = rs; |
this.tablesMap = LazyMap.decorate(new HashMap(), new Factory() { |
public Object create() { |
return new HashMap(); |
} |
}); |
this.tablesMap = new HashMap<>(); |
this.rsMD = null; |
} |
74,12 → 67,12 |
* @throws SQLException if an error occur while retrieving metadata. |
*/ |
public final int getIndex(String tableName, String fieldName) throws SQLException { |
final Map m = (Map) this.tablesMap.get(tableName); |
final Map<String, Integer> m = this.tablesMap.computeIfAbsent(tableName, (k) -> new HashMap<>()); |
if (!m.containsKey(fieldName)) { |
final int index = this.searchIndex(tableName, fieldName); |
m.put(fieldName, index < 1 ? null : new Integer(index)); |
} |
final Integer val = (Integer) m.get(fieldName); |
final Integer val = m.get(fieldName); |
return val == null ? -1 : val.intValue(); |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/changer/correct/FixSharedPrivate.java |
---|
25,6 → 25,7 |
import org.openconcerto.sql.model.SQLRowValuesListFetcher; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.SQLSelect.ArchiveMode; |
import org.openconcerto.sql.model.SQLSystem; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.model.graph.Path; |
34,6 → 35,7 |
import org.openconcerto.utils.cc.ITransformer; |
import java.sql.SQLException; |
import java.util.EnumSet; |
import java.util.List; |
/** |
70,6 → 72,14 |
} |
@Override |
protected EnumSet<SQLSystem> getCompatibleSystems() { |
// When executing deleteReq : |
// - if PRIVATE_REFS is temporary : "Can't reopen table" |
// - if not : "You can't specify target table 'PRIVATE_REFS' for update in FROM clause" |
return EnumSet.complementOf(EnumSet.of(SQLSystem.MYSQL)); |
} |
@Override |
protected void changeImpl(final SQLTable t) throws SQLException { |
getStream().print(t); |
final SQLElement elem = this.getDir().getElement(t); |
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/RowValuesTableModel.java |
---|
153,6 → 153,10 |
this.list.add(e); |
} |
public void setValidationField(SQLField validationField) { |
this.validationField = validationField; |
} |
public synchronized int getColumnCount() { |
return this.nbColumn; |
} |
/trunk/OpenConcerto/src/org/openconcerto/sql/sqlobject/ITextArticleWithCompletion.java |
---|
16,6 → 16,8 |
import org.openconcerto.sql.model.SQLField; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.SQLRowValuesListFetcher; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.model.Where; |
357,13 → 359,42 |
MultipleSQLSelectExecutor mult = new MultipleSQLSelectExecutor(this.tableArticle.getDBSystemRoot(), listSel); |
List<List<SQLRow>> resultList = mult.execute(); |
List<List<? extends SQLRowAccessor>> resultList = new ArrayList<>(); |
resultList.addAll(mult.execute()); |
for (List<SQLRow> list : resultList) { |
// Recherche dans les codes fournisseurs |
SQLTable tableCodeArt = this.tableArticle.getDBRoot().getTable("CODE_FOURNISSEUR"); |
SQLRowValues rowValsCodeF = new SQLRowValues(tableCodeArt); |
rowValsCodeF.putNulls("CODE"); |
rowValsCodeF.putRowValues("ID_ARTICLE").putNulls(this.tableArticle.getFieldsName()); |
for (SQLRow sqlRow : list) { |
final String codeText = aText; |
SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowValsCodeF); |
fetcher.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() { |
@Override |
public SQLSelect transformChecked(SQLSelect input) { |
Where wCodeFContains = new Where(tableCodeArt.getField("CODE"), "LIKE", "%" + codeText + "%"); |
input.setWhere(wCodeFContains); |
input.setLimit(SQL_RESULT_LIMIT); |
return input; |
} |
}); |
List<SQLRowValues> resultCodeF = fetcher.fetch(); |
resultList.add(2, resultCodeF); |
for (List<? extends SQLRowAccessor> list : resultList) { |
for (SQLRowAccessor sqlRow : list) { |
StringBuffer buf = new StringBuffer(); |
if (sqlRow.getTable().getName().equals("CODE_FOURNISSEUR")) { |
SQLRowAccessor rArt = sqlRow.getForeign("ID_ARTICLE"); |
buf.append(sqlRow.getString("CODE") + " -- "); |
buf.append(rArt.getString("CODE") + " -- "); |
buf.append(rArt.getString("NOM")); |
result.add(new IComboSelectionItem(rArt, buf.toString())); |
} else { |
if (sqlRow.getString("CODE_BARRE") != null && sqlRow.getString("CODE_BARRE").trim().length() > 0) { |
buf.append(sqlRow.getString("CODE_BARRE") + " -- "); |
} |
372,6 → 403,7 |
result.add(new IComboSelectionItem(sqlRow, buf.toString())); |
} |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/sync/SimpleSyncClient.java |
---|
204,8 → 204,12 |
} |
public DirContent getDir(final String path) throws Exception { |
if (path == null) { |
throw new IllegalArgumentException("null path"); |
} |
final HttpsURLConnection con = openConnection("/getDir"); |
final Response res = checkResponseCode(send(con, NetUtils.urlEncode("rp", path, "type", "json"))); |
final Response res = checkResponseCode(send(con, NetUtils.urlEncode("rp", path, "type", "json"), false)); |
if (!res.isSuccess()) |
return null; |
final JSONParser p = new JSONParser(JSONParser.MODE_STRICTEST); |
222,8 → 226,14 |
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 { |
if (path == null) { |
throw new IllegalArgumentException("null path"); |
} |
if (fileName == null) { |
throw new IllegalArgumentException("null fileName"); |
} |
final HttpsURLConnection con = openConnection("/get"); |
send(con, NetUtils.urlEncode("rn", fileName, "rp", path)); |
send(con, NetUtils.urlEncode("rn", fileName, "rp", path), false); |
final Response res = checkResponseCode(con, GETFILE_OK_CODES); |
if (res.getCode() == 404) { |
fileConsumer.accept(null, null); |
240,6 → 250,13 |
// 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 { |
if (path == null) { |
throw new IllegalArgumentException("null path"); |
} |
if (fileName == null) { |
throw new IllegalArgumentException("null fileName"); |
} |
final AtomicBoolean missing = new AtomicBoolean(true); |
final Response res = this.getFile(path, fileName, (fileAttrs, in) -> { |
missing.set(fileAttrs == null); |
253,8 → 270,14 |
} |
public Response deleteFile(final String path, final String fileName) throws IOException { |
if (path == null) { |
throw new IllegalArgumentException("null path"); |
} |
if (fileName == null) { |
throw new IllegalArgumentException("null fileName"); |
} |
final HttpsURLConnection con = openConnection("/delete"); |
return checkResponseCode(send(con, NetUtils.urlEncode("rn", fileName, "rp", path))); |
return checkResponseCode(send(con, NetUtils.urlEncode("rn", fileName, "rp", path), false)); |
} |
public final Response renameFile(final String path, final String fileName, final String newFileName) throws IOException { |
262,8 → 285,20 |
} |
public final Response renameFile(final String path, final String fileName, final String newPath, final String newFileName) throws IOException { |
if (path == null) { |
throw new IllegalArgumentException("null path"); |
} |
if (fileName == null) { |
throw new IllegalArgumentException("null fileName"); |
} |
if (newPath == null) { |
throw new IllegalArgumentException("null newPath"); |
} |
if (newFileName == null) { |
throw new IllegalArgumentException("null newFileName"); |
} |
final HttpsURLConnection con = openConnection("/rename"); |
return checkResponseCode(send(con, NetUtils.urlEncode("rn", fileName, "rp", path, "newPath", newPath, "newName", newFileName))); |
return checkResponseCode(send(con, NetUtils.urlEncode("rn", fileName, "rp", path, "newPath", newPath, "newName", newFileName), false)); |
} |
public Response sendFile(String path, File localFile) throws IOException { |
271,6 → 306,10 |
} |
public Response sendFile(String path, File localFile, final boolean overwrite) throws IOException { |
if (path == null) { |
throw new IllegalArgumentException("null path"); |
} |
final long size = localFile.length(); |
if (size >= Integer.MAX_VALUE) |
throw new OutOfMemoryError("Required array size too large : " + size); |
/trunk/OpenConcerto/src/org/openconcerto/utils/i18n/translation/messages_th.properties |
---|
New file |
0,0 → 1,4 |
true_key=\u0E08\u0E23\u0E34\u0E07 |
false_key=\u0E40\u0E17\u0E47\u0E08 |
yes_key=\u0E43\u0E0A\u0E48 |
no_key=\u0E44\u0E21\u0E48 |
/trunk/OpenConcerto/src/org/openconcerto/utils/PEMImporter.java |
---|
58,6 → 58,12 |
* @param the password to set to protect the private key |
*/ |
public static KeyStore createKeyStore(File privateKeyPem, File certificatePem, final String password) throws IOException, GeneralSecurityException { |
if (!privateKeyPem.exists()) { |
throw new IllegalArgumentException("private key file missing : " + privateKeyPem.getAbsolutePath()); |
} |
if (!certificatePem.exists()) { |
throw new IllegalArgumentException("certificate file missing : " + certificatePem.getAbsolutePath()); |
} |
final X509Certificate[] cert = createCertificates(certificatePem); |
final KeyStore keystore = KeyStore.getInstance("JKS"); |
keystore.load(null); |
/trunk/OpenConcerto/src/org/openconcerto/utils/StreamUtils.java |
---|
49,6 → 49,8 |
* @param in the source. |
* @param out the destination. |
* @throws IOException if an error occurs while reading or writing. |
* @throws RTInterruptedException if interrupted (can only be checked between |
* {@link InputStream#read(byte[], int, int)} reads). |
*/ |
public static void copy(InputStream in, OutputStream out) throws IOException { |
// TODO use in.transferTo(out) in Java 9 |
69,6 → 71,8 |
final long toRead = copyAll ? buffer.length : Math.min(length - totalCount, buffer.length); |
// since buffer.length is an int |
assert 0 < toRead && toRead <= Integer.MAX_VALUE; |
if (Thread.interrupted()) |
throw new RTInterruptedException(); |
final int count = in.read(buffer, 0, (int) toRead); |
if (count <= 0) { |
// like Files.copy(InputStream, OutputStream), stop if reading 0 bytes |
77,6 → 81,10 |
break; |
} |
totalCount += count; |
// if interrupted while blocked in read(), then we don't want to use the data read after |
// the interrupt. |
if (Thread.interrupted()) |
throw new RTInterruptedException(); |
out.write(buffer, 0, count); |
} |
// < if end of stream |
/trunk/OpenConcerto/src/org/openconcerto/utils/Value.java |
---|
13,7 → 13,10 |
package org.openconcerto.utils; |
import org.openconcerto.utils.cc.I2ExnFactory; |
import java.util.Map; |
import java.util.function.Supplier; |
/** |
* Null can be ambiguous, e.g. {@link Map#get(Object)}. This class allows to avoid the problem. |
157,6 → 160,33 |
return def; |
} |
public final Value<V> asSome(final V def) { |
if (this.hasValue()) |
return this; |
else |
return getSome(def); |
} |
// Same method names as Optional |
public final V orElse(final V def) { |
return this.getValue(def); |
} |
public final V orGet(final Supplier<? extends V> def) { |
if (this.hasValue()) |
return this.getValue(); |
else |
return def.get(); |
} |
public final <X extends Exception, X2 extends Exception> V orThrowingGet(final I2ExnFactory<? extends V, X, X2> def) throws X, X2 { |
if (this.hasValue()) |
return this.getValue(); |
else |
return def.createChecked(); |
} |
/** |
* Return <code>null</code> if and only if this has no value. |
* |
/trunk/OpenConcerto/src/org/openconcerto/utils/cache/ICacheSupport.java |
---|
107,6 → 107,7 |
} |
} |
boolean interrupted = false; |
if (didDie) { |
// only CacheTimeOut are in our executor (plus the runnable for trimWatchers()) |
// and all items in a cache (even the running ones) have a timeout (but they don't all |
118,6 → 119,15 |
} |
} |
// make sure that the currently executing runnable is done before checking |
while (true) { |
try { |
if (this.getTimer().awaitTermination(1, TimeUnit.SECONDS)) |
break; |
} catch (InterruptedException e) { |
interrupted = true; |
} |
} |
synchronized (this) { |
purgeWatchers(); |
assert this.watchers.isEmpty() : this.watchers.size() + " item(s) were not removed : " + this.watchers.values(); |
124,6 → 134,8 |
} |
} |
if (interrupted) |
Thread.currentThread().interrupt(); |
return didDie; |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/cache/LRUMap.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.utils.cache; |
import java.util.LinkedHashMap; |
public class LRUMap<K, V> extends LinkedHashMap<K, V> { |
static final float DEFAULT_LOAD_FACTOR = 0.75f; |
static final int REHASH_GROWTH = 2; |
private static final int MIN_CAPACITY = 4; |
private static final int SIZE_THRESHOLD = (int) (MIN_CAPACITY * DEFAULT_LOAD_FACTOR * REHASH_GROWTH); |
private int maxSize; |
public LRUMap(final int maxSize) { |
this(maxSize, maxSize <= SIZE_THRESHOLD ? MIN_CAPACITY : (int) (maxSize / DEFAULT_LOAD_FACTOR / REHASH_GROWTH + 1)); |
} |
public LRUMap(final int maxSize, final int initialCapacity) { |
this(maxSize, initialCapacity, DEFAULT_LOAD_FACTOR); |
} |
public LRUMap(final int maxSize, int initialCapacity, float loadFactor) { |
super(initialCapacity, loadFactor, true); |
this.setMaxSize(maxSize); |
} |
public final int getMaxSize() { |
return this.maxSize; |
} |
public final void setMaxSize(int maxSize) { |
this.maxSize = maxSize; |
} |
@Override |
protected final boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) { |
return this.size() > this.getMaxSize(); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/net/HTTPClient.java |
---|
116,7 → 116,7 |
return this.getToken() != null; |
} |
protected final String getToken() { |
public final String getToken() { |
return this.token; |
} |
144,8 → 144,9 |
con.setRequestProperty("Accept-Encoding", "gzip"); |
if (this.getSocketFactory() != null) |
con.setSSLSocketFactory(this.getSocketFactory()); |
if (getToken() != null) |
if (getToken() != null) { |
con.setRequestProperty("Authorization", "Bearer " + Base64.getEncoder().encodeToString(getToken().getBytes(StandardCharsets.UTF_8))); |
} |
return con; |
} |
153,12 → 154,13 |
return "gzip".equals(con.getContentEncoding()) ? new GZIPInputStream(con.getInputStream()) : con.getInputStream(); |
} |
public final HttpsURLConnection send(final HttpsURLConnection con, final String params) throws IOException { |
return this.send(con, params, true); |
public final HttpsURLConnection send(final HttpsURLConnection con, final String formUrlEncodedParams) throws IOException { |
return this.send(con, formUrlEncodedParams, true); |
} |
public final HttpsURLConnection send(final HttpsURLConnection con, final String params, final boolean allowGzip) throws IOException { |
return this.send(con, params.getBytes(StandardCharsets.UTF_8), allowGzip); |
public final HttpsURLConnection send(final HttpsURLConnection con, final String formUrlEncodedParams, final boolean allowGzip) throws IOException { |
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); |
return this.send(con, formUrlEncodedParams.getBytes(StandardCharsets.UTF_8), allowGzip); |
} |
public final HttpsURLConnection send(final HttpsURLConnection con, final byte[] toSend, final boolean allowGzip) throws IOException { |
/trunk/OpenConcerto/src/org/openconcerto/utils/TransformedComparator.java |
---|
14,12 → 14,9 |
package org.openconcerto.utils; |
import org.openconcerto.utils.cc.ITransformer; |
import org.openconcerto.utils.cc.Transformer; |
import java.util.Comparator; |
import org.apache.commons.collections.ComparatorUtils; |
/** |
* A comparator that transforms before comparing. |
* |
26,29 → 23,22 |
* @author Sylvain |
* |
* @param <E> the type of the objects before being transformed. |
* @param <T> the type of the objects after being transformed. |
*/ |
public class TransformedComparator<E, T> implements Comparator<E> { |
public class TransformedComparator<E> implements Comparator<E> { |
public static final <T> TransformedComparator<T, T> from(final Comparator<T> comp) { |
return new TransformedComparator<T, T>(Transformer.<T> nopTransformer(), comp); |
} |
private final Comparator<E> comp; |
private final ITransformer<E, T> transf; |
private final Comparator<T> comp; |
@SuppressWarnings("unchecked") |
public TransformedComparator(final ITransformer<E, T> transf) { |
this(transf, ComparatorUtils.NATURAL_COMPARATOR); |
public <T extends Comparable<T>> TransformedComparator(final ITransformer<E, T> transf) { |
this(transf, Comparator.naturalOrder()); |
} |
public TransformedComparator(final ITransformer<E, T> transf, final Comparator<T> comp) { |
public <T> TransformedComparator(final ITransformer<E, T> transf, final Comparator<T> comp) { |
super(); |
this.transf = transf; |
this.comp = comp; |
this.comp = (o1, o2) -> (comp.compare(transf.transformChecked(o1), transf.transformChecked(o2))); |
} |
@Override |
public int compare(E o1, E o2) { |
return this.comp.compare(this.transf.transformChecked(o1), this.transf.transformChecked(o2)); |
return this.comp.compare(o1, o2); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/PropertiesUtils.java |
---|
53,27 → 53,22 |
} |
public static final Properties createFromFile(final File f) throws IOException { |
return create(new BufferedInputStream(new FileInputStream(f))); |
try (final InputStream stream = new BufferedInputStream(new FileInputStream(f))) { |
return create(stream); |
} |
} |
public static final Properties createFromResource(final Class<?> ctxt, final String rsrc) throws IOException { |
return create(ctxt.getResourceAsStream(rsrc)); |
try (final InputStream stream = ctxt.getResourceAsStream(rsrc)) { |
return create(stream); |
} |
protected static final Properties create(final InputStream stream) throws IOException { |
return create(stream, true); |
} |
public static final Properties create(final InputStream stream, final boolean close) throws IOException { |
public static final Properties create(final InputStream stream) throws IOException { |
if (stream != null) { |
try { |
final Properties res = new Properties(); |
res.load(stream); |
return res; |
} finally { |
if (close) |
stream.close(); |
} |
} else { |
return null; |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/DropperQueue.java |
---|
15,12 → 15,12 |
import org.openconcerto.utils.cc.IClosure; |
import java.util.Collection; |
import java.util.Deque; |
import java.util.LinkedList; |
import java.util.concurrent.locks.Condition; |
import java.util.concurrent.locks.Lock; |
import java.util.concurrent.locks.ReentrantLock; |
import java.util.function.Function; |
import net.jcip.annotations.GuardedBy; |
import net.jcip.annotations.ThreadSafe; |
223,13 → 223,11 |
} |
public final void eachItemDo(final IClosure<T> c) { |
this.itemsDo(new IClosure<Collection<T>>() { |
@Override |
public void executeChecked(Collection<T> items) { |
this.itemsDo((items) -> { |
for (final T t : items) { |
c.executeChecked(t); |
} |
} |
return null; |
}); |
} |
240,11 → 238,19 |
* @param c what to do with our queue. |
*/ |
public final void itemsDo(IClosure<? super Deque<T>> c) { |
this.itemsDo((q) -> { |
c.executeChecked(q); |
return null; |
}); |
} |
public final <R> R itemsDo(Function<? super Deque<T>, R> c) { |
this.itemsLock.lock(); |
try { |
c.executeChecked(this.items); |
final R res = c.apply(this.items); |
if (!this.items.isEmpty()) |
this.notEmpty.signal(); |
return res; |
} finally { |
this.itemsLock.unlock(); |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/protocol/jarjar/Handler.java |
---|
120,7 → 120,7 |
// check for !/ |
if ((index = indexOfBangSlash(spec)) == -1) { |
throw new IllegalArgumentException("no " + JarJarURLConnection.SEPARATOR + " in spec"); |
throw new IllegalArgumentException("no " + JarJarURLConnection.SEPARATOR + " in spec: " + spec); |
} |
// test the inner URL |
try { |
/trunk/OpenConcerto/src/org/openconcerto/utils/protocol/JavaSourceFromString.java |
---|
13,15 → 13,36 |
package org.openconcerto.utils.protocol; |
import org.openconcerto.utils.FileUtils; |
import java.io.File; |
import java.io.IOException; |
import java.net.URI; |
import java.util.Arrays; |
import java.util.Collections; |
import javax.tools.JavaCompiler; |
import javax.tools.JavaFileObject; |
import javax.tools.SimpleJavaFileObject; |
import javax.tools.StandardJavaFileManager; |
import javax.tools.StandardLocation; |
import javax.tools.ToolProvider; |
/** |
* From {@link JavaCompiler} javadoc. |
*/ |
public class JavaSourceFromString extends SimpleJavaFileObject { |
static public boolean compile(final File outputDir, final JavaFileObject... classes) throws IOException { |
FileUtils.mkdir_p(outputDir); |
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); |
try (final StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null)) { |
fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singleton(outputDir)); |
return compiler.getTask(null, fileManager, null, null, null, Arrays.asList(classes)).call().booleanValue(); |
} |
} |
/** |
* The source code of this "file". |
*/ |
33,11 → 54,18 |
* @param name the name of the compilation unit represented by this file object |
* @param code the source code for the compilation unit represented by this file object |
*/ |
JavaSourceFromString(String name, String code) { |
public JavaSourceFromString(String name, String code) { |
super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); |
this.code = code; |
} |
public final String getClassFile() { |
// /pkg/Inner.java |
final String name = this.getName(); |
// pkg/Inner.class |
return name.substring(1, name.length() - Kind.SOURCE.extension.length()) + Kind.CLASS.extension; |
} |
@Override |
public CharSequence getCharContent(boolean ignoreEncodingErrors) { |
return this.code; |
/trunk/OpenConcerto/src/org/openconcerto/utils/protocol/Helper.java |
---|
56,28 → 56,38 |
} |
/** |
* Wrap the passed URL into a {@link Handler jarjar} one. Needed since the jre cannot read files |
* inside a jar inside a jar. |
* Return a jar URL to the root of a jar file. Needed since the JRE cannot read files inside a |
* jar inside a jar. |
* |
* @param u the URL to wrap, e.g. "jar:file:/C:/mylibs/Outer.jar!/Inner.jar". |
* @return the wrapped URL, if necessary, i.e. if <code>u</code> references a jar in a jar, e.g. |
* "jar:jarjar:file:/C:/mylibs/Outer.jar^/Inner.jar!/". |
* @return the wrapped URL, e.g. "jar:jarjar:file:/C:/mylibs/Outer.jar^/Inner.jar!/". |
*/ |
public static final URL toJarJar(URL u) { |
return toJarJar(u, ""); |
public static final URL intoJar(final URL u) { |
return intoJar(u, ""); |
} |
public static final URL toJarJar(final URL u, final String s) { |
public static final URL intoJar(final URL u, final String s) { |
if (!u.getPath().endsWith(".jar")) |
throw new IllegalArgumentException("Doesn't end with .jar :" + u); |
final URL res; |
// if it's a jar inside another jar |
if ("jar".equals(u.getProtocol()) && u.getPath().endsWith(".jar")) { |
if ("jar".equals(u.getProtocol())) { |
try { |
return new URL("jar:jar" + u.toString().replace('!', '^') + "!/" + s); |
res = new URL("jar:jar" + u.toExternalForm().replace('!', '^') + "!/" + s); |
} catch (MalformedURLException e) { |
// shouldn't happen since we modify a valid URL |
throw new IllegalStateException("Couldn't transform " + u, e); |
throw new IllegalStateException("Couldn't transform to jarjar " + u, e); |
} |
} else |
return u; |
} else { |
try { |
res = new URL("jar:" + u.toExternalForm() + "!/" + s); |
} catch (MalformedURLException e) { |
// shouldn't happen since constructed from a valid URL |
throw new IllegalStateException("Couldn't transform to jar URL " + u, e); |
} |
} |
return res; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/Base64.java |
---|
35,11 → 35,11 |
* change some method calls that you were making to support the new options format (<tt>int</tt>s |
* that you "OR" together).</li> |
* <li>v1.5.1 - Fixed bug when decompressing and decoding to a byte[] using |
* <tt>decode( String s, boolean gzipCompressed )</tt>. Added the ability to "suspend" encoding |
* in the Output Stream so you can turn on and off the encoding if you need to embed base64 data in |
* an otherwise "normal" stream (like an XML file).</li> |
* <li>v1.5 - Output stream pases on flush() command but doesn't do anything itself. This helps |
* when using GZIP streams. Added the ability to GZip-compress objects before encoding them.</li> |
* <tt>decode( String s, boolean gzipCompressed )</tt>. Added the ability to "suspend" encoding in |
* the Output Stream so you can turn on and off the encoding if you need to embed base64 data in an |
* otherwise "normal" stream (like an XML file).</li> |
* <li>v1.5 - Output stream pases on flush() command but doesn't do anything itself. This helps when |
* using GZIP streams. Added the ability to GZip-compress objects before encoding them.</li> |
* <li>v1.4 - Added helper methods to read/write files.</li> |
* <li>v1.3.6 - Fixed OutputStream.flush() so that 'position' is reset.</li> |
* <li>v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input stream where last |
50,9 → 50,9 |
* |
* <p> |
* I am placing this code in the Public Domain. Do with it as you will. This software comes with no |
* guarantees or warranties but with plenty of well-wishing instead! Please visit <a |
* href="http://iharder.net/base64">http://iharder.net/base64</a> periodically to check for updates |
* or to contribute improvements. |
* guarantees or warranties but with plenty of well-wishing instead! Please visit |
* <a href="http://iharder.net/base64">http://iharder.net/base64</a> periodically to check for |
* updates or to contribute improvements. |
* </p> |
* |
* @author Robert Harder |
95,11 → 95,11 |
/** The 64 valid Base64 values. */ |
private final static byte[] ALPHABET; |
private final static byte[] _NATIVE_ALPHABET = /* May be something funny like EBCDIC */ |
{ (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', |
(byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', |
(byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', |
(byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', |
(byte) '9', (byte) '+', (byte) '/' }; |
{ (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', |
(byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', |
(byte) 'e', (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', |
(byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7', |
(byte) '8', (byte) '9', (byte) '+', (byte) '/' }; |
/** Determine which ALPHABET to use. */ |
static { |
167,7 → 167,8 |
* Encodes up to the first three bytes of array <var>threeBytes</var> and returns a four-byte |
* array in Base64 notation. The actual number of significant bytes in your array is given by |
* <var>numSigBytes</var>. The array <var>threeBytes</var> needs only be as big as |
* <var>numSigBytes</var>. Code can reuse a byte array by passing a four-byte array as <var>b4</var>. |
* <var>numSigBytes</var>. Code can reuse a byte array by passing a four-byte array as |
* <var>b4</var>. |
* |
* @param b4 A reusable byte array to reduce array instantiation |
* @param threeBytes the array to convert |
181,13 → 182,13 |
} // end encode3to4 |
/** |
* Encodes up to three bytes of the array <var>source</var> and writes the resulting four |
* Base64 bytes to <var>destination</var>. The source and destination arrays can be manipulated |
* Encodes up to three bytes of the array <var>source</var> and writes the resulting four Base64 |
* bytes to <var>destination</var>. The source and destination arrays can be manipulated |
* anywhere along their length by specifying <var>srcOffset</var> and <var>destOffset</var>. |
* This method does not check to make sure your arrays are large enough to accomodate |
* <var>srcOffset</var> + 3 for the <var>source</var> array or <var>destOffset</var> + 4 for |
* the <var>destination</var> array. The actual number of significant bytes in your array is |
* given by <var>numSigBytes</var>. |
* <var>srcOffset</var> + 3 for the <var>source</var> array or <var>destOffset</var> + 4 for the |
* <var>destination</var> array. The actual number of significant bytes in your array is given |
* by <var>numSigBytes</var>. |
* |
* @param source the array to convert |
* @param srcOffset the index where conversion begins |
342,9 → 343,13 |
* @since 1.4 |
*/ |
public static String encodeBytes(byte[] source) { |
return encodeBytes(source, 0, source.length, NO_OPTIONS); |
return encodeBytes(source, 0, source.length, DONT_BREAK_LINES); |
} // end encodeBytes |
public static String encodeBytesBreakLines(byte[] source) { |
return encodeBytes(source, NO_OPTIONS); |
} |
/** |
* Encodes a byte array into Base64 notation. |
* <p> |
381,9 → 386,13 |
* @since 1.4 |
*/ |
public static String encodeBytes(byte[] source, int off, int len) { |
return encodeBytes(source, off, len, NO_OPTIONS); |
return encodeBytes(source, off, len, DONT_BREAK_LINES); |
} // end encodeBytes |
public static String encodeBytesBreakLines(byte[] source, int off, int len) { |
return encodeBytes(source, off, len, NO_OPTIONS); |
} |
/** |
* Encodes a byte array into Base64 notation. |
* <p> |
505,8 → 514,8 |
* of them) to <var>destination</var>. The source and destination arrays can be manipulated |
* anywhere along their length by specifying <var>srcOffset</var> and <var>destOffset</var>. |
* This method does not check to make sure your arrays are large enough to accomodate |
* <var>srcOffset</var> + 4 for the <var>source</var> array or <var>destOffset</var> + 3 for |
* the <var>destination</var> array. This method returns the actual number of bytes that were |
* <var>srcOffset</var> + 4 for the <var>source</var> array or <var>destOffset</var> + 3 for the |
* <var>destination</var> array. This method returns the actual number of bytes that were |
* converted from the Base64 encoding. |
* |
* |
694,8 → 703,8 |
} // end decode |
/** |
* Attempts to decode Base64 data and deserialize a Java Object within. Returns <tt>null</tt> |
* if there was an error. |
* Attempts to decode Base64 data and deserialize a Java Object within. Returns <tt>null</tt> if |
* there was an error. |
* |
* @param encodedObject The Base64 data to decode |
* @return The decoded and deserialized object |
909,8 → 918,8 |
/* ******** I N N E R C L A S S I N P U T S T R E A M ******** */ |
/** |
* A {@link Base64.InputStream} will read data from another <tt>java.io.InputStream</tt>, |
* given in the constructor, and encode/decode to/from Base64 notation on the fly. |
* A {@link Base64.InputStream} will read data from another <tt>java.io.InputStream</tt>, given |
* in the constructor, and encode/decode to/from Base64 notation on the fly. |
* |
* @see Base64 |
* @since 1.3 |
1107,8 → 1116,8 |
/* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */ |
/** |
* A {@link Base64.OutputStream} will write data to another <tt>java.io.OutputStream</tt>, |
* given in the constructor, and encode/decode to/from Base64 notation on the fly. |
* A {@link Base64.OutputStream} will write data to another <tt>java.io.OutputStream</tt>, given |
* in the constructor, and encode/decode to/from Base64 notation on the fly. |
* |
* @see Base64 |
* @since 1.3 |
/trunk/OpenConcerto/src/org/openconcerto/utils/prog/VMLauncher.java |
---|
15,6 → 15,7 |
import org.openconcerto.utils.FileUtils; |
import org.openconcerto.utils.OSFamily; |
import org.openconcerto.utils.OSFamily.Unix; |
import org.openconcerto.utils.ProcessStreams; |
import org.openconcerto.utils.PropertiesUtils; |
40,6 → 41,7 |
*/ |
public abstract class VMLauncher { |
private static final String PROPERTIES_EXT = ".properties"; |
/** |
* Boolean system property, if set to <code>true</code> then {@link #restart(Class, List)} will |
* simply return <code>null</code>. Useful e.g. when using IDE launch configuration (to debug). |
46,6 → 48,38 |
*/ |
static public final String NO_RESTART = "vm.noRestart"; |
// Explicitly passed to jpackage |
static public final String APPDIR_SYSPROP = "jpackage.app.dir"; |
// Automatically set by the jpackage launcher (could be set explicitly using --java-options |
// '-Djpackage.app-path=$APPDIR/../../bin/launcher' if jpackage ever changes that) |
static public final String APP_EXE_SYSPROP = "jpackage.app-path"; |
// The path to the app directory with the jar |
public static final File getJPackageAppDir() { |
final String appPath = System.getProperty(APPDIR_SYSPROP, ""); |
return appPath.isEmpty() ? null : new File(appPath); |
} |
// The path to the executable |
private static final String getJPackageAppPath() { |
final String appPath = System.getProperty(APP_EXE_SYSPROP, ""); |
return appPath.isEmpty() ? null : appPath; |
} |
private static final void addJPackageSystemPropertyArgument(final List<String> args, final String propName) { |
final String arg = getJPackageSystemPropertyArg(propName); |
if (arg != null) |
args.add(arg); |
} |
private static final String getJPackageSystemPropertyArg(final String propName) { |
final String val = System.getProperty(propName); |
if (val == null) |
return null; |
return "-D" + propName + "=" + val; |
} |
private static NativeLauncherFinder getNativeAppLauncher() { |
final OSFamily os = OSFamily.getInstance(); |
final NativeLauncherFinder l; |
53,6 → 87,8 |
l = new WinLauncherFinder(); |
} else if (os.equals(OSFamily.Mac)) { |
l = new MacLauncherFinder(); |
} else if (os instanceof Unix) { |
l = new UnixLauncherFinder(); |
} else { |
l = UnknownLauncherFinder; |
} |
98,13 → 134,28 |
* |
* @param args the program arguments. |
* @return the command. |
* @throws UnsupportedOperationException if {@link #getAppPath()} returns <code>null</code>. |
*/ |
public abstract List<String> getCommand(final List<String> args); |
public final List<String> getCommand(final List<String> args) throws UnsupportedOperationException { |
final String appPath = this.getAppPath(); |
if (appPath == null) |
throw new UnsupportedOperationException(); |
return getCommand(appPath, args); |
} |
protected List<String> getCommand(final String appPath, final List<String> args) { |
final List<String> command = new ArrayList<String>(4 + args.size()); |
command.add(appPath); |
command.addAll(args); |
return command; |
} |
} |
private static class MacLauncherFinder extends NativeLauncherFinder { |
private static final String APP_EXT = ".app"; |
private static final Pattern MAC_PATTERN = Pattern.compile(Pattern.quote(APP_EXT) + "/Contents/Resources(/Java)?/[^/]+\\.jar$"); |
// jpackage uses "Contents/app" |
private static final Pattern MAC_PATTERN = Pattern.compile(Pattern.quote(APP_EXT) + "/Contents/(Resources(/Java)?|app)/[^/]+\\.jar$"); |
@Override |
public String getAppPath() { |
112,8 → 163,7 |
if (matcher.matches()) { |
final String appPath = getFirstItem().substring(0, matcher.start() + APP_EXT.length()); |
final File contentsDir = new File(appPath, "Contents"); |
final List<String> bundleContent = Arrays.asList(contentsDir.list()); |
if (bundleContent.contains("Info.plist") && bundleContent.contains("PkgInfo") && new File(contentsDir, "MacOS").isDirectory()) |
if (new File(contentsDir, "Info.plist").isFile() && new File(contentsDir, "MacOS").isDirectory()) |
return appPath; |
} |
return null; |
120,12 → 170,12 |
} |
@Override |
public List<String> getCommand(List<String> args) { |
protected List<String> getCommand(String appPath, List<String> args) { |
final List<String> command = new ArrayList<String>(4 + args.size()); |
command.add("open"); |
// since we restarting we need to launch a new instance of us |
command.add("-n"); |
command.add(getAppPath()); |
command.add(appPath); |
command.add("--args"); |
command.addAll(args); |
return command; |
141,13 → 191,19 |
else |
return null; |
} |
} |
private static class UnixLauncherFinder extends NativeLauncherFinder { |
private final String jpackageApp; |
public UnixLauncherFinder() { |
this.jpackageApp = getJPackageAppPath(); |
} |
@Override |
public List<String> getCommand(List<String> args) { |
final List<String> command = new ArrayList<String>(4 + args.size()); |
command.add(getAppPath()); |
command.addAll(args); |
return command; |
public String getAppPath() { |
return this.jpackageApp; |
} |
} |
156,11 → 212,6 |
public String getAppPath() { |
return null; |
} |
@Override |
public List<String> getCommand(List<String> args) { |
throw new UnsupportedOperationException(); |
} |
}; |
public static final Process restart(final Class<?> mainClass, final String... args) throws IOException { |
221,7 → 272,8 |
public static final String PROPS_VMARGS = "VMARGS"; |
public static final String ENV_PROGARGS = "JAVA_PROGARGS"; |
// handle DOS, Mac and Unix newlines |
// Don't split on spaces to avoid dealing with quotes or escapes : vmArgs=-Dfoo bar\t-DotherProp |
// Handle DOS, Mac and Unix newlines (and tabs). |
private static final Pattern NL = Pattern.compile("\\p{Cntrl}+"); |
private File wd; |
232,6 → 284,8 |
public final File getLauncherWD() { |
if (this.wd == null) { |
final File appDir = getJPackageAppDir(); |
if (appDir == null) { |
final NativeLauncherFinder nativeAppLauncher = getNativeAppLauncher(); |
final String appPath = nativeAppLauncher.getAppPath(); |
if (appPath != null) |
242,7 → 296,10 |
// support launch in an IDE |
else |
this.wd = FileUtils.getWD(); |
} else { |
this.wd = appDir; |
} |
} |
return this.wd; |
} |
306,6 → 363,9 |
final boolean debug = Boolean.getBoolean("launcher.debug"); |
final String javaBinary = getJavaBinary(); |
final File sameJava = new File(System.getProperty("java.home"), "bin/" + javaBinary); |
// allow to know what binary (and thus java.home) was tested |
if (debug) |
System.err.println("sameJava : " + sameJava); |
final String java = sameJava.canExecute() ? sameJava.getAbsolutePath() : javaBinary; |
final File propFile = this.getPropFile(mainClass); |
final Properties props = this.getProps(propFile); |
320,21 → 380,31 |
} |
command.addAll(this.getVMArguments()); |
// for java the last specified property wins |
// For java the last specified property wins. MAYBE concat properties whose names start with |
// PROPS_VMARGS, that way we could override just one of many e.g. VMARGS.garbageCollector. |
if (propFile != null) { |
final List<String> appProps = this.getProp(props, PROPS_VMARGS); |
command.addAll(appProps); |
if (debug) { |
System.err.println("VM arguments from " + propFile + " : " + appProps); |
} |
// Don't use Properties(defaults) constructor since we want to combine values. |
final File localFile = FileUtils.prependSuffix(propFile, "-local", PROPERTIES_EXT); |
final File userFile = new File(System.getProperty("user.home"), ".java/ilm/" + propFile.getName()); |
final List<String> userProps = this.getProp(userFile, PROPS_VMARGS); |
command.addAll(userProps); |
for (final File f : Arrays.asList(localFile, userFile)) { |
final List<String> moreProps = this.getProp(f, PROPS_VMARGS); |
command.addAll(moreProps); |
if (debug) { |
System.err.println("appProps : " + appProps); |
System.err.println("userProps ( from " + userFile + ") : " + userProps); |
System.err.println("VM arguments from " + f + " : " + moreProps); |
} |
} |
} |
final String envVMArgs = System.getenv(ENV_VMARGS); |
if (envVMArgs != null) |
command.addAll(split(envVMArgs)); |
// launched app may also need this context |
addJPackageSystemPropertyArgument(command, APPDIR_SYSPROP); |
addJPackageSystemPropertyArgument(command, APP_EXE_SYSPROP); |
command.add("-cp"); |
command.add(getClassPath()); |
399,6 → 469,6 |
protected File getPropFile(final String mainClass) { |
final String className = mainClass.substring(mainClass.lastIndexOf('.') + 1); |
return new File(getWD(), className + ".properties"); |
return new File(getWD(), className + PROPERTIES_EXT); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/ReentrantEventDispatcher.java |
---|
New file |
0,0 → 1,84 |
/* |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
* |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved. |
* |
* The contents of this file are subject to the terms of the GNU General Public License Version 3 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific |
* language governing permissions and limitations under the License. |
* |
* When distributing the software, include this License Header Notice in each file. |
*/ |
package org.openconcerto.utils; |
import org.openconcerto.utils.cc.BiConsumerExn; |
import java.util.Iterator; |
import java.util.LinkedList; |
import java.util.Objects; |
/** |
* Allow to maintain the dispatching of events in order when a listener itself fires an event. |
* |
* @author sylvain |
* |
* @param <L> listener type. |
* @param <E> event type. |
* @param <X> exception type. |
*/ |
public final class ReentrantEventDispatcher<L, E, X extends Exception> { |
private final class DispatchingState extends Tuple3<Iterator<L>, BiConsumerExn<L, E, X>, E> { |
public DispatchingState(final Iterator<L> iter, BiConsumerExn<L, E, X> callback, final E evt) { |
super(Objects.requireNonNull(iter, "Missing iterator"), Objects.requireNonNull(callback, "Missing callback"), evt); |
} |
} |
private final ThreadLocal<LinkedList<DispatchingState>> events = new ThreadLocal<LinkedList<DispatchingState>>() { |
@Override |
protected LinkedList<DispatchingState> initialValue() { |
return new LinkedList<>(); |
} |
}; |
private final BiConsumerExn<L, E, X> callback; |
public ReentrantEventDispatcher() { |
this(null); |
} |
public ReentrantEventDispatcher(final BiConsumerExn<L, E, X> callback) { |
super(); |
this.callback = callback; |
} |
public final void fire(final Iterator<L> iter, final E evt) throws X { |
this.fire(iter, this.callback, evt); |
} |
public final void fire(final Iterator<L> iter, final BiConsumerExn<L, E, X> callback, final E evt) throws X { |
this.fire(new DispatchingState(iter, callback, evt)); |
} |
private final void fire(final DispatchingState newTuple) throws X { |
final LinkedList<DispatchingState> linkedList = this.events.get(); |
// add new event |
linkedList.addLast(newTuple); |
// process all pending events |
DispatchingState currentTuple; |
while ((currentTuple = linkedList.peekFirst()) != null) { |
final Iterator<L> currentIter = currentTuple.get0(); |
final BiConsumerExn<L, E, X> currentCallback = currentTuple.get1(); |
final E currentEvt = currentTuple.get2(); |
while (currentIter.hasNext()) { |
final L l = currentIter.next(); |
currentCallback.accept(l, currentEvt); |
} |
// not removeFirst() since the item might have been already removed |
linkedList.pollFirst(); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/CollectionUtils.java |
---|
16,6 → 16,7 |
import org.openconcerto.utils.cc.IClosure; |
import org.openconcerto.utils.cc.IPredicate; |
import org.openconcerto.utils.cc.ITransformer; |
import org.openconcerto.utils.cc.ITransformerExn; |
import org.openconcerto.utils.cc.IdentityHashSet; |
import org.openconcerto.utils.cc.IdentitySet; |
import org.openconcerto.utils.cc.LinkedIdentitySet; |
29,8 → 30,10 |
import java.util.Collections; |
import java.util.HashMap; |
import java.util.HashSet; |
import java.util.IdentityHashMap; |
import java.util.Iterator; |
import java.util.LinkedHashMap; |
import java.util.LinkedHashSet; |
import java.util.LinkedList; |
import java.util.List; |
import java.util.ListIterator; |
39,6 → 42,11 |
import java.util.NoSuchElementException; |
import java.util.RandomAccess; |
import java.util.Set; |
import java.util.SortedMap; |
import java.util.SortedSet; |
import java.util.TreeMap; |
import java.util.TreeSet; |
import java.util.function.Function; |
import java.util.regex.Pattern; |
/** |
240,12 → 248,8 |
delete(l, from, -1); |
} |
public static <T> void filter(Collection<T> collection, IPredicate<? super T> predicate) { |
org.apache.commons.collections.CollectionUtils.filter(collection, predicate); |
} |
public static <T> boolean exists(Collection<T> collection, IPredicate<? super T> predicate) { |
return org.apache.commons.collections.CollectionUtils.exists(collection, predicate); |
return collection.stream().anyMatch(predicate::evaluateChecked); |
} |
/** |
285,6 → 289,27 |
return map; |
} |
// compared to computeIfAbsent() : |
// 1. allow exceptions |
// 2. allow nulls |
static public <K, V, X extends Exception> V computeIfAbsent(final Map<K, V> map, final K key, final ITransformerExn<K, V, X> function, final boolean allowNullValue) throws X { |
V res = map.get(key); |
final boolean contains; |
if (allowNullValue) { |
contains = res != null || map.containsKey(key); |
} else { |
contains = res != null; |
} |
if (!contains) { |
res = function.transformChecked(key); |
if (res == null && !allowNullValue) |
throw new IllegalStateException("Null value computed for key '" + key + "'"); |
map.put(key, res); |
} |
assert allowNullValue || res != null; |
return res; |
} |
/** |
* Compute the index that have changed (added or removed) between 2 lists. One of the lists MUST |
* be a sublist of the other, ie the to go from one to the other we just add or remove items but |
377,8 → 402,8 |
return !Collections.disjoint(coll1, coll2); |
} |
static public final <T> boolean identityContains(final Collection<T> coll, final T item) { |
for (final T v : coll) { |
static public final boolean identityContains(final Collection<?> coll, final Object item) { |
for (final Object v : coll) { |
if (item == v) |
return true; |
} |
385,6 → 410,27 |
return false; |
} |
static public final boolean identityEquals(final List<?> coll1, final List<?> coll2) { |
if (coll1 == coll2) |
return true; |
final int size = coll1.size(); |
if (size != coll2.size()) |
return false; |
if (size == 0) |
return true; |
final Iterator<?> iter1 = coll1.iterator(); |
final Iterator<?> iter2 = coll2.iterator(); |
while (iter1.hasNext()) { |
final Object elem1 = iter1.next(); |
final Object elem2 = iter2.next(); |
if (elem1 != elem2) |
return false; |
} |
assert !iter2.hasNext(); |
return true; |
} |
/** |
* Convert an array to a list of a different type. |
* |
902,6 → 948,82 |
} |
} |
public static final <T> List<T> toImmutableList(final Collection<? extends T> coll) { |
return toImmutableList(coll, ArrayList::new); |
} |
public static final <T, C extends Collection<? extends T>> List<T> toImmutableList(final C coll, final Function<? super C, ? extends List<T>> createColl) { |
if (coll.isEmpty()) |
return Collections.emptyList(); |
return Collections.unmodifiableList(createColl.apply(coll)); |
} |
public static final <T> Set<T> toImmutableSet(final Collection<T> coll) { |
if (coll instanceof SortedSet) { |
// force TreeSet(SortedSet) to keep Comparator |
// ATTN see eclipse bug below about wrong constructor, we need SortedSet<T>, not |
// SortedSet<? extends T>, otherwise "Open Declaration" will match to TreeSet(SortedSet) |
// but not at runtime. |
return toImmutableSet((SortedSet<T>) coll, TreeSet::new); |
} else if (coll instanceof IdentitySet) { |
return toImmutableSet((IdentitySet<? extends T>) coll, LinkedIdentitySet::new); |
} else { |
// In doubt, keep order |
// ATTN LinkedHashSet extends HashSet |
return toImmutableSet(coll, coll.getClass() == HashSet.class ? HashSet::new : LinkedHashSet::new); |
} |
} |
public static final <T, C extends Collection<? extends T>> Set<T> toImmutableSet(final C coll, final Function<? super C, ? extends Set<T>> createColl) { |
if (coll.isEmpty()) |
return Collections.emptySet(); |
final Set<T> res = createColl.apply(coll); |
return Collections.unmodifiableSet(res); |
} |
/** |
* Return an immutable map equal to the passed one. |
* |
* @param <K> type of keys. |
* @param <V> type of values. |
* @param map the map, not "? extends K" to be able to copy {@link SortedMap}. |
* @return an immutable map. |
*/ |
public static final <K, V> Map<K, V> toImmutableMap(final Map<K, ? extends V> map) { |
if (map instanceof SortedMap) { |
// force TreeMap(SortedMap) to keep Comparator |
// ATTN see eclipse bug below about wrong constructor |
return toImmutableMap((SortedMap<K, ? extends V>) map, TreeMap::new); |
} else if (map instanceof IdentityHashMap) { |
return toImmutableMap((IdentityHashMap<? extends K, ? extends V>) map, IdentityHashMap::new); |
} else { |
// In doubt, keep order |
// ATTN LinkedHashMap extends HashMap |
return toImmutableMap(map, map.getClass() == HashMap.class ? HashMap::new : LinkedHashMap::new); |
} |
} |
/** |
* Return an immutable map with the same entries as the passed one. NOTE: <code>copyMap</code> |
* <strong>must</strong> copy the entries so that a modification of <code>map</code> doesn't |
* affect the copy. |
* |
* @param <K> type of keys. |
* @param <V> type of values. |
* @param <InMap> type of passed map, ATTN if {@link SortedMap} eclipse "Open Declaration" |
* matches <code>TreeMap::new</code> to {@link TreeMap#TreeMap(SortedMap)} ignoring |
* generic type (i.e. it is declared with "K" but we pass "? extends K") but |
* {@link TreeMap#TreeMap(Map)} is (correctly) executed at runtime. |
* @param map the map. |
* @param copyFunction how to copy the passed map. |
* @return an immutable map. |
*/ |
public static final <K, V, InMap extends Map<? extends K, ? extends V>> Map<K, V> toImmutableMap(final InMap map, final Function<? super InMap, ? extends Map<K, V>> copyFunction) { |
if (map.isEmpty()) |
return Collections.emptyMap(); |
return Collections.unmodifiableMap(copyFunction.apply(map)); |
} |
public static <K, V> Map<K, V> createMap(K key, V val, K key2, V val2) { |
// arguments are ordered, so should the result |
final Map<K, V> res = new LinkedHashMap<K, V>(); |
/trunk/OpenConcerto/src/org/openconcerto/utils/Destroyable.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.utils; |
import java.util.concurrent.TimeUnit; |
public interface Destroyable { |
void destroy(); |
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/Platform.java |
---|
14,6 → 14,7 |
package org.openconcerto.utils; |
import static org.openconcerto.utils.DesktopEnvironment.cmdSubstitution; |
import org.openconcerto.utils.cc.ITransformer; |
import java.io.BufferedReader; |
23,6 → 24,8 |
import java.math.BigDecimal; |
import java.net.InetAddress; |
import java.net.SocketException; |
import java.nio.file.Files; |
import java.nio.file.Paths; |
import java.util.ArrayList; |
import java.util.List; |
import java.util.logging.Level; |
43,8 → 46,10 |
final OSFamily os = OSFamily.getInstance(); |
if (os == OSFamily.Windows) { |
return CYGWIN; |
} else if (os == OSFamily.FreeBSD || os == OSFamily.Mac) { |
} else if (os == OSFamily.FreeBSD) { |
return FREEBSD; |
} else if (os == OSFamily.Mac) { |
return MACOS; |
} else { |
return LINUX; |
} |
57,12 → 62,23 |
public abstract String getPath(final File f); |
public final String getPID() throws IOException { |
// TODO remove reflection and getPreJava9PID() once on java 11 |
try { |
final Class<?> phClass = Class.forName("java.lang.ProcessHandle"); |
final Object ph = phClass.getMethod("current").invoke(null); |
return ((Number) phClass.getMethod("pid").invoke(ph)).toString(); |
} catch (ClassNotFoundException e) { |
// fall back |
} catch (Exception e) { |
throw new IOException("Couldn't get PID", e); |
} |
return getPreJava9PID(); |
} |
protected String getPreJava9PID() throws IOException { |
final Process p = this.eval("echo -n $PPID"); |
final BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); |
try { |
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()))) { |
return reader.readLine(); |
} finally { |
reader.close(); |
} |
} |
102,12 → 118,8 |
public final void append(File f1, File f2) throws IOException { |
final String c = "cat '" + f1.getAbsolutePath() + "' >> '" + f2.getAbsolutePath() + "'"; |
try { |
this.eval(c).waitFor(); |
} catch (InterruptedException e) { |
throw new IllegalStateException(e); |
this.waitForSuccess(this.eval(c), "append"); |
} |
} |
public Process cp_l(File src, File dest) throws IOException { |
return Runtime.getRuntime().exec(new String[] { "cp", "-prl", src.getAbsolutePath(), dest.getAbsolutePath() }); |
138,14 → 150,23 |
protected final PingResult ping(final String command, final int totalCount, int requiredCount) throws IOException { |
if (requiredCount <= 0) |
requiredCount = totalCount; |
final List<String> countAndLastLine = StringUtils.splitIntoLines(cmdSubstitution(eval(command))); |
// Keep errors out of cmdSubstitution() (e.g. "ping: sendto: Message too long" when |
// setDontFragment(true)) |
final Process proc = evalPB(command).redirectErrorStream(false).start(); |
final String output = cmdSubstitution(proc); |
try { |
this.waitForSuccess(proc, "ping"); |
final List<String> countAndLastLine = StringUtils.splitIntoLines(output); |
if (countAndLastLine.size() != 2) |
throw new IllegalStateException("Not 2 lines in " + countAndLastLine); |
final int replied = Integer.parseInt(countAndLastLine.get(0)); |
assert replied <= totalCount; |
final PingResult res = new PingResult(totalCount, replied, requiredCount, replied == 0 ? null : parsePingAverageRT(countAndLastLine.get(1).trim())); |
return res; |
final BigDecimal averageRTT = replied == 0 ? null : parsePingAverageRT(countAndLastLine.get(1).trim()); |
return new PingResult(totalCount, replied, requiredCount, averageRTT); |
} catch (Exception e) { |
throw new IllegalStateException("Couldn't use output :<<<\n" + output + "\n<<<", e); |
} |
} |
/** |
* Eval the passed string with bash. |
155,17 → 176,31 |
* @throws IOException If an I/O error occurs. |
*/ |
public final Process eval(String s) throws IOException { |
return Runtime.getRuntime().exec(new String[] { this.getBash(), "-c", s }); |
return evalPB(s).start(); |
} |
public final ProcessBuilder evalPB(String s) throws IOException { |
return new ProcessBuilder(this.getBash(), "-c", s); |
} |
public final int exitStatus(Process p) { |
return this.exitStatus(p, null); |
} |
public final int exitStatus(Process p, final String name) { |
try { |
return p.waitFor(); |
} catch (InterruptedException e) { |
throw new IllegalStateException(e); |
throw new RTInterruptedException("Interrupted while waiting for" + (name == null ? "" : " '" + name + "'") + " process", e); |
} |
} |
public final void waitForSuccess(final Process p, final String name) { |
final int exitStatus = exitStatus(p, name); |
if (exitStatus != 0) |
throw new IllegalStateException(name + " unsuccessful : " + exitStatus); |
} |
public abstract boolean isAdmin() throws IOException; |
private static abstract class UnixPlatform extends Platform { |
175,6 → 210,20 |
return true; |
} |
@Override |
public final String getPreJava9PID() throws IOException { |
final String symlink = getSelfProcessSymlink(); |
if (symlink == null) |
return super.getPreJava9PID(); |
// readSymbolicLink() seems to faster than getCanonicalFile() or toRealPath(). |
// Another way is using reflection for |
// ManagementFactory.getRuntimeMXBean().jvm.getProcessId() |
return Files.readSymbolicLink(Paths.get(symlink)).getFileName().toString(); |
} |
protected abstract String getSelfProcessSymlink(); |
public final boolean isRunning(final int pid) throws IOException { |
// --pid only works on Linux, -p also on Nexenta |
final Process p = Runtime.getRuntime().exec(new String[] { "ps", "-p", String.valueOf(pid) }); |
220,7 → 269,7 |
protected BigDecimal parsePingAverageRT(String statsLine) { |
final Matcher m = PING_STATS_PATTERN.matcher(statsLine); |
if (!m.matches()) |
throw new IllegalArgumentException("Not matching " + PING_STATS_PATTERN + " : " + statsLine); |
throw new IllegalArgumentException("Not matching " + PING_STATS_PATTERN + " :\n" + statsLine); |
return new BigDecimal(m.group(2)); |
} |
232,7 → 281,13 |
} |
private static final Platform LINUX = new UnixPlatform() { |
@Override |
protected String getSelfProcessSymlink() { |
return "/proc/self"; |
} |
@Override |
public PingResult ping(final InetAddress host, final PingBuilder pingBuilder, final int routingTableIndex) throws IOException { |
if (routingTableIndex > 0) |
throw new UnsupportedOperationException("On Linux, choosing a different routing table requires changing the system policy"); |
271,7 → 326,13 |
}; |
private static final Platform FREEBSD = new UnixPlatform() { |
@Override |
protected String getSelfProcessSymlink() { |
return "/proc/curproc"; |
} |
@Override |
public PingResult ping(final InetAddress host, final PingBuilder pingBuilder, final int routingTableIndex) throws IOException { |
final List<String> command = new ArrayList<String>(16); |
command.add("setfib"); |
308,6 → 369,18 |
} |
}; |
private static final Platform MACOS = new UnixPlatform() { |
@Override |
protected String getSelfProcessSymlink() { |
return null; |
} |
@Override |
protected PingResult ping(InetAddress host, PingBuilder pingBuilder, int routingTableIndex) throws IOException { |
return FREEBSD.ping(host, pingBuilder, routingTableIndex); |
} |
}; |
private static final class CygwinPlatform extends Platform { |
@Override |
347,13 → 420,9 |
public boolean ping(InetAddress host, final int timeout) throws IOException { |
// windows implem of isReachable() is buggy |
// see http://bordet.blogspot.com/2006/07/icmp-and-inetaddressisreachable.html |
try { |
final int exit = Runtime.getRuntime().exec("ping -n 1 -w " + timeout + " " + host.getHostAddress()).waitFor(); |
final int exit = this.exitStatus(Runtime.getRuntime().exec("ping -n 1 -w " + timeout + " " + host.getHostAddress()), "ping"); |
return exit == 0; |
} catch (InterruptedException e) { |
throw new IllegalStateException(e); |
} |
} |
@Override |
public PingResult ping(final InetAddress host, final PingBuilder pingBuilder, final int routingTableIndex) throws IOException { |
/trunk/OpenConcerto/src/org/openconcerto/utils/io/JSONConverter.java |
---|
152,6 → 152,12 |
} |
public static <T> T getParameterFromJSON(final JSONObject json, final String key, final Class<T> type, T defaultValue) { |
if (json == null) { |
throw new IllegalArgumentException("null JSON"); |
} |
if (key == null) { |
throw new IllegalArgumentException("null key"); |
} |
return json.containsKey(key) ? getObjectFromJSON(json.get(key), type) : defaultValue; |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/FileUtils.java |
---|
14,8 → 14,8 |
package org.openconcerto.utils; |
import org.openconcerto.utils.CollectionMap2.Mode; |
import org.openconcerto.utils.DesktopEnvironment.Gnome; |
import org.openconcerto.utils.OSFamily.Unix; |
import org.openconcerto.utils.ProcessStreams.Action; |
import org.openconcerto.utils.StringUtils.Escaper; |
import org.openconcerto.utils.cc.ExnTransformer; |
import org.openconcerto.utils.cc.IClosure; |
45,9 → 45,11 |
import java.nio.file.FileVisitResult; |
import java.nio.file.Files; |
import java.nio.file.LinkOption; |
import java.nio.file.OpenOption; |
import java.nio.file.Path; |
import java.nio.file.SimpleFileVisitor; |
import java.nio.file.StandardCopyOption; |
import java.nio.file.StandardOpenOption; |
import java.nio.file.attribute.BasicFileAttributes; |
import java.nio.file.attribute.PosixFileAttributeView; |
import java.nio.file.attribute.PosixFilePermissions; |
61,6 → 63,7 |
import java.util.List; |
import java.util.Map; |
import java.util.Map.Entry; |
import java.util.Objects; |
import java.util.Set; |
import java.util.logging.Level; |
import java.util.regex.Pattern; |
67,34 → 70,76 |
public final class FileUtils { |
public static void main(String[] args) throws Exception { |
final String cmd = args[0]; |
if ("browseFile".equals(cmd)) |
browseFile(new File(args[1])); |
else if ("browse".equals(cmd)) |
browse(new URI(args[1])); |
else |
System.err.println("Unkown command : " + cmd); |
} |
private FileUtils() { |
// all static |
} |
public static void browseFile(final File f) throws IOException { |
browse(null, Objects.requireNonNull(f)); |
} |
if (Desktop.isDesktopSupported()) { |
Desktop d = Desktop.getDesktop(); |
if (d.isSupported(Desktop.Action.BROWSE)) { |
d.browse(f.getCanonicalFile().toURI()); |
} else { |
openNative(f); |
private static void browse(URI uri, final File f) throws IOException { |
assert (uri == null) != (f == null); |
boolean handled = false; |
final Desktop.Action action = Desktop.Action.BROWSE; |
if (isDesktopDesirable(action) && Desktop.isDesktopSupported()) { |
final Desktop d = Desktop.getDesktop(); |
if (d.isSupported(action)) { |
if (uri == null) |
uri = f.getCanonicalFile().toURI(); |
if (!uri.getScheme().equals("file") && DesktopEnvironment.getDE() instanceof Gnome) { |
ProcessBuilder pb = null; |
final String version = DesktopEnvironment.getDE().getVersion(); |
// Ubuntu 12.04, 14.04, 16.04 |
if (version.startsWith("3.4.") || version.startsWith("3.10.") || version.startsWith("3.18.")) { |
pb = new ProcessBuilder("gvfs-mount", uri.toASCIIString()); |
// Ubuntu 18.04 |
} else if (version.startsWith("3.28")) { |
// gio/gio-tool-mount.c#mount() calls g_file_mount_enclosing_volume. |
// TODO find out how glib computes "the volume that contains the file |
// location". E.g why does mount "davs://example.com/webdav/dir/dir" mounts |
// "davs://example.com/webdav/". |
// Return 0 if not yet mounted, 2 if it was already mounted. |
pb = new ProcessBuilder("gio", "mount", uri.toASCIIString()); |
} |
} else { |
if (pb != null) { |
try { |
startDiscardingOutput(pb).waitFor(); |
} catch (InterruptedException e) { |
throw new RTInterruptedException("Interrupted while waiting on mount for " + uri, e); |
} |
} |
} |
d.browse(uri); |
handled = true; |
} |
} |
if (!handled) { |
// if the caller passed a file use it instead of our converted URI |
if (f != null) |
openNative(f); |
else |
openNative(uri); |
} |
} |
public static void browse(URI uri) throws Exception { |
final boolean windows = System.getProperty("os.name").startsWith("Windows"); |
if (windows) { |
Desktop.getDesktop().browse(uri); |
} else { |
String[] cmdarray = new String[] { "xdg-open", uri.toString() }; |
final int res = Runtime.getRuntime().exec(cmdarray).waitFor(); |
if (res != 0) |
throw new IOException("error (" + res + ") executing " + Arrays.asList(cmdarray)); |
public static boolean isDesktopDesirable(Desktop.Action action) { |
// apparently the JRE just checks if gnome libs are available (e.g. open Nautilus in XFCE) |
return !(action == Desktop.Action.BROWSE && OSFamily.getInstance() == OSFamily.Linux && !(DesktopEnvironment.getDE() instanceof Gnome)); |
} |
public static void browse(URI uri) throws IOException { |
browse(Objects.requireNonNull(uri), null); |
} |
public static void openFile(File f) throws IOException { |
675,17 → 720,67 |
return Files.readAllBytes(f.toPath()); |
} |
/** |
* Write the passed string with default charset to the passed file, truncating it. |
* |
* @param s the string. |
* @param f the file. |
* @throws IOException if an error occurs. |
* @deprecated use {@link #writeUTF8(Path, String, OpenOption...)} or |
* {@link #write2Step(String, Path)} |
*/ |
public static void write(String s, File f) throws IOException { |
write(s, f, null, false); |
write2Step(s, f, Charset.defaultCharset(), false); |
} |
public static void write(String s, File f, Charset charset, boolean append) throws IOException { |
try (final FileOutputStream fileStream = new FileOutputStream(f, append); |
final BufferedWriter w = new BufferedWriter(charset == null ? new OutputStreamWriter(fileStream) : new OutputStreamWriter(fileStream, charset))) { |
w.write(s); |
public static void writeUTF8(String s, File f) throws IOException { |
writeUTF8(f.toPath(), s); |
} |
public static void writeUTF8(Path path, String s, OpenOption... options) throws IOException { |
Files.write(path, s.getBytes(StandardCharsets.UTF_8), options); |
} |
public static void write2Step(String s, File f, Charset charset, boolean append) throws IOException { |
write2Step(s, f.toPath(), charset, append); |
} |
public static void write2Step(final String s, final Path f) throws IOException { |
// UTF_8 default like Files.newBufferedReader() |
write2Step(s, f, StandardCharsets.UTF_8); |
} |
public static void write2Step(final String s, final Path f, final Charset charset) throws IOException { |
write2Step(s, f, charset, false); |
} |
public static void write2Step(final String s, final Path f, final Charset charset, final boolean append) throws IOException { |
// create temporary file in the same directory so we can move it |
final Path tmpFile = Files.createTempFile(f.toAbsolutePath().getParent(), null, null); |
try { |
// 1. write elsewhere |
final byte[] bs = charset == null ? s.getBytes() : s.getBytes(charset); |
if (append) { |
// REPLACE_EXISTING since tmpFile exists |
Files.copy(f, tmpFile, StandardCopyOption.REPLACE_EXISTING); |
Files.write(tmpFile, bs, StandardOpenOption.APPEND); |
} else { |
Files.write(tmpFile, bs); |
} |
// 2. move into place (cannot use ATOMIC_MOVE because f might exists ; and we would need |
// to handle AtomicMoveNotSupportedException) |
Files.move(tmpFile, f, StandardCopyOption.REPLACE_EXISTING); |
// don't try to delete if move() successful |
} catch (RuntimeException | Error | IOException e) { |
try { |
Files.deleteIfExists(tmpFile); |
} catch (Exception e1) { |
e.addSuppressed(e1); |
} |
throw e; |
} |
} |
/** |
* Create a writer for the passed file, and write the XML declaration. |
* |
810,7 → 905,7 |
// 2. it sets the system flag so "dir" doesn't show the shortcut (unless you add /AS) |
// 3. the shortcut is recognized as a symlink thanks to a special attribute that can get |
// lost (e.g. copying in eclipse) |
ps = Runtime.getRuntime().exec(new String[] { "cscript", getShortCutFile().getAbsolutePath(), link.getAbsolutePath(), target.getCanonicalPath() }); |
ps = startDiscardingOutput("cscript", getShortCutFile().getAbsolutePath(), link.getAbsolutePath(), target.getCanonicalPath()); |
res = new File(link.getParentFile(), link.getName() + ".LNK"); |
} else { |
final String rel = FileUtils.relative(link.getAbsoluteFile().getParentFile(), target); |
817,11 → 912,9 |
// add -f to replace existing links |
// add -n so that ln -sf aDir anExistantLinkToIt succeed |
final String[] cmdarray = { "ln", "-sfn", rel, link.getAbsolutePath() }; |
ps = Runtime.getRuntime().exec(cmdarray); |
ps = startDiscardingOutput(cmdarray); |
res = link; |
} |
// no need for output, either it succeeds or it fails |
ProcessStreams.handle(ps, Action.CLOSE); |
try { |
final int exitValue = ps.waitFor(); |
if (exitValue == 0) |
885,6 → 978,8 |
* @param prefix the prefix string to be used in generating the directory's name. |
* @return the newly-created directory. |
* @throws IllegalStateException if the directory could not be created. |
* @deprecated use |
* {@link Files#createTempDirectory(String, java.nio.file.attribute.FileAttribute...)} |
*/ |
public static File createTempDir(final String prefix) { |
final File baseDir = new File(System.getProperty("java.io.tmpdir")); |
918,13 → 1013,14 |
for (int i = 0; i < executables.length; i++) { |
final String executable = executables[i]; |
try { |
ProcessStreams.handle(Runtime.getRuntime().exec(new String[] { executable, f.getCanonicalPath() }), Action.CLOSE); |
startDiscardingOutput(executable, f.getCanonicalPath()); |
return; |
} catch (IOException e) { |
exn.addSuppressed(new IOException("unable to open with " + executable, e)); |
// try the next one |
} |
} |
throw ExceptionUtils.createExn(IOException.class, "unable to open " + f + " with: " + Arrays.asList(executables), exn); |
throw new IOException("unable to open " + f, exn); |
} |
} |
936,20 → 1032,27 |
* @throws IOException if f couldn't be opened. |
*/ |
private static final void openNative(File f) throws IOException { |
openNative(f.getCanonicalPath()); |
} |
private static final void openNative(URI uri) throws IOException { |
openNative(uri.toASCIIString()); |
} |
private static final void openNative(String param) throws IOException { |
final OSFamily os = OSFamily.getInstance(); |
final String[] cmdarray; |
if (os == OSFamily.Windows) { |
cmdarray = new String[] { "cmd", "/c", "start", "\"\"", f.getCanonicalPath() }; |
cmdarray = new String[] { "cmd", "/c", "start", "\"\"", param }; |
} else if (os == OSFamily.Mac) { |
cmdarray = new String[] { "open", f.getCanonicalPath() }; |
cmdarray = new String[] { "open", param }; |
} else if (os instanceof Unix) { |
cmdarray = new String[] { "xdg-open", f.getCanonicalPath() }; |
cmdarray = new String[] { "xdg-open", param }; |
} else { |
throw new IOException("unknown way to open " + f); |
throw new IOException("unknown way to open " + param); |
} |
try { |
final Process ps = Runtime.getRuntime().exec(cmdarray); |
ProcessStreams.handle(ps, Action.CLOSE); |
final Process ps = startDiscardingOutput(cmdarray); |
// can wait since the command return as soon as the native application is launched |
// (i.e. this won't wait 30s for OpenOffice) |
final int res = ps.waitFor(); |
960,11 → 1063,20 |
} |
} |
private static final Process startDiscardingOutput(final String... command) throws IOException { |
return startDiscardingOutput(new ProcessBuilder(command)); |
} |
private static final Process startDiscardingOutput(final ProcessBuilder pb) throws IOException { |
final Process res = pb.redirectOutput(ProcessStreams.DISCARD).redirectError(ProcessStreams.DISCARD).start(); |
res.getOutputStream().close(); |
return res; |
} |
static final boolean gnomeRunning() { |
try { |
final Process ps = Runtime.getRuntime().exec(new String[] { "pgrep", "-u", System.getProperty("user.name"), "nautilus" }); |
final Process ps = startDiscardingOutput("pgrep", "-u", System.getProperty("user.name"), "nautilus"); |
// no need for output, use exit status |
ProcessStreams.handle(ps, Action.CLOSE); |
return ps.waitFor() == 0; |
} catch (Exception e) { |
return false; |
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/ITransformerWrapper.java |
---|
File deleted |
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/IFactoryWrapper.java |
---|
File deleted |
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/BiConsumerExn.java |
---|
New file |
0,0 → 1,19 |
/* |
* 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; |
@FunctionalInterface |
public interface BiConsumerExn<T, U, X extends Exception> { |
public void accept(T input, U input2) throws X; |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/ExnClosure.java |
---|
23,10 → 23,6 |
*/ |
public abstract class ExnClosure<E, X extends Exception> extends ExnTransformer<E, Object, X> implements IExnClosure<E, X> { |
public final void execute(Object input) { |
this.transform(input); |
} |
/** |
* Execute this closure, making sure that an exception of type <code>exnClass</code> is thrown. |
* |
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/CachedTransformer.java |
---|
New file |
0,0 → 1,60 |
/* |
* 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 org.openconcerto.utils.CollectionUtils; |
import org.openconcerto.utils.cache.LRUMap; |
import org.openconcerto.utils.cache.Memoizer; |
import java.util.Map; |
import net.jcip.annotations.NotThreadSafe; |
/** |
* Allow to cache the result of a function. |
* |
* @author sylvain |
* |
* @param <K> the type of the function parameter. |
* @param <V> the type of the function result. |
* @param <X> the type of the function exception. |
* @see LRUMap to limit cache size. |
* @see Memoizer for a thread-safe class with concurrent creation of entries. |
*/ |
@NotThreadSafe |
public class CachedTransformer<K, V, X extends Exception> implements ITransformerExn<K, V, X> { |
private final Map<K, V> map; |
private final boolean allowNullValue; |
private final ITransformerExn<K, V, X> function; |
public CachedTransformer(final Map<K, V> map, final ITransformerExn<K, V, X> function) { |
this(map, function, false); |
} |
public CachedTransformer(final Map<K, V> map, final ITransformerExn<K, V, X> function, final boolean allowNullValue) { |
this.map = map; |
this.function = function; |
this.allowNullValue = allowNullValue; |
} |
@Override |
public final V transformChecked(K key) throws X { |
return this.get(key); |
} |
public V get(K key) throws X { |
return CollectionUtils.computeIfAbsent(this.map, key, this.function, this.allowNullValue); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/Factory.java |
---|
13,20 → 13,15 |
package org.openconcerto.utils.cc; |
import org.apache.commons.collections.FactoryUtils; |
public abstract class Factory<E> implements IFactory<E>, ITransformer<Object, E> { |
public abstract class Factory<E> implements IFactory<E>, ITransformer<Object, E>, org.apache.commons.collections.Factory { |
public static final <N> IFactory<N> constantFactory(final N constantToReturn) { |
return new IFactoryWrapper<N>(FactoryUtils.constantFactory(constantToReturn)); |
if (constantToReturn == null) |
return ConstantFactory.nullFactory(); |
return new ConstantFactory<N>(constantToReturn); |
} |
@Override |
public final Object create() { |
return this.createChecked(); |
} |
@Override |
public final E transformChecked(Object input) { |
return this.createChecked(); |
}; |
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/IPredicate.java |
---|
13,10 → 13,8 |
package org.openconcerto.utils.cc; |
import org.apache.commons.collections.Predicate; |
public abstract class IPredicate<E> { |
public abstract class IPredicate<E> implements Predicate { |
private static final IPredicate<Object> truePred = new IPredicate<Object>() { |
@Override |
public boolean evaluateChecked(Object input) { |
51,12 → 49,6 |
return (IPredicate<N>) NotNullPred; |
} |
@SuppressWarnings("unchecked") |
@Override |
public boolean evaluate(Object object) { |
return this.evaluateChecked((E) object); |
} |
public abstract boolean evaluateChecked(E input); |
public final <F extends E> IPredicate<F> cast() { |
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/Transformer.java |
---|
15,7 → 15,7 |
import java.util.Map; |
public abstract class Transformer<E, T> implements ITransformer<E, T>, IClosure<E>, org.apache.commons.collections.Transformer { |
public abstract class Transformer<E, T> implements ITransformer<E, T>, IClosure<E> { |
private static final ITransformer<Object, Object> nopTransf = new ITransformer<Object, Object>() { |
@Override |
30,7 → 30,7 |
} |
public static final <K, V> ITransformer<K, V> fromMap(final Map<K, V> map) { |
return new Transformer<K, V>() { |
return new ITransformer<K, V>() { |
@Override |
public V transformChecked(K input) { |
return map.get(input); |
38,13 → 38,10 |
}; |
} |
@SuppressWarnings("unchecked") |
public final Object transform(Object input) { |
return this.transformChecked((E) input); |
} |
@Override |
public abstract T transformChecked(E input); |
@Override |
public final void executeChecked(E input) { |
this.transformChecked(input); |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/Closure.java |
---|
13,7 → 13,7 |
package org.openconcerto.utils.cc; |
public abstract class Closure<E> implements IClosure<E>, ITransformer<E, Object>, org.apache.commons.collections.Closure { |
public abstract class Closure<E> implements IClosure<E>, ITransformer<E, Object> { |
private static final IClosure<Object> nop = new IClosure<Object>() { |
@Override |
26,16 → 26,12 |
return (IClosure<N>) nop; |
} |
@SuppressWarnings("unchecked") |
public final void execute(Object input) { |
this.executeChecked((E) input); |
} |
@Override |
public abstract void executeChecked(E input); |
@Override |
public final Object transformChecked(E input) { |
this.executeChecked(input); |
return null; |
}; |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/ExnTransformer.java |
---|
15,8 → 15,6 |
import org.openconcerto.utils.ExceptionUtils; |
import org.apache.commons.collections.Transformer; |
/** |
* Transformer able to throw an exception. |
* |
26,13 → 24,8 |
* @param <T> return type |
* @param <X> exception type |
*/ |
public abstract class ExnTransformer<E, T, X extends Exception> implements Transformer, ITransformerExn<E, T, X> { |
public abstract class ExnTransformer<E, T, X extends Exception> implements ITransformerExn<E, T, X> { |
@SuppressWarnings("unchecked") |
public final Object transform(Object input) { |
return this.transformCheckedWithExn((E) input, IllegalStateException.class); |
} |
/** |
* Execute this transformer, making sure that an exception of type <code>exnClass</code> is |
* thrown. |
/trunk/OpenConcerto/src/org/openconcerto/utils/NetUtils.java |
---|
184,6 → 184,9 |
return content; |
} |
/** |
* Encode for POST message application/x-www-form-urlencoded |
*/ |
static public final String urlEncode(final String... kv) { |
final int size = kv.length; |
if (size % 2 != 0) |
195,6 → 198,9 |
return urlEncode(map); |
} |
/** |
* Encode for POST message application/x-www-form-urlencoded |
*/ |
static public final String urlEncode(final Map<String, ?> map) { |
if (map.isEmpty()) |
return ""; |
205,9 → 211,9 |
// Avoid null and "null" confusion. |
if (value != null) { |
try { |
sb.append(URLEncoder.encode(e.getKey(), charset)); |
sb.append(URLEncoder.encode(e.getKey(), charset).replace("+", "%20")); |
sb.append('='); |
sb.append(URLEncoder.encode(String.valueOf(value), charset)); |
sb.append(URLEncoder.encode(String.valueOf(value), charset).replace("+", "%20")); |
sb.append('&'); |
} catch (UnsupportedEncodingException exn) { |
throw new IllegalStateException("UTF-8 should be standard", exn); |
/trunk/OpenConcerto/src/org/openconcerto/utils/SleepingQueue.java |
---|
33,6 → 33,7 |
import java.util.concurrent.TimeUnit; |
import java.util.concurrent.atomic.AtomicBoolean; |
import java.util.concurrent.atomic.AtomicReference; |
import java.util.function.Function; |
import java.util.logging.Level; |
import net.jcip.annotations.GuardedBy; |
418,6 → 419,10 |
this.tasksQueue.itemsDo(c); |
} |
public final <R> R tasksDo(Function<? super Deque<RunnableFuture<?>>, R> c) { |
return this.tasksQueue.itemsDo(c); |
} |
private void cancelCheck(RunnableFuture<?> t) { |
if (t != null) |
synchronized (this) { |
/trunk/OpenConcerto/src/org/openconcerto/utils/TimeUtils.java |
---|
25,6 → 25,7 |
import java.util.List; |
import java.util.Map; |
import java.util.TimeZone; |
import java.util.concurrent.TimeUnit; |
import javax.xml.datatype.DatatypeConfigurationException; |
import javax.xml.datatype.DatatypeConstants; |
32,13 → 33,20 |
import javax.xml.datatype.DatatypeFactory; |
import javax.xml.datatype.Duration; |
import net.jcip.annotations.GuardedBy; |
import net.jcip.annotations.Immutable; |
public class TimeUtils { |
static public final int SECONDS_PER_MINUTE = 60; |
static public final int MINUTE_PER_HOUR = 60; |
static public final int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTE_PER_HOUR; |
@GuardedBy("TimeUtils.class") |
static private DatatypeFactory typeFactory = null; |
static private List<Field> FIELDS_LIST = Arrays.asList(DatatypeConstants.YEARS, DatatypeConstants.MONTHS, DatatypeConstants.DAYS, DatatypeConstants.HOURS, DatatypeConstants.MINUTES, |
static private final List<Field> FIELDS_LIST = Arrays.asList(DatatypeConstants.YEARS, DatatypeConstants.MONTHS, DatatypeConstants.DAYS, DatatypeConstants.HOURS, DatatypeConstants.MINUTES, |
DatatypeConstants.SECONDS); |
static private List<Field> DATE_FIELDS, TIME_FIELDS; |
static private final List<Field> DATE_FIELDS, TIME_FIELDS; |
static { |
final int dayIndex = FIELDS_LIST.indexOf(DatatypeConstants.DAYS); |
72,7 → 80,7 |
return f == DatatypeConstants.SECONDS ? BigDecimal.class : BigInteger.class; |
} |
static public final DatatypeFactory getTypeFactory() { |
static public synchronized final DatatypeFactory getTypeFactory() { |
if (typeFactory == null) |
try { |
typeFactory = DatatypeFactory.newInstance(); |
398,4 → 406,22 |
final long day2 = cal.getTimeInMillis(); |
return day1 == day2; |
} |
static public final boolean isEqual(final long amount1, final TimeUnit unit1, final long amount2, final TimeUnit unit2) { |
final long finerAmount, coarserAmount; |
final TimeUnit finer, coarser; |
// don't truncate |
if (unit1.compareTo(unit2) < 0) { |
finerAmount = amount1; |
finer = unit1; |
coarserAmount = amount2; |
coarser = unit2; |
} else { |
finerAmount = amount2; |
finer = unit2; |
coarserAmount = amount1; |
coarser = unit1; |
} |
return finerAmount == finer.convert(coarserAmount, coarser); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/QuickOrderedMap.java |
---|
New file |
0,0 → 1,138 |
/* |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
* |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved. |
* |
* The contents of this file are subject to the terms of the GNU General Public License Version 3 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific |
* language governing permissions and limitations under the License. |
* |
* When distributing the software, include this License Header Notice in each file. |
*/ |
package org.openconcerto.utils; |
import java.util.ArrayList; |
import java.util.Iterator; |
import java.util.Map; |
import java.util.Set; |
/** |
* Map optimisée pour les petites tailles (<50). |
* |
* Empreinte mémoire divisée 4 par rapport à HashMap. |
* |
* N'implemente pas Map pour ne pas exposer des méthodes sous-optimales |
* |
*/ |
public class QuickOrderedMap<K, V> { |
private final ArrayList<Object> keysAndValues; |
public QuickOrderedMap() { |
this(10); |
} |
public QuickOrderedMap(int initialCapacity) { |
this.keysAndValues = new ArrayList<>(initialCapacity * 2); |
} |
public int size() { |
return this.keysAndValues.size() / 2; |
} |
public boolean isEmpty() { |
return this.keysAndValues.isEmpty(); |
} |
public boolean containsKey(K key) { |
final int size = this.keysAndValues.size(); |
for (int i = 0; i < size; i += 2) { |
if (this.keysAndValues.get(i).equals(key)) { |
return true; |
} |
} |
return false; |
} |
public boolean containsValue(V value) { |
final int size = this.keysAndValues.size(); |
for (int i = 1; i < size; i += 2) { |
if (this.keysAndValues.get(i).equals(value)) { |
return true; |
} |
} |
return false; |
} |
@SuppressWarnings("unchecked") |
public K getKey(int index) { |
return (K) this.keysAndValues.get(index * 2); |
} |
@SuppressWarnings("unchecked") |
public V getValue(int index) { |
return (V) this.keysAndValues.get(1 + index * 2); |
} |
@SuppressWarnings("unchecked") |
public V get(K key) { |
final int size = this.keysAndValues.size(); |
for (int i = 0; i < size; i += 2) { |
if (this.keysAndValues.get(i).equals(key)) { |
return (V) this.keysAndValues.get(i + 1); |
} |
} |
return null; |
} |
@SuppressWarnings("unchecked") |
public V put(K key, V value) { |
final int size = this.keysAndValues.size(); |
for (int i = 0; i < size; i += 2) { |
if (this.keysAndValues.get(i).equals(key)) { |
final Object old = this.keysAndValues.get(i + 1); |
this.keysAndValues.set(i + 1, value); |
return (V) old; |
} |
} |
this.keysAndValues.add(key); |
this.keysAndValues.add(value); |
return null; |
} |
@SuppressWarnings("unchecked") |
public V remove(K key) { |
final int size = this.keysAndValues.size(); |
for (int i = 0; i < size; i += 2) { |
if (this.keysAndValues.get(i).equals(key)) { |
this.keysAndValues.remove(i); |
return (V) this.keysAndValues.remove(i); |
} |
} |
return null; |
} |
public void putAll(Map<? extends K, ? extends V> m) { |
final Set<? extends K> keySet = m.keySet(); |
if (!isEmpty()) { |
for (Iterator<? extends K> iterator = keySet.iterator(); iterator.hasNext();) { |
K key = iterator.next(); |
put(key, m.get(key)); |
} |
} else { |
for (Iterator<? extends K> iterator = keySet.iterator(); iterator.hasNext();) { |
K key = iterator.next(); |
this.keysAndValues.add(key); |
this.keysAndValues.add(m.get(key)); |
} |
} |
} |
public void clear() { |
this.keysAndValues.clear(); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/tools/SimpleURLClassLoader.java |
---|
New file |
0,0 → 1,169 |
/* |
* 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.tools; |
import org.openconcerto.utils.Log; |
import org.openconcerto.utils.StreamUtils; |
import java.io.File; |
import java.io.IOException; |
import java.io.InputStream; |
import java.net.HttpURLConnection; |
import java.net.MalformedURLException; |
import java.net.URL; |
import java.net.URLClassLoader; |
import java.net.URLConnection; |
import java.security.CodeSigner; |
import java.security.CodeSource; |
import java.security.SecureClassLoader; |
import java.util.ArrayList; |
import java.util.Collections; |
import java.util.List; |
import java.util.logging.Level; |
/** |
* Class loader which supports any URL. {@link URLClassLoader} only supports directories and jar |
* files, but is more optimized (e.g. for finding which URL contains a resource) |
* |
* @author sylvain |
*/ |
public class SimpleURLClassLoader extends SecureClassLoader { |
static public final URL toURL(final File f) { |
try { |
return f.toURI().toURL(); |
} catch (MalformedURLException e) { |
// shouldn't happen since constructed from a file |
throw new IllegalStateException("Couldn't transform file to URL " + f, e); |
} |
} |
static public class URLCollector { |
private final List<URL> urls = new ArrayList<>(); |
public final List<URL> copyToUnmodifiableList() { |
return Collections.unmodifiableList(new ArrayList<>(this.urls)); |
} |
public final URLCollector add(final URL url) { |
this.urls.add(url); |
return this; |
} |
public final URLCollector addDirectory(final File dir) { |
if (!dir.isDirectory()) |
throw new IllegalArgumentException("Not a directory : " + dir); |
return this.add(toURL(dir)); |
} |
public final URLCollector addJar(final File jar) { |
if (!jar.isFile()) |
throw new IllegalArgumentException("Not a file : " + jar); |
return this.addJar(toURL(jar)); |
} |
public final URLCollector addJar(final URL u) { |
return this.add(org.openconcerto.utils.protocol.Helper.intoJar(u)); |
} |
public final URLCollector addJars(final Iterable<URL> jars) { |
for (final URL jar : jars) |
this.addJar(jar); |
return this; |
} |
} |
// from ResourceBundle.Control |
static public final String toResourceName(String bundleName, String suffix) { |
StringBuilder sb = new StringBuilder(bundleName.length() + 1 + suffix.length()); |
sb.append(bundleName.replace('.', '/')).append('.').append(suffix); |
return sb.toString(); |
} |
static public final String toClassFile(String bundleName) { |
return toResourceName(bundleName, "class"); |
} |
private final List<URL> urls; |
public SimpleURLClassLoader(final URLCollector urls) { |
super(); |
this.urls = urls.copyToUnmodifiableList(); |
} |
public SimpleURLClassLoader(final URLCollector urls, final ClassLoader parent) { |
super(parent); |
this.urls = urls.copyToUnmodifiableList(); |
} |
protected URL createURL(final URL url, final String spec) throws MalformedURLException { |
return new URL(url, spec); |
} |
@Override |
protected Class<?> findClass(String name) throws ClassNotFoundException { |
for (final URL baseURL : this.urls) { |
try { |
final URL url = createURL(baseURL, toClassFile(name)); |
try (final InputStream ins = url.openConnection().getInputStream()) { |
try { |
final byte[] bytes = StreamUtils.read(ins); |
return this.defineClass(name, bytes, 0, bytes.length, new CodeSource(url, (CodeSigner[]) null)); |
} catch (IOException readExn) { |
// same behaviour as URLClassLoader.findClass() |
throw new ClassNotFoundException(name, readExn); |
} |
} |
} catch (IOException connectExn) { |
Log.get().log(Level.FINE, connectExn, () -> "Couldn't connect to " + baseURL + " for " + name); |
// next |
} |
} |
return super.findClass(name); |
} |
@Override |
protected URL findResource(String name) { |
for (final URL baseURL : this.urls) { |
try { |
final URL url = createURL(baseURL, name); |
boolean exists = false; |
if (url.getProtocol().equals("file")) { |
exists = new File(url.toURI()).exists(); |
} else { |
// From sun.misc.URLClassPath.Loader |
URLConnection uc = url.openConnection(); |
if (uc instanceof HttpURLConnection) { |
HttpURLConnection hconn = (HttpURLConnection) uc; |
hconn.setRequestMethod("HEAD"); |
exists = hconn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST; |
} else { |
// our best guess for the other cases |
uc.setUseCaches(false); |
try (final InputStream ins = uc.getInputStream()) { |
exists = true; |
} catch (IOException e) { |
exists = false; |
} |
} |
} |
if (exists) |
return url; |
} catch (Exception e) { |
// next |
} |
} |
return super.findResource(name); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/tools/Outer.java |
---|
New file |
0,0 → 1,77 |
/* |
* 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.tools; |
import org.openconcerto.utils.tools.SimpleURLClassLoader.URLCollector; |
import java.security.CodeSource; |
import java.security.Permission; |
import java.security.PermissionCollection; |
import java.security.Permissions; |
import java.security.Policy; |
import java.security.ProtectionDomain; |
import java.util.PropertyPermission; |
public final class Outer { |
public static void main(String[] args) throws Exception { |
final String className = args[0]; |
final String fieldName = args[1]; |
org.openconcerto.utils.protocol.Helper.register(); |
// Install SecurityManager to test SecureClassLoader.getPermissions(). |
final ClassLoader mainLoader = Outer.class.getClassLoader(); |
Policy.setPolicy(new Policy() { |
@Override |
public boolean implies(ProtectionDomain domain, Permission permission) { |
// our class loader gets all permission |
if (domain != null && domain.getClassLoader() == mainLoader) { |
return true; |
} |
return super.implies(domain, permission); |
} |
}); |
System.setSecurityManager(new SecurityManager()); |
final PermissionCollection innerPerms = new Permissions(); |
innerPerms.add(new RuntimePermission("accessDeclaredMembers")); |
if (Boolean.getBoolean("property.read")) |
innerPerms.add(new PropertyPermission("*", "read")); |
innerPerms.setReadOnly(); |
System.out.print(new Outer(className).getFieldValue(innerPerms, fieldName)); |
} |
private final String className; |
public Outer(String className) { |
super(); |
this.className = className; |
} |
public Object getFieldValue(final PermissionCollection perms, final String fieldName) throws ClassNotFoundException, ReflectiveOperationException { |
// needed to test loading from jar inside a jar |
if (!this.getClass().getResource(this.getClass().getSimpleName() + ".class").toExternalForm().startsWith("jar:file:")) |
throw new IllegalStateException("Class not loaded from a jar"); |
final ClassLoader loader = new SimpleURLClassLoader(new URLCollector().addJar(this.getClass().getResource("/inner.jar"))) { |
@Override |
protected PermissionCollection getPermissions(CodeSource codesource) { |
return perms; |
} |
}; |
final Class<?> loadedClass = loader.loadClass(this.className); |
return loadedClass.getDeclaredField(fieldName).get(null); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/DesktopEnvironment.java |
---|
21,10 → 21,13 |
import java.io.InputStream; |
import java.lang.reflect.Method; |
import java.nio.charset.Charset; |
import java.util.concurrent.FutureTask; |
import java.util.concurrent.RunnableFuture; |
import java.util.logging.Level; |
import java.util.regex.Matcher; |
import java.util.regex.Pattern; |
import javax.swing.SwingUtilities; |
import javax.swing.filechooser.FileSystemView; |
import javax.xml.parsers.DocumentBuilder; |
import javax.xml.parsers.DocumentBuilderFactory; |
32,6 → 35,9 |
import org.w3c.dom.Element; |
import org.w3c.dom.NodeList; |
import net.jcip.annotations.GuardedBy; |
import net.jcip.annotations.ThreadSafe; |
/** |
* A desktop environment like Gnome or MacOS. |
* |
38,6 → 44,7 |
* @author Sylvain CUAZ |
* @see #getDE() |
*/ |
@ThreadSafe |
public abstract class DesktopEnvironment { |
static public final class Gnome extends DesktopEnvironment { |
212,8 → 219,8 |
static public final class Mac extends DEisOS { |
// From CarbonCore/Folders.h |
private static final String kDocumentsDirectory = "docs"; |
private static final String kPreferencesDirectory = "pref"; |
public static final String kDocumentsDirectory = "docs"; |
public static final String kPreferencesDirectory = "pref"; |
private static Class<?> FileManagerClass; |
private static Short kUserDomain; |
private static Method OSTypeToInt; |
235,18 → 242,28 |
@Override |
public File getDocumentsFolder() { |
return getFolder(kDocumentsDirectory); |
return new File(System.getProperty("user.home"), "Documents/"); |
} |
@Override |
public File getPreferencesFolder(String appName) { |
return new File(getFolder(kPreferencesDirectory), appName); |
} |
// There was a warning until JRE v16, now "--add-exports |
// java.desktop/com.apple.eio=ALL-UNNAMED" is needed. Further this needs the EDT which is |
// undesirable just to get some paths. |
// https://bugs.openjdk.java.net/browse/JDK-8187981 |
@Deprecated |
public File getFolder(String type) { |
try { |
final Method findFolder = getFileManagerClass().getMethod("findFolder", Short.TYPE, Integer.TYPE); |
final String path = (String) findFolder.invoke(null, kUserDomain, OSTypeToInt.invoke(null, type)); |
final RunnableFuture<String> f = new FutureTask<>(() -> (String) findFolder.invoke(null, kUserDomain, OSTypeToInt.invoke(null, type))); |
// EDT needed at least for JRE v14-16 on macOS 10.15, otherwise the VM crashes : |
// Problematic frame: __NSAssertMainEventQueueIsCurrentEventQueue_block_invoke or |
// "The current event queue and the main event queue are not the same. This is |
// probably because _TSGetMainThread was called for the first time off the main |
// thread." |
if (SwingUtilities.isEventDispatchThread()) |
f.run(); |
else |
SwingUtilities.invokeLater(f); |
final String path = f.get(); |
return new File(path); |
} catch (RuntimeException e) { |
throw e; |
346,9 → 363,10 |
return new Unknown(); |
} |
@GuardedBy("DesktopEnvironment.class") |
private static DesktopEnvironment DE = null; |
public static final DesktopEnvironment getDE() { |
public synchronized static final DesktopEnvironment getDE() { |
if (DE == null) { |
DE = detectDE(); |
} |
355,10 → 373,11 |
return DE; |
} |
public static final void resetDE() { |
public synchronized static final void resetDE() { |
DE = null; |
} |
@GuardedBy("this") |
private String version; |
private DesktopEnvironment() { |
367,7 → 386,7 |
protected abstract String findVersion(); |
public final String getVersion() { |
public synchronized final String getVersion() { |
if (this.version == null) |
this.version = this.findVersion(); |
return this.version; |
378,17 → 397,6 |
return FileSystemView.getFileSystemView().getDefaultDirectory(); |
} |
/** |
* Where the configuration files are stored. |
* |
* @param appName the name of application. |
* @return the preferences folder. |
* @deprecated kept around to migrate existing files, but otherwise use {@link BaseDirs}. |
*/ |
public File getPreferencesFolder(final String appName) { |
return new File(System.getProperty("user.home"), "." + appName); |
} |
// on some systems arguments are not passed correctly by ProcessBuilder |
public String quoteParamForExec(String s) { |
return s; |
/trunk/OpenConcerto/src/org/openconcerto/utils/NoneSelectedButtonGroup.java |
---|
23,7 → 23,9 |
if (selected) { |
super.setSelected(model, selected); |
} else { |
if (model.isSelected()) { |
clearSelection(); |
} |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/ConcurrentUtils.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.utils; |
public class ConcurrentUtils { |
public static final boolean runLocked(final Object first, final Object second, final Runnable run) { |
if (second == first) |
return false; |
final int thisHash = System.identityHashCode(first); |
final int oHash = System.identityHashCode(second); |
final Object o1, o2; |
if (thisHash < oHash) { |
o1 = first; |
o2 = second; |
} else if (thisHash > oHash) { |
o1 = second; |
o2 = first; |
} else { |
throw new IllegalStateException("Hash equal"); |
} |
synchronized (o1) { |
synchronized (o2) { |
run.run(); |
} |
} |
return true; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/CollectionMap2Itf.java |
---|
16,17 → 16,46 |
import org.openconcerto.utils.CollectionMap2.Mode; |
import java.util.Collection; |
import java.util.Collections; |
import java.util.List; |
import java.util.Map; |
import java.util.Objects; |
import java.util.Set; |
import java.util.function.Function; |
public interface CollectionMap2Itf<K, C extends Collection<V>, V> extends Map<K, C> { |
public static interface ListMapItf<K, V> extends CollectionMap2Itf<K, List<V>, V> { |
/** |
* Change this instance and return an unmodifiable Map view. After this method, this |
* instance shouldn't be modified, e.g. if a new entry (with a modifiable collection) is |
* added then the returned object will be able to modify it. Contrary to |
* {@link ListMap#unmodifiableMap(ListMapItf)}, the returned object doesn't allocate any |
* memory. |
* |
* @return an unmodifiable Map view. |
* @see CollectionMap2Itf#convertToUnmodifiableMap(Function) |
*/ |
public default Map<K, List<V>> convertToUnmodifiableMap() { |
return convertToUnmodifiableMap(Collections::unmodifiableList); |
} |
} |
public static interface SetMapItf<K, V> extends CollectionMap2Itf<K, Set<V>, V> { |
/** |
* Change this instance and return an unmodifiable Map view. After this method, this |
* instance shouldn't be modified, e.g. if a new entry (with a modifiable collection) is |
* added then the returned object will be able to modify it. Contrary to |
* {@link SetMap#unmodifiableMap(ListMapItf)}, the returned object doesn't allocate any |
* memory. |
* |
* @return an unmodifiable Map view. |
* @see CollectionMap2Itf#convertToUnmodifiableMap(Function) |
*/ |
public default Map<K, Set<V>> convertToUnmodifiableMap() { |
return convertToUnmodifiableMap(Collections::unmodifiableSet); |
} |
} |
public Mode getMode(); |
116,4 → 145,24 |
public Set<K> removeAllEmptyCollections(); |
public Set<K> removeAllNullCollections(); |
public default void replaceAllNonNullValues(final Function<? super C, ? extends C> function) { |
this.replaceAll((k, v) -> v == null ? null : function.apply(v)); |
} |
/** |
* Change this instance and return an unmodifiable Map view. After this method, this instance |
* shouldn't be modified, e.g. if a new entry (with a modifiable collection) is added then the |
* returned object will be able to modify it. The returned object doesn't allocate any memory. |
* |
* @param toUnmodifiable how to replace collections with unmodifiable views, never passed |
* <code>null</code>. |
* @return an unmodifiable Map view. |
* @see SetMapItf#convertToUnmodifiableMap() |
* @see ListMapItf#convertToUnmodifiableMap() |
*/ |
public default Map<K, C> convertToUnmodifiableMap(final Function<? super C, ? extends C> toUnmodifiable) { |
this.replaceAllNonNullValues(Objects.requireNonNull(toUnmodifiable)); |
return Collections.unmodifiableMap(this); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/EmailClient.java |
---|
17,6 → 17,8 |
import org.openconcerto.utils.DesktopEnvironment.KDE; |
import org.openconcerto.utils.DesktopEnvironment.Mac; |
import org.openconcerto.utils.DesktopEnvironment.Windows; |
import org.openconcerto.utils.DesktopEnvironment.XFCE; |
import org.openconcerto.utils.OSFamily.Unix; |
import org.openconcerto.utils.io.PercentEncoder; |
import java.io.BufferedOutputStream; |
294,6 → 296,12 |
// ~/.kde/share/config/emaildefaults or /etc/kde (ou /usr/share/config qui est un |
// lien symbolique vers /etc/kde) |
return XDG; |
} else if (de instanceof XFCE) { |
// .config/xfce4/helpers.rc contains "MailReader=desktopName" |
// A custom one can be created in .local/share/xfce4/helpers/custom-MailReader.desktop |
return XDG; |
} else if (OSFamily.getInstance() instanceof Unix) { |
return XDG; |
} |
return MailTo; |
/trunk/OpenConcerto/src/org/openconcerto/utils/Zip.java |
---|
13,10 → 13,13 |
package org.openconcerto.utils; |
import org.openconcerto.utils.cc.ITransformerExn; |
import java.io.BufferedInputStream; |
import java.io.BufferedOutputStream; |
import java.io.ByteArrayInputStream; |
import java.io.ByteArrayOutputStream; |
import java.io.Closeable; |
import java.io.File; |
import java.io.FileInputStream; |
import java.io.FileNotFoundException; |
27,6 → 30,9 |
import java.nio.ByteBuffer; |
import java.util.Enumeration; |
import java.util.Set; |
import java.util.function.Function; |
import java.util.jar.JarEntry; |
import java.util.jar.JarOutputStream; |
import java.util.zip.CRC32; |
import java.util.zip.DeflaterOutputStream; |
import java.util.zip.InflaterInputStream; |
40,7 → 46,7 |
* @author ILM Informatique |
* @see org.openconcerto.utils.Unzip |
*/ |
public class Zip { |
public class Zip implements Closeable { |
static public byte[] deflate(final String s) throws IOException { |
return deflate(s.getBytes(StringUtils.UTF8)); |
121,10 → 127,16 |
createFrom(src, dest, entriesName).close(); |
} |
static public Zip createJar(final OutputStream out) { |
return new Zip(out, JarOutputStream::new, JarEntry::new); |
} |
// *** Instance |
private final OutputStream outstream; |
private final ITransformerExn<OutputStream, ZipOutputStream, IOException> createZipStream; |
private ZipOutputStream zos; |
private final Function<String, ZipEntry> createEntry; |
// is an entry open, ie addEntry() has been called but closeEntry() not yet |
private boolean entryOpen; |
144,27 → 156,40 |
* @param out un stream dans lequel écrire. |
*/ |
public Zip(OutputStream out) { |
this(out, ZipOutputStream::new, ZipEntry::new); |
} |
public Zip(OutputStream out, final ITransformerExn<OutputStream, ZipOutputStream, IOException> createZipStream, final Function<String, ZipEntry> createEntry) { |
this.outstream = out; |
this.createZipStream = createZipStream; |
this.zos = null; |
this.createEntry = createEntry; |
this.entryOpen = false; |
} |
@Override |
public synchronized void close() throws IOException { |
if (this.zos != null) { |
// ferme aussi le FileOutputStream |
this.zos.close(); |
} else { |
this.outstream.close(); |
} |
} |
// *** Ecriture |
private synchronized ZipOutputStream getOutStream() { |
private synchronized ZipOutputStream getOutStream() throws IOException { |
if (this.zos == null) { |
this.zos = new ZipOutputStream(this.outstream); |
this.zos = this.createZipStream.transformChecked(this.outstream); |
} |
return this.zos; |
} |
public ZipEntry createEntry(String name) { |
return this.createEntry.apply(name); |
} |
/** |
* Ajoute newFile dans ce fichier. Il sera enregistré dans le zip directement à la racine. |
* |
173,8 → 198,15 |
*/ |
public void zip(File newFile) throws IOException { |
// on ne garde que la derniere partie du chemin |
this.zip(newFile.getName(), newFile); |
} |
public void zip(final String entryName, final File newFile) throws IOException { |
final ZipEntry entry = this.createEntry(entryName); |
// TODO call ZipEntry.setCreationTime() |
entry.setTime(newFile.lastModified()); |
try (final BufferedInputStream ins = new BufferedInputStream(new FileInputStream(newFile))) { |
this.zip(newFile.getName(), ins); |
this.zip(entry, ins); |
} |
} |
185,9 → 217,13 |
* @param in l'ajout. |
* @throws IOException si in ne peut etre zippé. |
*/ |
public synchronized void zip(String name, InputStream in) throws IOException { |
this.putNextEntry(name); |
public void zip(String name, InputStream in) throws IOException { |
this.zip(this.createEntry(name), in); |
} |
public synchronized void zip(final ZipEntry entry, InputStream in) throws IOException { |
this.putNextEntry(entry); |
byte b[] = new byte[512]; |
int len = 0; |
while ((len = in.read(b)) != -1) { |
215,7 → 251,7 |
* @throws IOException if an error occurs. |
*/ |
public synchronized void zipNonCompressed(String name, byte[] in) throws IOException { |
final ZipEntry entry = new ZipEntry(name); |
final ZipEntry entry = createEntry(name); |
entry.setMethod(ZipEntry.STORED); |
final CRC32 crc = new CRC32(); |
crc.update(in); |
235,7 → 271,7 |
* @return a stream to write to the entry. |
* @throws IOException if a pb occurs. |
*/ |
public synchronized OutputStream createEntry(String name) throws IOException { |
public synchronized OutputStream createEntryStream(String name) throws IOException { |
this.putNextEntry(name); |
return new BufferedOutputStream(this.getOutStream()) { |
public void close() throws IOException { |
246,7 → 282,7 |
} |
private final synchronized void putNextEntry(String name) throws IOException, FileNotFoundException { |
this.putNextEntry(new ZipEntry(name)); |
this.putNextEntry(createEntry(name)); |
} |
private final synchronized void putNextEntry(ZipEntry entry) throws IOException, FileNotFoundException { |
/trunk/OpenConcerto/src/org/openconcerto/utils/function/ConstantSupplier.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.utils.function; |
import java.util.Objects; |
import net.jcip.annotations.Immutable; |
/** |
* A supplier returning a constant value. |
* |
* @author sylvain |
* @param <T> the type of results supplied by this supplier. |
* @see FunctionalSupplier#getConstant(Object) |
*/ |
@Immutable |
public final class ConstantSupplier<T> extends FunctionalSupplier<T> { |
private final T value; |
ConstantSupplier(final T value) { |
super(); |
this.value = value; |
} |
@Override |
public T get() { |
return this.value; |
} |
@Override |
public int hashCode() { |
return this.value == null ? 0 : this.value.hashCode(); |
} |
@Override |
public boolean equals(Object obj) { |
if (this == obj) |
return true; |
if (obj == null) |
return false; |
if (getClass() != obj.getClass()) |
return false; |
final ConstantSupplier<?> other = (ConstantSupplier<?>) obj; |
return Objects.equals(this.value, other.value); |
} |
@Override |
public String toString() { |
return this.getClass().getSimpleName() + " of " + this.get(); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/function/FunctionalSupplier.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.utils.function; |
import java.util.Objects; |
import java.util.function.Supplier; |
import net.jcip.annotations.GuardedBy; |
import net.jcip.annotations.ThreadSafe; |
/** |
* A Supplier that always returns the same value. Functional in the sense, that for the same input |
* (indeed none in this case) it returns the same output. |
* |
* @author sylvain |
* @param <T> the type of results supplied by this supplier. |
*/ |
@ThreadSafe |
public abstract class FunctionalSupplier<T> implements Supplier<T> { |
// Not an interface to restrict implementations (even inadvertently with the :: notation) |
@ThreadSafe |
static final class LazyValue<T> extends FunctionalSupplier<T> { |
private final Supplier<T> supplier; |
@GuardedBy("this") |
private boolean set; |
@GuardedBy("this") |
private T value; |
LazyValue(final Supplier<T> supplier) { |
super(); |
this.supplier = Objects.requireNonNull(supplier); |
this.set = false; |
} |
@Override |
public synchronized T get() { |
if (!this.set) { |
this.value = this.supplier.get(); |
this.set = true; |
} |
return this.value; |
} |
@Override |
public String toString() { |
return this.getClass().getSimpleName() + " for " + this.supplier; |
} |
} |
static public final <U> FunctionalSupplier<U> get(Supplier<U> orig) { |
return orig instanceof FunctionalSupplier ? (FunctionalSupplier<U>) orig : new LazyValue<>(orig); |
} |
static public final <U> ConstantSupplier<U> getConstant(U value) { |
return new ConstantSupplier<>(value); |
} |
// not public to restrict implementations |
FunctionalSupplier() { |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/utils/ProcessStreams.java |
---|
25,6 → 25,7 |
import java.util.concurrent.ExecutorService; |
import java.util.concurrent.Executors; |
import java.util.concurrent.Future; |
import java.util.function.Supplier; |
/** |
* Redirect streams of a process to System.out and System.err. |
60,7 → 61,7 |
// Added to Java 9 |
public static final Redirect DISCARD = Redirect.to(StreamUtils.NULL_FILE); |
static public final ProcessBuilder redirect(final ProcessBuilder pb) throws IOException { |
static public final ProcessBuilder redirect(final ProcessBuilder pb) { |
return pb.redirectErrorStream(true).redirectOutput(Redirect.INHERIT); |
} |
69,7 → 70,7 |
p.getInputStream().close(); |
p.getErrorStream().close(); |
} else if (action == Action.REDIRECT) { |
new ProcessStreams(p); |
new ProcessStreams(p, System.out, System.err); |
} else if (action == Action.CONSUME) { |
new ProcessStreams(p, StreamUtils.NULL_OS, StreamUtils.NULL_OS); |
} |
81,10 → 82,6 |
private final Future<?> out; |
private final Future<?> err; |
public ProcessStreams(final Process p) { |
this(p, System.out, System.err); |
} |
/** |
* Create a new instance and start reading from the passed process. If a passed |
* {@link OutputStream} is <code>null</code>, then the corresponding {@link InputStream} is not |
97,13 → 94,14 |
*/ |
public ProcessStreams(final Process p, final OutputStream out, final OutputStream err) { |
this.latch = new CountDownLatch(2); |
this.out = writeToAsync(p.getInputStream(), out); |
this.err = writeToAsync(p.getErrorStream(), err); |
this.out = writeToAsync(p::getInputStream, out); |
this.err = writeToAsync(p::getErrorStream, err); |
this.exec.submit(new Runnable() { |
@Override |
public void run() { |
try { |
ProcessStreams.this.latch.await(); |
} catch (InterruptedException e) { |
} catch (final InterruptedException e) { |
// ne rien faire |
e.printStackTrace(); |
} finally { |
121,7 → 119,7 |
this.stop(this.err); |
} |
private final void stop(Future<?> f) { |
private final void stop(final Future<?> f) { |
if (f == null) |
return; |
// TODO |
129,20 → 127,20 |
f.cancel(false); |
} |
private final Future<?> writeToAsync(final InputStream ins, final Object outs) { |
private final Future<?> writeToAsync(final Supplier<InputStream> insSupplier, final Object outs) { |
if (outs == null) { |
this.latch.countDown(); |
return null; |
} |
return this.exec.submit(new Callable<Object>() { |
public Object call() throws InterruptedException, IOException { |
try { |
@Override |
public Void call() throws InterruptedException, IOException { |
try (final InputStream ins = insSupplier.get()) { |
// PrintStream is also an OutputStream |
if (outs instanceof PrintStream) |
writeTo(ins, (PrintStream) outs); |
else |
StreamUtils.copy(ins, (OutputStream) outs); |
ins.close(); |
return null; |
} finally { |
ProcessStreams.this.latch.countDown(); |
159,7 → 157,7 |
* @throws InterruptedException if current thread is interrupted. |
* @throws IOException if I/O error. |
*/ |
public static final void writeTo(InputStream ins, PrintStream outs) throws InterruptedException, IOException { |
public static final void writeTo(final InputStream ins, final PrintStream outs) throws InterruptedException, IOException { |
final BufferedReader r = new BufferedReader(new InputStreamReader(ins)); |
String encodedName; |
while ((encodedName = r.readLine()) != null) { |
/trunk/OpenConcerto/src/org/openconcerto/xml/AbstractXMLDecoder.java |
---|
127,6 → 127,7 |
final String propAttr = getAttributeValue(elem, "property"); |
final String indexAttr = getAttributeValue(elem, "index"); |
final String methodAttr = getAttributeValue(elem, "method"); |
final String fieldAttr = getAttributeValue(elem, "field"); |
// statement or expression |
final Object res = evalContainer(elem, context, ids, new ExnTransformer<List<Object>, Object, Exception>() { |
157,8 → 158,11 |
throw new IllegalStateException("use index with neither List nor array: " + target); |
} else if (methodAttr != null) { |
res = invoke(target, methodAttr, args); |
} else |
} else if (fieldAttr != null) { |
res = ((Class<?>) target).getField(fieldAttr).get(null); |
} else { |
res = getCtor((Class<?>) target, args).newInstance(args.toArray()); |
} |
return res; |
} |
}); |
283,6 → 287,8 |
return cacheRes.getRes(); |
final Constructor res = findCtor(clazz, actualClasses); |
if (res == null) |
throw new IllegalStateException("No constructor in " + clazz + " for arguments " + actualClasses); |
cacheCtor.put(key, res); |
return res; |
} |
/trunk/OpenConcerto/src/org/openconcerto/xml/Step.java |
---|
13,6 → 13,7 |
package org.openconcerto.xml; |
import org.openconcerto.utils.Tuple2.List2; |
import org.openconcerto.utils.cc.IPredicate; |
import org.openconcerto.xml.SimpleXMLPath.Node; |
50,6 → 51,11 |
return ANY_ATTRIBUTE; |
} |
public static Step<Attribute> createAttributeStepFromQualifiedName(final String qName) { |
final List2<String> splitName = XMLUtils.splitQualifiedName(qName); |
return createAttributeStep(splitName.get1(), splitName.get0()); |
} |
public static Step<Attribute> createAttributeStep(final String name, final String ns) { |
return createAttributeStep(name, ns, null); |
} |
67,6 → 73,11 |
return ANY_CHILD_ELEMENT; |
} |
public static Step<Element> createElementStepFromQualifiedName(final String qName) { |
final List2<String> splitName = XMLUtils.splitQualifiedName(qName); |
return createElementStep(splitName.get1(), splitName.get0()); |
} |
public static Step<Element> createElementStep(final String name, final String ns) { |
return createElementStep(name, ns, null); |
} |
160,6 → 171,13 |
return res; |
} |
final List<String> getValues(List<T> jdom) { |
final List<String> res = new ArrayList<>(); |
for (final T n : jdom) |
res.add(this.node.getValue(n)); |
return res; |
} |
@Override |
public final String toString() { |
return this.getClass().getSimpleName() + " " + this.getAxis() + " " + this.ns + ":" + this.name; |
/trunk/OpenConcerto/src/org/openconcerto/xml/XMLUtils.java |
---|
13,6 → 13,8 |
package org.openconcerto.xml; |
import org.openconcerto.utils.Tuple2.List2; |
import javax.xml.stream.XMLStreamConstants; |
import javax.xml.stream.XMLStreamException; |
import javax.xml.stream.XMLStreamReader; |
117,6 → 119,31 |
return sb.toString(); |
} |
/** |
* Split prefix and local name. |
* |
* @param qName a qualified name, e.g. "ns:foo" or "foo". |
* @return first the prefix (<code>null</code> if none), then the local name |
* @throws IllegalArgumentException if invalid syntax. |
* @see <a href="https://www.w3.org/TR/xml-names/#ns-qualnames">Qualified Names</a> |
*/ |
public static List2<String> splitQualifiedName(final String qName) throws IllegalArgumentException { |
final int indexOfColon = qName.indexOf(':'); |
if (indexOfColon < 0) |
return new List2<>(null, qName); |
if (indexOfColon == 0) |
throw new IllegalArgumentException("Starts with colon : '" + qName + "'"); |
final int l = qName.length(); |
assert indexOfColon < l; |
if (indexOfColon == l - 1) |
throw new IllegalArgumentException("Ends with colon : '" + qName + "'"); |
final int secondColon = qName.indexOf(':', indexOfColon + 1); |
if (secondColon >= 0) |
throw new IllegalArgumentException("Two colons : '" + qName + "'"); |
return new List2<>(qName.substring(0, indexOfColon), qName.substring(indexOfColon + 1)); |
} |
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()); |
/trunk/OpenConcerto/src/org/openconcerto/xml/SimpleXMLPath.java |
---|
152,6 → 152,22 |
return this.lastItem.nextNodes(currentNodes); |
} |
public final List<String> selectValues(final Object n) { |
return this.selectValues(Collections.singletonList(n)); |
} |
/** |
* Return the string-value properties of the selected nodes. |
* |
* @param nodes the context. |
* @return the string values. |
* @see <a href="https://www.w3.org/TR/xpath-datamodel/#dm-string-value">string-value</a> |
*/ |
public final List<String> selectValues(final List<?> nodes) { |
final List<T> lastNodes = this.selectNodes(nodes); |
return this.lastItem.getValues(lastNodes); |
} |
// encapsulate differences about JDOM nodes |
static abstract class Node<T> { |
183,6 → 199,9 |
// viva jdom who doesn't have a common interface for getName() and getNS() |
abstract T filter(final T elem, final String name, final String ns); |
// Returns the XPath 1.0 string value of the passed node |
protected abstract String getValue(T n); |
@Override |
public final String toString() { |
return this.getClass().getSimpleName(); |
209,7 → 228,12 |
return null; |
return elem; |
} |
@Override |
protected String getValue(Attribute n) { |
return n.getValue(); |
} |
} |
static class ElementNode extends Node<Element> { |
257,5 → 281,10 |
return null; |
return elem; |
} |
@Override |
protected String getValue(Element n) { |
return n.getValue(); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/xml/XPathUtils.java |
---|
47,11 → 47,7 |
*/ |
public final static String namespace(String qName) { |
qName = basename(qName); |
final int colonIndex = qName.lastIndexOf(':'); |
if (colonIndex < 0) |
return null; |
else |
return qName.substring(0, colonIndex); |
return XMLUtils.splitQualifiedName(qName).get0(); |
} |
/** |
63,7 → 59,7 |
*/ |
public final static String localName(String qName) { |
qName = basename(qName); |
return qName.substring(qName.lastIndexOf(':') + 1); |
return XMLUtils.splitQualifiedName(qName).get1(); |
} |
private XPathUtils() { |
/trunk/OpenConcerto/src/org/openconcerto/task/TodoListPanel.java |
---|
371,7 → 371,11 |
this.addAncestorListener(new AncestorListener() { |
public void ancestorAdded(AncestorEvent event) { |
if (!TodoListPanel.this.model.isAutoRefreshing()) { |
TodoListPanel.this.model.addModelStateListener(TodoListPanel.this); |
TodoListPanel.this.model.enableUpdate(); |
} |
} |
public void ancestorMoved(AncestorEvent event) { |
} |
/trunk/OpenConcerto/src/org/openconcerto/task/TodoListModel.java |
---|
220,8 → 220,8 |
if (!isHistoryVisible()) { |
Where w3 = new Where(tableTache.getField("FAIT"), "=", Boolean.FALSE); |
Calendar cal = Calendar.getInstance(); |
cal.set(Calendar.HOUR_OF_DAY, 0); |
cal.set(Calendar.MINUTE, 0); |
// Voir les taches qui ont été faite les 15 dernières secondes |
cal.add(Calendar.SECOND, -15); |
Where w4 = new Where(tableTache.getField("DATE_FAIT"), "<>", (Object) null); |
w4 = w4.and(new Where(tableTache.getField("DATE_FAIT"), ">", cal.getTime())); |
w3 = w3.or(w4); |
394,6 → 394,17 |
fireTableRowsDeleted(row, row); |
} |
public boolean isAutoRefreshing() { |
return !this.stop; |
} |
public void enableUpdate() { |
if (this.stop == true) { |
this.stop = false; |
launchUpdaterThread(); |
} |
} |
@Override |
public void setValueAt(Object aValue, int rowIndex, int columnIndex) { |
synchronized (this.elements) { |
/trunk/OpenConcerto/src/org/openconcerto/task/config/ComptaBasePropsConfiguration.java |
---|
43,7 → 43,6 |
import java.io.File; |
import java.io.FileNotFoundException; |
import java.io.IOException; |
import java.io.InputStream; |
import java.sql.SQLException; |
import java.util.ArrayList; |
67,16 → 66,7 |
} else if (wdFile.isFile()) { |
confFile = wdFile; |
} else { |
// we added organisation name, so migrate preferences |
final File prefsFolder = BaseDirs.create(info).getPreferencesFolder(); |
if (!prefsFolder.exists()) { |
try { |
final File oldDir = DesktopEnvironment.getDE().getPreferencesFolder(info.getName()); |
Configuration.migrateToNewDir(oldDir, prefsFolder); |
} catch (IOException ex) { |
throw new IllegalStateException("Couldn't migrate preferences dir", ex); |
} |
} |
confFile = new File(prefsFolder, "main.properties"); |
} |
return confFile; |
/trunk/OpenConcerto/src/org/openconcerto/erp/modules/ComponentsContext.java |
---|
17,6 → 17,7 |
import org.openconcerto.sql.element.SQLElementDirectory; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.model.SQLName; |
import org.openconcerto.sql.sqlobject.SQLRequestComboBox; |
import org.openconcerto.sql.sqlobject.SQLTextCombo; |
import org.openconcerto.sql.view.DropManager; |
import org.openconcerto.sql.view.FileDropHandler; |
24,6 → 25,7 |
import org.openconcerto.utils.ListMap; |
import java.util.Set; |
import java.util.function.Supplier; |
import javax.swing.text.JTextComponent; |
73,9 → 75,9 |
} |
} |
public final void putAdditionalField(final String tableName, final String name, final JTextComponent comp) { |
public final void putAdditionalTextField(final String tableName, final String name, final Supplier<? extends JTextComponent> comp) { |
final SQLElement elem = checkField(tableName, name); |
if (elem.putAdditionalField(name, comp)) { |
if (elem.putAdditionalTextField(name, comp)) { |
this.fields.add(elem, name); |
} else { |
throw new IllegalStateException("Already added " + name + " in " + elem); |
82,9 → 84,9 |
} |
} |
public final void putAdditionalField(final String tableName, final String name, final SQLTextCombo comp) { |
public final void putAdditionalTextCombo(final String tableName, final String name, final Supplier<? extends SQLTextCombo> comp) { |
final SQLElement elem = checkField(tableName, name); |
if (elem.putAdditionalField(name, comp)) { |
if (elem.putAdditionalTextCombo(name, comp)) { |
this.fields.add(elem, name); |
} else { |
throw new IllegalStateException("Already added " + name + " in " + elem); |
91,6 → 93,15 |
} |
} |
public final void putAdditionalCombo(final String tableName, final String name, final Supplier<? extends SQLRequestComboBox> comp) { |
final SQLElement elem = checkField(tableName, name); |
if (elem.putAdditionalCombo(name, comp)) { |
this.fields.add(elem, name); |
} else { |
throw new IllegalStateException("Already added " + name + " in " + elem); |
} |
} |
final ListMap<SQLElement, String> getFields() { |
return this.fields; |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/modules/ModulePackager.java |
---|
216,7 → 216,7 |
final JarEntry e = entries.nextElement(); |
if (!e.getName().startsWith("META-INF")) { |
// use copy-constructor to keep all fields |
zip(out, new JarEntry(e), f.getInputStream(e)); |
zip(out, new JarEntry(e.getName()), f.getInputStream(e)); |
} |
} |
} finally { |
/trunk/OpenConcerto/src/org/openconcerto/erp/action/CreateFrameAbstractAction.java |
---|
50,9 → 50,12 |
final Object name = action.getValue(Action.NAME); |
WindowStateManager stateManager = null; |
if (name != null) { |
stateManager = new WindowStateManager(frame, new File(conf.getConfDir(), "Configuration" + File.separator + "Frame" + File.separator + name.toString() + ".xml"), |
true); |
if (conf == null) { |
System.err.println("Warning: no configuration for action " + action + ", unable to use a window state manager."); |
} else { |
stateManager = new WindowStateManager(frame, new File(conf.getConfDir(), "Configuration" + File.separator + "Frame" + File.separator + name.toString() + ".xml"), true); |
} |
} else { |
System.err.println("Warning: no action name for action " + action + ", unable to use a window state manager."); |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/action/NouvelleConnexionAction.java |
---|
35,6 → 35,9 |
import org.openconcerto.erp.rights.MenuComboRightEditor; |
import org.openconcerto.erp.utils.NXDatabaseAccessor; |
import org.openconcerto.map.model.Ville; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.PropsConfiguration; |
import org.openconcerto.sql.TM; |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.model.SQLBackgroundTableCache; |
import org.openconcerto.sql.model.SQLBase; |
64,6 → 67,7 |
import org.openconcerto.utils.ExceptionHandler; |
import org.openconcerto.utils.JImage; |
import org.openconcerto.utils.cc.IClosure; |
import org.openconcerto.utils.i18n.TranslationManager; |
import java.awt.Color; |
import java.awt.GridBagConstraints; |
81,6 → 85,7 |
import java.util.logging.Level; |
import javax.swing.Action; |
import javax.swing.JComponent; |
import javax.swing.JFrame; |
import javax.swing.JOptionPane; |
import javax.swing.JPanel; |
203,6 → 208,7 |
final String socTitle = comptaPropsConfiguration.getRowSociete() == null ? "" : ", [Société " + comptaPropsConfiguration.getRowSociete().getString("NOM") + "]"; |
f.setTitle(comptaPropsConfiguration.getAppName() + " " + version + socTitle); |
f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); |
} |
}); |
final FutureTask<?> showMainFrame = new FutureTask<Object>(new Runnable() { |
275,11 → 281,29 |
c.fill = GridBagConstraints.BOTH; |
this.connexionPanel = ConnexionPanel.create(r, image, !Gestion.isMinimalMode()); |
if (this.connexionPanel == null) |
final List<Locale> langs = Arrays.asList(Locale.FRANCE, Locale.CANADA_FRENCH, new Locale("fr", "CH"), new Locale("fr", "BE"), Locale.UK, Locale.CANADA, Locale.US, Locale.GERMANY, |
new Locale("de", "CH"), new Locale("es", "ES"), new Locale("pl", "PL")); |
if (this.connexionPanel == null) { |
final Locale locale = UserProps.getInstance().getLocale(); |
// for next launch |
UserProps.getInstance().setLocale(locale); |
// for current run |
((PropsConfiguration) Configuration.getInstance()).setLocale(locale); |
// for code that will never need more than one Locale concurrently |
// (e.g. used by TM singletons in various packages) |
Locale.setDefault(locale); |
// as explained in Locale.setDefault() javadoc : "be prepared to reinitialize |
// locale-sensitive code" |
JComponent.setDefaultLocale(locale); |
// throw RuntimeException like ResourceBundle.getBundle() at the beginning of this |
// method |
TranslationManager.createDefaultInstance(); |
TM.getInstance(); |
return null; |
this.connexionPanel.initLocalization(getClass().getName(), Arrays.asList(Locale.FRANCE, Locale.CANADA_FRENCH, new Locale("fr", "CH"), new Locale("fr", "BE"), Locale.UK, Locale.CANADA, |
Locale.US, Locale.GERMANY, new Locale("de", "CH"), new Locale("es", "ES"), new Locale("pl", "PL"))); |
} |
this.connexionPanel.initLocalization(getClass().getName(), langs); |
p.add(this.connexionPanel, c); |
final PanelFrame panelFrame = new PanelFrame(p, "Connexion"); |
panelFrame.setLocationRelativeTo(null); |
299,12 → 323,12 |
@Override |
public void run() { |
// laisse le temps au logiciel de demarrer |
ClasseCompte.loadClasseCompte(comptaConf); |
try { |
Thread.sleep(1000); |
} catch (InterruptedException e) { |
e.printStackTrace(); |
} |
ClasseCompte.loadClasseCompte(); |
CaisseCotisationSQLElement.getCaisseCotisation(); |
SQLPreferences prefs = SQLPreferences.getMemCached(comptaConf.getRootSociete()); |
/trunk/OpenConcerto/src/org/openconcerto/erp/injector/BrEltFactEltSQLInjector.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.injector; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.model.SQLInjector; |
public class BrEltFactEltSQLInjector extends SQLInjector { |
public BrEltFactEltSQLInjector(final DBRoot root) { |
super(root, "BON_RECEPTION_ELEMENT", "FACTURE_FOURNISSEUR_ELEMENT", false); |
createDefaultMap(); |
if (getDestination().contains("ID_COMMANDE_ELEMENT") && getSource().contains("ID_COMMANDE_ELEMENT")) { |
map(getSource().getField("ID_COMMANDE_ELEMENT"), getDestination().getField("ID_COMMANDE_ELEMENT")); |
} |
if (getDestination().contains("ID_BON_RECEPTION_ELEMENT")) { |
map(getSource().getKey(), getDestination().getField("ID_BON_RECEPTION_ELEMENT")); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/injector/CmdEltFactEltSQLInjector.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.erp.injector; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.model.SQLInjector; |
public class CmdEltFactEltSQLInjector extends SQLInjector { |
public CmdEltFactEltSQLInjector(final DBRoot root) { |
super(root, "COMMANDE_ELEMENT", "FACTURE_FOURNISSEUR_ELEMENT", false); |
createDefaultMap(); |
if (getDestination().contains("ID_COMMANDE_ELEMENT")) { |
map(getSource().getKey(), getDestination().getField("ID_COMMANDE_ELEMENT")); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/SheetUtils.java |
---|
154,9 → 154,18 |
PdfBoxGraphics2DFontTextDrawer fontTextDrawer = new PdfBoxGraphics2DFontTextDrawerDefaultFonts(); |
final File dir = new File("Fonts"); |
if (dir.exists()) { |
fontTextDrawer.registerFontFromDirectory(dir); |
System.out.println("Using fonts dir : " + dir.getAbsolutePath()); |
for (File f : dir.listFiles()) { |
if (f.isFile() && f.getName().toLowerCase().endsWith(".ttf")) { |
System.out.println("Registering font : " + f.getAbsolutePath()); |
fontTextDrawer.registerFont(f); |
} |
} |
} else { |
System.out.println("No custom fonts dir found : " + dir.getAbsolutePath()); |
} |
// Configure the renderer |
ODTRenderer renderer = new ODTRenderer(doc); |
renderer.setIgnoreMargins(false); |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/OOXMLTableImage.java |
---|
New file |
0,0 → 1,193 |
/* |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
* |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved. |
* |
* The contents of this file are subject to the terms of the GNU General Public License Version 3 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific |
* language governing permissions and limitations under the License. |
* |
* When distributing the software, include this License Header Notice in each file. |
*/ |
package org.openconcerto.erp.generationDoc; |
import org.openconcerto.erp.core.edm.Attachment; |
import org.openconcerto.erp.core.edm.AttachmentUtils; |
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.SQLTable; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.model.graph.Path; |
import org.openconcerto.utils.FileUtils; |
import org.openconcerto.utils.FillMode; |
import org.openconcerto.utils.ImageUtils; |
import org.openconcerto.utils.StringUtils; |
import java.awt.Color; |
import java.awt.image.BufferedImage; |
import java.io.ByteArrayOutputStream; |
import java.io.File; |
import java.io.IOException; |
import java.util.List; |
import javax.imageio.ImageIO; |
import org.jdom2.Element; |
public class OOXMLTableImage { |
private float x = 0; |
private float y = 0; |
private final float width, height; |
private int dpi = 300; |
private final int rowCount; |
// #ffffff |
private String bgColor = "#ffffff"; |
public final static String EDM_URL = "edm://miniature.png"; |
// C://Users/Toto.jpg ou edm://miniature.png (prendre nom miniature) |
private final String url; |
// ID_AFFAIRE.ID_CLIENT |
private String fieldPathEDM; |
private String edmProvider; |
// top,center,bottom |
private String vAlign = "center"; |
// left, center, right |
private String hAlign = "center"; |
private OOXMLElement xmlField; |
private final SQLRowAccessor row; |
public OOXMLTableImage(OOXMLElement xmlField, Element e, SQLRowAccessor row) { |
this.xmlField = xmlField; |
this.row = row; |
this.url = e.getAttributeValue("url"); |
this.fieldPathEDM = e.getAttributeValue("fieldPathEDM"); |
this.edmProvider = e.getAttributeValue("edmProvider"); |
this.width = Float.valueOf(e.getAttributeValue("width")); |
this.height = Float.valueOf(e.getAttributeValue("height")); |
this.rowCount = Integer.valueOf(e.getAttributeValue("rowCount")); |
if (e.getAttributeValue("x") != null && !e.getAttributeValue("x").isEmpty()) { |
this.x = Integer.valueOf(e.getAttributeValue("x")); |
} |
if (e.getAttributeValue("y") != null && !e.getAttributeValue("y").isEmpty()) { |
this.y = Integer.valueOf(e.getAttributeValue("y")); |
} |
} |
private byte[] img = null; |
private boolean cachedImg = false; |
public byte[] getImgBytes() throws IOException { |
if (this.cachedImg) { |
return this.img; |
} else { |
if (this.url.startsWith("edm://")) { |
Path p = new Path(this.row.getTable()); |
final SQLRow r = this.row.asRow(); |
final SQLRow rowToEdm; |
String sourceTableName = r.getTable().getName(); |
int sourceID = r.getID(); |
if (this.fieldPathEDM == null || this.fieldPathEDM.isEmpty() || this.fieldPathEDM.equalsIgnoreCase(".")) { |
rowToEdm = r; |
} else if (this.fieldPathEDM != null && this.fieldPathEDM.equalsIgnoreCase("EDM_PROVIDER")) { |
SpreadSheetCellValueProvider provider = SpreadSheetCellValueProviderManager.get(this.edmProvider); |
rowToEdm = (SQLRow) provider.getValue(new SpreadSheetCellValueContext(r)); |
if (rowToEdm == null) { |
return null; |
} else { |
sourceTableName = rowToEdm.getTable().getName(); |
sourceID = rowToEdm.getID(); |
} |
} else { |
List<String> fields = StringUtils.fastSplit(this.fieldPathEDM, '.'); |
if (fields.size() == 1) { |
sourceTableName = r.getTable().getForeignTable(fields.get(0)).getName(); |
sourceID = r.getForeignID(fields.get(0)); |
} else { |
for (String f : fields) { |
p = p.add(p.getLast().getField(f)); |
} |
rowToEdm = r.getDistantRow(p); |
sourceTableName = rowToEdm.getTable().getName(); |
sourceID = rowToEdm.getID(); |
} |
} |
final SQLTable tableAttachment = this.row.getTable().getTable("ATTACHMENT"); |
SQLRowValues rowVals = new SQLRowValues(tableAttachment); |
rowVals.putNulls(tableAttachment.getFieldsName()); |
SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowVals); |
Where where = new Where(tableAttachment.getField("SOURCE_TABLE"), "=", sourceTableName); |
where = where.and(new Where(tableAttachment.getField("SOURCE_ID"), "=", sourceID)); |
where = where.and(new Where(tableAttachment.getField("NAME"), "=", this.url.replaceAll("edm://", ""))); |
final List<SQLRowValues> rAttachments = fetcher.fetch(where); |
if (rAttachments.isEmpty()) { |
this.cachedImg = true; |
return null; |
} else { |
final SQLRowValues rowValsAttachment = rAttachments.get(0); |
final Attachment a = new Attachment(rowValsAttachment); |
final AttachmentUtils u = new AttachmentUtils(); |
final File f = u.getFile(a); |
BufferedImage unscaledImage = ImageIO.read(f); |
// 1 pouce = 25.4 mmm |
float scale = this.dpi / 25.4f; |
int maxWidth = (int) (this.width * scale); |
int maxHeight = (int) (this.height * scale); |
final BufferedImage im = ImageUtils.createQualityResizedImage(unscaledImage, maxWidth, maxHeight, false, new FillMode.ZoomOut(Color.WHITE), true); |
ByteArrayOutputStream output = new ByteArrayOutputStream(); |
ImageIO.write(im, "PNG", output); |
output.close(); |
this.img = output.toByteArray(); |
this.cachedImg = true; |
return this.img; |
} |
} else |
{ |
this.img = FileUtils.readBytes(new File(this.url)); |
this.cachedImg = true; |
return this.img; |
} |
} |
} |
public String getBgColor() { |
return this.bgColor; |
} |
public int getDpi() { |
return this.dpi; |
} |
public float getX() { |
return this.x; |
} |
public float getY() { |
return this.y; |
} |
public float getWidth() { |
return this.width; |
} |
public float getHeight() { |
return this.height; |
} |
public int getRowCount() { |
return this.rowCount; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/OOXMLTableField.java |
---|
43,6 → 43,9 |
private int idRef; |
private String style = ""; |
public OOXMLTableField(Element eltField, SQLRowAccessor row, SQLElement sqlElt, int id, int filterId, SQLRow rowLanguage, int idRef, OOXMLCache cache) { |
super(eltField, row, sqlElt, id, rowLanguage, cache); |
this.type = eltField.getAttributeValue("type"); |
247,4 → 250,9 |
return this.style; |
} |
public boolean isImage() { |
return this.type.equalsIgnoreCase("image"); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/provider/FormatedGlobalQtyTotalProvider.java |
---|
26,11 → 26,11 |
private final boolean shortName, alwaysShowOnZeroQty, pieceName; |
private static enum Type { |
public static enum Type { |
NORMAL, SHIPMENT |
} |
private final Type type; |
public final Type type; |
private FormatedGlobalQtyTotalProvider(Type t, boolean shortName) { |
this(t, shortName, false, false); |
46,7 → 46,7 |
public Object getValue(SpreadSheetCellValueContext context) { |
final SQLRowAccessor row = context.getRow(); |
final BigDecimal pv = row.getBigDecimal("PV_HT"); |
if (!alwaysShowOnZeroQty && pv.compareTo(BigDecimal.ZERO) == 0) { |
if (!this.alwaysShowOnZeroQty && pv.compareTo(BigDecimal.ZERO) == 0) { |
return null; |
} |
61,10 → 61,8 |
return String.valueOf(qte); |
} |
String result = ""; |
if (qte > 0) { |
if (qte > 1) { |
if (this.alwaysShowOnZeroQty || qte != 0) { |
result += qte + " x "; |
} |
final BigDecimal qteUV = row.getBigDecimal("QTE_UNITAIRE"); |
result += NumericFormat.getQtyDecimalFormat().format(qteUV); |
82,7 → 80,7 |
SpreadSheetCellValueProviderManager.put("supplychain.element.qtyunit", new FormatedGlobalQtyTotalProvider(Type.NORMAL, false)); |
SpreadSheetCellValueProviderManager.put("supplychain.element.qtyunit.deliver.short", new FormatedGlobalQtyTotalProvider(Type.SHIPMENT, true)); |
SpreadSheetCellValueProviderManager.put("supplychain.element.qtyunit.deliver", new FormatedGlobalQtyTotalProvider(Type.SHIPMENT, false)); |
SpreadSheetCellValueProviderManager.put("supplychain.element.qtyunit.deliver.short.with.quantity", new FormatedGlobalQtyTotalProvider(Type.SHIPMENT, true, true, true)); |
SpreadSheetCellValueProviderManager.put("supplychain.element.qtyunit.alwaysnamed.short.with.quantity", new FormatedGlobalQtyTotalProvider(Type.NORMAL, true, true, true)); |
SpreadSheetCellValueProviderManager.put("supplychain.element.qtyunit.alwaysnamed.short", new FormatedGlobalQtyTotalProvider(Type.NORMAL, true, false, true)); |
SpreadSheetCellValueProviderManager.put("supplychain.element.qtyunit.alwaysnamed", new FormatedGlobalQtyTotalProvider(Type.NORMAL, false, false, true)); |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/provider/ConditionsReglementDetailsProvider.java |
---|
44,15 → 44,15 |
if (ajours == 0 && njour == 0) { |
if (foreignRow.getBoolean("COMPTANT") != null && !foreignRow.getBoolean("COMPTANT")) { |
r = "Date de facture"; |
r += " Date de facture"; |
} else { |
r = "Comptant"; |
r += " Comptant"; |
} |
} else { |
if (ajours != 0) { |
r = "à" + ajours + ((ajours > 1) ? " jours" : " jour"); |
r += " à " + ajours + ((ajours > 1) ? " jours" : " jour"); |
} |
if (njour > 0 && njour < 31) { |
r += " le " + njour; |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/provider/TotalCommandeClientProvider.java |
---|
24,7 → 24,7 |
public class TotalCommandeClientProvider implements SpreadSheetCellValueProvider { |
public enum TypeTotalCommandeClientProvider { |
HT, TTC; |
HT, TTC, TVA; |
}; |
private final TypeTotalCommandeClientProvider type; |
40,9 → 40,16 |
for (SQLRowAccessor sqlRowAccessor : rows) { |
if (!sqlRowAccessor.isForeignEmpty("ID_COMMANDE_CLIENT")) { |
SQLRowAccessor rowCmd = sqlRowAccessor.getForeign("ID_COMMANDE_CLIENT"); |
total += (this.type == TypeTotalCommandeClientProvider.HT ? rowCmd.getLong("T_HT") : rowCmd.getLong("T_TTC")); |
if (this.type == TypeTotalCommandeClientProvider.HT) { |
total += rowCmd.getLong("T_HT"); |
} else if (this.type == TypeTotalCommandeClientProvider.TVA) { |
total += rowCmd.getLong("T_TVA"); |
} else if (this.type == TypeTotalCommandeClientProvider.TTC) { |
total += rowCmd.getLong("T_TTC"); |
} |
} |
} |
return new BigDecimal(total).movePointLeft(2); |
} |
49,6 → 56,7 |
public static void register() { |
SpreadSheetCellValueProviderManager.put("sales.account.command.total", new TotalCommandeClientProvider(TypeTotalCommandeClientProvider.HT)); |
SpreadSheetCellValueProviderManager.put("sales.account.command.total.ttc", new TotalCommandeClientProvider(TypeTotalCommandeClientProvider.TTC)); |
SpreadSheetCellValueProviderManager.put("sales.account.command.total.tva", new TotalCommandeClientProvider(TypeTotalCommandeClientProvider.TVA)); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/AbstractJOOReportsSheet.java |
---|
312,6 → 312,25 |
return new File(outputPDFDirectory, getFileName() + ".pdf"); |
} |
public void printDocument(PrinterJob job) { |
try { |
final File f = getDocumentFile(); |
if (!f.exists()) { |
generate(false, false, ""); |
} |
final Component doc = ComptaPropsConfiguration.getOOConnexion().loadDocument(f, true); |
doc.printDocument(job); |
doc.close(); |
} catch (Exception e) { |
ExceptionHandler.handle("Impossible d'imprimer le document OpenOffice", e); |
e.printStackTrace(); |
} |
} |
public void exportToPdf() { |
// Export vers PDF |
final File fileOutOO = getDocumentFile(); |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/gestcomm/RelanceSheet.java |
---|
18,6 → 18,7 |
import org.openconcerto.erp.generationDoc.AbstractJOOReportsSheet; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowListRSH; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.users.UserManager; |
65,6 → 66,12 |
} |
// Infos societe |
map.put("SocieteType", rowSoc.getString("TYPE")); |
map.put("SocieteTel", rowSoc.getString("NUM_TEL")); |
map.put("SocieteFax", rowSoc.getString("NUM_FAX")); |
map.put("SocieteRCS", rowSoc.getString("RCS")); |
map.put("SocieteSiret", rowSoc.getString("NUM_SIRET")); |
map.put("SocieteAPE", rowSoc.getString("NUM_APE")); |
map.put("SocieteCapital", GestionDevise.currencyToString(rowSoc.getBigDecimal("CAPITAL"))); |
map.put("SocieteNom", rowSoc.getString("NOM")); |
map.put("SocieteAdresse", rowSocAdresse.getString("RUE")); |
map.put("SocieteCodePostal", rowSocAdresse.getString("CODE_POSTAL")); |
137,19 → 144,27 |
SQLSelect sel = new SQLSelect(); |
sel.addSelect(this.rowRelance.getTable().getKey()); |
sel.addSelect(this.rowRelance.getTable().getField("DATE")); |
sel.setWhere(new Where(this.rowRelance.getTable().getField("ID_SAISIE_VENTE_FACTURE"), "=", this.rowRelance.getInt("ID_SAISIE_VENTE_FACTURE"))); |
sel.addFieldOrder(this.rowRelance.getTable().getField("DATE")); |
@SuppressWarnings("unchecked") |
List<Map<String, Number>> listResult = Configuration.getInstance().getBase().getDataSource().execute(sel.asString()); |
List<SQLRow> listResult = SQLRowListRSH.execute(sel); |
String oldDateRelance = ""; |
if (listResult != null && listResult.size() > 0) { |
Map<String, Number> o = listResult.get(0); |
Number n = o.get(this.rowRelance.getTable().getKey().getName()); |
SQLRow rowOldRelance = this.rowRelance.getTable().getRow(n.intValue()); |
SQLRow rowOldRelance = listResult.get(0); |
Date dOldRelance = (Date) rowOldRelance.getObject("DATE"); |
map.put("DatePremiereRelance", dateFormat2.format(dOldRelance)); |
for (SQLRow rowOldR : listResult) { |
oldDateRelance += dateFormat2.format((Date) rowOldR.getObject("DATE")) + ", "; |
} |
} else { |
map.put("DatePremiereRelance", ""); |
} |
map.put("DateAncienneRelance", oldDateRelance); |
return map; |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/OOXMLElement.java |
---|
212,4 → 212,7 |
return (k == null) ? false : k.equalsIgnoreCase("true"); |
} |
public boolean isImage() { |
return this.elt.getAttributeValue("type").equalsIgnoreCase("image"); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/OOgenerationXML.java |
---|
20,7 → 20,10 |
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement; |
import org.openconcerto.erp.core.finance.tax.model.TaxeCache; |
import org.openconcerto.erp.preferences.DefaultNXProps; |
import org.openconcerto.openoffice.LengthUnit; |
import org.openconcerto.openoffice.ODFrame; |
import org.openconcerto.openoffice.ODPackage; |
import org.openconcerto.openoffice.spreadsheet.BytesProducer.ByteArrayProducer; |
import org.openconcerto.openoffice.spreadsheet.MutableCell; |
import org.openconcerto.openoffice.spreadsheet.Sheet; |
import org.openconcerto.openoffice.spreadsheet.SpreadSheet; |
56,6 → 59,7 |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
import java.util.UUID; |
import javax.swing.JOptionPane; |
import javax.swing.SwingUtilities; |
700,10 → 704,28 |
value = null; |
styleOO = null; |
} |
int tmpCelluleAffect; |
int tmpCelluleAffect = fill(test ? "A1" : loc, value, sheet, tableField.isTypeReplace(), null, styleOO, test, tableField.isMultilineAuto(), tableField.isKeepingEmptyLines()); |
// tmpCelluleAffect = Math.max(tmpCelluleAffect, |
// tableField.getLine()); |
if (tableField.isImage()) { |
OOXMLTableImage tableImage = this.rowRefCache.getOOXMLTableImage(tableField, e, rowElt); |
tmpCelluleAffect = 1; |
try { |
if (tableImage.getImgBytes() != null) { |
MutableCell cell = sheet.getCellAt(test ? "A1" : loc); |
if (!test) { |
final ODFrame<SpreadSheet> frame = cell.addFrame(tableImage.getX(), tableImage.getY(), tableImage.getWidth(), tableImage.getHeight(), LengthUnit.MM); |
frame.addImage(UUID.randomUUID() + ".png", new ByteArrayProducer(tableImage.getImgBytes(), false)); |
} |
tmpCelluleAffect = tableImage.getRowCount(); |
} |
} catch (Exception e1) { |
// TODO popup??? |
e1.printStackTrace(); |
} |
} else { |
tmpCelluleAffect = fill(test ? "A1" : loc, value, sheet, tableField.isTypeReplace(), null, styleOO, test, tableField.isMultilineAuto(), tableField.isKeepingEmptyLines()); |
} |
if (tableField.getLine() != 1 && (!tableField.isLineOption() || (value != null && value.toString().trim().length() > 0))) { |
if (nbCellule >= tableField.getLine()) { |
tmpCelluleAffect = tmpCelluleAffect + nbCellule; |
795,11 → 817,27 |
if (result != null) { |
Object o = elt.getAttributeValue("sheet"); |
int sheet = (o == null) ? 0 : Integer.valueOf(o.toString().trim()); |
if (OOElt.isImage()) { |
OOXMLTableImage tableImage = new OOXMLTableImage(OOElt, elt, row); |
try { |
if (tableImage.getImgBytes() != null) { |
MutableCell cell = spreadSheet.getSheet(sheet).getCellAt(elt.getAttributeValue("location")); |
final ODFrame<SpreadSheet> frame = cell.addFrame(tableImage.getX(), tableImage.getY(), tableImage.getWidth(), tableImage.getHeight(), LengthUnit.MM); |
frame.addImage(UUID.randomUUID() + ".png", new ByteArrayProducer(tableImage.getImgBytes(), false)); |
} |
} catch (Exception e1) { |
// TODO popup??? |
e1.printStackTrace(); |
} |
} else { |
fill(elt.getAttributeValue("location"), result, spreadSheet.getSheet(sheet), OOElt.isTypeReplace(), OOElt.getReplacePattern(), null, false, OOElt.isMultilineAuto(), |
OOElt.isKeepingEmptyLines()); |
} |
} |
} |
} |
private static boolean isIncluded(int filterID, String foreignTable, int id, String fieldWhere, SQLRowAccessor rowElt) { |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationDoc/OOXMLCache.java |
---|
29,6 → 29,7 |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.utils.CompareUtils; |
import org.openconcerto.utils.ListMap; |
import org.openconcerto.utils.Tuple2; |
import org.openconcerto.utils.cc.ITransformer; |
import java.math.BigDecimal; |
39,16 → 40,30 |
import java.util.List; |
import java.util.Map; |
import org.jdom2.Element; |
public class OOXMLCache { |
private ITransformer<List<SQLRowAccessor>, List<SQLRowAccessor>> postProcess = null; |
private Map<SQLRowAccessor, Map<SQLTable, List<SQLRowAccessor>>> cacheReferent = new HashMap<SQLRowAccessor, Map<SQLTable, List<SQLRowAccessor>>>(); |
private Map<String, Map<Integer, SQLRowAccessor>> cacheForeign = new HashMap<String, Map<Integer, SQLRowAccessor>>(); |
private Map<Tuple2<String, SQLRowAccessor>, OOXMLTableImage> cacheImg = new HashMap<>(); |
public void setPostProcess(ITransformer<List<SQLRowAccessor>, List<SQLRowAccessor>> postProcess) { |
this.postProcess = postProcess; |
} |
public OOXMLTableImage getOOXMLTableImage(OOXMLElement x, Element e, SQLRowAccessor r) { |
Tuple2<String, SQLRowAccessor> key = Tuple2.create(e.getAttributeValue("fieldPathEDM"), r); |
if (this.cacheImg.containsKey(key)) { |
return this.cacheImg.get(key); |
} else { |
OOXMLTableImage img = new OOXMLTableImage(x, e, r); |
this.cacheImg.put(key, img); |
return img; |
} |
} |
protected SQLRowAccessor getForeignRow(SQLRowAccessor row, SQLField field) { |
Map<Integer, SQLRowAccessor> c = cacheForeign.get(field.getName()); |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/GenerationMvtSaisieKm.java |
---|
14,6 → 14,8 |
package org.openconcerto.erp.generationEcritures; |
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement; |
import org.openconcerto.erp.generationEcritures.provider.AccountingRecordsProvider; |
import org.openconcerto.erp.generationEcritures.provider.AccountingRecordsProviderManager; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowValues; |
28,6 → 30,8 |
private int idSaisieKm; |
private static final String source = "SAISIE_KM"; |
public static final String ID = "accounting.records.km"; |
public GenerationMvtSaisieKm(int idSaisieKm) { |
this.idSaisieKm = idSaisieKm; |
} |
47,8 → 51,15 |
this.putValue("ID_MOUVEMENT", new Integer(1)); |
// on calcule le nouveau numero de mouvement |
getNewMouvement(GenerationMvtSaisieKm.source, this.idSaisieKm, 1, (labelSaisie.length() == 0 ? "Saisie au km " : labelSaisie)); |
AccountingRecordsProvider provider = AccountingRecordsProviderManager.get(ID); |
SQLRowValues rowValsPiece = new SQLRowValues(pieceTable); |
rowValsPiece.put("NOM", (labelSaisie.length() == 0 ? "Saisie au km " : labelSaisie)); |
if (provider != null) { |
provider.putPieceLabel(saisieRow, rowValsPiece); |
} |
getNewMouvement(GenerationMvtSaisieKm.source, this.idSaisieKm, 1, rowValsPiece); |
// gnération des ecritures |
SQLTable tableElt = Configuration.getInstance().getRoot().findTable("SAISIE_KM_ELEMENT"); |
List<SQLRow> set = saisieRow.getReferentRows(tableElt); |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/GenerationReglementVenteNG.java |
---|
22,6 → 22,9 |
import org.openconcerto.erp.core.finance.payment.element.ModeDeReglementSQLElement; |
import org.openconcerto.erp.core.finance.payment.element.SEPAMandateSQLElement; |
import org.openconcerto.erp.core.finance.payment.element.TypeReglementSQLElement; |
import org.openconcerto.erp.core.finance.tax.model.TaxeCache; |
import org.openconcerto.erp.generationEcritures.provider.AccountingRecordsProvider; |
import org.openconcerto.erp.generationEcritures.provider.AccountingRecordsProviderManager; |
import org.openconcerto.erp.model.PrixTTC; |
import org.openconcerto.erp.preferences.GestionCommercialeGlobalPreferencePanel; |
import org.openconcerto.sql.Configuration; |
52,6 → 55,8 |
private static final SQLTable tablePrefCompte = base.getTable("PREFS_COMPTE"); |
private static final SQLRow rowPrefsCompte = tablePrefCompte.getRow(2); |
public static final String ID = "accounting.records.invoice.sales.payment"; |
public SQLRow ecrClient = null; |
public GenerationReglementVenteNG(String label, SQLRow rowClient, PrixTTC ttc, Date d, SQLRow modeReglement, SQLRow source, SQLRow mvtSource) throws SQLException { |
81,6 → 86,10 |
// TODO Nommage des ecritures |
this.nom = label; |
AccountingRecordsProvider provider = AccountingRecordsProviderManager.get(ID); |
if (provider != null) { |
provider.putLabel(source, this.mEcritures); |
} |
this.putValue("DATE", this.date); |
this.putValue("NOM", this.nom); |
236,6 → 245,31 |
this.putValue("CREDIT", Long.valueOf(0)); |
ajoutEcriture(); |
// FIXME remove getConf |
SQLRow rowSoc = ComptaPropsConfiguration.getInstanceCompta().getRowSociete(); |
if (rowSoc.getTable().contains("TVA_ENCAISSEMENT") && rowSoc.getBoolean("TVA_ENCAISSEMENT")) { |
SQLRow rowTaxe = TaxeCache.getCache().getFirstTaxe(); |
if (rowTaxe.contains("ID_COMPTE_PCE_COLLECTE_ENCAISSEMENT")) { |
SQLRowAccessor rowCompteTvaEnc = rowTaxe.getNonEmptyForeign("ID_COMPTE_PCE_COLLECTE_ENCAISSEMENT"); |
SQLRowAccessor rowCompteTvaCol = rowTaxe.getNonEmptyForeign("ID_COMPTE_PCE_COLLECTE"); |
if (rowCompteTvaCol != null && rowCompteTvaEnc != null) { |
Float taux = rowTaxe.getFloat("TAUX"); |
long tva = ttc.calculLongTVA(taux / 100.0); |
this.putValue("ID_COMPTE_PCE", rowCompteTvaCol.getID()); |
this.putValue("DEBIT", Long.valueOf(tva)); |
this.putValue("CREDIT", Long.valueOf(0)); |
ajoutEcriture(); |
this.putValue("ID_COMPTE_PCE", rowCompteTvaEnc.getID()); |
this.putValue("DEBIT", Long.valueOf(0)); |
this.putValue("CREDIT", Long.valueOf(tva)); |
ajoutEcriture(); |
} |
} |
} |
List<Integer> pieceIDs = new ArrayList<Integer>(); |
if (source.getTable().getName().equals("ENCAISSER_MONTANT")) { |
List<SQLRow> l = source.getReferentRows(base.getTable("ENCAISSER_MONTANT_ELEMENT")); |
299,9 → 333,13 |
SQLRowValues rowVals = new SQLRowValues(tableMouvement); |
rowVals.put("IDSOURCE", row.getID()); |
rowVals.update(this.idMvt); |
if (source.getTable().getName().equalsIgnoreCase("ENCAISSER_MONTANT")) { |
source.createEmptyUpdateRow().put("ID_MOUVEMENT", this.idMvt).commit(); |
} |
} |
} |
private void setDateReglement(SQLRow source, Date d) throws SQLException { |
List<SQLRow> sources = new ArrayList<SQLRow>(); |
460,4 → 498,5 |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/GenerationMvtAvoirFournisseur.java |
---|
109,12 → 109,14 |
if (rowFourn.getBoolean("UE")) { |
idCompteTVA = taxe.getForeignID("ID_COMPTE_PCE_DED_INTRA"); |
if (idCompteTVA <= 1) { |
idCompteTVA = rowPrefsCompte.getInt("ID_COMPTE_PCE_TVA_INTRA"); |
idCompteTVA = rowPrefsCompte.getInt("ID_COMPTE_PCE_TVA_ACHAT"); |
if (idCompteTVA <= 1) { |
idCompteTVA = ComptePCESQLElement.getIdComptePceDefault("TVAIntraComm"); |
idCompteTVA = ComptePCESQLElement.getIdComptePceDefault("TVADeductible"); |
} |
} |
} else { |
idCompteTVA = taxe.getForeignID("ID_COMPTE_PCE_DED"); |
if (idCompteTVA <= 1) { |
idCompteTVA = rowPrefsCompte.getInt("ID_COMPTE_PCE_TVA_ACHAT"); |
if (idCompteTVA <= 1) { |
idCompteTVA = ComptePCESQLElement.getIdComptePceDefault("TVADeductible"); |
121,6 → 123,7 |
} |
} |
} |
} |
this.putValue("ID_COMPTE_PCE", Integer.valueOf(idCompteTVA)); |
this.putValue("DEBIT", Long.valueOf(0)); |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/GenerationMvtFactureFournisseur.java |
---|
16,6 → 16,8 |
import org.openconcerto.erp.core.common.ui.TotalCalculator; |
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement; |
import org.openconcerto.erp.core.finance.accounting.element.JournalSQLElement; |
import org.openconcerto.erp.generationEcritures.provider.AccountingRecordsProvider; |
import org.openconcerto.erp.generationEcritures.provider.AccountingRecordsProviderManager; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.SQLRowValues; |
29,7 → 31,7 |
public class GenerationMvtFactureFournisseur extends GenerationEcritures implements Runnable { |
public static final String ID = "accounting.records.supply.order"; |
public static final String ID = "accounting.records.supplychain.order"; |
private int idFacture; |
private static final String source = "FACTURE_FOURNISSEUR"; |
65,6 → 67,11 |
// AccountingRecordsProvider provider = AccountingRecordsProviderManager.get(ID); |
// provider.putLabel(saisieRow, this.mEcritures); |
this.putValue("NOM", nom); |
AccountingRecordsProvider provider = AccountingRecordsProviderManager.get(ID); |
if (provider != null) { |
provider.putLabel(saisieRow, this.mEcritures); |
} |
this.putValue("ID_JOURNAL", GenerationMvtFactureFournisseur.journal); |
this.putValue("ID_MOUVEMENT", new Integer(1)); |
71,13 → 78,17 |
// on calcule le nouveau numero de mouvement |
if (this.idMvt == 1) { |
SQLRowValues rowValsPiece = new SQLRowValues(pieceTable); |
// provider.putPieceLabel(saisieRow, rowValsPiece); |
rowValsPiece.put("NOM", saisieRow.getObject("NUMERO").toString()); |
if (provider != null) { |
provider.putPieceLabel(saisieRow, rowValsPiece); |
} |
getNewMouvement(GenerationMvtFactureFournisseur.source, this.idFacture, 1, rowValsPiece); |
} else { |
SQLRowValues rowValsPiece = pieceTable.getTable("MOUVEMENT").getRow(idMvt).getForeign("ID_PIECE").asRowValues(); |
// provider.putPieceLabel(saisieRow, rowValsPiece); |
rowValsPiece.put("NOM", saisieRow.getObject("NUMERO").toString()); |
if (provider != null) { |
provider.putPieceLabel(saisieRow, rowValsPiece); |
} |
rowValsPiece.update(); |
this.putValue("ID_MOUVEMENT", new Integer(this.idMvt)); |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/GenerationMvtReglementChequeClient.java |
---|
13,9 → 13,10 |
package org.openconcerto.erp.generationEcritures; |
import org.openconcerto.erp.config.ComptaPropsConfiguration; |
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement; |
import org.openconcerto.erp.core.finance.accounting.element.JournalSQLElement; |
import org.openconcerto.erp.core.finance.accounting.element.MouvementSQLElement; |
import org.openconcerto.erp.core.finance.tax.model.TaxeCache; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.model.SQLRow; |
110,6 → 111,31 |
this.putValue("CREDIT", new Long(0)); |
ajoutEcriture(); |
// FIXME remove getConf |
SQLRow rowSoc = ComptaPropsConfiguration.getInstanceCompta().getRowSociete(); |
if (rowSoc.getTable().contains("TVA_ENCAISSEMENT") && rowSoc.getBoolean("TVA_ENCAISSEMENT")) { |
SQLRow rowTaxe = TaxeCache.getCache().getFirstTaxe(); |
if (rowTaxe.contains("ID_COMPTE_PCE_COLLECTE_ENCAISSEMENT")) { |
SQLRowAccessor rowCompteTvaEnc = rowTaxe.getNonEmptyForeign("ID_COMPTE_PCE_COLLECTE_ENCAISSEMENT"); |
SQLRowAccessor rowCompteTvaCol = rowTaxe.getNonEmptyForeign("ID_COMPTE_PCE_COLLECTE"); |
if (rowCompteTvaCol != null && rowCompteTvaEnc != null) { |
Float taux = rowTaxe.getFloat("TAUX"); |
long ht = Math.round(montant / (1.0 + (taux / 100.0))); |
long tva = montant - ht; |
this.putValue("ID_COMPTE_PCE", rowCompteTvaCol.getID()); |
this.putValue("DEBIT", Long.valueOf(tva)); |
this.putValue("CREDIT", Long.valueOf(0)); |
ajoutEcriture(); |
this.putValue("ID_COMPTE_PCE", rowCompteTvaEnc.getID()); |
this.putValue("DEBIT", Long.valueOf(0)); |
this.putValue("CREDIT", Long.valueOf(tva)); |
ajoutEcriture(); |
} |
} |
} |
List<Integer> pieceIDs = new ArrayList<Integer>(); |
pieceIDs.add(mouvementTable.getRow(idMvt).getForeignID("ID_PIECE")); |
lettrageAuto(pieceIDs, this.date); |
/trunk/OpenConcerto/src/org/openconcerto/erp/generationEcritures/GenerationReglementAchat.java |
---|
17,6 → 17,8 |
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement; |
import org.openconcerto.erp.core.finance.accounting.element.JournalSQLElement; |
import org.openconcerto.erp.core.finance.payment.element.ModeDeReglementSQLElement; |
import org.openconcerto.erp.generationEcritures.provider.AccountingRecordsProvider; |
import org.openconcerto.erp.generationEcritures.provider.AccountingRecordsProviderManager; |
import org.openconcerto.erp.model.PrixTTC; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowValues; |
35,6 → 37,10 |
public class GenerationReglementAchat extends GenerationEcritures { |
public static final String ID = "accounting.records.order.supplychain.payment"; |
// Journal Caisse |
private static final Integer journalCaisse = new Integer(JournalSQLElement.CAISSES); |
private static final SQLTable tablePrefCompte = base.getTable("PREFS_COMPTE"); |
61,6 → 67,10 |
// "Règlement achat" + SOURCE.getNom() ?? |
this.nom = "Règlement achat " + rowFournisseur.getString("NOM") + " (" + typeRegRow.getString("NOM") + ")"; |
AccountingRecordsProvider provider = AccountingRecordsProviderManager.get(ID); |
if (provider != null) { |
provider.putLabel(regMontantRow, this.mEcritures); |
} |
List<SQLRow> l = regMontantRow.getReferentRows(regMontantRow.getTable().getTable("REGLER_MONTANT_ELEMENT")); |
int mvtSource = -1; |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/reports/stat/action/ReportingCommercialFournisseurAction.java |
---|
New file |
0,0 → 1,43 |
/* |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
* |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved. |
* |
* The contents of this file are subject to the terms of the GNU General Public License Version 3 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific |
* language governing permissions and limitations under the License. |
* |
* When distributing the software, include this License Header Notice in each file. |
*/ |
package org.openconcerto.erp.core.reports.stat.action; |
import org.openconcerto.erp.action.CreateFrameAbstractAction; |
import org.openconcerto.erp.config.ComptaPropsConfiguration; |
import org.openconcerto.erp.core.common.ui.PanelFrame; |
import org.openconcerto.erp.core.customerrelationship.customer.report.ReportingCommercialFournisseurPanel; |
import org.openconcerto.sql.model.DBRoot; |
import javax.swing.Action; |
import javax.swing.JFrame; |
public class ReportingCommercialFournisseurAction extends CreateFrameAbstractAction { |
private static final String TITLE = "CA par commercial/fournisseur"; |
private DBRoot root; |
public ReportingCommercialFournisseurAction(ComptaPropsConfiguration conf) { |
super(); |
this.root = conf.getRootSociete(); |
this.putValue(Action.NAME, TITLE); |
this.mustLoadState = false; |
} |
public JFrame createFrame() { |
final PanelFrame panelFrame = new PanelFrame(new ReportingCommercialFournisseurPanel(this.root), TITLE); |
panelFrame.setResizable(false); |
return panelFrame; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/reports/history/ui/HistoriqueClientFrame.java |
---|
56,6 → 56,7 |
mapList.put("Echéances", Arrays.asList("ECHEANCE_CLIENT")); |
mapList.put("Relances", Arrays.asList("RELANCE")); |
mapList.put("Devis", Arrays.asList("DEVIS")); |
mapList.put("Commandes", Arrays.asList("COMMANDE_CLIENT")); |
mapList.put("Avoirs", Arrays.asList("AVOIR_CLIENT")); |
mapList.put("Articles facturés", Arrays.asList("SAISIE_VENTE_FACTURE_ELEMENT")); |
mapList.put("Articles proposés", Arrays.asList("DEVIS_ELEMENT")); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/stock/element/StockItem.java |
---|
96,13 → 96,13 |
} |
StockItemComponent comp = components.get(0); |
double real = comp.getItem().getRealQty() == 0 ? 0 : Math.ceil(comp.getItem().getRealQty() / (comp.getQty() * comp.getQtyUnit().doubleValue())); |
double virtual = comp.getItem().getVirtualQty() == 0 ? 0 : Math.ceil(comp.getItem().getVirtualQty() / (comp.getQty() * comp.getQtyUnit().doubleValue())); |
double real = comp.getItem().getRealQty() == 0 ? 0 : Math.floor(comp.getItem().getRealQty() / (comp.getQty() * comp.getQtyUnit().doubleValue())); |
double virtual = comp.getItem().getVirtualQty() == 0 ? 0 : Math.floor(comp.getItem().getVirtualQty() / (comp.getQty() * comp.getQtyUnit().doubleValue())); |
for (StockItemComponent stockItemComponent : components) { |
real = Math.min(real, stockItemComponent.getItem().getRealQty() == 0 ? 0 |
: Math.ceil(stockItemComponent.getItem().getRealQty() / (stockItemComponent.getQty() * stockItemComponent.getQtyUnit().doubleValue()))); |
: Math.floor(stockItemComponent.getItem().getRealQty() / (stockItemComponent.getQty() * stockItemComponent.getQtyUnit().doubleValue()))); |
virtual = Math.min(virtual, stockItemComponent.getItem().getVirtualQty() == 0 ? 0 |
: Math.ceil(stockItemComponent.getItem().getVirtualQty() / (stockItemComponent.getQty() * stockItemComponent.getQtyUnit().doubleValue()))); |
: Math.floor(stockItemComponent.getItem().getVirtualQty() / (stockItemComponent.getQty() * stockItemComponent.getQtyUnit().doubleValue()))); |
} |
// La quantité du kit ne peut être négative |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/stock/element/ComposedItemStockUpdater.java |
---|
21,6 → 21,8 |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.SQLSelectJoin; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.model.SQLTableEvent; |
import org.openconcerto.sql.model.SQLTableEvent.Mode; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.request.UpdateBuilder; |
import org.openconcerto.sql.utils.SQLUtils; |
114,8 → 116,9 |
for (String s : requests) { |
handlers.add(null); |
} |
// FIXME FIRE TABLE CHANGED TO UPDATE ILISTE ?? |
SQLUtils.executeMultiple(stockTable.getDBSystemRoot(), requests, handlers); |
stockTable.fire(new SQLTableEvent(stockTable, SQLRow.NONEXISTANT_ID, Mode.ROW_UPDATED)); |
} |
/** |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/stock/element/InventaireFromEtatStockImporter.java |
---|
385,7 → 385,7 |
} else { |
boolean contains = false; |
for (SQLRowValues sqlRowValues2 : referentRows) { |
if (!sqlRowValues2.isForeignEmpty("ID_ARTICLE") && sqlRowValues2.getForeign("ID_ARTICLE") != null && sqlRowValues2.getForeign("ID_ARTICLE").getString("CODE") != null) { |
if (sqlRowValues2.getForeign("ID_ARTICLE") != null && !sqlRowValues2.isForeignEmpty("ID_ARTICLE") && sqlRowValues2.getForeign("ID_ARTICLE").getString("CODE") != null) { |
if (codeKits.contains(sqlRowValues2.getForeign("ID_ARTICLE").getString("CODE"))) { |
contains = true; |
break; |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/supplier/action/NouvelHistoriqueListeFournAction.java |
---|
45,7 → 45,11 |
// l.add("SAISIE_ACHAT"); |
// l.add("CHEQUE_FOURNISSEUR"); |
Map<String, List<String>> mapList = new HashMap<String, List<String>>(); |
mapList.put("Commandes", Arrays.asList("COMMANDE")); |
mapList.put("Bons de réception", Arrays.asList("BON_RECEPTION")); |
mapList.put("Factures", Arrays.asList("FACTURE_FOURNISSEUR")); |
mapList.put("Achats", Arrays.asList("SAISIE_ACHAT")); |
mapList.put("Avoirs", Arrays.asList("AVOIR_FOURNISSEUR")); |
mapList.put("Chèques émis", Arrays.asList("CHEQUE_FOURNISSEUR")); |
final HistoriqueFournBilanPanel panelBilan = new HistoriqueFournBilanPanel(); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/supplier/component/FournisseurSQLComponent.java |
---|
378,7 → 378,7 |
// BIC |
JLabel labelBIC = new JLabel("BIC", SwingConstants.RIGHT); |
JTextField textBIC = new JTextField(12); |
JTextField textBIC = new JTextField(20); |
c2.gridx = 0; |
c2.gridy++; |
c2.weightx = 0; |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/purchase/importer/FacturXExporter.java |
---|
13,16 → 13,25 |
package org.openconcerto.erp.core.supplychain.purchase.importer; |
import org.openconcerto.erp.core.finance.payment.element.ModeDeReglementSQLElement; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.SQLRowValuesListFetcher; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.model.Where; |
import java.math.BigDecimal; |
import java.text.DecimalFormat; |
import java.text.DecimalFormatSymbols; |
import java.text.SimpleDateFormat; |
import java.util.ArrayList; |
import java.util.Collection; |
import java.util.Date; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Locale; |
import java.util.Map; |
import org.jdom2.Document; |
import org.jdom2.Element; |
34,18 → 43,27 |
* FacturX export (EN 16931 format) |
*/ |
public class FacturXExporter { |
private class Tax { |
// Taux, ex pour 20% : 20.00 |
BigDecimal rate; |
final BigDecimal rate; |
// Montant de la TVA |
BigDecimal amount; |
BigDecimal amount = BigDecimal.ZERO; |
// montant HT sur lequel s'applique la TVA |
BigDecimal basisAmount; |
BigDecimal basisAmount = BigDecimal.ZERO; |
public Tax(BigDecimal rate) { |
this.rate = rate; |
} |
public void add(BigDecimal taxAmount, |
BigDecimal basisAmount) { |
this.amount = this.amount.add(taxAmount); |
this.basisAmount = this.basisAmount.add(basisAmount); |
} |
} |
public static Namespace QDT_NS = Namespace.getNamespace("qdt", "urn:un:unece:uncefact:data:standard:QualifiedDataType:100"); |
public static Namespace RAM_NS = Namespace.getNamespace("ram", "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"); |
public static Namespace RSM_NS = Namespace.getNamespace("rsm", "urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"); |
56,26 → 74,55 |
FacturXExporter ex = new FacturXExporter(); |
System.err.println("FacturXExporter.main() " + ex.checkEAN13("5987854125989")); |
String xml = ex.createXMLFrom(null, 1); |
System.out.println(xml); |
// String xml = ex.createXMLFrom(null, 1); |
// System.out.println(xml); |
} |
public String createXMLFrom(DBRoot row, int invoiceId) { |
DecimalFormat formatAmount = new DecimalFormat("#0.00", DecimalFormatSymbols.getInstance(Locale.ENGLISH)); |
List<Tax> taxes = new ArrayList<>(); |
Tax t1 = new Tax(); |
t1.rate = new BigDecimal("20.0"); |
t1.amount = new BigDecimal("40.0"); |
t1.basisAmount = new BigDecimal("200.0"); |
taxes.add(t1); |
private boolean useCommonClient = false; |
DecimalFormat format = new DecimalFormat("#0.00", DecimalFormatSymbols.getInstance(Locale.ENGLISH)); |
public String createXMLFrom(DBRoot dbRoot, int invoiceId, SQLRow societeRow) { |
SQLTable factureTable = dbRoot.getTable("SAISIE_VENTE_FACTURE"); |
SQLRowValues rowValsToFetch = new SQLRowValues(factureTable); |
rowValsToFetch.putNulls("NUMERO", "DATE", "NOM", "T_TVA", "T_HT", "T_TTC", "NET_A_PAYER"); |
rowValsToFetch.putRowValues("ID_MODE_REGLEMENT").putNulls("COMPTANT", "AJOURS", "LENJOUR", "DATE_FACTURE", "FIN_MOIS").putRowValues("ID_TYPE_REGLEMENT").putNulls("NOM"); |
SQLRowValues putRowValuesClient = rowValsToFetch.putRowValues("ID_CLIENT"); |
putRowValuesClient.putNulls("NOM", "RESPONSABLE", "SIRET", "NUMERO_TVA", "MAIL", "TEL"); |
if (putRowValuesClient.getTable().contains("ID_CLIENT")) { |
this.useCommonClient = true; |
putRowValuesClient.putRowValues("ID_CLIENT").putNulls("NOM", "RESPONSABLE", "SIRET", "NUMERO_TVA", "MAIL", "TEL").putRowValues("ID_ADRESSE").putNulls("RUE", "VILLE", "CODE_POSTAL", |
"PAYS"); |
} |
putRowValuesClient.putRowValues("ID_ADRESSE").putNulls("RUE", "VILLE", "CODE_POSTAL", "PAYS"); |
putRowValuesClient.putRowValues("ID_ADRESSE_F").putNulls("RUE", "VILLE", "CODE_POSTAL", "PAYS"); |
rowValsToFetch.putRowValues("ID_ADRESSE").putNulls("RUE", "VILLE", "CODE_POSTAL", "PAYS"); |
SQLTable factureItemtable = dbRoot.getTable("SAISIE_VENTE_FACTURE_ELEMENT"); |
SQLRowValues rowValsItemsToFetch = new SQLRowValues(factureItemtable); |
rowValsItemsToFetch.putNulls("NIVEAU", "CODE", "NOM", "QTE", "QTE_UNITAIRE", "PV_HT", "T_PV_HT", "T_PV_TTC").putRowValues("ID_TAXE").put("TAUX", null); |
rowValsItemsToFetch.put("ID_SAISIE_VENTE_FACTURE", rowValsToFetch); |
List<SQLRowValues> factures = SQLRowValuesListFetcher.create(rowValsToFetch).fetch(new Where(factureTable.getKey(), "=", invoiceId)); |
SQLRowValues facture = factures.get(0); |
Collection<? extends SQLRowAccessor> factureItems = facture.getReferentRows(factureItemtable.getField("ID_SAISIE_VENTE_FACTURE")); |
Map<Integer, Tax> taxes = new HashMap<>(); |
// Tax t1 = new Tax(); |
// t1.rate = new BigDecimal("20.0"); |
// t1.amount = new BigDecimal("40.0"); |
// t1.basisAmount = new BigDecimal("200.0"); |
// taxes.add(t1); |
DecimalFormat fQty = new DecimalFormat("#0.########", DecimalFormatSymbols.getInstance(Locale.ENGLISH)); |
String invoiceNumber = "-"; |
Date invoiceDate = new Date(); |
String regNote = "SARL au capital de 50 000 EUR"; |
String legNote = "RCS MAVILLE 123 456 789"; |
int nbLines = 4; |
String invoiceNumber = facture.getString("NUMERO"); |
Date invoiceDate = facture.getDate("DATE").getTime(); |
String regNote = societeRow.getString("TYPE") + " au capital de " + societeRow.getObject("CAPITAL") + " €"; |
String legNote = societeRow.getString("RCS"); |
int nbLines = factureItems.size(); |
final Document doc = new Document(); |
Element root = new Element("CrossIndustryInvoice", RSM_NS); |
132,21 → 179,40 |
// SupplyChainTradeTransaction |
Element eSupplyChainTradeTransaction = new Element("SupplyChainTradeTransaction", RSM_NS); |
for (int i = 0; i < nbLines; i++) { |
String productCode = "a"; |
String productName = "b"; |
int lineID = 1; |
for (SQLRowAccessor rowItem : factureItems) { |
String productCode = rowItem.getString("CODE"); |
String productName = rowItem.getString("NOM").trim().length() == 0 ? "Ligne" : rowItem.getString("NOM"); |
BigDecimal pHT = new BigDecimal("12.46"); |
BigDecimal tax = new BigDecimal("0.20"); |
BigDecimal pTTC = new BigDecimal("14.95"); |
BigDecimal qte = new BigDecimal("10.0"); |
BigDecimal totalHTLigne = new BigDecimal("124.60"); |
final BigDecimal pHT, pTTC, totalHTLigne, totalTTCLigne; |
SQLRowAccessor taxeItem = rowItem.getForeign("ID_TAXE"); |
BigDecimal taxValue = new BigDecimal(taxeItem.getFloat("TAUX")).setScale(2); |
if (rowItem.getInt("NIVEAU") != 1) { |
pHT = BigDecimal.ZERO; |
pTTC = BigDecimal.ZERO; |
totalHTLigne = BigDecimal.ZERO; |
totalTTCLigne = BigDecimal.ZERO; |
} else { |
pHT = rowItem.getBigDecimal("PV_HT"); |
pTTC = pHT.multiply(taxValue.add(BigDecimal.ONE)); |
totalHTLigne = rowItem.getBigDecimal("T_PV_HT"); |
totalTTCLigne = rowItem.getBigDecimal("T_PV_TTC"); |
} |
int idTaxe = taxeItem.getID(); |
if (!taxes.containsKey(idTaxe)) { |
Tax t = new Tax(taxValue); |
taxes.put(idTaxe, t); |
} |
taxes.get(idTaxe).add(totalTTCLigne.subtract(totalHTLigne), totalHTLigne); |
BigDecimal qte = new BigDecimal(rowItem.getInt("QTE")).multiply(rowItem.getBigDecimal("QTE_UNITAIRE")); |
Element eLineItem = new Element("IncludedSupplyChainTradeLineItem", RAM_NS); |
// AssociatedDocumentLineDocument |
Element eAssociatedDocumentLineDocument = new Element("AssociatedDocumentLineDocument", RAM_NS); |
Element eLineID = new Element("LineID", RAM_NS); |
eLineID.setText(String.valueOf(i + 1)); |
eLineID.setText(String.valueOf(lineID++)); |
eAssociatedDocumentLineDocument.addContent(eLineID); |
eLineItem.addContent(eAssociatedDocumentLineDocument); |
// SpecifiedTradeProduct |
176,11 → 242,11 |
// Prix unitaire TTC |
Element eGrossPriceProductTradePrice = new Element("GrossPriceProductTradePrice", RAM_NS); |
Element eChargeAmount = new Element("ChargeAmount", RAM_NS); |
eChargeAmount.setText(format.format(pTTC)); |
eChargeAmount.setText(formatAmount.format(pTTC)); |
eGrossPriceProductTradePrice.addContent(eChargeAmount); |
Element eAppliedTradeAllowanceCharge = new Element("AppliedTradeAllowanceCharge", RAM_NS); |
Element eChargeIndicator = new Element("ChargeIndicator", RAM_NS); |
Element eIndicator = new Element("ChargeIndicator", UDT_NS); |
Element eIndicator = new Element("Indicator", UDT_NS); |
// pas de remise |
eIndicator.setText("false"); |
eChargeIndicator.addContent(eIndicator); |
188,17 → 254,17 |
Element eActualAmount = new Element("ActualAmount", RAM_NS); |
// Montant de TVA (unitaire) |
eActualAmount.setText(format.format(pTTC.subtract(pHT))); |
eActualAmount.setText(formatAmount.format(pTTC.subtract(pHT))); |
eAppliedTradeAllowanceCharge.addContent(eActualAmount); |
eGrossPriceProductTradePrice.addContent(eAppliedTradeAllowanceCharge); |
// eGrossPriceProductTradePrice.addContent(eAppliedTradeAllowanceCharge); |
eSpecifiedLineTradeAgreement.addContent(eGrossPriceProductTradePrice); |
// Prix unitaire HT |
Element eNetPriceProductTradePrice = new Element("NetPriceProductTradePrice", RAM_NS); |
Element eChargeAmountHT = new Element("ChargeAmount", RAM_NS); |
eChargeAmountHT.setText(format.format(pHT)); |
eChargeAmountHT.setText(formatAmount.format(pHT)); |
eNetPriceProductTradePrice.addContent(eChargeAmountHT); |
eSpecifiedLineTradeAgreement.addContent(eNetPriceProductTradePrice); |
240,7 → 306,7 |
Element eRateApplicablePercent = new Element("RateApplicablePercent", RAM_NS); |
// 20% -> 20.0 |
eRateApplicablePercent.setText(format.format(tax.multiply(new BigDecimal(100)))); |
eRateApplicablePercent.setText(formatAmount.format(taxValue)); |
eApplicableTradeTaxt.addContent(eRateApplicablePercent); |
eSpecifiedLineTradeSettlement.addContent(eApplicableTradeTaxt); |
248,7 → 314,7 |
Element eSpecifiedTradeSettlementLineMonetarySummation = new Element("SpecifiedTradeSettlementLineMonetarySummation", RAM_NS); |
// Total HT |
Element eLineTotalAmount = new Element("LineTotalAmount", RAM_NS); |
eLineTotalAmount.setText(format.format(totalHTLigne)); |
eLineTotalAmount.setText(formatAmount.format(totalHTLigne)); |
eSpecifiedTradeSettlementLineMonetarySummation.addContent(eLineTotalAmount); |
eSpecifiedLineTradeSettlement.addContent(eSpecifiedTradeSettlementLineMonetarySummation); |
257,12 → 323,11 |
eSupplyChainTradeTransaction.addContent(eLineItem); |
} |
addApplicableHeader(eSupplyChainTradeTransaction, taxes); |
root.addContent(ed); |
addApplicableHeader(societeRow, facture, eSupplyChainTradeTransaction, taxes.values()); |
ed.addContent(eSupplyChainTradeTransaction); |
root.addContent(eSupplyChainTradeTransaction); |
root.addContent(ed); |
final XMLOutputter xmlOutput = new XMLOutputter(); |
xmlOutput.setFormat(Format.getPrettyFormat()); |
return xmlOutput.outputString(doc); |
273,22 → 338,25 |
parent.addContent(element); |
} |
private void addApplicableHeader(Element eSupplyChainTradeTransaction, List<Tax> taxes) { |
private void addApplicableHeader(SQLRowAccessor rowSociete, SQLRowAccessor rowFacture, Element eSupplyChainTradeTransaction, Collection<Tax> taxes) { |
// |
// ApplicableHeaderTradeAgreement |
// |
final Element eApplicableHeaderTradeAgreement = new Element("ApplicableHeaderTradeAgreement", RAM_NS); |
addSupplierInfo(eApplicableHeaderTradeAgreement); |
addBuyerInfo(eApplicableHeaderTradeAgreement); |
addSupplierInfo(eApplicableHeaderTradeAgreement, rowSociete); |
addBuyerInfo(eApplicableHeaderTradeAgreement, rowFacture); |
String orderRef = ""; |
String contractRef = ""; |
// Date de livraison, facultative |
Date effectiveDeliveryDate = new Date(65454654); |
String invoiceNumber = "FA-2017-0010"; |
Date effectiveDeliveryDate = rowFacture.getDate("DATE").getTime(); |
String invoiceNumber = rowFacture.getString("NUMERO"); |
String currencyCode = "EUR"; |
String dueDescription = "30% d'acompte, solde à 30 j"; |
Date dueDate = new Date(65455654); |
SQLRowAccessor foreignMdr = rowFacture.getForeign("ID_MODE_REGLEMENT"); |
int ajours = foreignMdr.getInt("AJOURS"); |
int lenjour = foreignMdr.getInt("LENJOUR"); |
String dueDescription = (ajours > 0 ? "A " + ajours : "") + (lenjour > 0 ? " le " + lenjour : ""); |
Date dueDate = ModeDeReglementSQLElement.calculDate(foreignMdr, rowFacture.getDate("DATE").getTime()); |
final Element eBuyerOrderReferencedDocument = new Element("BuyerOrderReferencedDocument", RAM_NS); |
addValue(eBuyerOrderReferencedDocument, new Element("IssuerAssignedID", RAM_NS), orderRef); |
330,6 → 398,7 |
addValue(eApplicableHeaderTradeSettlement, new Element("PaymentReference", RAM_NS), invoiceNumber); |
addValue(eApplicableHeaderTradeSettlement, new Element("InvoiceCurrencyCode", RAM_NS), currencyCode); |
final Element aSpecifiedTradeSettlementPaymentMeans = new Element("SpecifiedTradeSettlementPaymentMeans", RAM_NS); |
addValue(aSpecifiedTradeSettlementPaymentMeans, new Element("TypeCode", RAM_NS), "57"); |
// <ram:TypeCode>30</ram:TypeCode> |
// <ram:Information>Virement sur compte Banque Fiducial</ram:Information> |
380,7 → 449,38 |
eApplicableHeaderTradeSettlement.addContent(eSpecifiedTradePaymentTerms); |
final Element eSpecifiedTradeSettlementHeaderMonetarySummation = new Element("SpecifiedTradeSettlementHeaderMonetarySummation", RAM_NS); |
final Element eTotalHT = new Element("LineTotalAmount", RAM_NS); |
eTotalHT.setText(this.formatAmount.format(new BigDecimal(rowFacture.getLong("T_HT")).movePointLeft(2))); |
eSpecifiedTradeSettlementHeaderMonetarySummation.addContent(eTotalHT); |
final Element eTotalBaseTVA = new Element("TaxBasisTotalAmount", RAM_NS); |
BigDecimal totalBaseTVA = BigDecimal.ZERO; |
for (Tax tax : taxes) { |
totalBaseTVA = totalBaseTVA.add(tax.basisAmount); |
} |
eTotalBaseTVA.setText(this.formatAmount.format(totalBaseTVA)); |
eSpecifiedTradeSettlementHeaderMonetarySummation.addContent(eTotalBaseTVA); |
final Element eTotalTVA = new Element("TaxTotalAmount", RAM_NS); |
eTotalTVA.setAttribute("currencyID", "EUR"); |
eTotalTVA.setText(this.formatAmount.format(new BigDecimal(rowFacture.getLong("T_TVA")).movePointLeft(2))); |
eSpecifiedTradeSettlementHeaderMonetarySummation.addContent(eTotalTVA); |
final Element eTotalTTC = new Element("GrandTotalAmount", RAM_NS); |
BigDecimal totalTTC = new BigDecimal(rowFacture.getLong("T_TTC")).movePointLeft(2); |
eTotalTTC.setText(this.formatAmount.format(totalTTC)); |
eSpecifiedTradeSettlementHeaderMonetarySummation.addContent(eTotalTTC); |
final Element eTotalPrepaid = new Element("TotalPrepaidAmount", RAM_NS); |
BigDecimal netApayer = new BigDecimal(rowFacture.getLong("NET_A_PAYER")).movePointLeft(2); |
eTotalPrepaid.setText(this.formatAmount.format(totalTTC.subtract(netApayer))); |
eSpecifiedTradeSettlementHeaderMonetarySummation.addContent(eTotalPrepaid); |
final Element eTotalDue = new Element("DuePayableAmount", RAM_NS); |
eTotalDue.setText(this.formatAmount.format(netApayer)); |
eSpecifiedTradeSettlementHeaderMonetarySummation.addContent(eTotalDue); |
// Total HT |
// <ram:LineTotalAmount>624.90</ram:LineTotalAmount> |
// Total HT sur leque est appliqué la TVA |
400,20 → 500,35 |
} |
private void addBuyerInfo(final Element eApplicableHeaderTradeAgreement) { |
private void addBuyerInfo(final Element eApplicableHeaderTradeAgreement, final SQLRowAccessor rowFacture) { |
SQLRowAccessor client = rowFacture.getForeign("ID_CLIENT"); |
SQLRowAccessor clientGestion = client; |
if (this.useCommonClient) { |
client = client.getForeign("ID_CLIENT"); |
} |
final SQLRowAccessor adr; |
if (!rowFacture.isForeignEmpty("ID_ADRESSE")) { |
adr = rowFacture.getForeign("ID_ADRESSE"); |
} else if (!clientGestion.isForeignEmpty("ID_ADRESSE_F")) { |
adr = clientGestion.getForeign("ID_ADRESSE_F"); |
} else { |
adr = client.getForeign("ID_ADRESSE"); |
} |
// Acheteur |
String buyerName = "Ma jolie boutique"; |
String buyerSIRET = "78787878400035"; |
String buyerVAT = "FR19787878784"; |
String buyerContactName = "Alexandre Payet"; |
String buyerPhone = "+33 4 72 07 08 67"; |
String buyerEmail = "alexandre.payet@majolieboutique.net"; |
String buyerAddrL1 = "35 rue de la République"; |
String buyerName = client.getString("NOM"); |
String buyerSIRET = client.getString("SIRET"); |
String buyerVAT = client.getString("NUMERO_TVA"); |
String buyerContactName = client.getString("RESPONSABLE"); |
String buyerPhone = client.getString("TEL"); |
String buyerEmail = client.getString("MAIL"); |
String buyerAddrL1 = adr.getString("RUE"); |
String buyerAddrL2 = ""; |
String buyerAddrL3 = ""; |
String buyerPostalCode = "69001"; |
String buyerCity = "Lyon"; |
String buyerCountryCode = "FR"; |
String buyerPostalCode = adr.getString("CODE_POSTAL"); |
String buyerCity = adr.getString("VILLE"); |
String buyerCountryCode = resolveCountryCode(adr.getString("PAYS")); |
final Element eBuyerTradeParty = new Element("BuyerTradeParty", RAM_NS); |
this.addValue(eBuyerTradeParty, new Element("Name", RAM_NS), buyerName); |
439,19 → 554,20 |
eBuyerTradeParty.addContent(eDefinedTradeContact); |
// Adresse postale |
final Element ePostalTradeAddress = new Element("PostalTradeAddress", RAM_NS); |
addValue(ePostalTradeAddress, new Element("LineOne>", RAM_NS), buyerAddrL1); |
addValue(ePostalTradeAddress, new Element("PostcodeCode", RAM_NS), buyerPostalCode); |
addValue(ePostalTradeAddress, new Element("LineOne", RAM_NS), buyerAddrL1); |
if (buyerAddrL2 != null && !buyerAddrL2.trim().isEmpty()) { |
addValue(ePostalTradeAddress, new Element("LineTwo>", RAM_NS), buyerAddrL2); |
addValue(ePostalTradeAddress, new Element("LineTwo", RAM_NS), buyerAddrL2); |
} |
if (buyerAddrL3 != null && !buyerAddrL3.trim().isEmpty()) { |
addValue(ePostalTradeAddress, new Element("LineThree>", RAM_NS), buyerAddrL3); |
addValue(ePostalTradeAddress, new Element("LineThree", RAM_NS), buyerAddrL3); |
} |
addValue(ePostalTradeAddress, new Element("PostcodeCode>", RAM_NS), buyerPostalCode); |
addValue(ePostalTradeAddress, new Element("CityName>", RAM_NS), buyerCity); |
addValue(ePostalTradeAddress, new Element("CountryID>", RAM_NS), buyerCountryCode); |
addValue(ePostalTradeAddress, new Element("CityName", RAM_NS), buyerCity); |
addValue(ePostalTradeAddress, new Element("CountryID", RAM_NS), buyerCountryCode); |
eBuyerTradeParty.addContent(ePostalTradeAddress); |
if (buyerVAT != null && buyerVAT.trim().length() > 0) { |
// TVA |
final Element eSpecifiedTaxRegistration = new Element("SpecifiedTaxRegistration", RAM_NS); |
final Element eSpecifiedTaxRegistrationId = new Element("ID", RAM_NS); |
459,23 → 575,24 |
eSpecifiedTaxRegistrationId.setText(buyerVAT); |
eSpecifiedTaxRegistration.addContent(eSpecifiedTaxRegistrationId); |
eBuyerTradeParty.addContent(eSpecifiedTaxRegistration); |
} |
eApplicableHeaderTradeAgreement.addContent(eBuyerTradeParty); |
} |
private void addSupplierInfo(final Element eApplicableHeaderTradeAgreement) { |
String supplierName = "Au bon moulin"; |
String supplierSIRET = "121321321321"; |
String supplierContactName = "Tony Dubois"; |
String supplierContactPhone = "+33 4 72 07 08 56"; |
String supplierContactEmail = "tony.dubois@aubonmoulin.fr"; |
String supplierAddrL1 = "3 rue du pont"; |
private void addSupplierInfo(final Element eApplicableHeaderTradeAgreement, SQLRowAccessor rowSociete) { |
String supplierName = rowSociete.getString("NOM"); |
String supplierSIRET = rowSociete.getString("NUM_SIRET"); |
String supplierContactName = ""; |
String supplierContactPhone = rowSociete.getString("NUM_TEL"); |
String supplierContactEmail = rowSociete.getString("MAIL"); |
SQLRowAccessor adr = rowSociete.getForeign("ID_ADRESSE_COMMON"); |
String supplierAddrL1 = adr.getString("RUE"); |
String supplierAddrL2 = ""; |
String supplierAddrL3 = ""; |
String supplierAddrPostalCode = "80100"; |
String supplierAddrCityName = "Abbeville"; |
String supplierAddrCountryID = "FR"; |
String supplierNumTVA = "FR121321321321"; |
String supplierAddrPostalCode = adr.getString("CODE_POSTAL"); |
String supplierAddrCityName = adr.getString("VILLE"); |
String supplierAddrCountryID = resolveCountryCode(adr.getString("PAYS")); |
String supplierNumTVA = rowSociete.getString("NUM_NII"); |
// Vendeur |
final Element eSellerTradeParty = new Element("SellerTradeParty", RAM_NS); |
addValue(eSellerTradeParty, new Element("Name", RAM_NS), supplierName); |
507,6 → 624,7 |
eSellerTradeParty.addContent(eDefinedTradeContact); |
final Element ePostalTradeAddress = new Element("PostalTradeAddress", RAM_NS); |
addValue(ePostalTradeAddress, new Element("PostcodeCode", RAM_NS), supplierAddrPostalCode); |
addValue(ePostalTradeAddress, new Element("LineOne", RAM_NS), supplierAddrL1); |
if (supplierAddrL2 != null && !supplierAddrL2.trim().isEmpty()) { |
addValue(ePostalTradeAddress, new Element("LineTwo", RAM_NS), supplierAddrL2); |
514,7 → 632,6 |
if (supplierAddrL3 != null && !supplierAddrL3.trim().isEmpty()) { |
addValue(ePostalTradeAddress, new Element("LineThree", RAM_NS), supplierAddrL3); |
} |
addValue(ePostalTradeAddress, new Element("PostcodeCode", RAM_NS), supplierAddrPostalCode); |
addValue(ePostalTradeAddress, new Element("CityName", RAM_NS), supplierAddrCityName); |
addValue(ePostalTradeAddress, new Element("CountryID", RAM_NS), supplierAddrCountryID); |
568,4 → 685,56 |
} |
return Integer.valueOf(code.substring(12, 13)).intValue() == checkdigit; |
} |
private String resolveCountryCode(String pays) { |
if (pays == null || pays.trim().length() == 0) { |
return "FR"; |
} else if (pays.toLowerCase().equals("france")) { |
return "FR"; |
} else if (pays.toLowerCase().equals("fr")) { |
return "FR"; |
} else if (pays.toLowerCase().equals("polska")) { |
return "PL"; |
} else if (pays.toLowerCase().equals("pologne")) { |
return "PL"; |
} else if (pays.toLowerCase().equals("pl")) { |
return "PL"; |
} else if (pays.toLowerCase().equals("allemagne")) { |
return "DE"; |
} else if (pays.toLowerCase().equals("de")) { |
return "DE"; |
} else if (pays.toLowerCase().equals("deutschland")) { |
return "DE"; |
} else if (pays.toLowerCase().equals("italie")) { |
return "IT"; |
} else if (pays.toLowerCase().equals("italy")) { |
return "IT"; |
} else if (pays.toLowerCase().equals("italia")) { |
return "IT"; |
} else if (pays.toLowerCase().equals("it")) { |
return "IT"; |
} else if (pays.toLowerCase().equals("espagne")) { |
return "SP"; |
} else if (pays.toLowerCase().equals("spain")) { |
return "SP"; |
} else if (pays.toLowerCase().equals("sp")) { |
return "SP"; |
} else if (pays.toLowerCase().equals("luxembourg")) { |
return "LU"; |
} else if (pays.toLowerCase().equals("lu")) { |
return "LU"; |
} else if (pays.toLowerCase().equals("portugal")) { |
return "PT"; |
} else if (pays.toLowerCase().equals("pt")) { |
return "PT"; |
} else if (pays.toLowerCase().equals("belgique")) { |
return "BE"; |
} else if (pays.toLowerCase().equals("belgium")) { |
return "BE"; |
} else if (pays.toLowerCase().equals("be")) { |
return "BE"; |
} else { |
return ""; |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/component/CommandeSQLComponent.java |
---|
95,19 → 95,19 |
public class CommandeSQLComponent extends TransfertBaseSQLComponent { |
private CommandeItemTable table = new CommandeItemTable(); |
private PanelOOSQLComponent panelOO; |
protected CommandeItemTable table = new CommandeItemTable(); |
protected PanelOOSQLComponent panelOO; |
private JUniqueTextField numeroUniqueCommande; |
private final SQLTable tableNum = getTable().getBase().getTable("NUMEROTATION_AUTO"); |
private final ITextArea infos = new ITextArea(3, 3); |
private ElementComboBox fourn = new ElementComboBox(); |
private final JCheckBox boxLivrClient = new JCheckBox("Livrer directement le client"); |
private DefaultElementSQLObject compAdr; |
final JPanel panelAdrSpec = new JPanel(new GridBagLayout()); |
protected JUniqueTextField numeroUniqueCommande; |
protected final SQLTable tableNum = getTable().getBase().getTable("NUMEROTATION_AUTO"); |
protected final ITextArea infos = new ITextArea(3, 3); |
protected ElementComboBox fourn = new ElementComboBox(); |
protected final JCheckBox boxLivrClient = new JCheckBox("Livrer directement le client"); |
protected DefaultElementSQLObject compAdr; |
protected final JPanel panelAdrSpec = new JPanel(new GridBagLayout()); |
protected ElementComboBox boxAdr; |
private JDate dateCommande = new JDate(true); |
private ElementSQLObject componentPrincipaleAdr; |
protected JDate dateCommande = new JDate(true); |
protected ElementSQLObject componentPrincipaleAdr; |
public CommandeSQLComponent() { |
super(Configuration.getInstance().getDirectory().getElement("COMMANDE")); |
571,7 → 571,7 |
c.anchor = GridBagConstraints.EAST; |
this.add(new JLabel(getLabelFor("NOM"), SwingConstants.RIGHT), c); |
final JTextField textNom = new JTextField(); |
final SQLTextCombo textNom = new SQLTextCombo(); |
c.gridx++; |
c.weightx = 1; |
this.add(textNom, c); |
653,6 → 653,7 |
DefaultGridBagConstraints.lockMinimumSize(this.fourn); |
DefaultGridBagConstraints.lockMinimumSize(commSel); |
this.addView(this.table.getRowValuesTable(), ""); |
} |
protected SQLRowValues getLivraisonAdr(SQLRow rowAffaire) { |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/component/FactureFournisseurSQLComponent.java |
---|
16,6 → 16,7 |
import org.openconcerto.erp.config.ComptaPropsConfiguration; |
import org.openconcerto.erp.core.common.component.TransfertBaseSQLComponent; |
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement; |
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement; |
import org.openconcerto.erp.core.common.ui.AbstractVenteArticleItemTable; |
import org.openconcerto.erp.core.common.ui.DeviseField; |
import org.openconcerto.erp.core.common.ui.TotalPanel; |
29,7 → 30,6 |
import org.openconcerto.erp.panel.PanelOOSQLComponent; |
import org.openconcerto.erp.preferences.DefaultNXProps; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.element.DefaultElementSQLObject; |
import org.openconcerto.sql.element.ElementSQLObject; |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.model.SQLBackgroundTableCache; |
41,16 → 41,19 |
import org.openconcerto.sql.preferences.SQLPreferences; |
import org.openconcerto.sql.request.ComboSQLRequest; |
import org.openconcerto.sql.sqlobject.ElementComboBox; |
import org.openconcerto.sql.sqlobject.JUniqueTextField; |
import org.openconcerto.sql.sqlobject.SQLRequestComboBox; |
import org.openconcerto.sql.users.UserManager; |
import org.openconcerto.sql.view.list.RowValuesTable; |
import org.openconcerto.sql.view.list.RowValuesTableModel; |
import org.openconcerto.ui.AutoHideListener; |
import org.openconcerto.ui.DefaultGridBagConstraints; |
import org.openconcerto.ui.FormLayouter; |
import org.openconcerto.ui.JDate; |
import org.openconcerto.ui.TitledSeparator; |
import org.openconcerto.ui.component.ITextArea; |
import org.openconcerto.ui.preferences.DefaultProps; |
import org.openconcerto.utils.ExceptionHandler; |
import org.openconcerto.utils.checks.ValidState; |
import org.openconcerto.utils.text.SimpleDocumentListener; |
import java.awt.Color; |
60,6 → 63,8 |
import java.beans.PropertyChangeListener; |
import java.math.BigDecimal; |
import java.sql.SQLException; |
import java.util.Arrays; |
import java.util.Date; |
import java.util.HashSet; |
import java.util.List; |
import java.util.Set; |
68,6 → 73,7 |
import javax.swing.JOptionPane; |
import javax.swing.JPanel; |
import javax.swing.JScrollPane; |
import javax.swing.JTabbedPane; |
import javax.swing.JTextField; |
import javax.swing.SwingConstants; |
import javax.swing.SwingUtilities; |
83,7 → 89,8 |
private ElementComboBox fourn = new ElementComboBox(); |
private ElementComboBox comptePCE = new ElementComboBox(); |
private ElementComboBox avoirFourn = new ElementComboBox(); |
private DefaultElementSQLObject compAdr; |
private ElementComboBox avoirFourn2 = new ElementComboBox(); |
private PanelOOSQLComponent panelOO; |
final JPanel panelAdrSpec = new JPanel(new GridBagLayout()); |
private JDate dateCommande = new JDate(); |
97,15 → 104,9 |
public void propertyChange(PropertyChangeEvent evt) { |
SQLRow rowFourn = fourn.getRequest().getPrimaryTable().getRow(fourn.getWantedID()); |
final SQLRow rowFourn = FactureFournisseurSQLComponent.this.fourn.getRequest().getPrimaryTable().getRow(FactureFournisseurSQLComponent.this.fourn.getWantedID()); |
if ((getMode() == Mode.INSERTION || !isFilling()) && rowFourn != null && !rowFourn.isUndefined()) { |
if (!isFilling() && rowFourn != null && !rowFourn.isUndefined()) { |
// SQLRow rowCharge = rowFourn.getForeign("ID_COMPTE_PCE_CHARGE"); |
// if (rowCharge != null && !rowCharge.isUndefined()) { |
// compteSel.setValue(rowCharge); |
// } |
int idModeRegl = rowFourn.getInt("ID_MODE_REGLEMENT"); |
if (idModeRegl > 1 && FactureFournisseurSQLComponent.this.eltModeRegl != null && getMode() == Mode.INSERTION) { |
SQLElement sqlEltModeRegl = getElement().getDirectory().getElement("MODE_REGLEMENT"); |
113,9 → 114,8 |
SQLRowValues rowVals = rowModeRegl.createUpdateRow(); |
rowVals.clearPrimaryKeys(); |
FactureFournisseurSQLComponent.this.eltModeRegl.setValue(rowVals); |
System.err.println("Select Mode regl " + idModeRegl); |
} |
// } |
} |
} |
139,21 → 139,79 |
return s; |
} |
@Override |
public synchronized ValidState getValidState() { |
if (getTable().contains("ID_COMPTE_PCE") && getTable().contains("ID_TYPE_CMD") && getTable().getTable("FACTURE_FOURNISSEUR_ELEMENT").contains("ID_COMPTE_PCE")) { |
SQLRequestComboBox boxCpt = (SQLRequestComboBox) getView("ID_COMPTE_PCE").getComp(); |
final SQLRow selectedCpt = boxCpt.getSelectedRow(); |
if (selectedCpt == null || selectedCpt.isUndefined()) { |
RowValuesTableModel tableRow = this.table.getRowValuesTable().getRowValuesTableModel(); |
for (int i = 0; i < tableRow.getRowCount(); i++) { |
SQLRowValues rowVals = tableRow.getRowValuesAt(i); |
if (rowVals.getInt("QTE") != 0 && (rowVals.getObject("ID_COMPTE_PCE") == null || rowVals.isForeignEmpty("ID_COMPTE_PCE"))) { |
return ValidState.create(false, "Aucun compte global sélectionné et une ligne avec une quantité > 0 n'est pas affectée à un compte!"); |
} |
} |
} |
} |
return super.getValidState(); |
} |
private JUniqueTextField numero; |
public void addViews() { |
this.setLayout(new GridBagLayout()); |
final GridBagConstraints c = new DefaultGridBagConstraints(); |
if (getTable().getTable("NUMEROTATION_AUTO").contains("FACTURE_FOURNISSEUR_START")) { |
this.numero = new JUniqueTextField(35) { |
@Override |
public String getAutoRefreshNumber() { |
if (getMode() == Mode.INSERTION) { |
final Date date = FactureFournisseurSQLComponent.this.dateCommande.getDate(); |
return NumerotationAutoSQLElement.getNextNumero(getElement().getClass(), date == null ? new Date() : date); |
} else { |
return null; |
} |
} |
}; |
this.dateCommande.addValueListener(new PropertyChangeListener() { |
@Override |
public void propertyChange(PropertyChangeEvent evt) { |
if (!isFilling() && FactureFournisseurSQLComponent.this.dateCommande.getValue() != null) { |
final String nextNumero = NumerotationAutoSQLElement.getNextNumero(getElement().getClass(), FactureFournisseurSQLComponent.this.dateCommande.getValue()); |
if (FactureFournisseurSQLComponent.this.numero.getText().trim().length() > 0 && !nextNumero.equalsIgnoreCase(FactureFournisseurSQLComponent.this.numero.getText())) { |
int answer = JOptionPane.showConfirmDialog(FactureFournisseurSQLComponent.this, "Voulez vous actualiser le numéro de la facture?", "Changement du numéro de facture", |
JOptionPane.YES_NO_OPTION); |
if (answer == JOptionPane.NO_OPTION) { |
return; |
} |
} |
FactureFournisseurSQLComponent.this.numero.setText(nextNumero); |
} |
} |
}); |
} else { |
this.numero = new JUniqueTextField(35); |
} |
// Numero du commande |
c.gridx = 0; |
c.weightx = 0; |
this.add(new JLabel(getLabelFor("NUMERO"), SwingConstants.RIGHT), c); |
JTextField numero = new JTextField(25); |
c.gridx++; |
c.weightx = 1; |
c.fill = GridBagConstraints.NONE; |
DefaultGridBagConstraints.lockMinimumSize(numero); |
this.add(numero, c); |
DefaultGridBagConstraints.lockMinimumSize(this.numero); |
this.add(this.numero, c); |
// Date |
JLabel labelDate = new JLabel(getLabelFor("DATE")); |
165,14 → 223,14 |
c.gridx++; |
c.fill = GridBagConstraints.NONE; |
this.add(dateCommande, c); |
this.add(this.dateCommande, c); |
this.dateCommande.addValueListener(new PropertyChangeListener() { |
@Override |
public void propertyChange(PropertyChangeEvent evt) { |
if (!isFilling() && dateCommande.getValue() != null) { |
table.setDateDevise(dateCommande.getValue()); |
if (!isFilling() && FactureFournisseurSQLComponent.this.dateCommande.getValue() != null) { |
FactureFournisseurSQLComponent.this.table.setDateDevise(FactureFournisseurSQLComponent.this.dateCommande.getValue()); |
updateLabelTauxConversion(); |
} |
} |
193,23 → 251,23 |
this.add(this.fourn, c); |
addRequiredSQLObject(this.fourn, "ID_FOURNISSEUR"); |
fourn.addModelListener("wantedID", new PropertyChangeListener() { |
this.fourn.addModelListener("wantedID", new PropertyChangeListener() { |
@Override |
public void propertyChange(PropertyChangeEvent evt) { |
int wantedID = fourn.getWantedID(); |
int wantedID = FactureFournisseurSQLComponent.this.fourn.getWantedID(); |
if (wantedID != SQLRow.NONEXISTANT_ID && wantedID >= SQLRow.MIN_VALID_ID) { |
final SQLRow rowF = getTable().getForeignTable("ID_FOURNISSEUR").getRow(wantedID); |
if (rowF.getObject("ID_CATEGORIE_COMPTABLE") != null && !rowF.isForeignEmpty("ID_CATEGORIE_COMPTABLE")) { |
table.setRowCatComptable(rowF.getForeign("ID_CATEGORIE_COMPTABLE")); |
FactureFournisseurSQLComponent.this.table.setRowCatComptable(rowF.getForeign("ID_CATEGORIE_COMPTABLE")); |
} else { |
table.setRowCatComptable(null); |
FactureFournisseurSQLComponent.this.table.setRowCatComptable(null); |
} |
} else { |
table.setRowCatComptable(null); |
FactureFournisseurSQLComponent.this.table.setRowCatComptable(null); |
} |
} |
}); |
250,8 → 308,8 |
@Override |
public void propertyChange(PropertyChangeEvent evt) { |
table.setFournisseur(fourn.getSelectedRow()); |
SQLRow row = fourn.getSelectedRow(); |
FactureFournisseurSQLComponent.this.table.setFournisseur(FactureFournisseurSQLComponent.this.fourn.getSelectedRow()); |
SQLRow row = FactureFournisseurSQLComponent.this.fourn.getSelectedRow(); |
if (!isFilling()) { |
if (row != null && !row.isUndefined() && !row.isForeignEmpty("ID_DEVISE")) { |
boxDevise.setValue(row.getForeignID("ID_DEVISE")); |
259,9 → 317,10 |
} |
if (row != null && !row.isUndefined()) { |
avoirFourn.getRequest().setWhere(new Where(avoirFourn.getRequest().getPrimaryTable().getField("ID_FOURNISSEUR"), "=", row.getID())); |
FactureFournisseurSQLComponent.this.avoirFourn.getRequest() |
.setWhere(new Where(FactureFournisseurSQLComponent.this.avoirFourn.getRequest().getPrimaryTable().getField("ID_FOURNISSEUR"), "=", row.getID())); |
} else { |
avoirFourn.getRequest().setWhere(null); |
FactureFournisseurSQLComponent.this.avoirFourn.getRequest().setWhere(null); |
} |
} |
}); |
355,21 → 414,21 |
@Override |
public void propertyChange(PropertyChangeEvent evt) { |
table.setDevise(boxDevise.getSelectedRow()); |
FactureFournisseurSQLComponent.this.table.setDevise(boxDevise.getSelectedRow()); |
updateLabelTauxConversion(); |
} |
}); |
fieldTaux.getDocument().addDocumentListener(new SimpleDocumentListener() { |
this.fieldTaux.getDocument().addDocumentListener(new SimpleDocumentListener() { |
@Override |
public void update(DocumentEvent e) { |
BigDecimal tauxConversion = null; |
if (fieldTaux.getText().trim().length() > 0) { |
tauxConversion = new BigDecimal(fieldTaux.getText()); |
if (FactureFournisseurSQLComponent.this.fieldTaux.getText().trim().length() > 0) { |
tauxConversion = new BigDecimal(FactureFournisseurSQLComponent.this.fieldTaux.getText()); |
} |
table.setTauxConversion(tauxConversion); |
FactureFournisseurSQLComponent.this.table.setTauxConversion(tauxConversion); |
updateLabelTauxConversion(); |
} |
}); |
379,13 → 438,13 |
@Override |
public void propertyChange(PropertyChangeEvent evt) { |
table.setFournisseur(fourn.getSelectedRow()); |
FactureFournisseurSQLComponent.this.table.setFournisseur(FactureFournisseurSQLComponent.this.fourn.getSelectedRow()); |
if (!isFilling()) { |
SQLRow row = fourn.getSelectedRow(); |
SQLRow row = FactureFournisseurSQLComponent.this.fourn.getSelectedRow(); |
if (row != null && !row.isUndefined()) { |
row.fetchValues(); |
if (!row.isForeignEmpty("ID_COMPTE_PCE_CHARGE")) { |
comptePCE.setValue(row.getForeign("ID_COMPTE_PCE_CHARGE")); |
FactureFournisseurSQLComponent.this.comptePCE.setValue(row.getForeign("ID_COMPTE_PCE_CHARGE")); |
} |
} |
} |
395,18 → 454,13 |
c.gridy++; |
c.weighty = 0; |
this.add(getBottomPanel(), c); |
ModeDeReglementSQLComponent modeReglComp; |
modeReglComp = (ModeDeReglementSQLComponent) this.eltModeRegl.getSQLChild(); |
ModeDeReglementSQLComponent modeReglComp = (ModeDeReglementSQLComponent) this.eltModeRegl.getSQLChild(); |
modeReglComp.addDateCompListener(this.dateCommande); |
// Modèle, visualiser, imprimer.. |
c.gridx = 0; |
c.gridy++; |
c.fill = GridBagConstraints.HORIZONTAL; |
c.anchor = GridBagConstraints.WEST; |
c.gridx = 0; |
c.gridy++; |
c.fill = GridBagConstraints.NONE; |
c.anchor = GridBagConstraints.SOUTHEAST; |
c.gridwidth = GridBagConstraints.REMAINDER; |
415,8 → 469,8 |
this.add(this.panelOO, c); |
addSQLObject(textNom, "NOM"); |
addRequiredSQLObject(dateCommande, "DATE"); |
addRequiredSQLObject(numero, "NUMERO"); |
addRequiredSQLObject(this.dateCommande, "DATE"); |
addRequiredSQLObject(this.numero, "NUMERO"); |
addSQLObject(this.infos, "INFOS"); |
DefaultGridBagConstraints.lockMinimumSize(this.fourn); |
439,60 → 493,80 |
final JPanel panel = new JPanel(new GridBagLayout()); |
final GridBagConstraints c = new DefaultGridBagConstraints(); |
// Colonne 1 : Infos |
JTabbedPane tabs = new JTabbedPane(); |
JPanel mainBottomPanel = new JPanel(); |
mainBottomPanel.setOpaque(false); |
tabs.add(mainBottomPanel, "Règlements et caractéristiques"); |
final JScrollPane scrollPane = new JScrollPane(this.infos); |
scrollPane.setBorder(null); |
tabs.add(scrollPane, getLabelFor("INFOS")); |
c.gridx = 0; |
c.weightx = 1; |
c.anchor = GridBagConstraints.WEST; |
c.fill = GridBagConstraints.HORIZONTAL; |
c.fill = GridBagConstraints.BOTH; |
panel.add(tabs, c); |
panel.add(new TitledSeparator(getLabelFor("INFOS")), c); |
mainBottomPanel.setLayout(new GridBagLayout()); |
GridBagConstraints cMainBottomPanel = new DefaultGridBagConstraints(); |
c.gridy++; |
c.weighty = 0; |
c.weightx = 1; |
c.fill = GridBagConstraints.BOTH; |
final JScrollPane scrollPane = new JScrollPane(this.infos); |
scrollPane.setBorder(null); |
panel.add(scrollPane, c); |
// Colonne 1 : Infos |
cMainBottomPanel.weighty = 0; |
cMainBottomPanel.weightx = 0; |
cMainBottomPanel.fill = GridBagConstraints.BOTH; |
this.addView("ID_MODE_REGLEMENT", REQ + ";" + DEC + ";" + SEP); |
this.eltModeRegl = (ElementSQLObject) this.getView("ID_MODE_REGLEMENT"); |
c.gridx++; |
c.fill = GridBagConstraints.NONE; |
c.weightx = 1; |
c.weighty = 1; |
eltModeRegl.setOpaque(false); |
panel.add(eltModeRegl, c); |
this.eltModeRegl.setOpaque(false); |
mainBottomPanel.add(this.eltModeRegl, cMainBottomPanel); |
// Colonne 2 : Poids & autres |
JPanel column2 = new JPanel(); |
column2.setOpaque(false); |
cMainBottomPanel.gridx++; |
cMainBottomPanel.weightx = 0; |
mainBottomPanel.add(column2, cMainBottomPanel); |
column2.setLayout(new GridBagLayout()); |
GridBagConstraints c2 = new DefaultGridBagConstraints(); |
c2.weightx = 0; |
c2.weighty = 0; |
c2.gridwidth = 1; |
c2.gridheight = 1; |
c2.fill = GridBagConstraints.HORIZONTAL; |
c2.anchor = GridBagConstraints.NORTHEAST; |
// Poids |
DefaultProps props = DefaultNXProps.getInstance(); |
Boolean b = props.getBooleanValue("ArticleShowPoids"); |
Boolean poidsVisible = props.getBooleanValue("ArticleShowPoids"); |
if (poidsVisible) { |
column2.add(new JLabel(getLabelFor("T_POIDS"), SwingConstants.RIGHT), c2); |
final JTextField textPoidsTotal = new JTextField(8); |
JTextField poids = new JTextField(); |
if (b) { |
final JPanel panelPoids = new JPanel(); |
panelPoids.add(new JLabel(getLabelFor("T_POIDS")), c); |
textPoidsTotal.setEnabled(false); |
textPoidsTotal.setHorizontalAlignment(JTextField.RIGHT); |
textPoidsTotal.setDisabledTextColor(Color.BLACK); |
c2.weightx = 1; |
c2.gridx++; |
column2.add(textPoidsTotal, c2); |
DefaultGridBagConstraints.lockMinimumSize(textPoidsTotal); |
addSQLObject(textPoidsTotal, "T_POIDS"); |
panelPoids.add(textPoidsTotal, c); |
this.table.getModel().addTableModelListener(new TableModelListener() { |
c.gridx++; |
c.gridy = 0; |
c.weightx = 0; |
c.weighty = 0; |
c.gridwidth = 1; |
c.gridheight = 2; |
c.fill = GridBagConstraints.NONE; |
c.anchor = GridBagConstraints.NORTHEAST; |
panel.add(panelPoids, c); |
DefaultGridBagConstraints.lockMinimumSize(panelPoids); |
addSQLObject(textPoidsTotal, "T_POIDS"); |
public void tableChanged(TableModelEvent e) { |
textPoidsTotal.setText(String.valueOf(FactureFournisseurSQLComponent.this.table.getPoidsTotal())); |
} |
}); |
} else { |
addSQLObject(poids, "T_POIDS"); |
addSQLObject(new JTextField(), "T_POIDS"); |
} |
DeviseField textPortHT = new DeviseField(); |
499,52 → 573,75 |
ElementComboBox comboTaxePort = new ElementComboBox(); |
DeviseField textRemiseHT = new DeviseField(); |
final JPanel panelPoids = new JPanel(new GridBagLayout()); |
GridBagConstraints cPort = new DefaultGridBagConstraints(); |
if (getTable().contains("PORT_HT")) { |
// Port HT |
addSQLObject(textPortHT, "PORT_HT"); |
cPort.gridx = 0; |
cPort.weightx = 0; |
panelPoids.add(new JLabel(getLabelFor("PORT_HT")), cPort); |
c2.gridx = 0; |
c2.gridy++; |
c2.weightx = 0; |
column2.add(new JLabel(getLabelFor("PORT_HT"), SwingConstants.RIGHT), c2); |
textPortHT.setHorizontalAlignment(JTextField.RIGHT); |
cPort.gridx++; |
cPort.weightx = 1; |
panelPoids.add(textPortHT, cPort); |
cPort.gridy++; |
cPort.gridx = 0; |
cPort.weightx = 0; |
c2.gridx++; |
c2.weightx = 1; |
column2.add(textPortHT, c2); |
// TVA sur port |
c2.gridy++; |
c2.gridx = 0; |
c2.weightx = 0; |
addRequiredSQLObject(comboTaxePort, "ID_TAXE_PORT"); |
panelPoids.add(new JLabel(getLabelFor("ID_TAXE_PORT")), cPort); |
cPort.gridx++; |
cPort.weightx = 0; |
panelPoids.add(comboTaxePort, cPort); |
c.gridx++; |
c.gridy = 0; |
c.weightx = 0; |
c.weighty = 0; |
c.gridwidth = 1; |
c.gridheight = 2; |
c.fill = GridBagConstraints.NONE; |
c.anchor = GridBagConstraints.NORTHEAST; |
panel.add(panelPoids, c); |
DefaultGridBagConstraints.lockMinimumSize(panelPoids); |
column2.add(new JLabel(getLabelFor("ID_TAXE_PORT"), SwingConstants.RIGHT), c2); |
c2.gridx++; |
c2.weightx = 0; |
column2.add(comboTaxePort, c2); |
// Remise HT |
addSQLObject(textRemiseHT, "REMISE_HT"); |
cPort.gridy++; |
cPort.gridx = 0; |
cPort.fill = GridBagConstraints.NONE; |
cPort.weightx = 0; |
panelPoids.add(new JLabel(getLabelFor("REMISE_HT")), cPort); |
c2.gridx = 0; |
c2.gridy++; |
c2.weightx = 0; |
column2.add(new JLabel(getLabelFor("REMISE_HT"), SwingConstants.RIGHT), c2); |
textRemiseHT.setHorizontalAlignment(JTextField.RIGHT); |
cPort.gridx++; |
cPort.weightx = 1; |
panelPoids.add(textRemiseHT, cPort); |
c2.gridx++; |
c2.weightx = 1; |
column2.add(textRemiseHT, c2); |
} |
// Total |
final JTextField textTvaAdujs; |
if (getTable().contains("TVA_ADJUSTMENT")) { |
textTvaAdujs = new JTextField(15); |
final JLabel labelTvaAdujst = new JLabel(getLabelFor("TVA_ADJUSTMENT"), SwingConstants.RIGHT); |
c2.gridx = 0; |
c2.gridy++; |
c2.weightx = 0; |
column2.add(labelTvaAdujst, c2); |
c2.gridx++; |
c2.weightx = 1; |
column2.add(textTvaAdujs, c2); |
addView(textTvaAdujs, "TVA_ADJUSTMENT"); |
DefaultGridBagConstraints.lockMinimumSize(textTvaAdujs); |
} else { |
textTvaAdujs = null; |
} |
c2.gridy++; |
c2.gridx = 0; |
column2.add(new JLabel("Avoirs", SwingConstants.RIGHT), c2); |
c2.gridx++; |
c2.fill = GridBagConstraints.NONE; |
c2.anchor = GridBagConstraints.EAST; |
column2.add(createPanelAvoir(), c2); |
c2.gridy++; |
column2.add(getModuleTotalPanel(), c2); |
c2.gridy++; |
JPanel filler = new JPanel(); |
filler.setOpaque(false); |
c2.weighty = 1; |
column2.add(filler, c2); |
// Colonne 4 Total |
DeviseField fieldHT = new DeviseField(); |
DeviseField fieldEco = new DeviseField(); |
DeviseField fieldTVA = new DeviseField(); |
552,7 → 649,7 |
DeviseField fieldService = new DeviseField(); |
fieldHT.setOpaque(false); |
fieldTVA.setOpaque(false); |
fieldTTC.setOpaque(false); |
this.fieldTTC.setOpaque(false); |
fieldService.setOpaque(false); |
addRequiredSQLObject(fieldDevise, "T_DEVISE"); |
addRequiredSQLObject(fieldEco, "T_ECO_CONTRIBUTION"); |
559,10 → 656,10 |
addRequiredSQLObject(fieldHT, "T_HT"); |
addRequiredSQLObject(fieldTVA, "T_TVA"); |
addRequiredSQLObject(fieldTTC, "T_TTC"); |
addRequiredSQLObject(this.fieldTTC, "T_TTC"); |
addRequiredSQLObject(fieldService, "T_SERVICE"); |
fieldTTC.getDocument().addDocumentListener(new SimpleDocumentListener() { |
this.fieldTTC.getDocument().addDocumentListener(new SimpleDocumentListener() { |
@Override |
public void update(DocumentEvent e) { |
refreshText(); |
578,21 → 675,9 |
this.allowEditable("T_SERVICE", false); |
this.allowEditable("T_POIDS", false); |
final TotalPanel totalTTC = new TotalPanel(this.table, fieldEco, fieldHT, fieldTVA, fieldTTC, textPortHT, textRemiseHT, fieldService, null, fieldDevise, null, null, |
final TotalPanel totalTTC = new TotalPanel(this.table, fieldEco, fieldHT, fieldTVA, this.fieldTTC, textPortHT, textRemiseHT, fieldService, null, fieldDevise, null, null, |
(getTable().contains("ID_TAXE_PORT") ? comboTaxePort : null), null); |
if (getTable().contains("TVA_ADJUSTMENT")) { |
final JTextField textTvaAdujs = new JTextField(15); |
JLabel labelTvaAdujst = new JLabel(getLabelFor("TVA_ADJUSTMENT")); |
labelTvaAdujst.setHorizontalAlignment(SwingConstants.RIGHT); |
cPort.gridx = 0; |
cPort.gridy++; |
panelPoids.add(labelTvaAdujst, cPort); |
cPort.gridx++; |
panelPoids.add(textTvaAdujs, cPort); |
addView(textTvaAdujs, "TVA_ADJUSTMENT"); |
if (textTvaAdujs != null) { |
totalTTC.setTextFixTVA(textTvaAdujs); |
textTvaAdujs.getDocument().addDocumentListener(new SimpleDocumentListener() { |
@Override |
621,44 → 706,23 |
totalTTC.updateTotal(); |
} |
}); |
DefaultGridBagConstraints.lockMinimumSize(textTvaAdujs); |
} |
c.gridx++; |
c.gridy--; |
c.gridwidth = GridBagConstraints.REMAINDER; |
c.gridheight = 2; |
c.gridy = 0; |
c.gridwidth = 1; |
c.gridheight = 1; |
c.anchor = GridBagConstraints.NORTHEAST; |
c.fill = GridBagConstraints.BOTH; |
c.fill = GridBagConstraints.HORIZONTAL; |
c.weighty = 0; |
DefaultGridBagConstraints.lockMinimumSize(totalTTC); |
panel.add(totalTTC, c); |
c.gridy += 3; |
c.gridheight = 1; |
c.fill = GridBagConstraints.NONE; |
c.anchor = GridBagConstraints.EAST; |
panel.add(createPanelAvoir(), c); |
c.gridy += 4; |
c.gridheight = 2; |
c.fill = GridBagConstraints.NONE; |
c.anchor = GridBagConstraints.EAST; |
panel.add(getModuleTotalPanel(), c); |
table.getModel().addTableModelListener(new TableModelListener() { |
public void tableChanged(TableModelEvent e) { |
textPoidsTotal.setText(String.valueOf(table.getPoidsTotal())); |
} |
}); |
this.fourn.addModelListener("wantedID", new PropertyChangeListener() { |
@Override |
public void propertyChange(PropertyChangeEvent evt) { |
final SQLRow selectedRow2 = fourn.getSelectedRow(); |
final SQLRow selectedRow2 = FactureFournisseurSQLComponent.this.fourn.getSelectedRow(); |
if (selectedRow2 != null && !selectedRow2.isUndefined()) { |
totalTTC.setIntraComm(selectedRow2.getBoolean("UE")); |
} else { |
686,7 → 750,6 |
@Override |
public void propertyChange(PropertyChangeEvent evt) { |
// TODO Raccord de méthode auto-généré |
totalTTC.updateTotal(); |
} |
}); |
717,6 → 780,24 |
public int insert(SQLRow order) { |
final SQLTable tableNum = getTable().getTable("NUMEROTATION_AUTO"); |
// incrémentation du numéro auto |
if (tableNum.contains("FACTURE_FOURNISSEUR_START") && NumerotationAutoSQLElement.getNextNumero(getElement().getClass(), new Date()).equalsIgnoreCase(this.numero.getText().trim())) { |
SQLRowValues rowVals = new SQLRowValues(tableNum); |
final SQLRow rowNumAuto = tableNum.getRow(2); |
if (rowNumAuto.getObject("FACTURE_FOURNISSEUR_START") != null) { |
int val = rowNumAuto.getInt("FACTURE_FOURNISSEUR_START"); |
val++; |
rowVals.put("FACTURE_FOURNISSEUR_START", new Integer(val)); |
try { |
rowVals.update(2); |
} catch (SQLException e) { |
e.printStackTrace(); |
} |
} |
} |
int idFacture = getSelectedID(); |
idFacture = super.insert(order); |
this.table.updateField("ID_FACTURE_FOURNISSEUR", idFacture); |
774,12 → 855,16 |
} |
public void commitAvoir(SQLRow rowFactureOld, SQLRow rowFacture) { |
try { |
if (rowFactureOld != null && rowFactureOld.getObject("ID_AVOIR_FOURNISSEUR") != null && !rowFactureOld.isForeignEmpty("ID_AVOIR_FOURNISSEUR") |
&& (rowFacture.getObject("ID_AVOIR_FOURNISSEUR") == null || rowFacture.isForeignEmpty("ID_AVOIR_FOURNISSEUR"))) { |
List<String> fieldsAvoir = Arrays.asList("ID_AVOIR_FOURNISSEUR", "ID_AVOIR_FOURNISSEUR_2"); |
for (String field : fieldsAvoir) { |
SQLRow rowAvoir = rowFactureOld.getForeignRow("ID_AVOIR_FOURNISSEUR"); |
if (rowFactureOld != null && rowFactureOld.getObject(field) != null && !rowFactureOld.isForeignEmpty(field) |
&& (rowFacture.getObject(field) == null || rowFacture.isForeignEmpty(field))) { |
SQLRow rowAvoir = rowFactureOld.getForeignRow(field); |
SQLRowValues rowVals = rowAvoir.createEmptyUpdateRow(); |
// Soldé |
790,9 → 875,9 |
} |
// on solde l'avoir |
if (rowFacture.getObject("ID_AVOIR_FOURNISSEUR") != null && !rowFacture.isForeignEmpty("ID_AVOIR_FOURNISSEUR")) { |
if (rowFacture.getObject(field) != null && !rowFacture.isForeignEmpty(field)) { |
SQLRow rowAvoir = rowFacture.getForeignRow("ID_AVOIR_FOURNISSEUR"); |
SQLRow rowAvoir = rowFacture.getForeignRow(field); |
SQLRowValues rowVals = rowAvoir.createEmptyUpdateRow(); |
rowVals.put("SOLDE", Boolean.TRUE); |
800,6 → 885,7 |
rowVals.update(); |
} |
} |
} catch (SQLException e) { |
ExceptionHandler.handle("Erreur lors la mise à jour de l'avoir associée!", e); |
} |
829,6 → 915,11 |
if (rowsComm != null) { |
rowVals.put("ID_COMMERCIAL", rowsComm.getID()); |
} |
if (getTable().getTable("NUMEROTATION_AUTO").contains("FACTURE_FOURNISSEUR_START")) { |
rowVals.put("NUMERO", NumerotationAutoSQLElement.getNextNumero(getElement().getClass(), new Date())); |
} |
rowVals.put("T_HT", Long.valueOf(0)); |
rowVals.put("T_SERVICE", Long.valueOf(0)); |
rowVals.put("T_DEVISE", Long.valueOf(0)); |
871,19 → 962,43 |
cA.gridx++; |
cA.weightx = 0; |
panelAvoir.add(this.textNetAPayer, cA); |
addView(textNetAPayer, "NET_A_PAYER"); |
addView(this.textNetAPayer, "NET_A_PAYER"); |
this.textNetAPayer.setHorizontalAlignment(SwingConstants.RIGHT); |
JLabel labelAvoir2 = new JLabel(getLabelFor("ID_AVOIR_FOURNISSEUR_2")); |
labelAvoir.setHorizontalAlignment(SwingConstants.RIGHT); |
cA.gridx = 0; |
cA.gridy++; |
cA.weightx = 1; |
labelAvoir.setHorizontalAlignment(SwingConstants.RIGHT); |
panelAvoir.add(labelAvoir2, cA); |
cA.weightx = 0; |
cA.gridx++; |
this.avoirFourn2 = new ElementComboBox(); |
this.avoirFourn2.setAddIconVisible(false); |
panelAvoir.add(this.avoirFourn2, cA); |
addView(this.avoirFourn2, "ID_AVOIR_FOURNISSEUR_2"); |
addView(this.avoirFourn, "ID_AVOIR_FOURNISSEUR"); |
addView(avoirTTC, "AVOIR_TTC"); |
this.avoirFourn.addValueListener(new PropertyChangeListener() { |
addView(this.avoirTTC, "AVOIR_TTC"); |
this.avoirFourn.addModelListener("wantedID", new PropertyChangeListener() { |
public void propertyChange(PropertyChangeEvent evt) { |
if (!isFilling()) { |
refreshText(); |
} |
} |
}); |
this.avoirFourn2.addModelListener("wantedID", new PropertyChangeListener() { |
public void propertyChange(PropertyChangeEvent evt) { |
if (!isFilling()) { |
refreshText(); |
} |
} |
}); |
return panelAvoir; |
} |
891,16 → 1006,16 |
Number n = this.fieldTTC.getValue(); |
long totalAvoirTTC = 0; |
long netAPayer = 0; |
long ttc = 0; |
if (n != null) { |
netAPayer = n.longValue(); |
ttc = n.longValue(); |
} |
if (this.avoirFourn.getSelectedId() > 1) { |
List<ElementComboBox> boxAvoir = Arrays.asList(this.avoirFourn, this.avoirFourn2); |
for (ElementComboBox elementComboBox : boxAvoir) { |
if (elementComboBox.getWantedID() > 1) { |
SQLTable tableAvoir = getTable().getForeignTable("ID_AVOIR_FOURNISSEUR"); |
if (n != null) { |
SQLRow rowAvoir = tableAvoir.getRow(this.avoirFourn.getSelectedId()); |
SQLRow rowAvoir = tableAvoir.getRow(elementComboBox.getWantedID()); |
long totalAvoir = ((Number) rowAvoir.getObject("MONTANT_TTC")).longValue(); |
if (getSelectedID() > 1) { |
SQLRow row = getTable().getRow(getSelectedID()); |
910,10 → 1025,10 |
} |
} |
long l = ttc - totalAvoir; |
long l = netAPayer - totalAvoir; |
if (l < 0) { |
l = 0; |
totalAvoirTTC = ttc; |
totalAvoirTTC = netAPayer; |
} else { |
totalAvoirTTC = totalAvoir; |
} |
920,6 → 1035,7 |
netAPayer = l; |
} |
} |
} |
this.textNetAPayer.setValue(netAPayer); |
this.avoirTTC.setValue(totalAvoirTTC); |
947,15 → 1063,7 |
if (!row.isForeignEmpty("ID_COMPTE_PCE")) { |
rowVals.put("ID_COMPTE_PCE", row.getForeignID("ID_COMPTE_PCE")); |
} |
// if (getTable().contains("ID_NUMEROTATION_AUTO")) { |
// rowVals.put("NUMERO", |
// NumerotationAutoSQLElement.getNextNumero(SaisieVenteFactureSQLElement.class, new |
// Date(), row.getForeign("ID_NUMEROTATION_AUTO"))); |
// } else { |
// rowVals.put("NUMERO", |
// NumerotationAutoSQLElement.getNextNumero(SaisieVenteFactureSQLElement.class, new |
// Date())); |
// } |
rowVals.put("NOM", row.getObject("NOM")); |
this.select(rowVals); |
} |
970,6 → 1078,12 |
SQLRowValues rowVals = rowElt.createUpdateRow(); |
rowVals.clearPrimaryKeys(); |
if (rowVals.getTable().contains("ID_COMMANDE_ELEMENT")) { |
rowVals.putEmptyLink("ID_COMMANDE_ELEMENT"); |
} |
if (rowVals.getTable().contains("ID_BON_RECEPTION_ELEMENT")) { |
rowVals.putEmptyLink("ID_BON_RECEPTION_ELEMENT"); |
} |
this.table.getModel().addRow(rowVals); |
int rowIndex = this.table.getModel().getRowCount() - 1; |
this.table.getModel().fireTableModelModified(rowIndex); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/component/SaisieAchatSQLComponent.java |
---|
340,7 → 340,7 |
} |
}); |
this.comboAvoir.addValueListener(new PropertyChangeListener() { |
this.comboAvoir.addModelListener("wantedID", new PropertyChangeListener() { |
@Override |
public void propertyChange(PropertyChangeEvent evt) { |
refreshText(); |
534,11 → 534,11 |
private void refreshText() { |
Number n = this.montant.getMontantTTC().getValue(); |
if (this.comboAvoir.getSelectedId() > 1) { |
if (this.comboAvoir.getWantedID() > 1) { |
SQLTable tableAvoir = Configuration.getInstance().getDirectory().getElement("AVOIR_FOURNISSEUR").getTable(); |
if (n != null) { |
long ttc = n.longValue(); |
SQLRow rowAvoir = tableAvoir.getRow(this.comboAvoir.getSelectedId()); |
SQLRow rowAvoir = tableAvoir.getRow(this.comboAvoir.getWantedID()); |
long totalAvoir = ((Number) rowAvoir.getObject("MONTANT_TTC")).longValue(); |
this.fieldMontantRegle.setValue(ttc - totalAvoir); |
} else { |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/table/ChiffrageCommandeTable.java |
---|
28,6 → 28,7 |
import org.openconcerto.sql.view.list.RowValuesTableRenderer; |
import org.openconcerto.sql.view.list.SQLTableElement; |
import org.openconcerto.ui.DefaultGridBagConstraints; |
import org.openconcerto.ui.table.XTableColumnModel; |
import org.openconcerto.utils.DecimalUtils; |
import java.awt.GridBagConstraints; |
36,7 → 37,9 |
import java.math.BigDecimal; |
import java.util.ArrayList; |
import java.util.Arrays; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
import java.util.Vector; |
import javax.swing.AbstractAction; |
80,7 → 83,9 |
final SQLField fieldHA = e.getTable().getField("PA_HT"); |
final DeviseNumericCellEditor editorPAHT = new DeviseNumericCellEditor(fieldHA); |
final SQLTableElement pa = new SQLTableElement(fieldHA, BigDecimal.class, editorPAHT); |
pa.setRenderer(new DeviseTableCellRenderer()); |
DeviseTableCellRenderer renderer = new DeviseTableCellRenderer(); |
renderer.setHideZeroValue(true); |
pa.setRenderer(renderer); |
if (e.getTable().contains("ID_CATEGORIE_HEURE")) { |
pa.setEditable(false); |
} |
89,7 → 94,7 |
final SQLField fieldPV = e.getTable().getField("PV_HT"); |
final DeviseNumericCellEditor editorPVHT = new DeviseNumericCellEditor(fieldPV); |
final SQLTableElement pv = new SQLTableElement(fieldPV, BigDecimal.class, editorPVHT); |
pv.setRenderer(new DeviseTableCellRenderer()); |
pv.setRenderer(renderer); |
list.add(pv); |
SQLTableElement qteU = new SQLTableElement(e.getTable().getField("QTE"), BigDecimal.class) { |
98,7 → 103,7 |
return BigDecimal.ZERO; |
} |
}; |
qteU.setRenderer(new DeviseTableCellRenderer()); |
qteU.setRenderer(renderer); |
list.add(qteU); |
if (e.getTable().contains("ANT")) { |
108,7 → 113,7 |
return BigDecimal.ZERO; |
} |
}; |
ant.setRenderer(new DeviseTableCellRenderer()); |
ant.setRenderer(renderer); |
list.add(ant); |
} |
119,7 → 124,7 |
return BigDecimal.ZERO; |
} |
}; |
restant.setRenderer(new DeviseTableCellRenderer()); |
restant.setRenderer(renderer); |
list.add(restant); |
} |
129,7 → 134,7 |
final SQLField fieldTotalHA = e.getTable().getField("T_PA_HT"); |
final DeviseNumericCellEditor editorTotalPAHT = new DeviseNumericCellEditor(fieldTotalHA); |
final SQLTableElement totalpa = new SQLTableElement(fieldTotalHA, BigDecimal.class, editorTotalPAHT); |
totalpa.setRenderer(new DeviseTableCellRenderer()); |
totalpa.setRenderer(renderer); |
totalpa.setEditable(false); |
list.add(totalpa); |
137,7 → 142,7 |
final DeviseNumericCellEditor editorTotalPVHT = new DeviseNumericCellEditor(fieldTotalPV); |
final SQLTableElement totalpv = new SQLTableElement(fieldTotalPV, BigDecimal.class, editorTotalPVHT); |
totalpv.setEditable(false); |
totalpv.setRenderer(new DeviseTableCellRenderer()); |
totalpv.setRenderer(renderer); |
list.add(totalpv); |
final SQLField fieldMarge = e.getTable().getField("MARGE"); |
144,7 → 149,7 |
final DeviseNumericCellEditor editorMarge = new DeviseNumericCellEditor(fieldMarge); |
final SQLTableElement marge = new SQLTableElement(fieldMarge, BigDecimal.class, editorMarge); |
marge.setEditable(false); |
marge.setRenderer(new DeviseTableCellRenderer()); |
marge.setRenderer(renderer); |
list.add(marge); |
SQLRowValues defautRow = new SQLRowValues(UndefinedRowValuesCache.getInstance().getDefaultRowValues(e.getTable())); |
154,6 → 159,17 |
ToolTipManager.sharedInstance().unregisterComponent(this.table); |
ToolTipManager.sharedInstance().unregisterComponent(this.table.getTableHeader()); |
this.table.readState(); |
Map<String, Boolean> mapCustom = getCustomVisibilityMap(); |
if (mapCustom != null) { |
for (String string : mapCustom.keySet()) { |
setColumnVisible(model.getColumnForField(string), mapCustom.get(string)); |
} |
} |
this.table.writeState(); |
// Autocompletion |
// AutoCompletionManager m = new AutoCompletionManager(tableElementNom, |
// ((ComptaPropsConfiguration) |
214,6 → 230,19 |
}); |
} |
protected void setColumnVisible(int col, boolean visible) { |
if (col >= 0) { |
XTableColumnModel columnModel = this.table.getColumnModel(); |
columnModel.setColumnVisible(columnModel.getColumnByModelIndex(col), visible); |
} |
} |
public static Map<String, Boolean> map = new HashMap<String, Boolean>(); |
protected Map<String, Boolean> getCustomVisibilityMap() { |
return map; |
} |
/** |
* |
*/ |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/table/FacturationCommandeTable.java |
---|
20,6 → 20,7 |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.model.UndefinedRowValuesCache; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.request.ComboSQLRequest; |
32,6 → 33,7 |
import org.openconcerto.ui.DefaultGridBagConstraints; |
import org.openconcerto.ui.table.PercentTableCellRenderer; |
import org.openconcerto.ui.table.TimestampTableCellEditor; |
import org.openconcerto.ui.table.XTableColumnModel; |
import java.awt.GridBagConstraints; |
import java.awt.GridBagLayout; |
40,7 → 42,9 |
import java.math.BigDecimal; |
import java.sql.Date; |
import java.sql.Timestamp; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
import java.util.Vector; |
import javax.swing.JButton; |
55,6 → 59,12 |
private RowValuesTableModel model; |
private SQLComponent comp; |
public static Map<String, Boolean> map = new HashMap<String, Boolean>(); |
protected Map<String, Boolean> getCustomVisibilityMap() { |
return map; |
} |
public FacturationCommandeTable(SQLComponent comp) { |
this.comp = comp; |
init(); |
89,6 → 99,7 |
final SQLTableElement comptant = new SQLTableElement(e.getTable().getField("COMPTANT")); |
list.add(comptant); |
// TODO fix return value of timestamp if not show hour return date object |
final SQLTableElement date = new SQLTableElement(e.getTable().getField("DATE_PREVISIONNELLE"), Date.class, new TimestampTableCellEditor(false) { |
@Override |
public Object getCellEditorValue() { |
110,30 → 121,21 |
ToolTipManager.sharedInstance().unregisterComponent(this.table); |
ToolTipManager.sharedInstance().unregisterComponent(this.table.getTableHeader()); |
// Autocompletion |
// AutoCompletionManager m = new AutoCompletionManager(tableElementNom, |
// ((ComptaPropsConfiguration) |
// Configuration.getInstance()).getSQLBaseSociete().getField("ECHANTILLON.NOM"), this.table, |
// this.table.getRowValuesTableModel()); |
// m.fill("NOM", "NOM"); |
// m.fill("PV_HT", "PV_HT"); |
Map<String, Boolean> mapCustom = getCustomVisibilityMap(); |
if (mapCustom != null) { |
for (String string : mapCustom.keySet()) { |
setColumnVisible(model.getColumnForField(string), mapCustom.get(string)); |
} |
} |
// // Calcul automatique du total HT |
// qteElement.addModificationListener(this.totalHT); |
// this.pvHT.addModificationListener(this.totalHT); |
// this.totalHT.setModifier(new CellDynamicModifier() { |
// public Object computeValueFrom(final SQLRowValues row, SQLTableElement source) { |
// System.out.println("Compute totalHT"); |
// |
// int qte = Integer.parseInt(row.getObject("QTE").toString()); |
// BigDecimal f = row.getBigDecimal("PV_HT"); |
// BigDecimal r = f.multiply(new BigDecimal(qte), DecimalUtils.HIGH_PRECISION); |
// return r; |
// } |
// |
// }); |
} |
protected void setColumnVisible(int col, boolean visible) { |
if (col >= 0) { |
XTableColumnModel columnModel = this.table.getColumnModel(); |
columnModel.setColumnVisible(columnModel.getColumnByModelIndex(col), visible); |
} |
} |
/** |
* |
152,7 → 154,7 |
this.add(new JLabel("Ajouter un terme"), c); |
final ElementComboBox boxCat = new ElementComboBox(); |
final SQLElement element = Configuration.getInstance().getDirectory().getElement("FACTURATION_COMMANDE_CLIENT"); |
final SQLElement element = getSQLElement(); |
ComboSQLRequest req = element.getComboRequest(true); |
req.setWhere(new Where(element.getTable().getField("CHOICE"), "=", Boolean.TRUE)); |
boxCat.init(element, req); |
178,10 → 180,13 |
return; |
} |
SQLRowValues rowVals = new SQLRowValues(Configuration.getInstance().getBase().getTable("FACTURATION_COMMANDE_CLIENT")); |
if (comp.getSelectedID() > 1) { |
final SQLTable table2 = getSQLElement().getTable(); |
SQLRowValues rowVals = new SQLRowValues(table2); |
if (table2.getName().equals("FACTURATION_COMMANDE_CLIENT")) { |
if (comp != null && comp.getSelectedID() > 1) { |
rowVals.put("ID_COMMANDE_CLIENT", comp.getSelectedID()); |
} |
} |
rowVals.put("NOM", rowCat.getObject("NOM")); |
rowVals.put("ID_TYPE_REGLEMENT", rowCat.getObject("ID_TYPE_REGLEMENT")); |
rowVals.put("AJOURS", rowCat.getObject("AJOURS")); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/element/FactureFournisseurSQLElement.java |
---|
14,6 → 14,7 |
package org.openconcerto.erp.core.supplychain.order.element; |
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement; |
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement; |
import org.openconcerto.erp.core.edm.AttachmentAction; |
import org.openconcerto.erp.core.supplychain.order.component.FactureFournisseurSQLComponent; |
import org.openconcerto.erp.generationDoc.gestcomm.FactureFournisseurXmlSheet; |
21,6 → 22,7 |
import org.openconcerto.sql.element.SQLComponent; |
import org.openconcerto.sql.model.FieldPath; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.model.graph.Path; |
import org.openconcerto.sql.view.EditFrame; |
import org.openconcerto.sql.view.EditPanel; |
74,7 → 76,12 |
} |
}; |
getRowActions().add(actionClone); |
final SQLTable tableNum = getTable().getTable("NUMEROTATION_AUTO"); |
// incrémentation du numéro auto |
if (tableNum.contains("FACTURE_FOURNISSEUR_START")) { |
NumerotationAutoSQLElement.addClass(this.getClass(), "FACTURE_FOURNISSEUR"); |
} |
} |
@Override |
public Set<String> getReadOnlyFields() { |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/element/CommandeSQLElement.java |
---|
16,6 → 16,7 |
import org.openconcerto.erp.config.Gestion; |
import org.openconcerto.erp.core.common.component.TransfertBaseSQLComponent; |
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement; |
import org.openconcerto.erp.core.edm.AttachmentAction; |
import org.openconcerto.erp.core.supplychain.order.component.CommandeSQLComponent; |
import org.openconcerto.erp.core.supplychain.order.component.SaisieAchatSQLComponent; |
import org.openconcerto.erp.core.supplychain.receipt.component.BonReceptionSQLComponent; |
62,6 → 63,12 |
public CommandeSQLElement() { |
super("COMMANDE", "une commande fournisseur", "commandes fournisseur"); |
if (getTable().contains("ATTACHMENTS")) { |
PredicateRowAction actionAttachment = new PredicateRowAction(new AttachmentAction().getAction(), true); |
actionAttachment.setPredicate(IListeEvent.getSingleSelectionPredicate()); |
getRowActions().add(actionAttachment); |
} |
getRowActions().addAll(new MouseSheetXmlListeListener(CommandeXmlSheet.class).getRowActions()); |
// Transfert vers BR |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/element/CustomerSQLElement.java |
---|
15,10 → 15,12 |
import org.openconcerto.erp.core.edm.AttachmentAction; |
import org.openconcerto.erp.core.reports.history.ui.HistoriqueClientFrame; |
import org.openconcerto.erp.preferences.GestionCommercialeGlobalPreferencePanel; |
import org.openconcerto.sql.element.GlobalMapper; |
import org.openconcerto.sql.element.GroupSQLComponent; |
import org.openconcerto.sql.element.SQLComponent; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.preferences.SQLPreferences; |
import org.openconcerto.sql.request.SQLFieldTranslator; |
import org.openconcerto.sql.view.list.IListe; |
import org.openconcerto.sql.view.list.IListeAction.IListeEvent; |
73,6 → 75,11 |
if (getTable().contains("GROUPE")) { |
fields.add("GROUPE"); |
} |
SQLPreferences prefs = new SQLPreferences(getTable().getDBRoot()); |
if (prefs.getBoolean(GestionCommercialeGlobalPreferencePanel.CATEGORIE_COMPTABLE_SPEC, false)) { |
fields.add("ID_CATEGORIE_COMPTABLE"); |
} |
fields.add("SOLDE_COMPTE"); |
fields.add("REMIND_DATE"); |
fields.add("OBSOLETE"); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/element/AgenceGroup.java |
---|
New file |
0,0 → 1,33 |
/* |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
* |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved. |
* |
* The contents of this file are subject to the terms of the GNU General Public License Version 3 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific |
* language governing permissions and limitations under the License. |
* |
* When distributing the software, include this License Header Notice in each file. |
*/ |
package org.openconcerto.erp.core.customerrelationship.customer.element; |
import org.openconcerto.ui.group.Group; |
import org.openconcerto.ui.group.LayoutHints; |
public class AgenceGroup extends Group { |
public AgenceGroup(String elemCode) { |
super(elemCode); |
addItem("customerrelationship.customer.agency.designation", LayoutHints.DEFAULT_VERY_LARGE_FIELD_HINTS); |
addItem("customerrelationship.customer.agency.phone1", LayoutHints.DEFAULT_VERY_LARGE_FIELD_HINTS); |
addItem("customerrelationship.customer.agency.email", LayoutHints.DEFAULT_VERY_LARGE_FIELD_HINTS); |
addItem("customerrelationship.customer.agency.fax", LayoutHints.DEFAULT_VERY_LARGE_FIELD_HINTS); |
addItem("customerrelationship.customer.agency.customer", LayoutHints.DEFAULT_VERY_LARGE_FIELD_HINTS); |
final Group gAddress = new Group("customerrelationship.customer.agency.grp1", LayoutHints.DEFAULT_SEPARATED_GROUP_HINTS); |
gAddress.addItem("customerrelationship.customer.agency.address", new LayoutHints(true, true, true, true, true, true, true, true)); |
this.add(gAddress); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/element/RelanceSQLElement.java |
---|
15,7 → 15,14 |
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement; |
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement; |
import org.openconcerto.erp.config.Log; |
import org.openconcerto.erp.core.common.ui.DeviseField; |
import org.openconcerto.erp.core.sales.invoice.element.SaisieVenteFactureSQLElement; |
import org.openconcerto.erp.core.sales.invoice.report.VenteFactureXmlSheet; |
import org.openconcerto.erp.generationDoc.A4; |
import org.openconcerto.erp.generationDoc.ProgressPrintingFrame; |
import org.openconcerto.erp.generationDoc.gestcomm.FicheRelanceSheet; |
import org.openconcerto.erp.generationDoc.gestcomm.RelanceSheet; |
import org.openconcerto.erp.preferences.PrinterNXProps; |
import org.openconcerto.sql.element.BaseSQLComponent; |
29,6 → 36,8 |
import org.openconcerto.sql.sqlobject.JUniqueTextField; |
import org.openconcerto.sql.view.EditFrame; |
import org.openconcerto.ui.DefaultGridBagConstraints; |
import org.openconcerto.sql.view.list.IListe; |
import org.openconcerto.sql.view.list.RowAction; |
import org.openconcerto.ui.JDate; |
import org.openconcerto.ui.component.ITextArea; |
import org.openconcerto.ui.component.InteractionMode; |
36,23 → 45,160 |
import java.awt.GridBagConstraints; |
import java.awt.GridBagLayout; |
import java.awt.Window; |
import java.awt.event.ActionEvent; |
import java.awt.print.Paper; |
import java.awt.print.PrinterException; |
import java.awt.print.PrinterJob; |
import java.sql.SQLException; |
import java.util.ArrayList; |
import java.util.Calendar; |
import java.util.List; |
import java.util.logging.Level; |
import javax.print.PrintService; |
import javax.print.attribute.Attribute; |
import javax.print.attribute.HashPrintRequestAttributeSet; |
import javax.print.attribute.Size2DSyntax; |
import javax.print.attribute.standard.Copies; |
import javax.print.attribute.standard.MediaPrintableArea; |
import javax.print.attribute.standard.MediaSizeName; |
import javax.swing.AbstractAction; |
import javax.swing.JCheckBox; |
import javax.swing.JLabel; |
import javax.swing.JPanel; |
import javax.swing.JSeparator; |
import javax.swing.SwingUtilities; |
import javax.swing.JOptionPane; |
import javax.swing.SwingUtilities; |
public class RelanceSQLElement extends ComptaSQLConfElement { |
public static final String ITEM_TYPE = "type.id"; |
public static final String ITEM_DATE = "date"; |
public static final String ITEM_NUMBER = "number"; |
public static final String ITEM_CUSTOMER = "customer.id"; |
public static final String ITEM_SALES_INVOICE_INPUT = "sales.invoice.input.id"; |
public static final String ITEM_AMOUNT = "amount"; |
public static final String ITEM_INFORMATIONS = "informations"; |
public static final String ITEM_VISUALIZATION = "visualization"; |
public static final String ITEM_PRINT = "impression"; |
private static final double POINTS_PER_INCH = 72.0; |
public RelanceSQLElement() { |
super("RELANCE", "une relance client", "relances clients"); |
RowAction actionShowDoc = new RowAction(new AbstractAction("Voir le document") { |
public void actionPerformed(ActionEvent e) { |
final RelanceSheet s = new RelanceSheet(IListe.get(e).getSelectedRow().asRow().fetchNew(false)); |
s.generate(false, false, ""); |
s.showDocument(); |
} |
}, false) { |
@Override |
public boolean enabledFor(List<SQLRowValues> selection) { |
if (selection.size() == 1) { |
SQLRowValues rowRelance = selection.get(0); |
boolean isNotMail = !(rowRelance.getForeign("ID_TYPE_LETTRE_RELANCE") == null || rowRelance.isForeignEmpty("ID_TYPE_LETTRE_RELANCE")); |
return isNotMail; |
} |
return false; |
} |
}; |
getRowActions().add(actionShowDoc); |
RowAction actionPrintDoc = new RowAction(new AbstractAction("Imprimer") { |
public void actionPerformed(ActionEvent e) { |
print(e, false); |
} |
}, false) { |
@Override |
public boolean enabledFor(List<SQLRowValues> selection) { |
if (selection.size() >= 1) { |
boolean isNotMail = true; |
for (SQLRowValues rowRelance : selection) { |
isNotMail &= !(rowRelance.getForeign("ID_TYPE_LETTRE_RELANCE") == null || rowRelance.isForeignEmpty("ID_TYPE_LETTRE_RELANCE")); |
} |
return isNotMail; |
} |
return false; |
} |
}; |
getRowActions().add(actionPrintDoc); |
// Impression |
RowAction actionPrintDocFact = new RowAction(new AbstractAction("Imprimer avec la facture") { |
public void actionPerformed(ActionEvent e) { |
print(e, true); |
} |
}, false) { |
@Override |
public boolean enabledFor(List<SQLRowValues> selection) { |
if (selection.size() >= 1) { |
boolean isNotMail = true; |
for (SQLRowValues rowRelance : selection) { |
isNotMail &= !(rowRelance.getForeign("ID_TYPE_LETTRE_RELANCE") == null || rowRelance.isForeignEmpty("ID_TYPE_LETTRE_RELANCE")); |
} |
return isNotMail; |
} |
return false; |
} |
}; |
getRowActions().add(actionPrintDocFact); |
// Générer |
RowAction actionGen = new RowAction(new AbstractAction("Générer le document") { |
public void actionPerformed(ActionEvent e) { |
for (SQLRowValues rowVals : IListe.get(e).getSelectedRows()) { |
final RelanceSheet s = new RelanceSheet(rowVals.asRow().fetchNew(false)); |
String printer = PrinterNXProps.getInstance().getStringProperty("RelancePrinter"); |
s.generate(false, true, printer, true); |
s.showDocument(); |
} |
} |
}, false) { |
@Override |
public boolean enabledFor(List<SQLRowValues> selection) { |
if (selection.size() >= 1) { |
SQLRowValues rowRelance = selection.get(0); |
boolean isNotMail = !(rowRelance.getForeign("ID_TYPE_LETTRE_RELANCE") == null || rowRelance.isForeignEmpty("ID_TYPE_LETTRE_RELANCE")); |
return isNotMail; |
} |
return false; |
} |
}; |
getRowActions().add(actionGen); |
RowAction actionFiche = new RowAction(new AbstractAction("Créer la fiche de relance") { |
public void actionPerformed(ActionEvent e) { |
try { |
FicheRelanceSheet sheet = new FicheRelanceSheet(IListe.get(e).getSelectedRow().asRow().fetchNew(false)); |
sheet.createDocumentAsynchronous(); |
sheet.showPrintAndExportAsynchronous(true, false, true); |
} catch (Exception ex) { |
ExceptionHandler.handle("Impression impossible", ex); |
} |
} |
}, false) { |
@Override |
public boolean enabledFor(List<SQLRowValues> selection) { |
return (selection.size() == 1); |
} |
}; |
getRowActions().add(actionFiche); |
} |
protected List<String> getListFields() { |
final List<String> l = new ArrayList<String>(); |
l.add("NUMERO"); |
302,4 → 448,103 |
protected String createCode() { |
return this.createCodeOfPackage() + ".chaseletter"; |
} |
public void print(final ActionEvent ev, boolean withInvoice) { |
// |
final IListe ilist = IListe.get(ev); |
String printerName = PrinterNXProps.getInstance().getStringProperty("RelancePrinter"); |
// Printer configuration |
final PrinterJob printJob = PrinterJob.getPrinterJob(); |
// Set the printer |
PrintService myService = null; |
if (printerName != null && printerName.trim().length() > 0) { |
final PrintService[] services = PrinterJob.lookupPrintServices(); |
for (int i = 0; i < services.length; i++) { |
if (services[i].getName().equals(printerName)) { |
myService = services[i]; |
break; |
} |
} |
if (myService != null) { |
try { |
printJob.setPrintService(myService); |
} catch (PrinterException e) { |
Log.get().log(Level.SEVERE, "cannot print", e); |
JOptionPane.showMessageDialog(null, "Imprimante non compatible"); |
return; |
} |
} |
} |
final HashPrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet(); |
// L'impression est forcée en A4, sur OpenSuse le format est en |
// Letter par défaut alors que l'imprimante est en A4 dans le système |
final MediaSizeName media = MediaSizeName.ISO_A4; |
attributes.add(media); |
Paper paper = new A4(0, 0); |
final MediaPrintableArea printableArea = new MediaPrintableArea((float) (paper.getImageableX() / POINTS_PER_INCH), (float) (paper.getImageableY() / POINTS_PER_INCH), |
(float) (paper.getImageableWidth() / POINTS_PER_INCH), (float) (paper.getImageableHeight() / POINTS_PER_INCH), Size2DSyntax.INCH); |
attributes.add(printableArea); |
attributes.add(new Copies(1)); |
boolean okToPrint = printJob.printDialog(attributes); |
final Attribute attribute = attributes.get(Copies.class); |
if (attribute != null) { |
final Copies attributeCopies = (Copies) attribute; |
final int value = attributeCopies.getValue(); |
printJob.setCopies(value); |
} else { |
printJob.setCopies(1); |
} |
if (okToPrint) { |
Window w = SwingUtilities.getWindowAncestor(ilist); |
final ProgressPrintingFrame pFrame = new ProgressPrintingFrame(w, printJob, "Impression", "Impression en cours", 300); |
// Génération + impression |
final List<SQLRowValues> rows = IListe.get(ev).getSelectedRows(); |
final Thread thread = new Thread() { |
@Override |
public void run() { |
final int size = rows.size(); |
for (int i = 0; i < size; i++) { |
final int index = i; |
SwingUtilities.invokeLater(new Runnable() { |
@Override |
public void run() { |
pFrame.setMessage("Document " + (index + 1) + "/" + size); |
pFrame.setProgress((100 * (index + 1)) / size); |
} |
}); |
if (!pFrame.isCancelled()) { |
SQLRowValues r = rows.get(i); |
SQLRow rowRelance = r.asRow().fetchNew(false); |
RelanceSheet s = new RelanceSheet(rowRelance); |
s.printDocument(printJob); |
if (withInvoice) { |
SaisieVenteFactureSQLElement element = getDirectory().getElement(SaisieVenteFactureSQLElement.class); |
final VenteFactureXmlSheet sheet = new VenteFactureXmlSheet(rowRelance.getForeignRow("ID_SAISIE_VENTE_FACTURE")); |
try { |
sheet.getOrCreateDocumentFile(); |
sheet.printDocument(printJob); |
} catch (Exception e) { |
ExceptionHandler.handle("Erreur lors de la création de la facture", e); |
} |
} |
} |
} |
} |
}; |
thread.setPriority(Thread.MIN_PRIORITY); |
thread.setDaemon(true); |
pFrame.setLocationRelativeTo(ilist); |
pFrame.setVisible(true); |
thread.start(); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/element/CustomerSQLComponent.java |
---|
18,6 → 18,7 |
import org.openconcerto.erp.core.customerrelationship.customer.ui.AdresseClientItemTable; |
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement; |
import org.openconcerto.erp.core.sales.product.element.ClientCodeArticleTable; |
import org.openconcerto.erp.core.sales.product.ui.CustomerProductFamilyQtyPriceListTable; |
import org.openconcerto.erp.core.sales.product.ui.CustomerProductQtyPriceListTable; |
import org.openconcerto.erp.preferences.GestionCommercialeGlobalPreferencePanel; |
import org.openconcerto.erp.preferences.ModeReglementDefautPrefPanel; |
42,7 → 43,10 |
import org.openconcerto.sql.view.EditFrame; |
import org.openconcerto.sql.view.EditPanel.EditMode; |
import org.openconcerto.sql.view.IListFrame; |
import org.openconcerto.sql.view.IListPanel; |
import org.openconcerto.sql.view.ListeAddPanel; |
import org.openconcerto.sql.view.list.IListe; |
import org.openconcerto.sql.view.list.SQLTableModelSource; |
import org.openconcerto.ui.DefaultGridBagConstraints; |
import org.openconcerto.ui.FrameUtil; |
import org.openconcerto.ui.JDate; |
65,6 → 69,7 |
import javax.swing.AbstractAction; |
import javax.swing.Icon; |
import javax.swing.JButton; |
import javax.swing.JCheckBox; |
import javax.swing.JComponent; |
import javax.swing.JLabel; |
95,8 → 100,10 |
}; |
private CustomerProductQtyPriceListTable clienTarifTable = new CustomerProductQtyPriceListTable(); |
private CustomerProductFamilyQtyPriceListTable clienFamilleTarifTable = new CustomerProductFamilyQtyPriceListTable(); |
private SQLRowValues defaultContactRowVals = new SQLRowValues(UndefinedRowValuesCache.getInstance().getDefaultRowValues(this.contactTable)); |
private JCheckBox checkAdrLivraison, checkAdrFacturation; |
private IListPanel agencePanel; |
public CustomerSQLComponent(SQLElement element) { |
super(element); |
172,10 → 179,34 |
return new JDate(true); |
} else if (id.equals("customerrelationship.customer.contacts")) { |
return this.table; |
} else if (id.equals("customerrelationship.customer.agencies")) { |
SQLElement elementAgence = getElement().getDirectory().getElement("AGENCE"); |
SQLTableModelSource source = elementAgence.createTableSource(Where.FALSE); |
this.agencePanel = new ListeAddPanel(elementAgence, new IListe(source)) { |
@Override |
protected void handleAction(JButton source, ActionEvent evt) { |
if (source == this.buttonAjouter) { |
if (getMode() == Mode.MODIFICATION && getSelectedID() != SQLRow.NONEXISTANT_ID) { |
SQLRowValues rowValsAgency = new SQLRowValues(elementAgence.getTable()); |
rowValsAgency.put("ID_CLIENT", getSelectedID()); |
this.getCreateFrame().getSQLComponent().select(rowValsAgency); |
} |
FrameUtil.show(this.getCreateFrame()); |
} else { |
super.handleAction(source, evt); |
} |
} |
}; |
if (getMode() == Mode.INSERTION || getMode() == Mode.READ_ONLY) { |
this.agencePanel.getButtonAdd().setEnabled(false); |
} |
return this.agencePanel; |
} 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.customfamilytarif")) { |
return this.clienFamilleTarifTable; |
} else if (id.equals("customerrelationship.customer.addresses")) { |
return createAdressesComponent(); |
} else if (id.equals("NOM")) { |
253,6 → 284,7 |
final int selectedID = getSelectedID(); |
this.table.updateField("ID_CLIENT", selectedID); |
this.clienTarifTable.updateField("ID_CLIENT", selectedID); |
this.clienFamilleTarifTable.updateField("ID_CLIENT", selectedID); |
this.tableCustomProduct.updateField("ID_CLIENT", selectedID); |
this.adresseTable.updateField("ID_CLIENT", selectedID); |
} |
265,10 → 297,16 |
if (r != null) { |
this.table.insertFrom("ID_CLIENT", r.asRowValues()); |
this.clienTarifTable.insertFrom("ID_CLIENT", r.asRowValues()); |
this.clienFamilleTarifTable.insertFrom("ID_CLIENT", r.asRowValues()); |
this.tableCustomProduct.insertFrom("ID_CLIENT", r.asRowValues()); |
this.adresseTable.insertFrom("ID_CLIENT", r.asRowValues()); |
} |
if (r != null && r.hasID()) { |
this.agencePanel.getListe().getRequest().setWhere(new Where(this.agencePanel.getListe().getRequest().getPrimaryTable().getField("ID_CLIENT"), "=", r.getID())); |
} else { |
this.agencePanel.getListe().getRequest().setWhere(Where.FALSE); |
} |
} |
@Override |
public int insert(SQLRow order) { |
304,6 → 342,8 |
} else { |
id = super.insert(order); |
this.table.updateField("ID_CLIENT", id); |
this.clienTarifTable.updateField("ID_CLIENT", id); |
this.clienFamilleTarifTable.updateField("ID_CLIENT", id); |
this.tableCustomProduct.updateField("ID_CLIENT", id); |
this.clienTarifTable.updateField("ID_CLIENT", id); |
this.adresseTable.updateField("ID_CLIENT", id); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/element/AgenceSQLElement.java |
---|
New file |
0,0 → 1,108 |
/* |
* 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.element.ElementSQLObject; |
import org.openconcerto.sql.element.GroupSQLComponent; |
import org.openconcerto.sql.element.SQLComponent; |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.model.DBRoot; |
import org.openconcerto.sql.sqlobject.ElementComboBox; |
import org.openconcerto.ui.JLabelBold; |
import org.openconcerto.ui.group.Group; |
import java.util.ArrayList; |
import java.util.HashSet; |
import java.util.List; |
import java.util.Set; |
import javax.swing.JComponent; |
import javax.swing.JLabel; |
public class AgenceSQLElement extends SQLElement { |
public AgenceSQLElement(DBRoot root) { |
super(root.findTable("AGENCE")); |
// TODO Auto-generated constructor stub |
} |
@Override |
protected List<String> getListFields() { |
List<String> list = new ArrayList<>(2); |
list.add("DESIGNATION"); |
list.add("ID_CLIENT"); |
list.add("ID_ADRESSE"); |
return list; |
} |
@Override |
public Group getGroupForCreation() { |
// TODO Auto-generated method stub |
return super.getGroupForCreation(); |
} |
@Override |
protected SQLComponent createComponent() { |
return new GroupSQLComponent(this, new AgenceGroup(this.getCode())) { |
@Override |
public JComponent createEditor(String id) { |
if (id.equals("customerrelationship.customer.agency.address")) { |
org.openconcerto.sql.element.ElementSQLObject c = (ElementSQLObject) super.createEditor(id); |
c.setRequired(true); |
return c; |
} |
if (id.equals("customerrelationship.customer.agency.customer")) { |
ElementComboBox compClient = new ElementComboBox(); |
compClient.setVisible(false); |
return compClient; |
} |
return super.createEditor(id); |
} |
@Override |
protected Set<String> createRequiredNames() { |
final Set<String> required = new HashSet<>(); |
required.add("customerrelationship.customer.agency.designation"); |
return required; |
} |
@Override |
public JComponent createLabel(String id) { |
if (id.equals("customerrelationship.customer.agency.customer")) { |
JLabel label = new JLabel(); |
label.setVisible(false); |
return label; |
} |
if (id.equals("customerrelationship.customer.agency.grp1")) { |
JLabel label = new JLabel(); |
label.setVisible(false); |
return label; |
} else if (id.equals("customerrelationship.customer.agency.address")) { |
return new JLabelBold("Adresse de l'agence"); |
} else { |
return super.createLabel(id); |
} |
} |
}; |
} |
@Override |
protected String createCode() { |
return "customerrelationship.customer.agency"; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/element/CustomerGroup.java |
---|
57,6 → 57,10 |
this.add(gAddress); |
final Group gAgency = new Group("customerrelationship.customer.agency"); |
gAgency.addItem("customerrelationship.customer.agencies", new LayoutHints(true, true, true, true, true, true, true, true)); |
this.add(gAgency); |
final Group gContact = new Group("customerrelationship.customer.contact", LayoutHints.DEFAULT_SEPARATED_GROUP_HINTS); |
gContact.addItem("customerrelationship.customer.contacts", new LayoutHints(true, true, true, true, true, true, true, true)); |
this.add(gContact); |
95,8 → 99,10 |
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)); |
gCustomRemiseProduct.addItem("customerrelationship.customer.customfamilytarif", new LayoutHints(true, true, true, true, true, true, true, true)); |
this.add(gCustomRemiseProduct); |
this.add(gState); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/report/ReportingCommercialFournisseurCreator.java |
---|
New file |
0,0 → 1,127 |
/* |
* 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 ReportingCommercialFournisseurCreator { |
final private Date deb, fin; |
final private DBRoot root; |
public ReportingCommercialFournisseurCreator(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_ELEMENT"); |
SQLRowValues rowValues = new SQLRowValues(tableFacture); |
rowValues.putRowValues("ID_SAISIE_VENTE_FACTURE").putRowValues("ID_COMMERCIAL").putNulls("PRENOM", "NOM"); |
rowValues.putRowValues("ID_ARTICLE").putRowValues("ID_FOURNISSEUR").putNulls("CODE", "NOM"); |
rowValues.putNulls("T_PV_HT", "T_PV_TTC"); |
SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowValues); |
fetcher.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() { |
@Override |
public SQLSelect transformChecked(SQLSelect input) { |
Where w = new Where(input.getJoinFromField(tableFacture.getField("ID_SAISIE_VENTE_FACTURE")).getJoinedTable().getField("DATE"), deb, fin); |
input.setWhere(w); |
return input; |
} |
}); |
Map<Integer, ReportingCommercial> mapCommercial = new HashMap<>(); |
List<SQLRowValues> result = fetcher.fetch(); |
for (SQLRowValues sqlRowValues : result) { |
if (!sqlRowValues.isForeignEmpty("ID_ARTICLE")) { |
SQLRowAccessor rowArticle = sqlRowValues.getForeign("ID_ARTICLE"); |
if (!rowArticle.isForeignEmpty("ID_FOURNISSEUR")) { |
SQLRowAccessor rowFournisseur = rowArticle.getForeign("ID_FOURNISSEUR"); |
int commercialID = sqlRowValues.getForeign("ID_SAISIE_VENTE_FACTURE").getForeignID("ID_COMMERCIAL"); |
if (!mapCommercial.containsKey(commercialID)) { |
SQLRowAccessor commercialRow = sqlRowValues.getForeign("ID_SAISIE_VENTE_FACTURE").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_PV_HT")).movePointLeft(2); |
r.add(rowFournisseur.getString("NOM"), bigDecimal); |
} |
} |
} |
// Avoir |
final SQLTable tableAvoir = this.root.getTable("AVOIR_CLIENT_ELEMENT"); |
SQLRowValues rowValuesAvoir = new SQLRowValues(tableAvoir); |
rowValuesAvoir.putRowValues("ID_AVOIR_CLIENT").putRowValues("ID_COMMERCIAL").putNulls("PRENOM", "NOM"); |
rowValuesAvoir.putRowValues("ID_ARTICLE").putRowValues("ID_FOURNISSEUR").putNulls("CODE", "NOM"); |
rowValuesAvoir.putNulls("T_PV_HT", "T_PV_TTC"); |
SQLRowValuesListFetcher fetcherAvoir = SQLRowValuesListFetcher.create(rowValuesAvoir); |
fetcherAvoir.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() { |
@Override |
public SQLSelect transformChecked(SQLSelect input) { |
Where w = new Where(input.getJoinFromField(tableAvoir.getField("ID_AVOIR_CLIENT")).getJoinedTable().getField("DATE"), deb, fin); |
input.setWhere(w); |
return input; |
} |
}); |
List<SQLRowValues> resultA = fetcherAvoir.fetch(); |
for (SQLRowValues sqlRowValues : resultA) { |
if (!sqlRowValues.isForeignEmpty("ID_ARTICLE")) { |
SQLRowAccessor rowArticle = sqlRowValues.getForeign("ID_ARTICLE"); |
if (!rowArticle.isForeignEmpty("ID_FOURNISSEUR")) { |
SQLRowAccessor rowFournisseur = rowArticle.getForeign("ID_FOURNISSEUR"); |
int commercialID = sqlRowValues.getForeign("ID_AVOIR_CLIENT").getForeignID("ID_COMMERCIAL"); |
if (!mapCommercial.containsKey(commercialID)) { |
SQLRowAccessor commercialRow = sqlRowValues.getForeign("ID_AVOIR_CLIENT").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_PV_HT")).movePointLeft(2).negate(); |
r.add(rowFournisseur.getString("NOM"), bigDecimal); |
} |
} |
} |
return mapCommercial.values(); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/report/ReportingCommercialFournisseurPanel.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 ReportingCommercialFournisseurPanel extends JPanel { |
public ReportingCommercialFournisseurPanel(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() { |
ReportingCommercialFournisseurCreator creator = new ReportingCommercialFournisseurCreator(dateDeb.getValue(), dateFin.getValue(), root); |
List<ReportingCommercial> list = new ArrayList<>(creator.getValues()); |
ReportingCommercialPDF reporting = new ReportingCommercialPDF(list); |
File file; |
try { |
file = File.createTempFile("ReportingCommericalFournisseur", ".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(ReportingCommercialFournisseurPanel.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/finance/accounting/model/PointageModel.java |
---|
14,6 → 14,7 |
package org.openconcerto.erp.core.finance.accounting.model; |
import org.openconcerto.erp.config.ComptaPropsConfiguration; |
import org.openconcerto.erp.core.common.ui.DeviseField; |
import org.openconcerto.erp.core.finance.accounting.ui.PointagePanel; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.model.SQLBase; |
111,6 → 112,11 |
private SwingWorker<String, Object> workerUpdater; |
public void updateTotauxCompte() { |
updateTotauxCompte(null, null, null); |
} |
public void updateTotauxCompte(final DeviseField depart, final DeviseField arrive, final DeviseField ecart) { |
final Date deb = panel.getDateDeb(); |
final Date fin = panel.getDateFin(); |
232,6 → 238,15 |
if (isCancelled()) { |
return; |
} |
if (arrive != null && depart != null && ecart != null) { |
final Long valueArrive = arrive.getValue(); |
final Long valueDepart = depart.getValue(); |
if (valueArrive != null && valueDepart != null) { |
ecart.setValue(valueArrive - valueDepart + PointageModel.this.debitNonPointe - PointageModel.this.creditNonPointe); |
} else { |
ecart.setValue(null); |
} |
} |
PointageModel.this.fireTableDataChanged(); |
} |
}; |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/element/SaisieKmSQLElement.java |
---|
16,20 → 16,28 |
import org.openconcerto.erp.config.ComptaPropsConfiguration; |
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement; |
import org.openconcerto.erp.core.finance.accounting.ui.AnalytiqueItemTable; |
import org.openconcerto.erp.core.finance.accounting.ui.ComptabiliteWorkflowPreferencePanel; |
import org.openconcerto.erp.core.finance.accounting.ui.PropoLettrage; |
import org.openconcerto.erp.core.finance.accounting.ui.SaisieKmItemTable; |
import org.openconcerto.erp.generationEcritures.GenerationMvtSaisieKm; |
import org.openconcerto.erp.generationEcritures.provider.AccountingRecordsProvider; |
import org.openconcerto.erp.generationEcritures.provider.AccountingRecordsProviderManager; |
import org.openconcerto.erp.preferences.DefaultNXProps; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.element.BaseSQLComponent; |
import org.openconcerto.sql.element.SQLComponent; |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.model.SQLBase; |
import org.openconcerto.sql.model.SQLName; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.model.TableRef; |
import org.openconcerto.sql.model.UndefinedRowValuesCache; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.request.UpdateBuilder; |
import org.openconcerto.sql.sqlobject.ElementComboBox; |
import org.openconcerto.sql.utils.SQLUtils; |
import org.openconcerto.sql.view.list.RowValuesTableModel; |
432,9 → 440,25 |
} |
}); |
this.updateEcriture(getTable().getRow(id)); |
} catch (SQLException exn) { |
ExceptionHandler.handle("Erreur lors de la création des écritures associées à la saisie au kilometre.", exn); |
} |
boolean showPropoLettrage = Boolean.valueOf(DefaultNXProps.getInstance().getProperty(ComptabiliteWorkflowPreferencePanel.LETTRAGE_PROPO_KM)); |
if (showPropoLettrage) { |
if (id > SQLRow.NONEXISTANT_ID) { |
final SQLRow rowKM = getTable().getRow(id); |
SwingUtilities.invokeLater(new Runnable() { |
@Override |
public void run() { |
PropoLettrage lettragePropo = new PropoLettrage(getElement().getDirectory().getElement(EcritureSQLElement.class)); |
lettragePropo.transfert(rowKM); |
} |
}); |
} |
} |
return id; |
} |
466,7 → 490,19 |
this.tableKm.updateField("ID_SAISIE_KM", getSelectedID()); |
System.err.println("UPDATE ECRITURE"); |
this.updateEcriture(getElement().getTable().getRow(getSelectedID())); |
boolean showPropoLettrage = Boolean.valueOf(DefaultNXProps.getInstance().getProperty(ComptabiliteWorkflowPreferencePanel.LETTRAGE_PROPO_KM)); |
if (showPropoLettrage) { |
SQLRow rowKM = getTable().getRow(getSelectedID()); |
SwingUtilities.invokeLater(new Runnable() { |
@Override |
public void run() { |
PropoLettrage lettragePropo = new PropoLettrage(getElement().getDirectory().getElement(EcritureSQLElement.class)); |
lettragePropo.transfert(rowKM); |
} |
}); |
} |
} |
private Date dTemp = null; |
521,8 → 557,15 |
final SQLRow mvt = rowSaisieKm.getForeign("ID_MOUVEMENT"); |
final SQLRow piece = mvt.getForeign("ID_PIECE"); |
String labelSaisie = rowSaisieKm.getString("NOM"); |
piece.createEmptyUpdateRow().put("NOM", (labelSaisie.length() == 0 ? "Saisie au km " : labelSaisie)).commit(); |
AccountingRecordsProvider provider = AccountingRecordsProviderManager.get(GenerationMvtSaisieKm.ID); |
SQLRowValues rowValsPiece = piece.asRowValues(); |
rowValsPiece.put("NOM", (labelSaisie.length() == 0 ? "Saisie au km " : labelSaisie)); |
if (provider != null) { |
provider.putPieceLabel(rowSaisieKm, rowValsPiece); |
} |
rowValsPiece.commit(); |
// Mise à jour des écritures |
for (SQLRow rowKmElement : myListKmItem) { |
581,11 → 624,54 |
listEcr.remove(sqlRow); |
} |
} |
} |
} |
// Suppression des lettrages déséquilibré (ex : si on modifie un |
// montant d'une écriture lettrée) |
SQLSelect sel = new SQLSelect(); |
sel.addSelect(ecritureTable.getField("LETTRAGE")); |
sel.addGroupBy(ecritureTable.getField("LETTRAGE")); |
final TableRef aliasEcrTable = sel.getAlias(ecritureTable); |
final String quoteDebit = new SQLName(aliasEcrTable.getAlias(), "DEBIT").quote(); |
final String quoteCredit = new SQLName(aliasEcrTable.getAlias(), "CREDIT").quote(); |
sel.setHaving(Where.createRaw("SUM (" + quoteCredit + ") != SUM(" + quoteDebit + ")", aliasEcrTable.getField("DEBIT"))); |
List<String> resultBadLettrage = getElement().getTable().getDBSystemRoot().getDataSource().executeCol(sel.asString()); |
if (resultBadLettrage != null && !resultBadLettrage.isEmpty()) { |
UpdateBuilder update = new UpdateBuilder(ecritureTable); |
update.setObject(ecritureTable.getField("LETTRAGE"), ""); |
update.setObject(ecritureTable.getField("DATE_LETTRAGE"), null); |
Where w = new Where(ecritureTable.getField("LETTRAGE"), resultBadLettrage); |
update.setWhere(w); |
getElement().getTable().getDBSystemRoot().getDataSource().execute(update.asString()); |
} |
} |
// Suppression des lettrages déséquilibré (ex : si on modifie un |
// montant d'une écriture lettrée) |
SQLSelect sel = new SQLSelect(); |
sel.addSelect(ecritureTable.getField("LETTRAGE")); |
sel.addGroupBy(ecritureTable.getField("LETTRAGE")); |
final TableRef aliasEcrTable = sel.getAlias(ecritureTable); |
final String quoteDebit = new SQLName(aliasEcrTable.getAlias(), "DEBIT").quote(); |
final String quoteCredit = new SQLName(aliasEcrTable.getAlias(), "CREDIT").quote(); |
sel.setWhere(Where.isNotNull(ecritureTable.getField("LETTRAGE")).and(new Where(ecritureTable.getField("LETTRAGE"), "!=", ""))); |
sel.setHaving(Where.createRaw("SUM (" + quoteCredit + ") != SUM(" + quoteDebit + ")", aliasEcrTable.getField("DEBIT"))); |
List<String> resultBadLettrage = getTable().getDBSystemRoot().getDataSource().executeCol(sel.asString()); |
if (resultBadLettrage != null && !resultBadLettrage.isEmpty()) { |
UpdateBuilder update = new UpdateBuilder(ecritureTable); |
update.setObject(ecritureTable.getField("LETTRAGE"), ""); |
update.setObject(ecritureTable.getField("DATE_LETTRAGE"), null); |
Where w = new Where(ecritureTable.getField("LETTRAGE"), resultBadLettrage); |
update.setWhere(w); |
getTable().getDBSystemRoot().getDataSource().execute(update.asString()); |
} |
if (!listEcr.isEmpty()) { |
final EcritureSQLElement e = (EcritureSQLElement) Configuration.getInstance().getDirectory().getElement(ecritureTable); |
for (SQLRow sqlRow : listEcr) { |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/element/EcritureSQLElement.java |
---|
35,6 → 35,7 |
import org.openconcerto.sql.model.SQLBase; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.SQLRowListRSH; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.SQLTable; |
292,6 → 293,7 |
public final SQLTableModelSourceOnline createLettrageTableSource() { |
final List<String> listEcriture = new ArrayList<String>(); |
listEcriture.add("LETTRAGE"); |
listEcriture.add("LETTRAGE_PARTIEL"); |
listEcriture.add("ID_COMPTE_PCE"); |
listEcriture.add("ID_MOUVEMENT"); |
if (getTable().contains("NOM_PIECE")) { |
668,14 → 670,16 |
@Override |
public Object create() throws SQLException { |
// on recupere l'ensemble des ecritures associées au mouvement |
SQLSelect selEcritures = new SQLSelect(); |
selEcritures.addSelect(tableEcriture.getField("ID")); |
selEcritures.addSelect(tableEcriture.getField("VALIDE")); |
selEcritures.addSelect(tableEcriture.getField("LETTRAGE")); |
selEcritures.setWhere(tableEcriture.getField("ID_MOUVEMENT"), "=", idMvt); |
List l = (List) base.getDataSource().execute(selEcritures.asString(), new ArrayListHandler()); |
for (int i = 0; i < l.size(); i++) { |
Object[] tmp = (Object[]) l.get(i); |
archiveEcriture(tableEcriture.getRow(Integer.parseInt(tmp[0].toString()))); |
List<SQLRow> rowEcr = SQLRowListRSH.execute(selEcritures); |
for (SQLRow r : rowEcr) { |
archiveEcriture(r); |
} |
return null; |
717,14 → 721,15 |
* @param row |
* @throws SQLException |
*/ |
public void archiveEcriture(SQLRow row) throws SQLException { |
public void archiveEcriture(SQLRowAccessor row) throws SQLException { |
if (!row.getBoolean("VALIDE")) { |
SQLRowValues rowVals = new SQLRowValues(this.getTable()); |
rowVals.put("IDUSER_DELETE", UserManager.getInstance().getCurrentUser().getId()); |
rowVals.put("ARCHIVE", 1); |
rowVals.update(row.getID()); |
UpdateBuilder builderArc = new UpdateBuilder(getTable()); |
builderArc.setObject("IDUSER_DELETE", UserManager.getInstance().getCurrentUser().getId()); |
builderArc.setObject("ARCHIVE", 1); |
builderArc.setWhere(new Where(getTable().getKey(), "=", row.getID())); |
getTable().getDBSystemRoot().getDataSource().execute(builderArc.asString()); |
// Annulation du lettrage si l'ecriture est lettrée pour ne pas avoir de lettrage |
// déséquilibré |
736,7 → 741,7 |
builder.setWhere(new Where(getTable().getField("LETTRAGE"), "=", codeLettrage)); |
getTable().getDBSystemRoot().getDataSource().execute(builder.asString()); |
} |
getTable().fireRowDeleted(row.getID()); |
// super.archive(row, true); |
} else { |
System.err.println("Impossible de supprimer une ecriture validée"); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/report/GrandLivreSheetXML.java |
---|
72,14 → 72,6 |
Date date; |
@Override |
public String getName() { |
if (this.date == null) { |
this.date = new Date(); |
} |
return "GrandLivre" + date.getTime(); |
} |
@Override |
protected String getStoragePathP() { |
return "Grand Livre"; |
} |
109,21 → 101,16 |
private String toDay = dateFormat.format(new Date()); |
private int size; |
// private void makeEntete(int rowDeb) { |
// |
// this.mCell.put("A" + rowDeb, this.rowSociete.getObject("NOM")); |
// this.mCell.put("G" + rowDeb, "Edition du " + this.toDay); |
// // this.mCell.put("D" + (rowDeb + 2), "Grand livre"); |
// // System.err.println("MAKE ENTETE"); |
// } |
// |
// private void makePiedPage(int row, String comptes) { |
// this.mCell.put("A" + row, "Compte : " + comptes); |
// this.mCell.put("E" + row, "Période du " + dateFormatEcr.format(this.dateDu) + " au " + |
// dateFormatEcr.format(this.dateAu)); |
// } |
private List<Map<String, Object>> recapSousTotaux = new ArrayList<>(); |
@Override |
public String getName() { |
if (this.date == null) { |
this.date = new Date(); |
} |
return "GrandLivre" + this.date.getTime(); |
} |
private void makeSousTotal(String numCpt, String nomCpt, Map<String, Object> line, Map<Integer, String> style, int pos, long debit, long credit) { |
style.put(pos, "Titre 1"); |
522,9 → 509,8 |
} |
private List<Integer> getListeCompteSolde() { |
SQLSelect sel = new SQLSelect(base); |
sel.addSelect(tableCompte.getField("ID")); |
SQLSelect sel = new SQLSelect(); |
sel.addSelect(tableEcriture.getField("ID_COMPTE_PCE")); |
sel.addSelect(tableEcriture.getField("DEBIT"), "SUM"); |
sel.addSelect(tableEcriture.getField("CREDIT"), "SUM"); |
531,8 → 517,9 |
Where w = getWhere(null); |
sel.setWhere(w); |
sel.addGroupBy(tableEcriture.getField("ID_COMPTE_PCE")); |
String req = sel.asString() + " GROUP BY \"COMPTE_PCE\".\"ID\""; |
String req = sel.asString(); |
System.err.println(req); |
List<Object[]> l = (List) base.getDataSource().execute(req, new ArrayListHandler()); |
List<Integer> list = new ArrayList<Integer>(); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/report/BalanceSheet.java |
---|
350,7 → 350,7 |
} |
if (this.centralClient && !numeroCpt.equalsIgnoreCase("411") && numeroCpt.startsWith("411")) { |
if (addedLine || !this.centralFournImmo) { |
if (addedLine) { |
posLine--; |
j--; |
} else { |
370,7 → 370,7 |
this.mCell.put("A" + posLine, numCptFourn); |
this.mCell.put("B" + posLine, nomCptFourn); |
} else if (this.centralFournImmo && !numeroCpt.equalsIgnoreCase("404") && numeroCpt.startsWith("404")) { |
if (addedLineImmo || !this.centralFourn) { |
if (addedLineImmo) { |
posLine--; |
j--; |
} else { |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/report/Map2033A.java |
---|
404,9 → 404,9 |
// 'Caisse |
// Racine = "53" |
// S084=511+512(D)...517+5187+54+58(D)+53 |
long v084 = this.sommeCompte.soldeCompteDebiteur(510, 517, true, this.dateDebut, this.dateFin) + this.sommeCompte.soldeCompteDebiteur(5180, 5185, true, this.dateDebut, this.dateFin) |
+ this.sommeCompte.soldeCompteDebiteur(5187, 5189, true, this.dateDebut, this.dateFin) + this.sommeCompte.sommeCompteFils("54", this.dateDebut, this.dateFin) |
+ this.sommeCompte.sommeCompteFils("53", this.dateDebut, this.dateFin) + this.sommeCompte.sommeCompteFils("58", this.dateDebut, this.dateFin); |
long v084 = this.sommeCompte.soldeCompteDebiteur(510, 517, true, this.dateDebut, this.dateFin) + this.sommeCompte.soldeCompteDebiteur(518, 518, true, this.dateDebut, this.dateFin) |
+ this.sommeCompte.sommeCompteFils("54", this.dateDebut, this.dateFin) + this.sommeCompte.sommeCompteFils("53", this.dateDebut, this.dateFin) |
+ this.sommeCompte.sommeCompteFils("58", this.dateDebut, this.dateFin); |
this.m.put("ACTIF1.11", GestionDevise.currencyToString(v084, false)); |
682,13 → 682,13 |
* this.sommeCompte.soldeCompteCrediteur(5180, 5180, true) - |
* this.sommeCompte.sommeCompteFils("5186") ; |
*/ |
long v156 = -this.sommeCompte.sommeCompteFils("161", this.dateDebut, this.dateFin) - this.sommeCompte.soldeCompte(163, 166, true, this.dateDebut, this.dateFin) |
- this.sommeCompte.soldeCompte(1680, 1681, true, this.dateDebut, this.dateFin) - this.sommeCompte.soldeCompte(1682, 1682, true, this.dateDebut, this.dateFin) |
- this.sommeCompte.soldeCompte(1684, 1689, true, this.dateDebut, this.dateFin) - this.sommeCompte.sommeCompteFils("17", this.dateDebut, this.dateFin) |
- this.sommeCompte.sommeCompteFils("426", this.dateDebut, this.dateFin) + this.sommeCompte.soldeCompteCrediteur(450, 454, true, this.dateDebut, this.dateFin) |
+ this.sommeCompte.soldeCompteCrediteur(456, 456, true, this.dateDebut, this.dateFin) + this.sommeCompte.soldeCompteCrediteur(458, 459, true, this.dateDebut, this.dateFin) |
+ this.sommeCompte.soldeCompteCrediteur(512, 517, true, this.dateDebut, this.dateFin) - this.sommeCompte.sommeCompteFils("518", this.dateDebut, this.dateFin) |
- this.sommeCompte.sommeCompteFils("519", this.dateDebut, this.dateFin); |
long v156 = -this.sommeCompte.sommeCompteFils("160", this.dateDebut, this.dateFin) - this.sommeCompte.sommeCompteFils("161", this.dateDebut, this.dateFin) |
- this.sommeCompte.soldeCompte(163, 166, true, this.dateDebut, this.dateFin) - this.sommeCompte.soldeCompte(1680, 1681, true, this.dateDebut, this.dateFin) |
- this.sommeCompte.soldeCompte(1682, 1682, true, this.dateDebut, this.dateFin) - this.sommeCompte.soldeCompte(1684, 1689, true, this.dateDebut, this.dateFin) |
- this.sommeCompte.sommeCompteFils("17", this.dateDebut, this.dateFin) - this.sommeCompte.sommeCompteFils("426", this.dateDebut, this.dateFin) |
+ this.sommeCompte.soldeCompteCrediteur(450, 454, true, this.dateDebut, this.dateFin) + this.sommeCompte.soldeCompteCrediteur(456, 456, true, this.dateDebut, this.dateFin) |
+ this.sommeCompte.soldeCompteCrediteur(458, 459, true, this.dateDebut, this.dateFin) + this.sommeCompte.soldeCompteCrediteur(512, 517, true, this.dateDebut, this.dateFin) |
+ this.sommeCompte.soldeCompteCrediteur(518, 518, true, this.dateDebut, this.dateFin) - this.sommeCompte.sommeCompteFils("519", this.dateDebut, this.dateFin); |
this.m.put("PASSIF3.25", GestionDevise.currencyToString(v156, false)); |
// 151 |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/report/Map2033B.java |
---|
183,7 → 183,8 |
******************************************************************************************/ |
// 234 SommeSolde( 607, 608* )+SommeSolde( 6097, 6097* ) |
long v234 = this.sommeCompte.soldeCompte(607, 607, true, this.dateDeb, this.dateFin) + this.sommeCompte.soldeCompte(6097, 6097, true, this.dateDeb, this.dateFin) |
+ this.sommeCompte.soldeCompte(6087, 6087, true, this.dateDeb, this.dateFin); |
+ this.sommeCompte.soldeCompte(608, 608, true, this.dateDeb, this.dateFin) - this.sommeCompte.soldeCompte(6081, 6086, true, this.dateDeb, this.dateFin); |
this.m.put("CHARGES3.8", GestionDevise.currencyToString(v234, false)); |
// 208 |
206,7 → 207,7 |
// S238=601+602+6091+6092 |
// FIX Abaque ajout 609 |
long v238 = this.sommeCompte.soldeCompte(601, 602, true, this.dateDeb, this.dateFin) + this.sommeCompte.soldeCompte(609, 609, true, this.dateDeb, this.dateFin) |
- this.sommeCompte.soldeCompte(6093, 6099, true, this.dateDeb, this.dateFin) + this.sommeCompte.soldeCompte(6081, 6082, true, this.dateDeb, this.dateFin); |
- this.sommeCompte.soldeCompte(6093, 6099, true, this.dateDeb, this.dateFin) + this.sommeCompte.soldeCompte(6081, 6083, true, this.dateDeb, this.dateFin); |
this.m.put("CHARGES3.10", GestionDevise.currencyToString(v238, false)); |
// 212 |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/PropoLettrageTableModel.java |
---|
New file |
0,0 → 1,106 |
/* |
* 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.finance.accounting.ui; |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.model.SQLRowValues; |
import java.util.Arrays; |
import java.util.Date; |
import java.util.List; |
import javax.swing.table.AbstractTableModel; |
public class PropoLettrageTableModel extends AbstractTableModel { |
List<SQLRowValues> datas; |
List<String> colName = Arrays.asList("Libellé", "N° Mouvement", "Pièce", "Pièce commerciale", "Date", "Débit", "Crédit"); |
List<String> fieldName = Arrays.asList("NOM", "ID_MOUVEMENT", "ID_PIECE", "PIECE_COMMERCIALE", "DATE", "DEBIT", "CREDIT"); |
List<Class<?>> colClass = Arrays.asList(String.class, Integer.class, String.class, String.class, Date.class, Long.class, Long.class); |
SQLElement eltEcr; |
public PropoLettrageTableModel(SQLElement eltEcr, List<SQLRowValues> datas) { |
this.datas = datas; |
this.eltEcr = eltEcr; |
} |
@Override |
public boolean isCellEditable(int rowIndex, int columnIndex) { |
return false; |
} |
@Override |
public Class<?> getColumnClass(int columnIndex) { |
return this.colClass.get(columnIndex); |
} |
@Override |
public int getRowCount() { |
return this.datas.size(); |
} |
@Override |
public int getColumnCount() { |
return this.fieldName.size(); |
} |
@Override |
public String getColumnName(int column) { |
String field = this.colName.get(column); |
return field; |
} |
@Override |
public Object getValueAt(int rowIndex, int columnIndex) { |
final SQLRowValues sqlRowValues = this.datas.get(rowIndex); |
final String fieldName2 = this.fieldName.get(columnIndex); |
if (fieldName2.startsWith("ID_")) { |
if (fieldName2.equals("ID_MOUVEMENT")) { |
return sqlRowValues.getForeign("ID_MOUVEMENT").getInt("NUMERO"); |
} else { |
return sqlRowValues.getForeign("ID_MOUVEMENT").getForeign("ID_PIECE").getString("NOM"); |
} |
} else { |
return sqlRowValues.getObject(fieldName2); |
} |
} |
public boolean isSelectionEqual(int[] selectionIndex) { |
if (selectionIndex == null || selectionIndex.length == 0) { |
return false; |
} else { |
long l = 0; |
for (int i : selectionIndex) { |
l += this.datas.get(i).getLong("DEBIT"); |
l -= this.datas.get(i).getLong("CREDIT"); |
} |
return l == 0; |
} |
} |
@Override |
public void setValueAt(Object aValue, int rowIndex, int columnIndex) { |
// this.datas.get(rowIndex).put(columnIndex, aValue); |
} |
public SQLRowValues getRowValuesAt(int index) { |
return this.datas.get(index); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/ComptaPrefTreeNode.java |
---|
96,6 → 96,10 |
nsGlobale.add(new PrefTreeNode(PayeGlobalPreferencePanel.class, "Paye", new String[] { "paye", "csg" })); |
// Comptabilité |
final PrefTreeNode nCompta = new PrefTreeNode(ComptabiliteWorkflowPreferencePanel.class, "Comptabilité", new String[] { "comptabilité", "lettrage" }); |
nsGlobale.add(nCompta); |
// Gestion commerciale |
final PrefTreeNode nGestionArticle = new PrefTreeNode(GestionArticlePreferencePanel.class, "Gestion des articles", new String[] { "articles", "gestion", "longueur", "largeur", "poids" }); |
final PrefTreeNode nGestionPiece = new PrefTreeNode(GestionPieceCommercialePanel.class, "Gestion des pièces commerciales", new String[] { "mouvements", "pieces", "facture" }); |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/LettragePanel.java |
---|
18,10 → 18,12 |
import org.openconcerto.erp.core.common.ui.DeviseNiceTableCellRenderer; |
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement; |
import org.openconcerto.erp.core.finance.accounting.element.EcritureSQLElement; |
import org.openconcerto.erp.core.finance.accounting.element.JournalSQLElement; |
import org.openconcerto.erp.core.finance.accounting.element.MouvementSQLElement; |
import org.openconcerto.erp.core.finance.accounting.model.LettrageModel; |
import org.openconcerto.erp.model.ISQLCompteSelector; |
import org.openconcerto.erp.rights.ComptaUserRight; |
import org.openconcerto.erp.utils.LowerCaseFormatFilter; |
import org.openconcerto.erp.utils.UpperCaseFormatFilter; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.element.SQLElement; |
28,18 → 30,29 |
import org.openconcerto.sql.element.SQLElementDirectory; |
import org.openconcerto.sql.model.SQLBase; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowAccessor; |
import org.openconcerto.sql.model.SQLRowListRSH; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.SQLSystem; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.model.UndefinedRowValuesCache; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.request.ComboSQLRequest; |
import org.openconcerto.sql.users.rights.UserRightsManager; |
import org.openconcerto.sql.view.EditFrame; |
import org.openconcerto.sql.view.EditPanel.EditMode; |
import org.openconcerto.sql.view.EditPanelListener; |
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.ui.DefaultGridBagConstraints; |
import org.openconcerto.ui.FontUtils; |
import org.openconcerto.ui.JDate; |
import org.openconcerto.ui.TitledSeparator; |
import org.openconcerto.ui.warning.JLabelWarning; |
import org.openconcerto.utils.ExceptionHandler; |
import org.openconcerto.utils.ListMap; |
import org.openconcerto.utils.text.DocumentFilterList; |
import org.openconcerto.utils.text.DocumentFilterList.FilterType; |
import org.openconcerto.utils.text.SimpleDocumentListener; |
63,7 → 76,10 |
import java.text.ParseException; |
import java.util.ArrayList; |
import java.util.Date; |
import java.util.HashMap; |
import java.util.List; |
import java.util.Map; |
import java.util.Map.Entry; |
import javax.swing.AbstractAction; |
import javax.swing.BorderFactory; |
85,7 → 101,7 |
public class LettragePanel extends JPanel { |
private ListPanelEcritures ecriturePanel; |
private JTextField codeLettrage; |
private JTextField codeLettrage, codeLettragePartiel; |
private ISQLCompteSelector selCompte; |
private JCheckBox boxValidEcriture, boxAddSousCompte; |
private JPanel warningPanel, warningSolde; |
101,6 → 117,7 |
private int modeSelect; |
private LettrageModel model; |
private JButton buttonLettrer; |
private final JButton buttonRegler = new JButton("Régler"); |
private JDate dateDeb, dateFin, dateLettrage; |
public LettragePanel() { |
162,6 → 179,20 |
this.add(this.codeLettrage, c); |
this.codeLettrage.setText(NumerotationAutoSQLElement.getNextCodeLettrage()); |
JLabel labelCodepartiel = new JLabel("Code lettrage partiel"); |
labelCodepartiel.setHorizontalAlignment(SwingConstants.RIGHT); |
c.gridx++; |
c.gridwidth = 1; |
c.weightx = 0; |
this.add(labelCodepartiel, c); |
this.codeLettragePartiel = new JTextField(10); |
DocumentFilterList.add((AbstractDocument) this.codeLettragePartiel.getDocument(), new LowerCaseFormatFilter(), FilterType.SIMPLE_FILTER); |
c.gridx++; |
c.weightx = 1; |
this.add(this.codeLettragePartiel, c); |
this.codeLettragePartiel.setText(getNextCodeLettragePartiel()); |
// Warning si aucun code rentré |
createPanelWarning(); |
c.gridwidth = GridBagConstraints.REMAINDER; |
323,6 → 354,7 |
this.add(this.boxValidEcriture, c); |
JPanel panelButton = new JPanel(); |
panelButton.add(this.buttonRegler, c); |
// Boutton lettrer |
355,20 → 387,276 |
this.add(buttonClose, c); |
this.buttonLettrer.addActionListener(new ActionListener() { |
public void actionPerformed(ActionEvent e) { |
try { |
int[] rowIndex = LettragePanel.this.ecriturePanel.getListe().getJTable().getSelectedRows(); |
actionLettrage(rowIndex, false); |
} catch (SQLException e1) { |
ExceptionHandler.handle("Erreur de lettrage", e1); |
} |
// System.err.println("Action lettrage sur " + i); |
actionLettrage(rowIndex); |
} |
}); |
this.buttonRegler.addActionListener(new ActionListener() { |
public void actionPerformed(ActionEvent e) { |
final List<SQLRowValues> res = LettragePanel.this.ecriturePanel.getListe().getSelectedRows(); |
final SQLTable tableKm = LettragePanel.this.ecriturePanel.getListe().getSource().getPrimaryTable().getTable("SAISIE_KM"); |
SQLRowValues rowValsKm = new SQLRowValues(tableKm); |
rowValsKm.put("DATE", new Date()); |
rowValsKm.put("ID_JOURNAL", JournalSQLElement.BANQUES); |
long solde = LettragePanel.this.model.getSoldeSelection(); |
final SQLTable tableKmItem = tableKm.getTable("SAISIE_KM_ELEMENT"); |
List<String> pieces = new ArrayList<>(); |
for (SQLRowValues sqlRowValues : res) { |
SQLRowValues rowValsKmItemTiers = new SQLRowValues(UndefinedRowValuesCache.getInstance().getDefaultRowValues(tableKmItem)); |
rowValsKmItemTiers.put("NUMERO", sqlRowValues.getForeign("ID_COMPTE_PCE").getString("NUMERO")); |
rowValsKmItemTiers.put("NOM", sqlRowValues.getForeign("ID_COMPTE_PCE").getString("NOM")); |
final String pieceNom; |
if (sqlRowValues.getString("NOM_PIECE").trim().length() > 0) { |
pieceNom = sqlRowValues.getString("NOM_PIECE"); |
} else { |
pieceNom = sqlRowValues.getForeign("ID_MOUVEMENT").getForeign("ID_PIECE").getString("NOM"); |
} |
rowValsKmItemTiers.put("NOM_PIECE", pieceNom); |
if (pieceNom != null && pieceNom.trim().length() > 0) { |
pieces.add(pieceNom); |
} |
rowValsKmItemTiers.put("CREDIT", sqlRowValues.getLong("DEBIT")); |
rowValsKmItemTiers.put("DEBIT", sqlRowValues.getLong("CREDIT")); |
if (rowValsKmItemTiers.getTable().contains("MONTANT_ECHEANCE")) { |
rowValsKmItemTiers.put("MONTANT_ECHEANCE", sqlRowValues.getLong("CREDIT")); |
} |
rowValsKmItemTiers.put("ID_SAISIE_KM", rowValsKm); |
} |
SQLRowValues rowValsKmItemBq = new SQLRowValues(UndefinedRowValuesCache.getInstance().getDefaultRowValues(tableKmItem)); |
boolean achat = solde < 0; |
// Compte bq |
int idPce = tableKm.getTable("TYPE_REGLEMENT").getRow(2).getInt("ID_COMPTE_PCE_" + (achat ? "FOURN" : "CLIENT")); |
if (idPce <= 1) { |
try { |
idPce = ComptePCESQLElement.getIdComptePceDefault("VenteCB"); |
} catch (Exception e1) { |
// TODO Auto-generated catch block |
e1.printStackTrace(); |
} |
} |
final SQLTable tableAccount = tableKmItem.getTable("COMPTE_PCE"); |
SQLRow rowCptBq = tableAccount.getRow(idPce); |
rowValsKmItemBq.put("NUMERO", rowCptBq.getString("NUMERO")); |
rowValsKmItemBq.put("NOM", rowCptBq.getString("NOM")); |
if (!pieces.isEmpty()) { |
StringBuilder build = new StringBuilder(); |
int nbPieces = pieces.size(); |
int i = 0; |
for (String string : pieces) { |
build.append(string); |
i++; |
if (i < nbPieces) { |
build.append(", "); |
} |
} |
rowValsKmItemBq.put("NOM_PIECE", build.toString()); |
} |
if (solde > 0) { |
rowValsKmItemBq.put("CREDIT", solde); |
rowValsKmItemBq.put("DEBIT", 0L); |
} else { |
rowValsKmItemBq.put("DEBIT", -solde); |
rowValsKmItemBq.put("CREDIT", 0L); |
} |
rowValsKmItemBq.put("ID_SAISIE_KM", rowValsKm); |
EditFrame frame = new EditFrame(Configuration.getInstance().getDirectory().getElement("SAISIE_KM"), EditMode.CREATION); |
frame.getSQLComponent().select(rowValsKm); |
frame.setVisible(true); |
frame.addEditPanelListener(new EditPanelListener() { |
@Override |
public void modified() { |
// TODO Auto-generated method stub |
} |
@Override |
public void inserted(int id) { |
List<SQLRow> rowsInserted = tableKm.getRow(id).getReferentRows(tableKmItem); |
List<String> piece = new ArrayList<>(); |
List<SQLRowAccessor> rowsToLettre = new ArrayList<>(); |
long solde = 0; |
for (SQLRowValues sqlRowValues : res) { |
rowsToLettre.add(sqlRowValues); |
final String nomPiece = sqlRowValues.getString("NOM_PIECE"); |
if (sqlRowValues.getForeign("ID_COMPTE_PCE").getString("NUMERO").startsWith("4") && nomPiece.trim().length() > 0) { |
piece.add(nomPiece); |
} |
solde += sqlRowValues.getLong("DEBIT"); |
solde -= sqlRowValues.getLong("CREDIT"); |
} |
for (SQLRow sqlRow : rowsInserted) { |
SQLRow rowEcr = sqlRow.getForeign("ID_ECRITURE"); |
final String nomPiece = sqlRow.getString("NOM_PIECE"); |
if (rowEcr.getString("COMPTE_NUMERO").startsWith("4")) { |
solde += rowEcr.getLong("DEBIT"); |
solde -= rowEcr.getLong("CREDIT"); |
if (nomPiece.trim().length() > 0) { |
piece.add(nomPiece); |
} |
rowsToLettre.add(rowEcr); |
} |
} |
if (solde == 0) { |
final String codeLettre = codeLettrage.getText().trim(); |
for (SQLRowAccessor row2 : rowsToLettre) { |
SQLRowValues rowVals = new SQLRowValues(row2.getTable()); |
// Lettrage |
// On lettre ou relettre la ligne avec le code saisi |
if (codeLettre.length() > 0) { |
rowVals.put("LETTRAGE_PARTIEL", ""); |
rowVals.put("LETTRAGE", codeLettre); |
rowVals.put("DATE_LETTRAGE", dateLettrage.getDate()); |
try { |
rowVals.update(row2.getID()); |
} catch (SQLException e1) { |
e1.printStackTrace(); |
} |
} |
} |
// Mise à jour du code de lettrage |
SQLElement elt = Configuration.getInstance().getDirectory().getElement("NUMEROTATION_AUTO"); |
SQLRowValues rowVals = elt.getTable().getRow(2).createEmptyUpdateRow(); |
rowVals.put("CODE_LETTRAGE", codeLettre); |
try { |
rowVals.update(); |
} catch (SQLException e) { |
e.printStackTrace(); |
} |
codeLettrage.setText(getNextCodeLettrage()); |
model.updateTotauxCompte(); |
} else { |
String codeLettreP = codeLettragePartiel.getText().trim(); |
String codeLettre = codeLettrage.getText().trim(); |
SQLSelect selEcr = new SQLSelect(); |
SQLTable tableEcr = tableKm.getTable("ECRITURE"); |
selEcr.addSelect(tableEcr.getKey()); |
selEcr.addSelect(tableEcr.getField("NOM_PIECE")); |
selEcr.addSelect(tableEcr.getField("DEBIT")); |
selEcr.addSelect(tableEcr.getField("CREDIT")); |
selEcr.addSelect(tableEcr.getField("LETTRAGE")); |
selEcr.addSelect(tableEcr.getField("LETTRAGE_PARTIEL")); |
Where w2 = new Where(tableEcr.getField("NOM_PIECE"), piece); |
w2 = w2.and(new Where(tableEcr.getField("COMPTE_NUMERO"), "LIKE", "40%").or(new Where(tableEcr.getField("COMPTE_NUMERO"), "LIKE", "41%"))); |
w2 = w2.and(new Where(tableEcr.getField("DATE_LETTRAGE"), "=", (Object) null)); |
selEcr.setWhere(w2); |
List<SQLRow> rows = SQLRowListRSH.execute(selEcr); |
ListMap<String, SQLRow> mapPiece = new ListMap<>(); |
Map<String, Long> soldePiece = new HashMap<>(); |
for (SQLRow sqlRow : rows) { |
String pieceName = sqlRow.getString("NOM_PIECE"); |
mapPiece.add(pieceName, sqlRow); |
long soldeRow = sqlRow.getLong("DEBIT") - sqlRow.getLong("CREDIT"); |
if (soldePiece.containsKey(pieceName)) { |
soldePiece.put(pieceName, soldePiece.get(pieceName) + soldeRow); |
} else { |
soldePiece.put(pieceName, soldeRow); |
} |
} |
for (Entry<String, List<SQLRow>> entry : mapPiece.entrySet()) { |
if (soldePiece.get(entry.getKey()) == 0) { |
try { |
for (SQLRow rowEcr : entry.getValue()) { |
SQLRowValues rowVals = rowEcr.createEmptyUpdateRow(); |
// Lettrage |
// On lettre ou relettre la ligne avec le code saisi |
if (codeLettre.length() > 0) { |
rowVals.put("LETTRAGE_PARTIEL", ""); |
rowVals.put("LETTRAGE", codeLettre); |
rowVals.put("DATE_LETTRAGE", dateLettrage.getDate()); |
rowVals.update(); |
} |
} |
// Mise à jour du code de lettrage |
SQLElement elt = Configuration.getInstance().getDirectory().getElement("NUMEROTATION_AUTO"); |
SQLRowValues rowVals = elt.getTable().getRow(2).createEmptyUpdateRow(); |
rowVals.put("CODE_LETTRAGE", codeLettre); |
rowVals.update(); |
codeLettre = getNextCodeLettrage(); |
} catch (SQLException e) { |
e.printStackTrace(); |
} |
} else { |
try { |
for (SQLRow rowEcr : entry.getValue()) { |
SQLRowValues rowVals = rowEcr.createEmptyUpdateRow(); |
// Lettrage |
// On lettre ou relettre la ligne avec le code saisi |
if (codeLettreP.length() > 0) { |
rowVals.put("LETTRAGE_PARTIEL", codeLettreP); |
rowVals.update(); |
} |
} |
// Mise à jour du code de lettrage |
SQLElement elt = Configuration.getInstance().getDirectory().getElement("NUMEROTATION_AUTO"); |
SQLRowValues rowVals = elt.getTable().getRow(2).createEmptyUpdateRow(); |
rowVals.put("CODE_LETTRAGE_PARTIEL", codeLettreP); |
rowVals.update(); |
codeLettreP = getNextCodeLettragePartiel(); |
} catch (SQLException e) { |
e.printStackTrace(); |
} |
} |
} |
codeLettrage.setText(getNextCodeLettrage()); |
codeLettragePartiel.setText(getNextCodeLettragePartiel()); |
model.updateTotauxCompte(); |
} |
} |
@Override |
public void deleted() { |
// TODO Auto-generated method stub |
} |
@Override |
public void cancelled() { |
// TODO Auto-generated method stub |
} |
}); |
} |
}); |
buttonDelettrer.addActionListener(new ActionListener() { |
public void actionPerformed(ActionEvent e) { |
int[] rowIndex = LettragePanel.this.ecriturePanel.getListe().getJTable().getSelectedRows(); |
actionDelettrage(rowIndex); |
actionDelettrage(rowIndex, false); |
} |
}); |
397,6 → 685,7 |
LettragePanel.this.warningSolde.setVisible(LettragePanel.this.model.getSoldeSelection() != 0); |
buttonDelettrer.setEnabled(LettragePanel.this.model.getSoldeSelection() == 0); |
LettragePanel.this.buttonLettrer.setEnabled(LettragePanel.this.model.getSoldeSelection() == 0); |
LettragePanel.this.buttonRegler.setEnabled(!LettragePanel.this.ecriturePanel.getListe().getSelectedRows().isEmpty()); |
} |
}); |
434,27 → 723,59 |
this.buttonLettrer.setEnabled((this.codeLettrage.getText().trim().length() != 0)); |
} |
private String getNextCodeLettragePartiel() { |
return Configuration.getInstance().getDirectory().getElement(NumerotationAutoSQLElement.class).getNextCodeLettragePartiel(); |
} |
private String getNextCodeLettrage() { |
return Configuration.getInstance().getDirectory().getElement(NumerotationAutoSQLElement.class).getNextCodeLettrage(); |
} |
/* Menu clic Droit */ |
private void addActionMenuDroit() { |
// JPopupMenu menu = new JPopupMenu(); |
this.ecriturePanel.getListe().addRowAction(new AbstractAction("Voir la source") { |
PredicateRowAction action = new PredicateRowAction(new AbstractAction() { |
public void actionPerformed(ActionEvent e) { |
SQLRow rowEcr = LettragePanel.this.ecriturePanel.getListe().fetchSelectedRow(); |
MouvementSQLElement.showSource(rowEcr.getInt("ID_MOUVEMENT")); |
} |
}, "financing.accouning.entries.source.show"); |
}, false, "financing.accouning.entries.source.show"); |
action.setPredicate(IListeEvent.getSingleSelectionPredicate()); |
// if (this.codeLettrage.getText().trim().length() != 0) { |
this.ecriturePanel.getListe().addIListeAction(action); |
final AbstractAction abstractAction = new AbstractAction() { |
public void actionPerformed(ActionEvent e) { |
try { |
int[] rowIndex = LettragePanel.this.ecriturePanel.getListe().getJTable().getSelectedRows(); |
actionLettrage(rowIndex); |
actionLettrage(rowIndex, false); |
} catch (SQLException e1) { |
ExceptionHandler.handle("erreur de lettrage", e1); |
} |
} |
}; |
this.ecriturePanel.getListe().addRowAction(abstractAction, "financing.accouning.entries.match"); |
PredicateRowAction actionLettre = new PredicateRowAction(abstractAction, false, "financing.accouning.entries.match"); |
actionLettre.setPredicate(IListeEvent.getNonEmptySelectionPredicate()); |
this.ecriturePanel.getListe().addIListeAction(actionLettre); |
final AbstractAction abstractActionPartiel = new AbstractAction("Lettrage Partiel") { |
public void actionPerformed(ActionEvent e) { |
try { |
int[] rowIndex = LettragePanel.this.ecriturePanel.getListe().getJTable().getSelectedRows(); |
actionLettrage(rowIndex, true); |
} catch (SQLException e1) { |
ExceptionHandler.handle("erreur de lettrage", e1); |
} |
} |
}; |
PredicateRowAction actionLettreP = new PredicateRowAction(abstractActionPartiel, false, "financing.accouning.entries.match.partial"); |
actionLettreP.setPredicate(IListeEvent.getNonEmptySelectionPredicate()); |
this.ecriturePanel.getListe().addIListeAction(actionLettreP); |
// } |
this.codeLettrage.getDocument().addDocumentListener(new SimpleDocumentListener() { |
@Override |
467,13 → 788,20 |
public void actionPerformed(ActionEvent e) { |
int[] rowIndex = LettragePanel.this.ecriturePanel.getListe().getJTable().getSelectedRows(); |
actionDelettrage(rowIndex); |
actionDelettrage(rowIndex, false); |
} |
}, "financing.accouning.entries.unmatch"); |
// menu.show(mE.getComponent(), mE.getPoint().x, mE.getPoint().y); |
this.ecriturePanel.getListe().addRowAction(new AbstractAction("Délettrer partiel") { |
public void actionPerformed(ActionEvent e) { |
int[] rowIndex = LettragePanel.this.ecriturePanel.getListe().getJTable().getSelectedRows(); |
actionDelettrage(rowIndex, true); |
} |
}, "financing.accouning.entries.unmatch.partial"); |
} |
/* Panel Warning no numero releve */ |
private void createPanelWarning() { |
525,9 → 853,17 |
} |
// Lettre la ligne passée en parametre |
private void actionLettrage(int[] rowIndex) { |
String codeLettre = this.codeLettrage.getText().trim(); |
private void actionLettrage(int[] rowIndex, boolean partiel) throws SQLException { |
String codeLettre; |
if (partiel) { |
codeLettre = this.codeLettragePartiel.getText().trim(); |
} else { |
codeLettre = this.codeLettrage.getText().trim(); |
} |
// FIXME : transaction |
List<SQLRow> rowsSelected = new ArrayList<SQLRow>(rowIndex.length); |
long solde = 0; |
540,7 → 876,7 |
solde -= ((Long) row.getObject("CREDIT")).longValue(); |
} |
if (solde == 0) { |
if (partiel || solde == 0) { |
for (SQLRow row2 : rowsSelected) { |
555,8 → 891,12 |
EcritureSQLElement.validationEcritures(row2.getInt("ID_MOUVEMENT")); |
} |
if (partiel) { |
rowVals.put("LETTRAGE_PARTIEL", codeLettre); |
} else { |
rowVals.put("LETTRAGE", codeLettre); |
rowVals.put("DATE_LETTRAGE", this.dateLettrage.getDate()); |
} |
try { |
rowVals.update(row2.getID()); |
} catch (SQLException e1) { |
568,7 → 908,11 |
// Mise à jour du code de lettrage |
SQLElement elt = Configuration.getInstance().getDirectory().getElement("NUMEROTATION_AUTO"); |
SQLRowValues rowVals = elt.getTable().getRow(2).createEmptyUpdateRow(); |
if (partiel) { |
rowVals.put("CODE_LETTRAGE_PARTIEL", codeLettre); |
} else { |
rowVals.put("CODE_LETTRAGE", codeLettre); |
} |
try { |
rowVals.update(); |
} catch (SQLException e) { |
576,6 → 920,12 |
} |
this.codeLettrage.setText(NumerotationAutoSQLElement.getNextCodeLettrage()); |
if (partiel) { |
this.codeLettragePartiel.setText(getNextCodeLettragePartiel()); |
} else { |
this.codeLettrage.setText(getNextCodeLettrage()); |
} |
this.model.updateTotauxCompte(); |
} |
} |
592,7 → 942,7 |
} |
// Pointe la ligne passée en parametre |
private void actionDelettrage(int[] rowIndex) { |
private void actionDelettrage(int[] rowIndex, boolean partiel) { |
List<SQLRow> rowsSelected = new ArrayList<SQLRow>(rowIndex.length); |
606,11 → 956,22 |
solde -= ((Long) row.getObject("CREDIT")).longValue(); |
} |
if (solde == 0) { |
if (partiel || solde == 0) { |
for (SQLRow row : rowsSelected) { |
SQLRowValues rowVals = new SQLRowValues(this.tableEcr); |
if (partiel) { |
// Dépointage |
if (row.getString("LETTRAGE_PARTIEL").trim().length() != 0) { |
rowVals.put("LETTRAGE_PARTIEL", ""); |
try { |
rowVals.update(row.getID()); |
} catch (SQLException e1) { |
e1.printStackTrace(); |
} |
} |
} else { |
// Dépointage |
if (row.getString("LETTRAGE").trim().length() != 0) { |
624,6 → 985,7 |
} |
} |
} |
} |
this.model.updateTotauxCompte(); |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/ComptabiliteWorkflowPreferencePanel.java |
---|
New file |
0,0 → 1,135 |
/* |
* 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.finance.accounting.ui; |
import org.openconcerto.erp.config.ComptaPropsConfiguration; |
import org.openconcerto.erp.preferences.DefaultNXProps; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.model.SQLBase; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.request.SQLFieldTranslator; |
import org.openconcerto.ui.DefaultGridBagConstraints; |
import org.openconcerto.ui.preferences.DefaultPreferencePanel; |
import java.awt.GridBagConstraints; |
import java.awt.GridBagLayout; |
import java.sql.SQLException; |
import javax.swing.JCheckBox; |
import javax.swing.JOptionPane; |
import javax.swing.JPanel; |
import javax.swing.SwingUtilities; |
public class ComptabiliteWorkflowPreferencePanel extends DefaultPreferencePanel { |
public static final String LETTRAGE_PROPO_KM = "LettragePropoKM"; |
private final static SQLBase base = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete(); |
private static final SQLTable tablePrefCompte = base.getTable("PREFS_COMPTE"); |
private SQLRowValues rowPrefCompteVals = new SQLRowValues(tablePrefCompte); |
private JCheckBox checkLettrageKmPropo = new JCheckBox("Afficher une fenêtre de lettrage lors d'une saisie au kilomètre."); |
private JCheckBox checkLettrageAuto = new JCheckBox("Activer le lettrage automatique."); |
private JCheckBox checkHideCompteFacture = new JCheckBox("Ne pas afficher les comptes dans les factures."); |
private JCheckBox checkHideCompteClient = new JCheckBox("Ne pas afficher les comptes dans les clients."); |
private JCheckBox checkHideAnalytique = new JCheckBox("Ne pas afficher l'analytique dans les saisies au kilomètre."); |
public ComptabiliteWorkflowPreferencePanel() { |
super(); |
final SQLRow rowPrefCompte = tablePrefCompte.getRow(2); |
this.rowPrefCompteVals.loadAbsolutelyAll(rowPrefCompte); |
this.setLayout(new GridBagLayout()); |
final GridBagConstraints c = new DefaultGridBagConstraints(); |
c.fill = GridBagConstraints.HORIZONTAL; |
c.anchor = GridBagConstraints.WEST; |
c.gridx = 0; |
c.gridy = 0; |
c.gridwidth = 1; |
c.gridheight = 1; |
c.weightx = 1; |
c.weighty = 0; |
c.gridwidth = GridBagConstraints.REMAINDER; |
this.add(this.checkLettrageAuto, c); |
c.gridy++; |
this.add(this.checkLettrageKmPropo, c); |
c.gridy++; |
this.add(this.checkHideCompteClient, c); |
c.gridy++; |
this.add(this.checkHideCompteFacture, c); |
c.gridy++; |
this.add(this.checkHideAnalytique, c); |
c.gridy++; |
// Spacer |
c.weighty = 1; |
c.gridy++; |
this.add(new JPanel(), c); |
setValues(); |
} |
public void storeValues() { |
this.rowPrefCompteVals.put("AUTO_LETTRAGE", this.checkLettrageAuto.isSelected()); |
DefaultNXProps.getInstance().setProperty(LETTRAGE_PROPO_KM, String.valueOf(this.checkLettrageKmPropo.isSelected())); |
DefaultNXProps.getInstance().setProperty("HideCompteClient", String.valueOf(this.checkHideCompteClient.isSelected())); |
DefaultNXProps.getInstance().setProperty("HideCompteFacture", String.valueOf(this.checkHideCompteFacture.isSelected())); |
DefaultNXProps.getInstance().setProperty("HideAnalytique", String.valueOf(this.checkHideAnalytique.isSelected())); |
DefaultNXProps.getInstance().store(); |
try { |
final Object[] pb = this.rowPrefCompteVals.getInvalid(); |
if (pb != null) { |
final SQLFieldTranslator trans = Configuration.getInstance().getTranslator(); |
JOptionPane.showMessageDialog(SwingUtilities.getRoot(this), "Impossible de valider les modifications! Le champ <" |
+ trans.getLabelFor(this.rowPrefCompteVals.getTable().getField(pb[0].toString())) + "> pointe sur un compte invalide!(" + pb[1] + ")"); |
} else { |
this.rowPrefCompteVals.update(); |
} |
} catch (SQLException e) { |
e.printStackTrace(); |
} |
} |
public void restoreToDefaults() { |
this.checkLettrageAuto.setSelected(false); |
this.checkLettrageKmPropo.setSelected(false); |
} |
public String getTitleName() { |
return "Comptabilité"; |
} |
private void setValues() { |
try { |
this.checkLettrageAuto.setSelected(rowPrefCompteVals.getBoolean("AUTO_LETTRAGE")); |
this.checkLettrageKmPropo.setSelected(Boolean.valueOf(DefaultNXProps.getInstance().getProperty(LETTRAGE_PROPO_KM))); |
this.checkHideCompteClient.setSelected(Boolean.valueOf(DefaultNXProps.getInstance().getProperty("HideCompteClient"))); |
this.checkHideCompteFacture.setSelected(Boolean.valueOf(DefaultNXProps.getInstance().getProperty("HideCompteFacture"))); |
this.checkHideAnalytique.setSelected(Boolean.valueOf(DefaultNXProps.getInstance().getProperty("HideAnalytique"))); |
} catch (Exception e) { |
e.printStackTrace(); |
} |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/PointagePanel.java |
---|
14,6 → 14,7 |
package org.openconcerto.erp.core.finance.accounting.ui; |
import org.openconcerto.erp.config.ComptaPropsConfiguration; |
import org.openconcerto.erp.core.common.ui.DeviseField; |
import org.openconcerto.erp.core.common.ui.DeviseNiceTableCellRenderer; |
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement; |
import org.openconcerto.erp.core.finance.accounting.element.EcritureSQLElement; |
74,7 → 75,6 |
import javax.swing.SwingUtilities; |
import javax.swing.SwingWorker; |
import javax.swing.event.DocumentEvent; |
import javax.swing.event.DocumentListener; |
import javax.swing.event.TableModelEvent; |
import javax.swing.event.TableModelListener; |
86,6 → 86,9 |
private final JDate datePointee; |
private JCheckBox boxValidEcriture; |
private JPanel warningPanel; |
private final DeviseField fieldSoldeD = new DeviseField(15); |
private final DeviseField fieldSoldeA = new DeviseField(15); |
private final DeviseField fieldEcart = new DeviseField(15); |
private final SQLBase base = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete(); |
private final SQLTable tableEcr = this.base.getTable("ECRITURE"); |
204,6 → 207,67 |
c.gridwidth = 1; |
this.add(this.datePointee, c); |
JPanel panelCheckValue = new JPanel(new GridBagLayout()); |
GridBagConstraints cCheck = new DefaultGridBagConstraints(); |
JLabel labelSoldeD = new JLabel("Solde de départ"); |
labelSoldeD.setHorizontalAlignment(SwingConstants.RIGHT); |
cCheck.gridwidth = 1; |
cCheck.weightx = 0; |
panelCheckValue.add(labelSoldeD, cCheck); |
cCheck.fill = GridBagConstraints.NONE; |
cCheck.weightx = 1; |
cCheck.gridx++; |
cCheck.gridwidth = 1; |
panelCheckValue.add(this.fieldSoldeD, cCheck); |
JLabel labelSoldeA = new JLabel("Solde d'arrivée"); |
labelSoldeA.setHorizontalAlignment(SwingConstants.RIGHT); |
cCheck.gridx++; |
cCheck.gridwidth = 1; |
cCheck.weightx = 0; |
panelCheckValue.add(labelSoldeA, cCheck); |
cCheck.fill = GridBagConstraints.NONE; |
cCheck.weightx = 1; |
cCheck.gridx++; |
cCheck.gridwidth = 1; |
panelCheckValue.add(this.fieldSoldeA, cCheck); |
JLabel labelEcart = new JLabel("Ecart pointage"); |
labelEcart.setHorizontalAlignment(SwingConstants.RIGHT); |
cCheck.gridx++; |
cCheck.gridwidth = 1; |
cCheck.weightx = 0; |
panelCheckValue.add(labelEcart, cCheck); |
cCheck.fill = GridBagConstraints.NONE; |
cCheck.weightx = 1; |
cCheck.gridx++; |
cCheck.gridwidth = 1; |
this.fieldEcart.setEditable(false); |
panelCheckValue.add(this.fieldEcart, cCheck); |
c.gridx++; |
c.gridwidth = 3; |
c.weightx = 1; |
this.add(panelCheckValue, c); |
this.fieldSoldeA.getDocument().addDocumentListener(new SimpleDocumentListener() { |
@Override |
public void update(DocumentEvent e) { |
PointagePanel.this.model.updateTotauxCompte(PointagePanel.this.fieldSoldeD, PointagePanel.this.fieldSoldeA, PointagePanel.this.fieldEcart); |
} |
}); |
this.fieldSoldeD.getDocument().addDocumentListener(new SimpleDocumentListener() { |
@Override |
public void update(DocumentEvent e) { |
PointagePanel.this.model.updateTotauxCompte(PointagePanel.this.fieldSoldeD, PointagePanel.this.fieldSoldeA, PointagePanel.this.fieldEcart); |
} |
}); |
TitledSeparator sepPeriode = new TitledSeparator("Filtre "); |
c.gridy++; |
c.gridx = 0; |
244,7 → 308,7 |
this.dateDeb.addValueListener(new PropertyChangeListener() { |
public void propertyChange(PropertyChangeEvent evt) { |
changeListRequest(); |
PointagePanel.this.model.updateTotauxCompte(); |
PointagePanel.this.model.updateTotauxCompte(PointagePanel.this.fieldSoldeD, PointagePanel.this.fieldSoldeA, PointagePanel.this.fieldEcart); |
} |
}); |
254,7 → 318,7 |
this.dateFin.addValueListener(new PropertyChangeListener() { |
public void propertyChange(PropertyChangeEvent evt) { |
changeListRequest(); |
PointagePanel.this.model.updateTotauxCompte(); |
PointagePanel.this.model.updateTotauxCompte(PointagePanel.this.fieldSoldeD, PointagePanel.this.fieldSoldeA, PointagePanel.this.fieldEcart); |
} |
}); |
446,7 → 510,7 |
this.ecriturePanel.getListe().addListener(new TableModelListener() { |
@Override |
public void tableChanged(TableModelEvent e) { |
PointagePanel.this.model.updateTotauxCompte(); |
PointagePanel.this.model.updateTotauxCompte(PointagePanel.this.fieldSoldeD, PointagePanel.this.fieldSoldeA, PointagePanel.this.fieldEcart); |
} |
}); |
457,7 → 521,7 |
public void update(DocumentEvent e) { |
PointagePanel.this.warningPanel.setVisible((PointagePanel.this.codePointage.getText().trim().length() == 0)); |
PointagePanel.this.buttonPointer.setEnabled((PointagePanel.this.codePointage.getText().trim().length() != 0)); |
PointagePanel.this.model.updateTotauxCompte(); |
PointagePanel.this.model.updateTotauxCompte(PointagePanel.this.fieldSoldeD, PointagePanel.this.fieldSoldeA, PointagePanel.this.fieldEcart); |
} |
}); |
569,7 → 633,7 |
e1.printStackTrace(); |
} |
} |
this.model.updateTotauxCompte(); |
this.model.updateTotauxCompte(PointagePanel.this.fieldSoldeD, PointagePanel.this.fieldSoldeA, PointagePanel.this.fieldEcart); |
} |
public ListPanelEcritures getEcriturePanel() { |
596,7 → 660,7 |
e1.printStackTrace(); |
} |
} |
this.model.updateTotauxCompte(); |
this.model.updateTotauxCompte(PointagePanel.this.fieldSoldeD, PointagePanel.this.fieldSoldeA, PointagePanel.this.fieldEcart); |
} |
/* |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/PropoLettrage.java |
---|
New file |
0,0 → 1,239 |
/* |
* 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.finance.accounting.ui; |
import org.openconcerto.erp.config.Gestion; |
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.element.SQLElement; |
import org.openconcerto.sql.model.ConnectionHandlerNoSetup; |
import org.openconcerto.sql.model.SQLDataSource; |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLRowValues; |
import org.openconcerto.sql.model.SQLRowValuesListFetcher; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.sql.utils.SQLUtils; |
import org.openconcerto.ui.DefaultGridBagConstraints; |
import org.openconcerto.ui.FrameUtil; |
import org.openconcerto.ui.JDate; |
import org.openconcerto.ui.JLabelBold; |
import org.openconcerto.utils.TableSorter; |
import org.openconcerto.utils.Tuple2; |
import java.awt.GridBagConstraints; |
import java.awt.GridBagLayout; |
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.sql.SQLException; |
import java.util.Date; |
import java.util.HashSet; |
import java.util.List; |
import java.util.Set; |
import javax.swing.AbstractAction; |
import javax.swing.ImageIcon; |
import javax.swing.JButton; |
import javax.swing.JDialog; |
import javax.swing.JLabel; |
import javax.swing.JPanel; |
import javax.swing.JScrollPane; |
import javax.swing.JTable; |
public class PropoLettrage { |
private SQLElement eltEcr; |
private Date dateKm; |
public PropoLettrage(SQLElement eltEcr) { |
this.eltEcr = eltEcr; |
} |
public void transfert(SQLRow rowKM) { |
List<SQLRow> rowItems = rowKM.getReferentRows(rowKM.getTable().getTable("SAISIE_KM_ELEMENT").getField("ID_SAISIE_KM")); |
this.dateKm = rowKM.getDate("DATE").getTime(); |
Set<Tuple2<String, String>> cpts = new HashSet(); |
for (SQLRow sqlRow : rowItems) { |
final String cptNumero = sqlRow.getString("NUMERO"); |
if (cptNumero.startsWith("40") || cptNumero.startsWith("41")) { |
cpts.add(Tuple2.create(cptNumero, sqlRow.getString("NOM"))); |
} |
} |
if (!cpts.isEmpty()) { |
for (Tuple2<String, String> cpt : cpts) { |
SQLRowValues rowValsEcr = new SQLRowValues(this.eltEcr.getTable()); |
rowValsEcr.putNulls("DEBIT", "CREDIT", "ID", "COMPTE_NOM", "COMPTE_NUMERO", "NOM", "NOM_PIECE", "DATE"); |
rowValsEcr.putRowValues("ID_MOUVEMENT").putNulls("NUMERO").putRowValues("ID_PIECE").putNulls("NOM"); |
List<SQLRowValues> resultEcrNonLettrees = SQLRowValuesListFetcher.create(rowValsEcr).fetch(new Where(this.eltEcr.getTable().getField("COMPTE_NUMERO"), "=", cpt.get0()) |
.and(new Where(this.eltEcr.getTable().getField("LETTRAGE"), "=", "").or(new Where(this.eltEcr.getTable().getField("LETTRAGE"), "=", (Object) null)))); |
showPreview(resultEcrNonLettrees, cpt); |
} |
} |
} |
private void showPreview(final List<SQLRowValues> rows, Tuple2<String, String> compte) { |
if (rows.isEmpty() || rows.size() == 1) { |
return; |
} |
JPanel panelPreview = new JPanel(new GridBagLayout()); |
GridBagConstraints c = new DefaultGridBagConstraints(); |
final PropoLettrageTableModel propoModel = new PropoLettrageTableModel(this.eltEcr, rows); |
final TableSorter s = new TableSorter(propoModel); |
final JTable table = new JTable(s); |
s.setTableHeader(table.getTableHeader()); |
final int columnCount = table.getColumnCount(); |
for (int col = 0; col < columnCount; col++) { |
table.getColumnModel().getColumn(col).setCellRenderer(new PropoLettrageRenderer()); |
} |
c.gridwidth = GridBagConstraints.REMAINDER; |
panelPreview.add(new JLabelBold("Ecritures non lettrées du compte " + compte.get0() + " " + compte.get1()), c); |
c.gridx = 0; |
c.gridy++; |
c.fill = GridBagConstraints.BOTH; |
c.gridwidth = GridBagConstraints.REMAINDER; |
c.weightx = 1; |
c.weighty = 1; |
panelPreview.add(new JScrollPane(table), c); |
c.gridy++; |
c.gridx = 0; |
c.gridwidth = 1; |
c.weighty = 0; |
c.weightx = 0; |
c.fill = GridBagConstraints.HORIZONTAL; |
panelPreview.add(new JLabel("Lettrer les écritures sélectionnées à la date du "), c); |
final JDate date = new JDate(); |
date.setValue(this.dateKm); |
c.gridx++; |
panelPreview.add(date); |
JDialog diag = new JDialog(); |
diag.setModal(true); |
diag.setContentPane(panelPreview); |
diag.setTitle("Lettrage " + compte.get0() + " " + compte.get1()); |
c.gridy++; |
c.fill = GridBagConstraints.NONE; |
c.anchor = GridBagConstraints.EAST; |
c.weightx = 1; |
c.weighty = 0; |
c.gridwidth = 1; |
final JButton valid = new JButton(new AbstractAction("Lettrer") { |
@Override |
public void actionPerformed(ActionEvent e) { |
try { |
SQLUtils.executeAtomic(eltEcr.getTable().getDBSystemRoot().getDataSource(), new ConnectionHandlerNoSetup<Object, Exception>() { |
@Override |
public Object handle(SQLDataSource ds) throws SQLException, Exception { |
String codeLettre = NumerotationAutoSQLElement.getNextCodeLettrage(); |
int[] selectedRows = table.getSelectedRows(); |
int[] modelRows = new int[selectedRows.length]; |
int nb = 0; |
for (int i : selectedRows) { |
modelRows[nb] = s.modelIndex(i); |
nb++; |
} |
final Date dateLettrage = date.getValue() == null ? new Date() : date.getValue(); |
for (int index : modelRows) { |
SQLRowValues rowValsEcr = propoModel.getRowValuesAt(index).createEmptyUpdateRow(); |
// Lettrage |
// On lettre ou relettre la ligne avec le code saisi |
if (codeLettre.length() > 0) { |
rowValsEcr.put("LETTRAGE", codeLettre); |
rowValsEcr.put("DATE_LETTRAGE", dateLettrage); |
rowValsEcr.update(); |
} |
} |
// Mise à jour du code de lettrage |
SQLElement elt = Configuration.getInstance().getDirectory().getElement("NUMEROTATION_AUTO"); |
SQLRowValues rowVals = elt.getTable().getRow(2).createEmptyUpdateRow(); |
rowVals.put("CODE_LETTRAGE", codeLettre); |
rowVals.update(); |
return null; |
} |
}); |
} catch (Exception e1) { |
org.openconcerto.utils.ExceptionHandler.handle("Erreur lors du lettrage", e1); |
} |
diag.dispose(); |
} |
}); |
panelPreview.add(valid, c); |
valid.setEnabled(false); |
c.weightx = 0; |
c.gridx++; |
JButton fermer = new JButton(new AbstractAction("Fermer") { |
@Override |
public void actionPerformed(ActionEvent e) { |
diag.dispose(); |
} |
}); |
panelPreview.add(fermer, c); |
table.addMouseListener(new MouseAdapter() { |
public void mouseReleased(MouseEvent e) { |
int[] selectedRows = table.getSelectedRows(); |
int[] modelRows = new int[selectedRows.length]; |
int nb = 0; |
for (int i : selectedRows) { |
modelRows[nb] = s.modelIndex(i); |
nb++; |
} |
valid.setEnabled(propoModel.isSelectionEqual(modelRows)); |
} |
}); |
table.addKeyListener(new KeyAdapter() { |
public void keyReleased(KeyEvent e) { |
int[] selectedRows = table.getSelectedRows(); |
int[] modelRows = new int[selectedRows.length]; |
int nb = 0; |
for (int i : selectedRows) { |
modelRows[nb] = s.modelIndex(i); |
nb++; |
} |
valid.setEnabled(propoModel.isSelectionEqual(modelRows)); |
} |
}); |
diag.pack(); |
diag.setIconImage(new ImageIcon(Gestion.class.getResource("frameicon.png")).getImage()); |
diag.setLocationRelativeTo(null); |
FrameUtil.show(diag); |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/SuppressionEcrituresPanel.java |
---|
20,6 → 20,7 |
import org.openconcerto.sql.model.SQLRow; |
import org.openconcerto.sql.model.SQLSelect; |
import org.openconcerto.sql.model.SQLTable; |
import org.openconcerto.sql.model.Where; |
import org.openconcerto.ui.DefaultGridBagConstraints; |
import org.openconcerto.ui.warning.JLabelWarning; |
27,7 → 28,10 |
import java.awt.GridBagLayout; |
import java.awt.event.ActionEvent; |
import java.awt.event.ActionListener; |
import java.util.ArrayList; |
import java.util.HashSet; |
import java.util.List; |
import java.util.Set; |
import javax.swing.JButton; |
import javax.swing.JFrame; |
69,13 → 73,20 |
c.gridx = 0; |
this.add(labelMouv, c); |
s.append(idS[0]); |
List<Integer> idMvts = new ArrayList<>(); |
for (int i = 1; i < idS.length; i++) { |
idMvts.add(idS[i]); |
s.append(", "); |
s.append(idS[i]); |
} |
s.append(')'); |
Set<String> lettrage = getLettrage(idMvts); |
if (lettrage != null && !lettrage.isEmpty()) { |
s.append("\nAttention certaines écritures sont lettrées avec les codes(" + org.openconcerto.utils.CollectionUtils.join(lettrage, ",") + "!"); |
} |
labelMouv.setText(s.toString()); |
} |
JButton buttonOK = new JButton("OK"); |
132,4 → 143,26 |
return idS; |
} |
private Set<String> getLettrage(List<Integer> mvtIds) { |
Set<String> codes = new HashSet<>(); |
SQLBase b = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete(); |
SQLTable tableEcr = b.getTable("ECRITURE"); |
SQLSelect sel = new SQLSelect(); |
sel.setDistinct(true); |
sel.addSelect(tableEcr.getField("LETTRAGE")); |
sel.setWhere(new Where(tableEcr.getField("ID_MOUVEMENT"), mvtIds).and(new Where(tableEcr.getField("LETTRAGE"), "=", "").and(new Where(tableEcr.getField("LETTRAGE"), "!=", (Object) null)))); |
List l = (List) b.getDataSource().execute(sel.asString(), new ArrayListHandler()); |
for (int i = 0; i < l.size(); i++) { |
Object[] tmp = (Object[]) l.get(i); |
codes.add(((String) tmp[0])); |
} |
return codes; |
} |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/CompteGestCommPreferencePanel.java |
---|
18,7 → 18,6 |
import org.openconcerto.erp.core.finance.accounting.element.JournalSQLElement; |
import org.openconcerto.erp.generationEcritures.GenerationMvtSaisieVenteFacture; |
import org.openconcerto.erp.model.ISQLCompteSelector; |
import org.openconcerto.erp.preferences.DefaultNXProps; |
import org.openconcerto.sql.Configuration; |
import org.openconcerto.sql.model.SQLBase; |
import org.openconcerto.sql.model.SQLRow; |
36,7 → 35,6 |
import java.awt.Insets; |
import java.sql.SQLException; |
import javax.swing.JCheckBox; |
import javax.swing.JLabel; |
import javax.swing.JOptionPane; |
import javax.swing.JPanel; |
50,10 → 48,6 |
private final static SQLBase base = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete(); |
private static final SQLTable tablePrefCompte = base.getTable("PREFS_COMPTE"); |
private SQLRowValues rowPrefCompteVals = new SQLRowValues(tablePrefCompte); |
private JCheckBox checkLettrageAuto = new JCheckBox("Activer le lettrage automatique."); |
private JCheckBox checkHideCompteFacture = new JCheckBox("Ne pas afficher les comptes dans les factures."); |
private JCheckBox checkHideCompteClient = new JCheckBox("Ne pas afficher les comptes dans les clients."); |
private JCheckBox checkHideAnalytique = new JCheckBox("Ne pas afficher l'analytique dans les saisies au kilomètre."); |
public CompteGestCommPreferencePanel() { |
super(); |
78,14 → 72,6 |
c.weighty = 0; |
c.gridwidth = GridBagConstraints.REMAINDER; |
this.add(this.checkLettrageAuto, c); |
c.gridy++; |
this.add(this.checkHideCompteClient, c); |
c.gridy++; |
this.add(this.checkHideCompteFacture, c); |
c.gridy++; |
this.add(this.checkHideAnalytique, c); |
c.gridy++; |
/******************************************************************************************* |
* SAISIE DES ACHATS |
375,11 → 361,6 |
this.rowPrefCompteVals.put("ID_COMPTE_PCE_TVA_IMMO", this.selCompteTVAImmo.getValue()); |
this.rowPrefCompteVals.put("ID_COMPTE_PCE_PORT_SOUMIS", this.selComptePortSoumis.getValue()); |
this.rowPrefCompteVals.put("ID_COMPTE_PCE_PORT_NON_SOUMIS", this.selComptePortNonSoumis.getValue()); |
this.rowPrefCompteVals.put("AUTO_LETTRAGE", this.checkLettrageAuto.isSelected()); |
DefaultNXProps.getInstance().setProperty("HideCompteClient", String.valueOf(this.checkHideCompteClient.isSelected())); |
DefaultNXProps.getInstance().setProperty("HideCompteFacture", String.valueOf(this.checkHideCompteFacture.isSelected())); |
DefaultNXProps.getInstance().setProperty("HideAnalytique", String.valueOf(this.checkHideAnalytique.isSelected())); |
DefaultNXProps.getInstance().store(); |
try { |
final Object[] pb = this.rowPrefCompteVals.getInvalid(); |
if (pb != null) { |
402,8 → 383,6 |
compte = ComptePCESQLElement.getComptePceDefault("Achats"); |
this.checkLettrageAuto.setSelected(false); |
int value = ComptePCESQLElement.getId(compte); |
this.selCompteAchat.setValue(value); |
525,20 → 504,16 |
} |
this.selJrnlValEnc.setValue(value); |
} |
setComboValues(selCompteFourn, "ID_COMPTE_PCE_FOURNISSEUR", "Fournisseurs"); |
setComboValues(selCompteClient, "ID_COMPTE_PCE_CLIENT", "Clients"); |
setComboValues(selCompteAvanceClient, "ID_COMPTE_PCE_AVANCE_CLIENT", "AvanceClients"); |
setComboValues(selCompteValeurEncaissement, "ID_COMPTE_PCE_VALEUR_ENCAISSEMENT", "ValeurEncaissement"); |
setComboValues(selComptePortSoumis, "ID_COMPTE_PCE_PORT_SOUMIS", "PortVenteSoumisTVA"); |
setComboValues(selComptePortNonSoumis, "ID_COMPTE_PCE_PORT_NON_SOUMIS", "PortVenteNonSoumisTVA"); |
setComboValues(selCompteTVACol, "ID_COMPTE_PCE_TVA_VENTE", "TVACollectee"); |
setComboValues(selCompteTVADed, "ID_COMPTE_PCE_TVA_ACHAT", "TVADeductible"); |
setComboValues(selCompteTVAIntraComm, "ID_COMPTE_PCE_TVA_INTRA", "TVAIntraComm"); |
setComboValues(selCompteTVAImmo, "ID_COMPTE_PCE_TVA_IMMO", "TVAImmo"); |
this.checkLettrageAuto.setSelected(rowPrefCompteVals.getBoolean("AUTO_LETTRAGE")); |
this.checkHideCompteClient.setSelected(Boolean.valueOf(DefaultNXProps.getInstance().getProperty("HideCompteClient"))); |
this.checkHideCompteFacture.setSelected(Boolean.valueOf(DefaultNXProps.getInstance().getProperty("HideCompteFacture"))); |
this.checkHideAnalytique.setSelected(Boolean.valueOf(DefaultNXProps.getInstance().getProperty("HideAnalytique"))); |
setComboValues(this.selCompteFourn, "ID_COMPTE_PCE_FOURNISSEUR", "Fournisseurs"); |
setComboValues(this.selCompteClient, "ID_COMPTE_PCE_CLIENT", "Clients"); |
setComboValues(this.selCompteAvanceClient, "ID_COMPTE_PCE_AVANCE_CLIENT", "AvanceClients"); |
setComboValues(this.selCompteValeurEncaissement, "ID_COMPTE_PCE_VALEUR_ENCAISSEMENT", "ValeurEncaissement"); |
setComboValues(this.selComptePortSoumis, "ID_COMPTE_PCE_PORT_SOUMIS", "PortVenteSoumisTVA"); |
setComboValues(this.selComptePortNonSoumis, "ID_COMPTE_PCE_PORT_NON_SOUMIS", "PortVenteNonSoumisTVA"); |
setComboValues(this.selCompteTVACol, "ID_COMPTE_PCE_TVA_VENTE", "TVACollectee"); |
setComboValues(this.selCompteTVADed, "ID_COMPTE_PCE_TVA_ACHAT", "TVADeductible"); |
setComboValues(this.selCompteTVAIntraComm, "ID_COMPTE_PCE_TVA_INTRA", "TVAIntraComm"); |
setComboValues(this.selCompteTVAImmo, "ID_COMPTE_PCE_TVA_IMMO", "TVAImmo"); |
} catch (Exception e) { |
e.printStackTrace(); |
} |
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/ListeGestCommEltPanel.java |
---|
152,6 → 152,9 |
} |
editModifyFrame.selectionId(this.getListe().getSelectedId()); |
editModifyFrame.setVisible(true); |
// |