package ch.elexis.TarmedRechnung;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
import org.jdom.Element;
import org.jdom.Verifier;
import ch.elexis.TarmedRechnung.XMLExporter.VatRateSum;
import ch.elexis.core.constants.StringConstants;
import ch.elexis.data.Konsultation;
import ch.elexis.data.Kontakt;
import ch.elexis.data.Mandant;
import ch.elexis.data.Person;
import ch.elexis.data.Rechnung;
import ch.elexis.data.Rechnungssteller;
import ch.elexis.data.Verrechnet;
import ch.elexis.tarmedprefs.TarmedRequirements;
import ch.rgw.tools.Money;
import ch.rgw.tools.StringTool;
import ch.rgw.tools.TimeTool;
public class XMLExporterUtil {
private static final String ELEMENT_EMAIL = "email"; //$NON-NLS-1$
private static final String ELEMENT_ONLINE = "online"; //$NON-NLS-1$
public static Element buildRechnungsstellerAdressElement(final Kontakt k){
return buildAdressElement(k, false, true);
}
public static Element buildAdressElement(final Kontakt k){
return buildAdressElement(k, false, false);
}
public static Element buildAdressElement(final Kontakt k, final boolean useAnschrift){
return buildAdressElement(k, useAnschrift, false);
}
public static Element buildAdressElement(final Kontakt k, final boolean useAnschrift,
boolean checkAnrede){
Element ret;
boolean anredeOrganization = false;
if (checkAnrede) {
String anrede = (String) k.getInfoElement("Anrede");
anredeOrganization = (anrede == null || anrede.isEmpty());
}
if (k.istPerson() == false || anredeOrganization) {
ret = new Element("company", XMLExporter.nsinvoice); //$NON-NLS-1$
Element companyname = new Element("companyname", XMLExporter.nsinvoice); //$NON-NLS-1$
companyname.setText(StringTool.limitLength(k.get(Kontakt.FLD_NAME1), 35));
ret.addContent(companyname);
ret.addContent(buildPostalElement(k));
Element telcom = buildTelekomElement(k);
if (telcom != null && !telcom.getChildren().isEmpty()) {
ret.addContent(telcom);
}
Element onlineElement = buildOnlineElement(k);
if (onlineElement != null) {
ret.addContent(onlineElement);
}
} else {
ret = new Element("person", XMLExporter.nsinvoice); //$NON-NLS-1$
Element familyname = new Element("familyname", XMLExporter.nsinvoice); //$NON-NLS-1$
Element givenname = new Element("givenname", XMLExporter.nsinvoice); //$NON-NLS-1$
String anschrift = k.get(Kontakt.FLD_ANSCHRIFT);
if (!useAnschrift || StringTool.isNothing(anschrift)
|| anschrift.equals(k.createStdAnschrift())) {
setAttributeIfNotEmptyWithLimit(ret, "salutation", k.getInfoString("Anrede"), 35); //$NON-NLS-1$ //$NON-NLS-2$
setAttributeIfNotEmptyWithLimit(ret, "title", k.get(Person.TITLE), 35); //$NON-NLS-1$
familyname.setText(StringTool.limitLength(k.get(Kontakt.FLD_NAME1), 35));
String gn = k.get(StringTool.limitLength(Kontakt.FLD_NAME2, 35));
if (StringTool.isNothing(gn)) {
gn = "Unbekannt"; // make validator happy //$NON-NLS-1$
}
givenname.setText(gn);
ret.addContent(familyname);
ret.addContent(givenname);
ret.addContent(buildPostalElement(k));
} else {
Postanschrift postAnschrift = new Postanschrift(k);
familyname.setText(StringTool.limitLength(postAnschrift.name, 35));
givenname.setText(StringTool.limitLength(postAnschrift.vorname, 35));
setAttributeIfNotEmptyWithLimit(ret, "salutation", postAnschrift.anrede, 35); //$NON-NLS-1$
ret.addContent(familyname);
ret.addContent(givenname);
ret.addContent(buildPostalElement(postAnschrift));
}
Element telcom = buildTelekomElement(k);
if (telcom != null && !telcom.getChildren().isEmpty()) {
ret.addContent(telcom);
}
Element onlineElement = buildOnlineElement(k);
if (onlineElement != null) {
ret.addContent(onlineElement);
}
}
return ret;
}
public static Element buildPostalElement(final Kontakt k){
Element ret = new Element("postal", XMLExporter.nsinvoice); //$NON-NLS-1$
addElementIfExists(ret, "pobox", null, StringTool.limitLength(k.getInfoString("Postfach"), //$NON-NLS-1$ //$NON-NLS-2$
35), null);
addElementIfExists(ret,
"street", null, StringTool.limitLength(k.get(Kontakt.FLD_STREET), 35), null); //$NON-NLS-1$
Element zip =
addElementIfExists(ret,
"zip", null, StringTool.limitLength(k.get(Kontakt.FLD_ZIP), 9), "0000"); //$NON-NLS-1$ //$NON-NLS-2$
setAttributeIfNotEmpty(zip,
"countrycode", StringTool.limitLength(k.get(Kontakt.FLD_COUNTRY), 3)); //$NON-NLS-1$
addElementIfExists(
ret,
"city", null, StringTool.limitLength(k.get(Kontakt.FLD_PLACE), 35), Messages.XMLExporter_Unknown); //$NON-NLS-1$
return ret;
}
public static Element buildPostalElement(final Postanschrift postanschrift){
Element ret = new Element("postal", XMLExporter.nsinvoice); //$NON-NLS-1$
addElementIfExists(ret, "pobox", null, StringTool.limitLength(postanschrift.adresse2, 35), //$NON-NLS-1$
null);
addElementIfExists(ret, "street", null, StringTool.limitLength(postanschrift.adresse1, 35), //$NON-NLS-1$
null);
Element zip =
addElementIfExists(ret, "zip", null, StringTool.limitLength(postanschrift.plz, 9), //$NON-NLS-1$
"0000"); //$NON-NLS-1$
setAttributeIfNotEmpty(zip, "countrycode", StringTool.limitLength(postanschrift.land, 3)); //$NON-NLS-1$
addElementIfExists(ret, "city", null, StringTool.limitLength(postanschrift.ort, 35), //$NON-NLS-1$
Messages.XMLExporter_unknown);
return ret;
}
public static Element buildOnlineElement(final Kontakt k){
// Element ret = new Element("online", XMLExporter.nsinvoice);
// String email = StringTool.limitLength(k.get("E-Mail"), 70);
// if (!email.matches(".+@.+")) {
// email = "mail@invalid.invalid";
// }
// addElementIfExists(ret, "email", null, k.get("E-Mail"),
// "mail@invalid.invalid");
// addElementIfExists(ret, "url", null,
// StringTool.limitLength(k.get("Website"), 100), null);
// return ret;
// Tony Schaller, 28.12.2008:
// optimized code: online element is created when it contains real
// content, only
Element ret = null;
// mail adresse
String value = getValidXMLString(StringTool.limitLength(k.get(Kontakt.FLD_E_MAIL), 70));
if (!value.equals(StringConstants.EMPTY)) {
if (!value.matches(".+@.+")) { //$NON-NLS-1$
value = "mail@invalid.invalid"; //$NON-NLS-1$
}
if (ret == null) {
ret = new Element(ELEMENT_ONLINE, XMLExporter.nsinvoice);
}
addElementIfExists(ret, ELEMENT_EMAIL, null, value, null);
}
// webseite
value = getValidXMLString(StringTool.limitLength(k.get(Kontakt.FLD_WEBSITE), 100));
if (!value.equals(StringConstants.EMPTY)) {
if (ret == null) {
ret = new Element(ELEMENT_ONLINE, XMLExporter.nsinvoice);
addElementIfExists(ret, ELEMENT_EMAIL, null, "mail@invalid.invalid", null); //$NON-NLS-1$
}
addElementIfExists(ret, "url", null, value, null); //$NON-NLS-1$
}
return ret;
}
public static Element buildTelekomElement(final Kontakt k){
Element ret = new Element("telecom", XMLExporter.nsinvoice); //$NON-NLS-1$
addElementIfExists(ret,
"phone", null, StringTool.limitLength(k.get(Kontakt.FLD_PHONE1), 25), //$NON-NLS-1$
null); //$NON-NLS-1$
addElementIfExists(ret,
"fax", null, StringTool.limitLength(k.get(Kontakt.FLD_FAX), 25), null); //$NON-NLS-1$
return ret;
}
public static boolean setAttributeIfNotEmpty(final Element element, final String name,
final String value){
if (element == null) {
return false;
}
if (StringTool.isNothing(name)) {
return false;
}
if (StringTool.isNothing(value)) {
return false;
}
element.setAttribute(name, value);
return true;
}
public static boolean setAttributeIfNotEmptyWithLimit(final Element element, final String name,
String value, final int len){
if (value.length() >= len) {
value = value.substring(0, len - 1);
}
return setAttributeIfNotEmpty(element, name, value);
}
public static String makeTarmedDatum(final String datum){
return new TimeTool(datum).toString(TimeTool.DATE_MYSQL) + "T00:00:00"; //$NON-NLS-1$
}
public static TimeTool getFirstKonsDate(Rechnung rechnung){
TimeTool ret = new TimeTool(TimeTool.END_OF_UNIX_EPOCH);
List<Konsultation> konsultationen = rechnung.getKonsultationen();
for (Konsultation konsultation : konsultationen) {
TimeTool tt = new TimeTool(konsultation.getDatum());
if (tt.isBefore(ret)) {
ret.set(tt);
}
}
return ret;
}
public static TimeTool getLastKonsDate(Rechnung rechnung){
TimeTool ret = new TimeTool(TimeTool.BEGINNING_OF_UNIX_EPOCH);
List<Konsultation> konsultationen = rechnung.getKonsultationen();
for (Konsultation konsultation : konsultationen) {
TimeTool tt = new TimeTool(konsultation.getDatum());
if (tt.isAfter(ret)) {
ret.set(tt);
}
}
return ret;
}
private static Element addElementIfExists(final Element parent, final String name,
final String attr, String val, final String defValue){
if (StringTool.isNothing(val)) {
val = defValue;
}
if (!StringTool.isNothing(val)) {
Element ret = new Element(name, XMLExporter.nsinvoice);
if (attr == null) {
ret.setText(val);
} else {
ret.setAttribute(attr, val);
}
parent.addContent(ret);
return ret;
}
return null;
}
public static void setAttributeWithDefault(final Element element, final String name,
String value, final String def){
if (element != null) {
if (!StringTool.isNothing(name)) {
if (StringTool.isNothing(value)) {
value = def;
}
element.setAttribute(name, value);
}
}
}
/**
* Set the correct VAT Attribute based on the Verrechent and the info if the Rechnungssteller
* has to pay VAT.
*
* @param verrechnet
* @param amount
* @param el
*/
public static void setVatAttribute(Verrechnet verrechnet, Money amount, Element el,
VatRateSum vatsum){
double value = 0.0;
String vatScale = verrechnet.getDetail(Verrechnet.VATSCALE);
if (vatScale != null && vatScale.length() > 0)
value = Double.parseDouble(vatScale);
el.setAttribute(XMLExporter.ATTR_VAT_RATE, Double.toString(value)); //$NON-NLS-1$
vatsum.add(value, amount.doubleValue());
}
/**
* Determine the EAN of the responsible Kontakt for a Konsultation. The search for thee right
* contact is in the following order.<br\>
* 1. configured via ResponsibleComposite on RechnungsPref preference page for the Mandant of
* the consultation<br\>
* 2. Rechnungssteller of the Mandant of the consultation if not an organization<br\>
* 3. the Mandant of the consultation<\br>
*
* @param kons
* @return
*/
public static String getResponsibleEAN(Konsultation kons){
Kontakt responsibleKontakt = null;
String responsibleId =
(String) kons.getMandant().getInfoElement(TarmedRequirements.RESPONSIBLE_INFO_KEY);
if (responsibleId != null && !responsibleId.isEmpty()) {
responsibleKontakt = Mandant.load(responsibleId);
} else {
Rechnungssteller rechnungssteller = kons.getMandant().getRechnungssteller();
String anrede = rechnungssteller.getInfoString("Anrede");
// only way to determine if rechnungssteller is a organization is testing empty anrede
if (anrede != null && !anrede.isEmpty()) {
responsibleKontakt = rechnungssteller;
} else {
responsibleKontakt = kons.getMandant();
}
}
return TarmedRequirements.getEAN(responsibleKontakt);
}
private static class Postanschrift {
private String anrede = StringConstants.EMPTY;
private String name = StringConstants.EMPTY;
private String vorname = StringConstants.EMPTY;
private String adresse1 = StringConstants.EMPTY;
private String adresse2 = StringConstants.EMPTY;
private String plz = StringConstants.EMPTY;
private String ort = StringConstants.EMPTY;
private String land = StringConstants.EMPTY;
public Postanschrift(final Kontakt k){
super();
init(k);
}
private void init(final Kontakt k){
String postAnschrift = k.getPostAnschrift(true);
// Zeilen lesen
StringTokenizer tokenizer = new StringTokenizer(postAnschrift, StringConstants.LF);
List<String> zeileList = new Vector<String>();
while (tokenizer.hasMoreElements()) {
zeileList.add(tokenizer.nextToken());
}
// Zeilen interpretieren (so gut es geht)
String plzOrt = ""; //$NON-NLS-1$
String nameVorname = ""; //$NON-NLS-1$
final int len = zeileList.size();
switch (len) {
case 0: // Kann gar nicht sein, aber man weiss ja nie!
throw new IllegalArgumentException(Messages.XMLExporter_NoPostal);
case 1: // Nur Name vorname
nameVorname = zeileList.get(0);
break;
case 2: // NameVorname, Ortsangaben
nameVorname = zeileList.get(0);
plzOrt = zeileList.get(1);
break;
case 3: // NameVorname, Adr1, Ortsangaben ODER Anrede, NameVorname,
// Ortsangaben
if (zeileList.get(0).indexOf(" ") < 0) { //$NON-NLS-1$
// Erste Zeile Anrede
anrede = zeileList.get(0);
nameVorname = zeileList.get(1);
plzOrt = zeileList.get(2);
} else {
// Erste Zeile NameVorname
nameVorname = zeileList.get(0);
adresse1 = zeileList.get(1);
plzOrt = zeileList.get(2);
}
break;
case 4: // NameVorname, Adr1, Adr2, Ortsangaben ODER Anrede,
// NameVorname, Adr1,
// Ortsangaben
if (zeileList.get(0).indexOf(" ") < 0) { //$NON-NLS-1$
// Erste Zeile Anrede
anrede = zeileList.get(0);
nameVorname = zeileList.get(1);
adresse1 = zeileList.get(2);
plzOrt = zeileList.get(3);
} else {
// Erste Zeile NameVorname
nameVorname = zeileList.get(0);
adresse1 = zeileList.get(1);
adresse2 = zeileList.get(2);
plzOrt = zeileList.get(3);
}
break;
default:
if (len > 4) { // Anrede, NameVorname, Adr1, Adr2, Ortsangaben
anrede = zeileList.get(0);
nameVorname = zeileList.get(1);
adresse1 = zeileList.get(2);
adresse2 = zeileList.get(3);
plzOrt = zeileList.get(4);
}
break;
}
// NameVorname aufteilen. Z.B. Von Allmen Christoph
if (!StringTool.isNothing(nameVorname)) {
nameVorname = nameVorname.trim();
int index = nameVorname.lastIndexOf(" "); // Z.B. Von Allmen Christoph //$NON-NLS-1$
if (index > 0) {
name = nameVorname.substring(0, index);
vorname = nameVorname.substring(index + 1);
} else {
name = nameVorname;
}
}
// plzOrt parsen. Z.B. CH-3600 Lenzburg
land = k.get(Kontakt.FLD_COUNTRY);
if (plzOrt.length() > 3 && plzOrt.substring(0, 3).indexOf("-") > 0) { //$NON-NLS-1$
// Land exists
int index = plzOrt.indexOf("-"); //$NON-NLS-1$
land = plzOrt.substring(0, index);
plzOrt = plzOrt.substring(index + 1);
}
plz = k.get(Kontakt.FLD_ZIP);
if (plzOrt.indexOf(" ") > 0) { //$NON-NLS-1$
// Read zip code
int index = plzOrt.indexOf(StringConstants.SPACE);
plz = plzOrt.substring(0, index);
plzOrt = plzOrt.substring(index + 1);
}
ort = plzOrt;
}
}
public static void negate(Element el, String attr){
String v = el.getAttributeValue(attr);
if (!StringTool.isNothing(v)) {
if (!v.equals(StringConstants.DOUBLE_ZERO)) {
if (v.startsWith(StringConstants.DASH)) {
v = v.substring(1);
} else {
v = StringConstants.DASH + v;
}
el.setAttribute(attr, v);
}
}
}
public static String getValidXMLString(String source){
StringBuilder ret = new StringBuilder();
for (int i = 0, len = source.length(); i < len; i++) {
// skip non valid XML characters
if (Verifier.isXMLCharacter(source.charAt(i))) {
ret.append(source.charAt(i));
}
}
return ret.toString();
}
}