Java tutorial
/******************************************************************************* * Copyright (c) 2013-2016 MEDEVIT. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * MEDEVIT <office@medevit.at> - initial API and implementation ******************************************************************************/ package at.medevit.ch.artikelstamm.elexis.common.importer; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import javax.xml.bind.JAXBException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.statushandlers.StatusManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; import at.medevit.ch.artikelstamm.ARTIKELSTAMM; import at.medevit.ch.artikelstamm.ARTIKELSTAMM.ITEMS.ITEM; import at.medevit.ch.artikelstamm.ARTIKELSTAMM.LIMITATIONS.LIMITATION; import at.medevit.ch.artikelstamm.ARTIKELSTAMM.PRODUCTS.PRODUCT; import at.medevit.ch.artikelstamm.ArtikelstammConstants.TYPE; import at.medevit.ch.artikelstamm.ArtikelstammHelper; import at.medevit.ch.artikelstamm.BlackBoxReason; import at.medevit.ch.artikelstamm.DATASOURCEType; import at.medevit.ch.artikelstamm.SALECDType; import at.medevit.ch.artikelstamm.elexis.common.PluginConstants; import at.medevit.ch.artikelstamm.elexis.common.ui.provider.atccache.ATCCodeCache; import ch.artikelstamm.elexis.common.ArtikelstammItem; import ch.elexis.core.constants.StringConstants; import ch.elexis.core.data.events.ElexisEventDispatcher; import ch.elexis.core.data.status.ElexisStatus; import ch.elexis.core.data.util.LocalLock; import ch.elexis.core.jdt.Nullable; import ch.elexis.core.ui.UiDesk; import ch.elexis.data.PersistentObject; import ch.elexis.data.Query; import ch.rgw.tools.JdbcLink; import ch.rgw.tools.JdbcLink.Stm; import ch.rgw.tools.TimeTool; public class ArtikelstammImporter { private static Logger log = LoggerFactory.getLogger(ArtikelstammImporter.class); private static Map<String, PRODUCT> products = new HashMap<String, PRODUCT>(); private static Map<String, LIMITATION> limitations = new HashMap<String, LIMITATION>(); private static volatile boolean userCanceled = false; /** * * @param monitor * @param input * @param version * the version to set. If <code>null</code> the current version will be simply * increased by one * @return */ public static IStatus performImport(IProgressMonitor monitor, InputStream input, @Nullable Integer newVersion) { LocalLock lock = new LocalLock("ArtikelstammImporter"); if (!lock.tryLock()) { UiDesk.syncExec(new Runnable() { @Override public void run() { if (MessageDialog.openQuestion(Display.getDefault().getActiveShell(), "", "Der Importer ist durch einen anderen Benutzer gestartet.\nDie Artikelstammeintrge werden bereits importiert.\n\n" + "Startzeit: " + new TimeTool(lock.getLockCurrentMillis()).toString(TimeTool.LARGE_GER) + "\nGestartet durch: " + lock.getLockMessage() + "\n\nWollen Sie den Importer trotzdem nochmal starten ?")) { lock.unlock(); lock.tryLock(); userCanceled = false; } else { userCanceled = true; } } }); } if (userCanceled) { userCanceled = false; return Status.OK_STATUS; } try { SubMonitor subMonitor = SubMonitor.convert(monitor, 100); subMonitor.setTaskName("Einlesen der Aktualisierungsdaten"); ARTIKELSTAMM importStamm = null; try { importStamm = ArtikelstammHelper.unmarshallInputStream(input); } catch (JAXBException | SAXException je) { String msg = "Fehler beim Einlesen der Import-Datei"; Status status = new ElexisStatus(IStatus.ERROR, PluginConstants.PLUGIN_ID, ElexisStatus.CODE_NOFEEDBACK, msg, je); StatusManager.getManager().handle(status, StatusManager.SHOW); log.error(msg, je); lock.unlock(); return Status.CANCEL_STATUS; } subMonitor.worked(10); if (newVersion == null) { int month = importStamm.getBUILDDATETIME().getMonth(); int year = importStamm.getBUILDDATETIME().getYear(); newVersion = Integer.valueOf("" + (year - 2000) + month); log.info("[PI] No newVersion provided. Setting to [{}].", newVersion); } try { DATASOURCEType datasourceType = ArtikelstammItem.getDatasourceType(); String message = "Trying to import dataset sourced [" + importStamm.getDATASOURCE().value() + "] while existent database is sourced [" + datasourceType.value() + "]. Please contact support. Exiting."; if (importStamm.getDATASOURCE() != datasourceType) { log.error(message); lock.unlock(); return new Status(Status.ERROR, PluginConstants.PLUGIN_ID, message); } } catch (IllegalArgumentException iae) { ArtikelstammItem.setDataSourceType(importStamm.getDATASOURCE()); } int currentVersion = ArtikelstammItem.getCurrentVersion(); log.info("[PI] Aktualisiere v" + currentVersion + " auf v" + newVersion); subMonitor.setTaskName("Lese Produkte und Limitationen..."); populateProducsAndLimitationsMap(importStamm); subMonitor.worked(5); subMonitor.setTaskName("Setze alle Elemente auf inaktiv..."); inactivateNonBlackboxedItems(); subMonitor.worked(5); long startTime = System.currentTimeMillis(); subMonitor.setTaskName("Importiere Artikelstamm " + importStamm.getCREATIONDATETIME().getMonth() + "/" + importStamm.getCREATIONDATETIME().getYear()); updateOrAddItems(newVersion, importStamm, subMonitor.split(50)); updateOrAddProducts(newVersion, importStamm, subMonitor.split(20)); // update the version number for type importStammType subMonitor.setTaskName("Setze neue Versionsnummer"); ArtikelstammItem.setCurrentVersion(newVersion); ArtikelstammItem .setImportSetCreationDate(importStamm.getCREATIONDATETIME().toGregorianCalendar().getTime()); subMonitor.worked(5); long endTime = System.currentTimeMillis(); ElexisEventDispatcher.reload(ArtikelstammItem.class); log.info("[PI] Artikelstamm import took " + ((endTime - startTime) / 1000) + "sec. Will rebuild ATCCodeCache"); ATCCodeCache.rebuildCache(subMonitor.split(5)); log.info("[PI] Artikelstamm finished rebuilding ATCCodeCache"); } finally { lock.unlock(); } return Status.OK_STATUS; } private static void inactivateNonBlackboxedItems() { log.debug("[BB] Setting all items inactive..."); Stm stm = PersistentObject.getConnection().getStatement(); stm.exec("UPDATE " + ArtikelstammItem.TABLENAME + " SET " + ArtikelstammItem.FLD_BLACKBOXED + Query.EQUALS + JdbcLink.wrap(Integer.toString(BlackBoxReason.INACTIVE.getNumercialReason())) + " WHERE " + ArtikelstammItem.FLD_BLACKBOXED + Query.EQUALS + JdbcLink.wrap(Integer.toString(BlackBoxReason.NOT_BLACKBOXED.getNumercialReason()))); PersistentObject.getConnection().releaseStatement(stm); } private static void populateProducsAndLimitationsMap(ARTIKELSTAMM importStamm) { products = importStamm.getPRODUCTS().getPRODUCT().stream() .collect(Collectors.toMap(p -> p.getPRODNO(), p -> p)); limitations = importStamm.getLIMITATIONS().getLIMITATION().stream() .collect(Collectors.toMap(l -> l.getLIMNAMEBAG(), l -> l)); } /** * * @param version * @param importStamm * @param monitor */ private static void updateOrAddProducts(int newVersion, ARTIKELSTAMM importStamm, IProgressMonitor monitor) { SubMonitor subMonitor = SubMonitor.convert(monitor, 1); List<PRODUCT> importProductList = importStamm.getPRODUCTS().getPRODUCT(); subMonitor.beginTask("Importiere " + importProductList.size() + " Produkte", importProductList.size()); log.debug("[IP] Update or import {} products...", importProductList.size()); for (PRODUCT product : importProductList) { String prodno = product.getPRODNO(); ArtikelstammItem foundProduct = ArtikelstammItem.load(prodno); if (!foundProduct.exists()) { String trimmedDscr = trimDSCR(product.getDSCR(), product.getPRODNO()); foundProduct = new ArtikelstammItem(newVersion, TYPE.X, product.getPRODNO(), null, trimmedDscr, StringConstants.EMPTY); log.trace("[IP] Adding product " + foundProduct.getId() + " (" + foundProduct.getDSCR() + ")"); } log.trace("[IP] Updating product " + foundProduct.getId() + " (" + product.getDSCR() + ")"); setValuesOnArtikelstammProdukt(foundProduct, product, newVersion); subMonitor.worked(1); } subMonitor.done(); } private static String trimDSCR(String dscr, String itemId) { if (dscr.length() > 100) { log.trace("[IP] Delimiting dscr [{}] for product/item [{}] to 100 characters.", itemId, dscr); dscr = dscr.substring(0, 100); } return dscr; } private static void setValuesOnArtikelstammProdukt(ArtikelstammItem ai, PRODUCT product, final int cummulatedVersion) { List<String> fields = new ArrayList<>(); List<String> values = new ArrayList<>(); fields.add(ArtikelstammItem.FLD_BLACKBOXED); values.add(Integer.toString(BlackBoxReason.NOT_BLACKBOXED.getNumercialReason())); fields.add(ArtikelstammItem.FLD_CUMMULATED_VERSION); values.add(cummulatedVersion + ""); fields.add(ArtikelstammItem.FLD_ATC); values.add(product.getATC()); fields.add(ArtikelstammItem.FLD_DSCR); values.add(trimDSCR(product.getDSCR(), product.getPRODNO())); ai.set(fields.toArray(new String[0]), values.toArray(new String[0])); } private static void updateOrAddItems(int newVersion, ARTIKELSTAMM importStamm, IProgressMonitor monitor) { SubMonitor subMonitor = SubMonitor.convert(monitor, 1); List<ITEM> importItemList = importStamm.getITEMS().getITEM(); subMonitor.beginTask("Importiere " + importItemList.size() + " items", importItemList.size()); log.debug("[II] Update or import {} items...", importItemList.size()); for (ITEM item : importItemList) { String pharmaCode = String.format("%07d", item.getPHAR()); Query<ArtikelstammItem> qre = new Query<ArtikelstammItem>(ArtikelstammItem.class); qre.add(ArtikelstammItem.FLD_GTIN, Query.LIKE, item.getGTIN()); ArtikelstammItem foundItem = null; List<ArtikelstammItem> result = qre.execute(); if (result.size() == 0) { foundItem = ArtikelstammItem.loadByPHARNo(pharmaCode); log.debug("[II] Found using loadByPHARNo {} item {}", pharmaCode, foundItem == null ? "null" : foundItem.getId()); } else if (result.size() == 1) { foundItem = result.get(0); } else if (result.size() > 1) { log.warn("[II] Found multiple items for GTIN [" + item.getGTIN() + "]"); // Is the case in Stauffacher DB, where legacy articles have been imported for (ArtikelstammItem artikelstammItem : result) { if (artikelstammItem.getBlackBoxReason() == BlackBoxReason.INACTIVE) { foundItem = artikelstammItem; log.warn("[II] Selected ID [" + foundItem.getId() + "] to update."); } } } boolean keepOverriddenPublicPrice = false; boolean keepOverriddenPkgSize = false; if (foundItem == null) { String trimmedDscr = trimDSCR(item.getDSCR(), item.getGTIN()); String ptString = Character.toString(item.getPHARMATYPE().charAt(0)); TYPE pharmaType = TYPE.valueOf(ptString.toUpperCase()); foundItem = new ArtikelstammItem(newVersion, pharmaType, item.getGTIN(), item.getPHAR(), trimmedDscr, StringConstants.EMPTY); log.trace("[II] Adding article " + foundItem.getId() + " (" + item.getDSCR() + ")"); } else { // check if article has overridden public price keepOverriddenPublicPrice = foundItem.isUserDefinedPrice(); keepOverriddenPkgSize = foundItem.isUserDefinedPkgSize(); } log.trace("[II] Updating article " + foundItem.getId() + " (" + item.getDSCR() + ")"); setValuesOnArtikelstammItem(foundItem, item, newVersion, keepOverriddenPublicPrice, keepOverriddenPkgSize); subMonitor.worked(1); } subMonitor.done(); } private static void setValuesOnArtikelstammItem(ArtikelstammItem ai, ITEM item, final int cummulatedVersion, boolean keepOverriddenPublicPrice, boolean keepOverriddenPkgSize) { List<String> fields = new ArrayList<>(); List<String> values = new ArrayList<>(); fields.add(ArtikelstammItem.FLD_CUMMULATED_VERSION); values.add(cummulatedVersion + ""); fields.add(ArtikelstammItem.FLD_PHAR); values.add((item.getPHAR() != null) ? String.format("%07d", item.getPHAR()) : null); fields.add(ArtikelstammItem.FLD_BLACKBOXED); SALECDType salecd = item.getSALECD(); if (SALECDType.A == salecd) { values.add(Integer.toString(BlackBoxReason.NOT_BLACKBOXED.getNumercialReason())); } else { values.add(Integer.toString(BlackBoxReason.INACTIVE.getNumercialReason())); } fields.add(ArtikelstammItem.FLD_GTIN); values.add(item.getGTIN()); fields.add(ArtikelstammItem.FLD_DSCR); values.add(trimDSCR(item.getDSCR(), item.getGTIN())); PRODUCT product = (item.getPRODNO() != null) ? products.get(item.getPRODNO()) : null; if (product == null) { product = new PRODUCT(); } fields.add(ArtikelstammItem.FLD_ATC); values.add(product.getATC()); fields.add(ArtikelstammItem.FLD_PRODNO); values.add(item.getPRODNO()); // LIMITATION String limnamebag = product.getLIMNAMEBAG(); LIMITATION limitation = null; Integer limitationPts = null; String limitationDscr = null; if (limnamebag != null) { limitation = limitations.get(limnamebag); if (limitation != null) { limitationPts = limitation.getLIMITATIONPTS(); limitationDscr = limitation.getDSCR(); } } fields.add(ArtikelstammItem.FLD_LIMITATION); values.add(limitation != null ? StringConstants.ONE : StringConstants.ZERO); fields.add(ArtikelstammItem.FLD_LIMITATION_PTS); values.add((limitationPts != null) ? limitationPts.toString() : null); fields.add(ArtikelstammItem.FLD_LIMITATION_TEXT); values.add(limitationDscr); String compName = null; String compGln = null; if (item.getCOMP() != null) { compName = item.getCOMP().getNAME(); compGln = item.getCOMP().getGLN(); } fields.add(ArtikelstammItem.FLD_COMP_NAME); values.add(compName); fields.add(ArtikelstammItem.FLD_COMP_GLN); values.add(compGln); fields.add(ArtikelstammItem.FLD_PEXF); values.add((item.getPEXF() != null) ? item.getPEXF().toString() : null); if (!keepOverriddenPublicPrice) { fields.add(ArtikelstammItem.FLD_PPUB); values.add((item.getPPUB() != null) ? item.getPPUB().toString() : null); } else { if (item.getPPUB() != null) { ai.setExtInfoStoredObjectByKey(ArtikelstammItem.EXTINFO_VAL_PPUB_OVERRIDE_STORE, item.getPPUB().toString()); log.info("[II] [{}] Updating ppub override store to [{}]", ai.getId(), item.getPPUB()); } } fields.add(ArtikelstammItem.FLD_SL_ENTRY); values.add((item.isSLENTRY() != null && item.isSLENTRY()) ? StringConstants.ONE : StringConstants.ZERO); fields.add(ArtikelstammItem.FLD_DEDUCTIBLE); values.add((item.getDEDUCTIBLE() != null) ? item.getDEDUCTIBLE().toString() : null); fields.add(ArtikelstammItem.FLD_GENERIC_TYPE); values.add(item.getGENERICTYPE()); fields.add(ArtikelstammItem.FLD_IKSCAT); values.add(item.getIKSCAT()); fields.add(ArtikelstammItem.FLD_NARCOTIC); values.add((item.isNARCOTIC() != null && item.isNARCOTIC()) ? StringConstants.ONE : StringConstants.ZERO); fields.add(ArtikelstammItem.FLD_LPPV); values.add((item.isLPPV() != null && item.isLPPV()) ? StringConstants.ONE : StringConstants.ZERO); if (!keepOverriddenPkgSize) { String pkgSize = (item.getPKGSIZE() != null) ? item.getPKGSIZE().toString() : null; values.add((pkgSize != null && pkgSize.length() > 6) ? pkgSize.substring(0, 6).toString() : pkgSize); if (pkgSize != null && pkgSize.length() > 6) { log.warn("[II] Delimited pkg size for [{}] being [{}] to 6 characters.", ai.getId(), item.getPKGSIZE().toString()); } } else { if (item.getPKGSIZE() != null) { ai.setExtInfoStoredObjectByKey(ArtikelstammItem.EXTINFO_VAL_PKG_SIZE_OVERRIDE_STORE, item.getPKGSIZE().toString()); log.info("[II] [{}] Updating PKG_SIZE override store to [{}]", ai.getId(), item.getPKGSIZE()); } } ai.set(fields.toArray(new String[0]), values.toArray(new String[0])); } }