1977 changed files with 116063 additions and 46915 deletions
@ -1,78 +1,75 @@ |
|||||||
package de.memtext.util; |
package de.memtext.util; |
||||||
|
|
||||||
import java.io.IOException; |
import java.io.IOException; |
||||||
|
|
||||||
import javax.servlet.ServletException; |
import jakarta.servlet.ServletException; |
||||||
import javax.servlet.http.HttpServletRequest; |
import jakarta.servlet.http.HttpServletRequest; |
||||||
import javax.servlet.http.HttpServletResponse; |
import jakarta.servlet.http.HttpServletResponse; |
||||||
import javax.xml.transform.ErrorListener; |
import javax.xml.transform.ErrorListener; |
||||||
import javax.xml.transform.TransformerException; |
import javax.xml.transform.TransformerException; |
||||||
|
|
||||||
import de.superx.servlet.ServletBasics; |
import de.superx.servlet.ServletBasics; |
||||||
|
|
||||||
/** |
/** |
||||||
* Abstrakte Basisklasse für ServletHelper-Objekt, nimmt request und response |
* Abstrakte Basisklasse für ServletHelper-Objekt, nimmt request und response |
||||||
* und den Logger auf. Objekte, die erweitern müssen (wie bei Thread) run() |
* und den Logger auf. Objekte, die erweitern müssen (wie bei Thread) run() |
||||||
* aufrufen. Dann wird die Authentifizierung geprüft und wenn die OK ist, wird |
* aufrufen. Dann wird die Authentifizierung geprüft und wenn die OK ist, wird |
||||||
* die perform()-Methode des eigentlichen Objekts aufgerufen (die z.B. Maske |
* die perform()-Methode des eigentlichen Objekts aufgerufen (die z.B. Maske |
||||||
* aufbaut oder Tabelle holt). wenn eine Exception auftritt sorgt run() dafür, |
* aufbaut oder Tabelle holt). wenn eine Exception auftritt sorgt run() dafür, |
||||||
* dass der Fehler gemeldet wird. Als Variablen enthält diese Klasse bereits den |
* dass der Fehler gemeldet wird. Als Variablen enthält diese Klasse bereits den |
||||||
* StringBuffer returnText mit dem geplanten Rückgabetext. Und userid mit der |
* StringBuffer returnText mit dem geplanten Rückgabetext. Und userid mit der |
||||||
* UserId (wenn Authentifizierung OK) |
* UserId (wenn Authentifizierung OK) |
||||||
*/ |
*/ |
||||||
public abstract class ServletHelper extends ServletBasics{ |
public abstract class ServletHelper extends ServletBasics { |
||||||
|
|
||||||
|
|
||||||
public ServletHelper(HttpServletRequest request, |
public ServletHelper(HttpServletRequest request, HttpServletResponse response, String sessiontype) throws IOException { |
||||||
HttpServletResponse response, String sessiontype) |
super(request, response, sessiontype); |
||||||
throws IOException { |
} |
||||||
super(request,response,sessiontype); |
|
||||||
} |
/** |
||||||
|
* Prüft falls gewünscht die Authentifizierung (existiert eine |
||||||
/** |
* superx-Session) danach wird die abstrakte Methode perform aufgerufen. Die |
||||||
* Prüft falls gewünscht die Authentifizierung (existiert eine |
* meisten Exceptions werden also Infomeldung an den User weitergegeben |
||||||
* superx-Session) danach wird die abstrakte Methode perform aufgerufen. Die |
* |
||||||
* meisten Exceptions werden also Infomeldung an den User weitergegeben |
* @param isAuthentificationCheckWanted |
||||||
* |
* @throws IOException |
||||||
* @param isAuthentificationCheckWanted |
*/ |
||||||
* @throws IOException |
public void run(boolean isAuthentificationCheckWanted) throws IOException, ServletException { |
||||||
*/ |
try { |
||||||
public void run(boolean isAuthentificationCheckWanted) throws IOException, |
if (isAuthentificationCheckWanted) { |
||||||
ServletException { |
checkSessionType(); |
||||||
try { |
} |
||||||
if (isAuthentificationCheckWanted) { |
|
||||||
checkSessionType(); |
perform(); |
||||||
} |
|
||||||
|
} catch (Exception e) { |
||||||
perform(); |
|
||||||
|
} |
||||||
} catch (Exception e) { |
} |
||||||
|
|
||||||
} |
abstract protected void perform() throws Exception; |
||||||
} |
|
||||||
|
class DummyErrorListener implements ErrorListener { |
||||||
abstract protected void perform() throws Exception; |
|
||||||
|
@Override |
||||||
class DummyErrorListener implements ErrorListener { |
public void warning(TransformerException exception) throws TransformerException { |
||||||
|
} |
||||||
public void warning(TransformerException exception) |
|
||||||
throws TransformerException { |
@Override |
||||||
} |
public void error(TransformerException exception) throws TransformerException { |
||||||
|
} |
||||||
public void error(TransformerException exception) |
|
||||||
throws TransformerException { |
@Override |
||||||
} |
public void fatalError(TransformerException exception) throws TransformerException { |
||||||
|
System.out.println(exception); |
||||||
public void fatalError(TransformerException exception) |
} |
||||||
throws TransformerException { |
|
||||||
System.out.println(exception); |
} |
||||||
} |
} |
||||||
|
|
||||||
} |
//Created on 30.09.2004 at 08:59:42
|
||||||
} |
|
||||||
|
//Created on 27.02.2006 at 18:50:31
|
||||||
//Created on 30.09.2004 at 08:59:42
|
|
||||||
|
//refactored to servletBasis 10.8.2011
|
||||||
//Created on 27.02.2006 at 18:50:31
|
|
||||||
|
|
||||||
//refactored to servletBasis 10.8.2011
|
|
||||||
|
|||||||
@ -0,0 +1,88 @@ |
|||||||
|
package de.superx.bianalysis; |
||||||
|
|
||||||
|
import de.superx.bianalysis.models.DimensionAttribute; |
||||||
|
import de.superx.bianalysis.models.Measure; |
||||||
|
|
||||||
|
public class ColumnElement { |
||||||
|
|
||||||
|
public String caption; |
||||||
|
public String header; |
||||||
|
public String dimensionAttributeFilter; |
||||||
|
public Measure measure; |
||||||
|
public int columnNumber; |
||||||
|
|
||||||
|
public ColumnElement(String caption, String dimensionAttributeFilter) { |
||||||
|
this.caption = caption; |
||||||
|
this.dimensionAttributeFilter = dimensionAttributeFilter; |
||||||
|
} |
||||||
|
|
||||||
|
public ColumnElement(String caption, String dimensionAttributeFilter, Measure measure, int col) { |
||||||
|
this.caption = caption; |
||||||
|
this.dimensionAttributeFilter = dimensionAttributeFilter; |
||||||
|
this.measure = measure; |
||||||
|
this.columnNumber = col; |
||||||
|
} |
||||||
|
|
||||||
|
public ColumnElement(Measure measure, int index) { |
||||||
|
this.caption = "Kennzahl|" + measure.getId().composedId; |
||||||
|
this.header = "Kennzahl|" + measure.getCaption(); |
||||||
|
this.measure = measure; |
||||||
|
this.columnNumber = index; |
||||||
|
} |
||||||
|
|
||||||
|
public ColumnElement(ColumnElement currentColumnElement) { |
||||||
|
this.caption = currentColumnElement.caption; |
||||||
|
this.dimensionAttributeFilter = currentColumnElement.dimensionAttributeFilter; |
||||||
|
this.measure = currentColumnElement.measure; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Builds the attribute part of a columns's 'field' member. |
||||||
|
* |
||||||
|
* The attribute part is a crucial component of the column's identifier |
||||||
|
* and typically consists of IDs and associated values. |
||||||
|
* |
||||||
|
* <p>Example of an attribute part: |
||||||
|
* <pre> |
||||||
|
* "conf:123 : conf:124 |weiblich" |
||||||
|
* </pre> |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* <p>In the context of a complete 'field' member, it might appear as: |
||||||
|
* <pre> |
||||||
|
* "conf:123: conf:124|weiblich || Kennzahl|res:123" |
||||||
|
* </pre> |
||||||
|
* where the part before "||" is the attribute part, and after is the measure.</p> |
||||||
|
* |
||||||
|
* The 'field' member serves as a unique identifier for each column. |
||||||
|
* |
||||||
|
* @see ColumnElementBuilder For the complete column building process |
||||||
|
*/ |
||||||
|
public static String buildField(DimensionAttribute attr, String value) { |
||||||
|
// The conformed id takes precedence, so that we can merge reports
|
||||||
|
String attrId = attr.getAttrConformedId(); |
||||||
|
if(attrId == null) { |
||||||
|
attrId = attr.getStringId(); |
||||||
|
} |
||||||
|
|
||||||
|
String dimId = attr.getDimConformedId(); |
||||||
|
if(dimId == null) { |
||||||
|
dimId = attr.getDimId(); |
||||||
|
} |
||||||
|
|
||||||
|
return dimId + ": " + attrId + "|" + value; |
||||||
|
} |
||||||
|
|
||||||
|
public static String buildHeader(DimensionAttribute attr, String value) { |
||||||
|
return attr.getCaption() + ": " + attr.getCaption() + "|" + value; |
||||||
|
} |
||||||
|
|
||||||
|
public static String buildFilter(DimensionAttribute attr, String value) { |
||||||
|
return attr.getDimensionTableAlias() + "." + attr.getColumnname() + " = '" + value + "'"; |
||||||
|
} |
||||||
|
|
||||||
|
public void setHeader(String finalHeader) { |
||||||
|
this.header = finalHeader; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,157 @@ |
|||||||
|
package de.superx.bianalysis; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.StringJoiner; |
||||||
|
|
||||||
|
import org.apache.log4j.Logger; |
||||||
|
|
||||||
|
import de.superx.bianalysis.models.DimensionAttribute; |
||||||
|
import de.superx.bianalysis.models.Filter; |
||||||
|
import de.superx.bianalysis.models.Measure; |
||||||
|
import de.superx.common.NotYetImplementedException; |
||||||
|
|
||||||
|
public class ColumnElementBuilder { |
||||||
|
|
||||||
|
private static Logger logger = Logger.getLogger(ColumnElementBuilder.class); |
||||||
|
|
||||||
|
/** |
||||||
|
* Lets assume we have the two Dimensions X and Y each with one Attribute. DA for X |
||||||
|
* and DB for Y. Both Attributes have two possible values DA1, DA2 and DB1, DB2. There |
||||||
|
* also exist two Measures M1, M2. |
||||||
|
* |
||||||
|
* If the users wants to see all attributes and measures the header of the cross table looks like this: |
||||||
|
* |
||||||
|
* +-----------------------+----------------------+ |
||||||
|
* | DA1 | DA2 | |
||||||
|
* +-----------+-----------+-----------+----------+ |
||||||
|
* | DB1 | DB2 | DB1 | DB2 | |
||||||
|
* +-----+-----+-----+-----+-----+-----+-----+----+ |
||||||
|
* | M1 | M2 | M1 | M2 | M1 | M2 | M1 | M2 | |
||||||
|
* +=====+=====+=====+=====+=====+=====+=====+====+ |
||||||
|
* | | | | | | | | | |
||||||
|
* +-----+-----+-----+-----+-----+-----+-----+----+ |
||||||
|
* |
||||||
|
* This header would be defined like follows: |
||||||
|
* |
||||||
|
* "X: DA | DA1 || Y: DB | DB1 || Kennzahl| M1" |
||||||
|
* "X: DA | DA1 || Y: DB | DB1 || Kennzahl| M2" |
||||||
|
* "X: DA | DA1 || Y: DB | DB2 || Kennzahl| M1" |
||||||
|
* "X: DA | DA1 || Y: DB | DB2 || Kennzahl| M2" |
||||||
|
* "X: DA | DA2 || Y: DB | DB1 || Kennzahl| M1" |
||||||
|
* "X: DA | DA2 || Y: DB | DB1 || Kennzahl| M2" |
||||||
|
* "X: DA | DA2 || Y: DB | DB2 || Kennzahl| M1" |
||||||
|
* "X: DA | DA2 || Y: DB | DB2 || Kennzahl| M2" |
||||||
|
* |
||||||
|
* Every single line is represented by one 'ColumnElement'. |
||||||
|
* @throws NotYetImplementedException |
||||||
|
*/ |
||||||
|
public static List<ColumnElement> buildColumnElements(ReportMetadata metadata) { |
||||||
|
|
||||||
|
List<Filter> filters = metadata.filters; |
||||||
|
List<Measure> measures = metadata.measures; |
||||||
|
List<DimensionAttribute> dimensionAttributes = metadata.topDimensionAttributes; |
||||||
|
|
||||||
|
List<ColumnElement> columnElements = new ArrayList<ColumnElement>(); |
||||||
|
final String HEADER_DIVIDER = " || "; |
||||||
|
final String KENNZAHL_IDENTIFIER = "Kennzahl|"; |
||||||
|
|
||||||
|
if(measures == null || measures.isEmpty()) { |
||||||
|
// edge case 1: no measures were selected, simply return empty columnElements list
|
||||||
|
return columnElements; |
||||||
|
} |
||||||
|
|
||||||
|
// for every column there exists an offset of 'maxbridgelvl' if a hierarchy-attribute was selected
|
||||||
|
int colStartPoint = metadata.getHierarchyAttributes().size() * metadata.maxBridgeLvl; |
||||||
|
if(dimensionAttributes == null || dimensionAttributes.isEmpty()) { |
||||||
|
// edge case 2: no dimension attributes were selected, only display the measures
|
||||||
|
for (Measure measure : measures) { |
||||||
|
columnElements.add(new ColumnElement(measure, colStartPoint + columnElements.size())); |
||||||
|
} |
||||||
|
return columnElements; |
||||||
|
} |
||||||
|
|
||||||
|
// for every single column combination (one list of combined attribute values) we build one 'ColumnElement' object
|
||||||
|
List<List<String>> dimAttrCombinations = cartesianProductOfDimensionAttributeValues(dimensionAttributes, filters); |
||||||
|
for (int i = 0; i < dimAttrCombinations.size(); i++) { |
||||||
|
StringJoiner captionJoiner = new StringJoiner(HEADER_DIVIDER); |
||||||
|
StringJoiner headerJoiner = new StringJoiner(HEADER_DIVIDER); |
||||||
|
StringJoiner filterJoiner = new StringJoiner(" AND "); |
||||||
|
List<String> comb = dimAttrCombinations.get(i); |
||||||
|
for(int j = 0; j < comb.size(); j++) { |
||||||
|
DimensionAttribute attr = dimensionAttributes.get(j); |
||||||
|
String value = comb.get(j); |
||||||
|
captionJoiner.add(ColumnElement.buildField(attr, value)); |
||||||
|
headerJoiner.add(ColumnElement.buildHeader(attr, value)); |
||||||
|
filterJoiner.add(ColumnElement.buildFilter(attr, value)); |
||||||
|
} |
||||||
|
String partialCaption = captionJoiner.toString(); |
||||||
|
String partialHeader = headerJoiner.toString(); |
||||||
|
String filter = filterJoiner.toString(); |
||||||
|
for (Measure measure : measures) { |
||||||
|
String finalCaption = partialCaption + HEADER_DIVIDER + KENNZAHL_IDENTIFIER + measure.getId().composedId; |
||||||
|
String finalHeader = partialHeader + HEADER_DIVIDER + KENNZAHL_IDENTIFIER + measure.getCaption(); |
||||||
|
ColumnElement colElement = new ColumnElement(finalCaption, filter, measure, colStartPoint + columnElements.size()); |
||||||
|
colElement.setHeader(finalHeader); |
||||||
|
columnElements.add(colElement); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return columnElements; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* Computes all possible combination of dimension attribute values. |
||||||
|
* Each of the individual combinations is a specific column. |
||||||
|
* |
||||||
|
* Example |
||||||
|
* Input: DimensionAttributes = {DA, DB}, each with two possible values DA1, DA2, DB1, DB2, Filters = { } |
||||||
|
* Output: {{DA1, DB1}, {DA1, DB2}, {DA2, DB1}, {DA2, DB2}} |
||||||
|
* |
||||||
|
* If the user choose the following Filter = {DB2} |
||||||
|
* Output: {{DA1, DB2}, {DA2, DB2}} |
||||||
|
* |
||||||
|
* @param dimensionAttributes The list of choosen dimension attributes. |
||||||
|
* @param filters The list of choosen filters. |
||||||
|
* @return A list containing the cartesian product of all the possible combination for a set of dimension attributes and filters. |
||||||
|
*/ |
||||||
|
private static List<List<String>> cartesianProductOfDimensionAttributeValues(List<DimensionAttribute> dimensionAttributes, List<Filter> filters){ |
||||||
|
List<List<String>> allDimAttrVals = new ArrayList<>(); |
||||||
|
for (DimensionAttribute attr: dimensionAttributes) { |
||||||
|
//if(attr.bridge != null) {
|
||||||
|
// continue;
|
||||||
|
//}
|
||||||
|
// did the user choose a filter for this attribute ?
|
||||||
|
Filter compoundFilter = Filter.findFilterById(filters, attr.getId()); |
||||||
|
if(compoundFilter != null) { |
||||||
|
// if yes only use the filter values
|
||||||
|
allDimAttrVals.add(compoundFilter.filterValues); |
||||||
|
} else { |
||||||
|
// if no use all possible attribute values
|
||||||
|
allDimAttrVals.add(attr.getDimensionAttributeValues()); |
||||||
|
} |
||||||
|
} |
||||||
|
// compute and return all possible column combinations
|
||||||
|
return cartesian(allDimAttrVals); |
||||||
|
} |
||||||
|
|
||||||
|
private static List<List<String>> cartesian(List<List<String>> lists) { |
||||||
|
List<List<String>> result = new ArrayList<>(); |
||||||
|
if(lists.size() == 0) { |
||||||
|
result.add(new ArrayList<>()); |
||||||
|
return result; |
||||||
|
} |
||||||
|
List<String> curr = lists.get(0); |
||||||
|
List<List<String>> remainingLists = cartesian(lists.subList(1, lists.size())); |
||||||
|
for (String val : curr) { |
||||||
|
for (List<String> list : remainingLists) { |
||||||
|
List<String> resultList = new ArrayList<>(); |
||||||
|
resultList.add(val); |
||||||
|
resultList.addAll(list); |
||||||
|
result.add(resultList); |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,415 @@ |
|||||||
|
package de.superx.bianalysis; |
||||||
|
|
||||||
|
import java.text.SimpleDateFormat; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Date; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
import org.apache.poi.ss.usermodel.BorderStyle; |
||||||
|
import org.apache.poi.ss.usermodel.Cell; |
||||||
|
import org.apache.poi.ss.usermodel.CellStyle; |
||||||
|
import org.apache.poi.ss.usermodel.Font; |
||||||
|
import org.apache.poi.ss.usermodel.Footer; |
||||||
|
import org.apache.poi.ss.usermodel.Header; |
||||||
|
import org.apache.poi.ss.usermodel.Row; |
||||||
|
import org.apache.poi.ss.util.CellRangeAddress; |
||||||
|
import org.apache.poi.xssf.usermodel.XSSFCellStyle; |
||||||
|
import org.apache.poi.xssf.usermodel.XSSFSheet; |
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
||||||
|
|
||||||
|
import de.superx.bianalysis.models.InfoItem; |
||||||
|
import de.superx.rest.model.Column; |
||||||
|
import de.superx.rest.model.ColumnType; |
||||||
|
import de.superx.rest.model.Result; |
||||||
|
import de.superx.rest.model.ResultType; |
||||||
|
|
||||||
|
public class ExcelSheetBuilder { |
||||||
|
|
||||||
|
private Result result; |
||||||
|
private XSSFWorkbook workbook; |
||||||
|
private XSSFSheet sheet; |
||||||
|
private String reportName; |
||||||
|
private String reportDescription; |
||||||
|
private String date; |
||||||
|
private int leftDimensionAttributes; |
||||||
|
private int topDimensionAttributes = 0; |
||||||
|
|
||||||
|
private List<Column> visibleColumns; |
||||||
|
private final boolean mergeCells = true; |
||||||
|
private final int startingRow = 1; |
||||||
|
|
||||||
|
private static HashMap<String, Integer> defaultStyles = new HashMap<>(); |
||||||
|
|
||||||
|
public ExcelSheetBuilder(Result result) { |
||||||
|
this.result = result; |
||||||
|
this.visibleColumns = getVisibleColumns(result); |
||||||
|
this.workbook = new XSSFWorkbook(); |
||||||
|
initializeDefaultStyles(); |
||||||
|
|
||||||
|
leftDimensionAttributes = this.result.info.leftDimensionAttributes.size(); |
||||||
|
if(this.result.info.topDimensionAttributes != null && this.result.info.topDimensionAttributes.size() > 0) { |
||||||
|
topDimensionAttributes = this.result.info.topDimensionAttributes.size(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public XSSFWorkbook build() { |
||||||
|
int rowNum = startingRow; |
||||||
|
rowNum = createRowsFromGrid(createReportInfoGrid(), rowNum); |
||||||
|
rowNum += 2; // rows between report info and header
|
||||||
|
int reportInfoEnd = rowNum; |
||||||
|
|
||||||
|
String[][] grid = createHeaderGrid(); |
||||||
|
|
||||||
|
rowNum = createRowsFromGrid(grid, rowNum); |
||||||
|
rowNum = createDataRows(rowNum); |
||||||
|
rowNum = createTotalRow(rowNum); |
||||||
|
|
||||||
|
if(mergeCells) { |
||||||
|
mergeHeaderCells(grid, 0, reportInfoEnd); |
||||||
|
} |
||||||
|
|
||||||
|
styleHeaderCells(reportInfoEnd, grid); |
||||||
|
styleDataCells(reportInfoEnd + grid.length); |
||||||
|
styleTotalRowCells(rowNum); |
||||||
|
styleReportInfoCells(); |
||||||
|
|
||||||
|
Footer footer = sheet.getFooter(); |
||||||
|
Header header = sheet.getHeader(); |
||||||
|
header.setLeft(reportName); |
||||||
|
header.setRight(this.date); |
||||||
|
footer.setRight("Seite &P von &N"); |
||||||
|
|
||||||
|
return workbook; |
||||||
|
} |
||||||
|
|
||||||
|
private void initializeDefaultStyles() { |
||||||
|
//ReportInfoCells
|
||||||
|
XSSFCellStyle infoStyle = workbook.createCellStyle(); |
||||||
|
Font infoFont = workbook.createFont(); |
||||||
|
infoFont.setBold(true); |
||||||
|
infoStyle.setFont(infoFont); |
||||||
|
|
||||||
|
defaultStyles.put("info", Integer.valueOf(infoStyle.getIndex())); |
||||||
|
|
||||||
|
//Header
|
||||||
|
XSSFCellStyle headerStyle = workbook.createCellStyle(); |
||||||
|
headerStyle.setBorderBottom(BorderStyle.THIN); |
||||||
|
headerStyle.setBorderLeft(BorderStyle.THIN); |
||||||
|
headerStyle.setBorderRight(BorderStyle.THIN); |
||||||
|
headerStyle.setBorderTop(BorderStyle.THIN); |
||||||
|
Font headerFont = workbook.createFont(); |
||||||
|
headerFont.setBold(true); |
||||||
|
headerStyle.setFont(headerFont); |
||||||
|
|
||||||
|
defaultStyles.put("header", Integer.valueOf(headerStyle.getIndex())); |
||||||
|
|
||||||
|
//Data
|
||||||
|
XSSFCellStyle dataStyle = workbook.createCellStyle(); |
||||||
|
dataStyle.setBorderBottom(BorderStyle.HAIR); |
||||||
|
dataStyle.setBorderLeft(BorderStyle.HAIR); |
||||||
|
dataStyle.setBorderRight(BorderStyle.HAIR); |
||||||
|
dataStyle.setBorderTop(BorderStyle.HAIR); |
||||||
|
|
||||||
|
defaultStyles.put("data", Integer.valueOf(dataStyle.getIndex())); |
||||||
|
|
||||||
|
//Total
|
||||||
|
XSSFCellStyle totalStyle = workbook.createCellStyle(); |
||||||
|
totalStyle.setBorderBottom(BorderStyle.THIN); |
||||||
|
totalStyle.setBorderLeft(BorderStyle.THIN); |
||||||
|
totalStyle.setBorderRight(BorderStyle.THIN); |
||||||
|
totalStyle.setBorderTop(BorderStyle.DOUBLE); |
||||||
|
Font totalFont = workbook.createFont(); |
||||||
|
totalFont.setBold(true); |
||||||
|
totalStyle.setFont(totalFont); |
||||||
|
|
||||||
|
defaultStyles.put("total", Integer.valueOf(totalStyle.getIndex())); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void styleTotalRowCells(int rowNum) { |
||||||
|
int current = rowNum; |
||||||
|
Row row = sheet.getRow(--current); |
||||||
|
for (int i = 0; i < visibleColumns.size(); i++) { |
||||||
|
Cell cell = row.getCell(i); |
||||||
|
cell.setCellStyle(getTotalCellStyle(workbook)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private int createTotalRow(int startFrom) { |
||||||
|
de.superx.rest.model.Row totalRow = result.getTotalRow(); |
||||||
|
int rowNum = startFrom; |
||||||
|
Row row = sheet.createRow(rowNum++); |
||||||
|
Cell labelCell = row.createCell(0); |
||||||
|
labelCell.setCellValue("Gesamt"); |
||||||
|
for (int i = 1; i < visibleColumns.size(); i++) { |
||||||
|
Column col = visibleColumns.get(i); |
||||||
|
Cell cell = row.createCell(i); |
||||||
|
if(col.type.equals(ColumnType.StringColumn)) { |
||||||
|
cell.setCellValue(""); |
||||||
|
} else { |
||||||
|
Object obj = totalRow.cells.get(col.field); |
||||||
|
if(obj == null) { |
||||||
|
cell.setCellValue(""); |
||||||
|
continue; |
||||||
|
} |
||||||
|
Double value = Double.valueOf(String.valueOf(obj)); |
||||||
|
cell.setCellValue(value.doubleValue()); |
||||||
|
} |
||||||
|
} |
||||||
|
return rowNum; |
||||||
|
} |
||||||
|
|
||||||
|
private void styleReportInfoCells() { |
||||||
|
Row row = sheet.getRow(startingRow); |
||||||
|
Cell cell = row.getCell(0); |
||||||
|
cell.setCellStyle(workbook.getCellStyleAt(defaultStyles.get("info").intValue())); |
||||||
|
} |
||||||
|
|
||||||
|
private String[][] createReportInfoGrid() { |
||||||
|
|
||||||
|
List<List<String>> gridList = new ArrayList<>(); |
||||||
|
gridList.add(List.of("Informationen zur BI-Analyse", "")); |
||||||
|
gridList.add(List.of("Name:", this.reportName)); |
||||||
|
gridList.add(List.of("Beschreibung:", this.reportDescription)); |
||||||
|
|
||||||
|
String sachgebiet = this.result.info.sachgebiete.stream().collect(Collectors.joining(", ")); |
||||||
|
String theme = getInfoCaptions(this.result.info.facttables); |
||||||
|
String measures = getInfoCaptions(this.result.info.measures); |
||||||
|
String topAttributes = getInfoCaptions(this.result.info.topDimensionAttributes); |
||||||
|
String leftAttributes = getInfoCaptions(this.result.info.leftDimensionAttributes); |
||||||
|
String filter = this.result.info.filter.stream().collect(Collectors.joining(", ")); |
||||||
|
String lastUpdateBad = this.result.info.lastUpdateBiad; |
||||||
|
|
||||||
|
if(sachgebiet != null) { |
||||||
|
gridList.add(List.of("Sachgebiet:", sachgebiet)); |
||||||
|
} |
||||||
|
if(theme != null) { |
||||||
|
gridList.add(List.of("Thema:", theme)); |
||||||
|
} |
||||||
|
if(measures != null) { |
||||||
|
gridList.add(List.of("Kennzahlen:", measures)); |
||||||
|
} |
||||||
|
if(leftAttributes != null) { |
||||||
|
gridList.add(List.of("Zeilenattribute:", leftAttributes)); |
||||||
|
} |
||||||
|
if(topAttributes != null) { |
||||||
|
gridList.add(List.of("Spaltenattribute:", topAttributes)); |
||||||
|
} |
||||||
|
if(filter != null) { |
||||||
|
gridList.add(List.of("Filter:", filter)); |
||||||
|
} |
||||||
|
if(lastUpdateBad != null) { |
||||||
|
gridList.add(List.of("Letztes Update von BI-Analyse-Daten:", lastUpdateBad)); |
||||||
|
} |
||||||
|
if(result.resultType.equals(ResultType.FlatTable)) { |
||||||
|
gridList.add(List.of("Tabellentyp:", "Flache Tabelle")); |
||||||
|
} else if(result.resultType.equals(ResultType.DrilldownTableGroupable)) { |
||||||
|
gridList.add(List.of("Tabellentyp:", "Hierarchische Tabelle")); |
||||||
|
} |
||||||
|
return listToStringGrid(gridList); |
||||||
|
} |
||||||
|
|
||||||
|
private static String getInfoCaptions(List<InfoItem> infoItems) { |
||||||
|
if(infoItems != null && infoItems.size() > 0) { |
||||||
|
return infoItems.stream().map(f->f.caption).collect(Collectors.joining(", ")); |
||||||
|
} |
||||||
|
return ""; |
||||||
|
} |
||||||
|
|
||||||
|
private static String[][] listToStringGrid(List<List<String>> list) { |
||||||
|
String[][] result = new String[list.size()][list.get(0).size()]; |
||||||
|
for (int i = 0; i < result.length; i++) { |
||||||
|
for (int j = 0; j < result[i].length; j++) { |
||||||
|
result[i][j] = list.get(i).get(j); |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
private static CellRangeAddress mergeCellByOffset(int firstRow, int lastRow, int firstCol, int lastCol, int xOffset, int yOffset) { |
||||||
|
return new CellRangeAddress(firstRow + yOffset, lastRow + yOffset, firstCol + xOffset, lastCol + xOffset); |
||||||
|
} |
||||||
|
|
||||||
|
private void styleHeaderCells(int start, String[][] grid) { |
||||||
|
for (int i = 0; i < grid.length; i++) { |
||||||
|
Row row = this.sheet.getRow(i+start); |
||||||
|
row.setHeightInPoints((short) 25); |
||||||
|
for (int j = 0; j < grid[i].length; j++) { |
||||||
|
Cell cell = row.getCell(j); |
||||||
|
cell.setCellStyle(getHeaderStyle(workbook)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static CellStyle getHeaderStyle(XSSFWorkbook workbook) { |
||||||
|
return workbook.getCellStyleAt(defaultStyles.get("header").intValue()); |
||||||
|
} |
||||||
|
|
||||||
|
private static CellStyle getDataCellStyle(XSSFWorkbook workbook) { |
||||||
|
return workbook.getCellStyleAt(defaultStyles.get("data").intValue()); |
||||||
|
} |
||||||
|
|
||||||
|
private static CellStyle getTotalCellStyle(XSSFWorkbook workbook) { |
||||||
|
return workbook.getCellStyleAt(defaultStyles.get("total").intValue()); |
||||||
|
} |
||||||
|
|
||||||
|
private void styleDataCells(int startDataCells) { |
||||||
|
for (int i = startDataCells; i < startDataCells + this.result.rows.size(); i++) { |
||||||
|
Row row = this.sheet.getRow(i); |
||||||
|
for (int j = 0; j < this.visibleColumns.size(); j++) { |
||||||
|
Cell cell = row.getCell(j); |
||||||
|
if(this.visibleColumns.get(j).groupable) { |
||||||
|
cell.setCellStyle(getHeaderStyle(workbook)); |
||||||
|
} else { |
||||||
|
cell.setCellStyle(getDataCellStyle(workbook)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void mergeHeaderCells(String grid[][], int xOffset, int yOffset) { |
||||||
|
// merge header grid cells
|
||||||
|
if(topDimensionAttributes > 0) { |
||||||
|
for(int i = 0; i < grid.length; i++) { |
||||||
|
String lastCell = ""; |
||||||
|
int cellsToMerge = 0; |
||||||
|
for (int j = 0; j < grid[i].length; j++) { |
||||||
|
String currentCell = grid[i][j]; |
||||||
|
if(!currentCell.equals(lastCell) && cellsToMerge > 0) { |
||||||
|
sheet.addMergedRegion(mergeCellByOffset(i, i, j - cellsToMerge - 1, j - 1, xOffset, yOffset)); |
||||||
|
} |
||||||
|
if(currentCell.equals(lastCell)) { |
||||||
|
cellsToMerge++; |
||||||
|
} else { |
||||||
|
cellsToMerge = 0; |
||||||
|
} |
||||||
|
lastCell = currentCell; |
||||||
|
} |
||||||
|
if(cellsToMerge > 0) { |
||||||
|
int j = grid[i].length - 1; |
||||||
|
sheet.addMergedRegion(mergeCellByOffset(i, i, j - cellsToMerge, j, xOffset, yOffset)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// merge left header cols
|
||||||
|
if(grid.length > 1) { |
||||||
|
for (int i = 0; i < leftDimensionAttributes; i++) { |
||||||
|
sheet.addMergedRegion(mergeCellByOffset(0, grid.length - 1, i, i, xOffset, yOffset)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private int createRowsFromGrid(String[][] grid, int startFrom) { |
||||||
|
if(grid == null) { |
||||||
|
return startFrom; |
||||||
|
} |
||||||
|
int rowNum = startFrom; |
||||||
|
for (int i = 0; i < grid.length; i++) { |
||||||
|
Row poiRow = sheet.createRow(rowNum++); |
||||||
|
int colNum = 0; |
||||||
|
for (int j = 0; j < grid[i].length; j++) { |
||||||
|
Cell cell = poiRow.createCell(colNum++); |
||||||
|
if(grid[i][j] != null && !grid[i][j].isBlank()) { |
||||||
|
cell.setCellValue(grid[i][j]); |
||||||
|
} else { |
||||||
|
cell.setBlank(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return rowNum; |
||||||
|
} |
||||||
|
|
||||||
|
private int createDataRows(int startFrom) { |
||||||
|
int rowNum = startFrom; |
||||||
|
// build cells from row data without sumrow
|
||||||
|
List<de.superx.rest.model.Row> resultRows = result.rows.stream().filter(r -> r.aggregated != -1).collect(Collectors.toList()); |
||||||
|
Row[] rows = new Row[resultRows.size()]; |
||||||
|
for (int i = 0; i < resultRows.size(); i++) { |
||||||
|
rows[i] = sheet.createRow(rowNum++); |
||||||
|
rows[i].setHeightInPoints((short) 20); |
||||||
|
} |
||||||
|
for (int i = 0; i < visibleColumns.size(); i++) { |
||||||
|
Column col = visibleColumns.get(i); |
||||||
|
for(int j = 0; j < resultRows.size(); j++) { |
||||||
|
Object obj = resultRows.get(j).cells.get(col.field); |
||||||
|
String objVal = String.valueOf(obj); |
||||||
|
Cell cell = rows[j].createCell(i); |
||||||
|
if(obj == null) { |
||||||
|
cell.setBlank(); |
||||||
|
continue; |
||||||
|
} |
||||||
|
if(col.type == ColumnType.IntegerColumn || col.type == ColumnType.DecimalColumn) { |
||||||
|
Double value = Double.valueOf(objVal); |
||||||
|
cell.setCellValue(value.doubleValue()); |
||||||
|
} else { |
||||||
|
cell.setCellValue(obj.toString()); |
||||||
|
} |
||||||
|
//if(col.groupable) {
|
||||||
|
// cell.setCellStyle(style);
|
||||||
|
//}
|
||||||
|
} |
||||||
|
} |
||||||
|
return rowNum; |
||||||
|
} |
||||||
|
|
||||||
|
private String[][] createHeaderGrid(){ |
||||||
|
int colSize = visibleColumns.size(); |
||||||
|
int rowSize = topDimensionAttributes + 1; |
||||||
|
String[][] grid = new String[rowSize][colSize]; |
||||||
|
|
||||||
|
for(int i = 0; i < colSize; i++) { |
||||||
|
Column column= this.visibleColumns.get(i); |
||||||
|
String[] columnHeader = column.header.split("\\|\\|"); |
||||||
|
boolean isLeftDimensionAttributeColumn = (columnHeader.length == 1 && !columnHeader[0].contains("|"))? true : false; |
||||||
|
for(int j = 0; j < rowSize; j++) { |
||||||
|
if(isLeftDimensionAttributeColumn) { |
||||||
|
grid[j][i] = columnHeader[0]; |
||||||
|
}else { |
||||||
|
String header = columnHeader[j]; |
||||||
|
String[] headerValues = header.split("\\|"); |
||||||
|
grid[j][i] = headerValues[1]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return grid; |
||||||
|
} |
||||||
|
|
||||||
|
public ExcelSheetBuilder withFileName(String name) { |
||||||
|
this.sheet = workbook.createSheet(name); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public ExcelSheetBuilder withReportName(String name) { |
||||||
|
this.reportName = replaceEmptyString(name, "Nicht gespeicherte BI-Analyse"); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public ExcelSheetBuilder withDescription(String description) { |
||||||
|
this.reportDescription = replaceEmptyString(description, "-"); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
private static String replaceEmptyString(String value, String replacement) { |
||||||
|
if(value == null || value.isBlank()) { |
||||||
|
return replacement; |
||||||
|
} |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
public ExcelSheetBuilder withDate(Date currentDate) { |
||||||
|
this.date = new SimpleDateFormat("dd.MM.yyyy HH:mm").format(currentDate); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
private static List<Column> getVisibleColumns(Result result) { |
||||||
|
return result.columns |
||||||
|
.stream() |
||||||
|
.filter(col -> !col.hidden) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,21 @@ |
|||||||
|
package de.superx.bianalysis; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
|
||||||
|
public class FaultyMetadataException extends RuntimeException { |
||||||
|
|
||||||
|
private static final long serialVersionUID = -5959640234409065198L; |
||||||
|
|
||||||
|
public FaultyMetadataException(String message) { |
||||||
|
super(message); |
||||||
|
} |
||||||
|
|
||||||
|
public FaultyMetadataException(Identifier id) { |
||||||
|
super("Metadata Object with ID: '" + id.composedId + "' does not exist."); |
||||||
|
} |
||||||
|
|
||||||
|
public FaultyMetadataException(Identifier id, String metaType) { |
||||||
|
super("Metadata " + metaType + " with ID: '" + id.composedId + "' does not exist."); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,57 @@ |
|||||||
|
package de.superx.bianalysis; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.models.Filter; |
||||||
|
import de.superx.bianalysis.service.DbMetaAdapter; |
||||||
|
|
||||||
|
public class ReportDefinition { |
||||||
|
|
||||||
|
public List<Identifier> factTableIds; |
||||||
|
public List<Identifier> leftDimensionAttributeIds; |
||||||
|
public List<Identifier> topDimensionAttributeIds; |
||||||
|
public List<Identifier> measureIds; |
||||||
|
public List<Filter> filters; |
||||||
|
public boolean hideEmptyColumns; |
||||||
|
|
||||||
|
public ReportDefinition() { |
||||||
|
this.factTableIds = new ArrayList<>(); |
||||||
|
this.leftDimensionAttributeIds = new ArrayList<>(); |
||||||
|
this.topDimensionAttributeIds = new ArrayList<>(); |
||||||
|
this.measureIds = new ArrayList<>(); |
||||||
|
this.filters = new ArrayList<>(); |
||||||
|
this.hideEmptyColumns = false; |
||||||
|
} |
||||||
|
|
||||||
|
public ReportDefinition(ReportDefinition definition) { |
||||||
|
super(); |
||||||
|
this.factTableIds = definition.factTableIds; |
||||||
|
this.topDimensionAttributeIds = definition.topDimensionAttributeIds; |
||||||
|
this.measureIds = definition.measureIds; |
||||||
|
this.filters = definition.filters; |
||||||
|
this.leftDimensionAttributeIds = new ArrayList<>(); |
||||||
|
this.hideEmptyColumns = definition.hideEmptyColumns; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public ReportMetadata getReportMetadata(DbMetaAdapter dbAdapter, Identifier factTableId) { |
||||||
|
ReportMetadata reportMetadata = new ReportMetadata(this, factTableId, dbAdapter); |
||||||
|
return reportMetadata; |
||||||
|
} |
||||||
|
|
||||||
|
public static List<Identifier> getAttributesForDefinitions(List<ReportDefinition> definitions){ |
||||||
|
List<Identifier> ids = new ArrayList<>(); |
||||||
|
for (ReportDefinition def : definitions) { |
||||||
|
for (Identifier id : def.topDimensionAttributeIds) { |
||||||
|
ids.add(id); |
||||||
|
} |
||||||
|
for (Identifier id : def.leftDimensionAttributeIds) { |
||||||
|
ids.add(id); |
||||||
|
} |
||||||
|
} |
||||||
|
return ids; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,338 @@ |
|||||||
|
package de.superx.bianalysis; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.models.DimensionAttribute; |
||||||
|
import de.superx.bianalysis.models.FactTable; |
||||||
|
import de.superx.bianalysis.models.Filter; |
||||||
|
import de.superx.bianalysis.models.InfoItem; |
||||||
|
import de.superx.bianalysis.models.Measure; |
||||||
|
import de.superx.bianalysis.service.DbMetaAdapter; |
||||||
|
import de.superx.jdbc.entity.Sachgebiet; |
||||||
|
|
||||||
|
public class ReportMetadata { |
||||||
|
|
||||||
|
public final FactTable factTable; |
||||||
|
public final Sachgebiet sachgebiet; |
||||||
|
public final List<DimensionAttribute> leftDimensionAttributes; |
||||||
|
public final List<DimensionAttribute> topDimensionAttributes; |
||||||
|
public final List<Measure> measures; |
||||||
|
public final List<Filter> filters; |
||||||
|
|
||||||
|
public String lastBiadUpdate; |
||||||
|
|
||||||
|
// only used if hierarchy dimension is present in left dim attributes
|
||||||
|
public int maxBridgeLvl; |
||||||
|
public int minBridgeLvl; |
||||||
|
|
||||||
|
public DbMetaAdapter dbMetaAdapter; |
||||||
|
|
||||||
|
public boolean hideEmptyColumns; |
||||||
|
|
||||||
|
public ReportMetadata(ReportDefinition reportDefinition, Identifier factTableId, DbMetaAdapter dbAdapter) { |
||||||
|
this.dbMetaAdapter = dbAdapter; |
||||||
|
if(factTableId == null) { // merged Report
|
||||||
|
this.factTable = new FactTable(); |
||||||
|
this.sachgebiet = new Sachgebiet(); |
||||||
|
} else { |
||||||
|
this.factTable = dbAdapter.getFactTable(factTableId); |
||||||
|
this.sachgebiet = dbAdapter.getSachgebietById(this.factTable.getSachgebiettid()); |
||||||
|
} |
||||||
|
List<DimensionAttribute> databaseOrderedLeftDimensionAttributes = dbAdapter.getDimensionAttributeMetadata(reportDefinition.leftDimensionAttributeIds, factTableId); |
||||||
|
this.leftDimensionAttributes = reorderDimensionAttributesToReportOrder(databaseOrderedLeftDimensionAttributes, reportDefinition, false); |
||||||
|
List<DimensionAttribute> databaseOrderedTopDimensionAttributes = dbAdapter.getDimensionAttributeMetadata(reportDefinition.topDimensionAttributeIds, factTableId); |
||||||
|
this.topDimensionAttributes = reorderDimensionAttributesToReportOrder(databaseOrderedTopDimensionAttributes, reportDefinition, true); |
||||||
|
List<Measure> databaseOrderedMeasures = dbAdapter.getMeasureMetadata(reportDefinition.measureIds); |
||||||
|
this.measures = reorderMeasuresToReportOrder(databaseOrderedMeasures, reportDefinition); |
||||||
|
if (reportDefinition.filters != null) { |
||||||
|
this.filters = dbAdapter.getFilterMetadata(reportDefinition.filters); |
||||||
|
} else { |
||||||
|
this.filters = new ArrayList<Filter>(); |
||||||
|
} |
||||||
|
this.setTopDimensionAttributeValues(dbAdapter); |
||||||
|
if(factTableId != null) { |
||||||
|
this.setMaxBridgeLvl(); |
||||||
|
} else { |
||||||
|
// for merged report
|
||||||
|
this.setMaxBridgeLvlForConformed(reportDefinition.factTableIds); |
||||||
|
} |
||||||
|
this.lastBiadUpdate = dbAdapter.getLastUpdate(440); |
||||||
|
this.hideEmptyColumns = reportDefinition.hideEmptyColumns; |
||||||
|
} |
||||||
|
|
||||||
|
public ReportMetadata(ReportMetadata metadata, List<DimensionAttribute> leftDimensionAttributes) { |
||||||
|
this.dbMetaAdapter = metadata.dbMetaAdapter; |
||||||
|
this.factTable = metadata.factTable; |
||||||
|
this.sachgebiet = metadata.sachgebiet; |
||||||
|
this.topDimensionAttributes = metadata.topDimensionAttributes; |
||||||
|
this.measures = metadata.measures; |
||||||
|
this.filters = metadata.filters; |
||||||
|
this.leftDimensionAttributes = leftDimensionAttributes; |
||||||
|
this.hideEmptyColumns = metadata.hideEmptyColumns; |
||||||
|
} |
||||||
|
|
||||||
|
public ReportMetadata() { |
||||||
|
this.factTable = new FactTable(); |
||||||
|
this.sachgebiet = new Sachgebiet(); |
||||||
|
this.leftDimensionAttributes = new ArrayList<>(); |
||||||
|
this.topDimensionAttributes = new ArrayList<>(); |
||||||
|
this.measures = new ArrayList<>(); |
||||||
|
this.filters = new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
public List<DimensionAttribute> getSortOrderLeftDimensionAttributes(){ |
||||||
|
return leftDimensionAttributes.stream().filter(d -> d.getSortOrderColumn() != null).collect(Collectors.toList()); |
||||||
|
} |
||||||
|
|
||||||
|
private void setMaxBridgeLvl() { |
||||||
|
List<DimensionAttribute> attrs = leftDimensionAttributes |
||||||
|
.stream() |
||||||
|
.filter(a -> a.isHierarchy() ) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
if(attrs.size() > 1) { |
||||||
|
throw new RuntimeException("NOT YET IMPLEMENTED: There can only be one hierarchy attribute."); |
||||||
|
} |
||||||
|
if(!attrs.isEmpty()) { |
||||||
|
this.maxBridgeLvl = dbMetaAdapter.getBridgeMaxLevel(attrs.get(0), this); |
||||||
|
this.minBridgeLvl = dbMetaAdapter.getBridgeMinLevel(getHierarchyFilter(), this.maxBridgeLvl, attrs.get(0).getTablename()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void setMaxBridgeLvlForConformed(List<Identifier> factTableIds) { |
||||||
|
List<DimensionAttribute> attrs = leftDimensionAttributes |
||||||
|
.stream() |
||||||
|
.filter(a -> a.isHierarchy()) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
if(!attrs.isEmpty()) { |
||||||
|
DimensionAttribute attr = attrs.get(0); |
||||||
|
int lvl = 0; |
||||||
|
for (Identifier fact : factTableIds) { |
||||||
|
String name = dbMetaAdapter.getFactTableNameMaxBridgeLvl(fact, attr.getId()); |
||||||
|
if(name == null || name.isBlank()) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
int value = -1; |
||||||
|
Identifier checkedAttr = dbMetaAdapter.checkIfFactTableHasDimensionAttribute(attr.getId(), fact); |
||||||
|
if (checkedAttr != null && !checkedAttr.equals(attr.getId())) { |
||||||
|
DimensionAttribute rolePlayingAttribute = dbMetaAdapter.getDimensionAttributeMetadataById(checkedAttr); |
||||||
|
value = dbMetaAdapter.getBridgeMaxLevel(rolePlayingAttribute, this, name); |
||||||
|
} |
||||||
|
if (value > lvl) { |
||||||
|
lvl = value; |
||||||
|
} |
||||||
|
} |
||||||
|
this.maxBridgeLvl = lvl; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void setTopDimensionAttributeValues(DbMetaAdapter dbAdapter) { |
||||||
|
for(DimensionAttribute attr : this.topDimensionAttributes) { |
||||||
|
Filter filter = getFilterForDimensionAttribute(attr.getId()); |
||||||
|
if(filter != null) { |
||||||
|
attr.setDimensionAttributeValues(filter.filterValues); |
||||||
|
} else { |
||||||
|
attr.setDimensionAttributeValues(dbAdapter.getDimensionAttributeValues(attr, null, null)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private Filter getFilterForDimensionAttribute(Identifier id) { |
||||||
|
return this.filters |
||||||
|
.stream() |
||||||
|
.filter(f -> f.dimensionAttributeId.equals(id)) |
||||||
|
.findFirst() |
||||||
|
.orElse(null); |
||||||
|
} |
||||||
|
|
||||||
|
private static List<Measure> reorderMeasuresToReportOrder(List<Measure> measures, ReportDefinition reportDefinition) { |
||||||
|
List<Measure> orderedMeasures = new ArrayList<Measure>(); |
||||||
|
reportDefinition.measureIds.forEach(measureId -> { |
||||||
|
Measure nextMeasure = measures |
||||||
|
.stream() |
||||||
|
.filter( measure -> measure.getId().equals( measureId ) ) |
||||||
|
.findFirst() |
||||||
|
.orElse(null); |
||||||
|
orderedMeasures.add(nextMeasure); |
||||||
|
}); |
||||||
|
return orderedMeasures; |
||||||
|
} |
||||||
|
|
||||||
|
public static List<DimensionAttribute> reorderDimensionAttributesToReportOrder(List<DimensionAttribute> dimensionAttributes, ReportDefinition reportDefinition, boolean isTopAttribute) { |
||||||
|
List<DimensionAttribute> orderedDimensionAttributes = new ArrayList<DimensionAttribute>(); |
||||||
|
List<Identifier> attributeIds; |
||||||
|
if (isTopAttribute) { |
||||||
|
attributeIds = reportDefinition.topDimensionAttributeIds; |
||||||
|
} else { |
||||||
|
attributeIds = reportDefinition.leftDimensionAttributeIds; |
||||||
|
} |
||||||
|
attributeIds.forEach(attributeId -> { |
||||||
|
DimensionAttribute nextAttribute = dimensionAttributes |
||||||
|
.stream() |
||||||
|
.filter( dimensionAttribute -> dimensionAttribute.getId().equals( attributeId )) |
||||||
|
.findFirst() |
||||||
|
.orElse(null); |
||||||
|
orderedDimensionAttributes.add(nextAttribute); |
||||||
|
}); |
||||||
|
return orderedDimensionAttributes; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public DimensionAttribute getDimById(Identifier id) { |
||||||
|
DimensionAttribute attr = topDimensionAttributes |
||||||
|
.stream() |
||||||
|
.filter(a -> a.getDimensionId().equals(id)) |
||||||
|
.findFirst() |
||||||
|
.orElse(null); |
||||||
|
|
||||||
|
if(attr != null) { |
||||||
|
return attr; |
||||||
|
} |
||||||
|
|
||||||
|
attr = leftDimensionAttributes |
||||||
|
.stream() |
||||||
|
.filter(a -> a.getDimensionId().equals(id)) |
||||||
|
.findFirst() |
||||||
|
.orElse(null); |
||||||
|
|
||||||
|
return attr; |
||||||
|
} |
||||||
|
|
||||||
|
public DimensionAttribute getDimAttrById(Identifier id) { |
||||||
|
DimensionAttribute attr = topDimensionAttributes |
||||||
|
.stream() |
||||||
|
.filter(a -> a.getId().equals(id)) |
||||||
|
.findFirst() |
||||||
|
.orElse(null); |
||||||
|
|
||||||
|
if(attr != null) { |
||||||
|
return attr; |
||||||
|
} |
||||||
|
|
||||||
|
attr = leftDimensionAttributes |
||||||
|
.stream() |
||||||
|
.filter(a -> a.getId().equals(id)) |
||||||
|
.findFirst() |
||||||
|
.orElse(null); |
||||||
|
|
||||||
|
return attr; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* We want to join dimension tables only once. There we need a list of unique ids of |
||||||
|
* the dimensions, otherwise we duplicate our joins. |
||||||
|
*/ |
||||||
|
public List<DimensionAttribute> getUniqueDimensionAttributes(){ |
||||||
|
|
||||||
|
Map<String, DimensionAttribute> joinTables = new HashMap<String, DimensionAttribute>(); |
||||||
|
|
||||||
|
for (DimensionAttribute attr : leftDimensionAttributes) { |
||||||
|
if(!joinTables.containsKey(attr.getDimensionTableAlias())) { |
||||||
|
joinTables.put(attr.getDimensionTableAlias(), attr); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
for (DimensionAttribute attr : topDimensionAttributes) { |
||||||
|
if(!joinTables.containsKey(attr.getDimensionTableAlias())) { |
||||||
|
joinTables.put(attr.getDimensionTableAlias(), attr); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// join dimension if attribute occurs in filter
|
||||||
|
for (Filter filter : filters) { |
||||||
|
Identifier attrId = filter.dimensionAttributeId; |
||||||
|
DimensionAttribute attr = dbMetaAdapter.getDimensionAttributeMetadataById(attrId); |
||||||
|
if(!joinTables.containsKey(attr.getDimensionTableAlias())) { |
||||||
|
joinTables.put(attr.getDimensionTableAlias(), attr); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// join dimension if measure has a filter for an attribute
|
||||||
|
for (Measure measure : measures) { |
||||||
|
if(measure.filterAttributeId != null) { |
||||||
|
Identifier attrId = measure.filterAttributeId; |
||||||
|
DimensionAttribute attr = dbMetaAdapter.getDimensionAttributeMetadataById(attrId); |
||||||
|
if(!joinTables.containsKey(attr.getDimensionTableAlias())) { |
||||||
|
joinTables.put(attr.getDimensionTableAlias(), attr); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return new ArrayList<DimensionAttribute>(joinTables.values()); |
||||||
|
} |
||||||
|
|
||||||
|
public List<InfoItem> getMeasureInfo() { |
||||||
|
if(measures != null && !measures.isEmpty()) { |
||||||
|
return measures.stream().map(m-> |
||||||
|
new InfoItem(m.getId().composedId, m.getCaption(), m.getDescription())).collect(Collectors.toList()); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public List<InfoItem> getTopDimAttrAsInfo() { |
||||||
|
if(topDimensionAttributes != null && !topDimensionAttributes.isEmpty()) { |
||||||
|
return topDimensionAttributes.stream().map(m-> |
||||||
|
new InfoItem(m.getStringId(), m.getCaption(), m.getDescription())).collect(Collectors.toList()); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Filter> getFilterNoHierarchy() { |
||||||
|
List<Filter> filterNoBridge = new ArrayList<>(); |
||||||
|
for (Filter filter : this.filters) { |
||||||
|
DimensionAttribute attr = dbMetaAdapter.getDimensionAttributeById(filter.dimensionAttributeId); |
||||||
|
if(!attr.isHierarchy()) { |
||||||
|
filterNoBridge.add(filter); |
||||||
|
} |
||||||
|
} |
||||||
|
return filterNoBridge; |
||||||
|
} |
||||||
|
|
||||||
|
public List<InfoItem> getLeftDimAttrAsInfo() { |
||||||
|
if(leftDimensionAttributes != null && !leftDimensionAttributes.isEmpty()) { |
||||||
|
return leftDimensionAttributes.stream().map(m-> |
||||||
|
new InfoItem(m.getStringId(), m.getCaption(), m.getDescription())).collect(Collectors.toList()); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public List<String> getFilterAsInfo(){ |
||||||
|
ArrayList<String> filterList = new ArrayList<String>(); |
||||||
|
DimensionAttribute dimAttr; |
||||||
|
for (Filter filter: filters) { |
||||||
|
dimAttr = filter.getDimAttribute(this); |
||||||
|
if(dimAttr == null) { |
||||||
|
dimAttr = dbMetaAdapter.getDimensionAttributeById(filter.dimensionAttributeId); |
||||||
|
} |
||||||
|
filterList.add(" (" + dimAttr.getCaption() + ") " + filter.getValuesAsString()); |
||||||
|
} |
||||||
|
return filterList; |
||||||
|
} |
||||||
|
|
||||||
|
public List<DimensionAttribute> getHierarchyAttributes() { |
||||||
|
return leftDimensionAttributes |
||||||
|
.stream() |
||||||
|
.filter(a -> a.isHierarchy()) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
} |
||||||
|
|
||||||
|
public List<Filter> getHierarchyFilter(){ |
||||||
|
List<Filter> hierarchyFilter = new ArrayList<>(); |
||||||
|
for (Filter filter : this.filters) { |
||||||
|
if(isHierarchyFilter(filter)) { |
||||||
|
hierarchyFilter.add(filter); |
||||||
|
} |
||||||
|
} |
||||||
|
return hierarchyFilter; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isHierarchyFilter(Filter filter) { |
||||||
|
return dbMetaAdapter.isAttributeHierarchyBridge(filter.dimensionAttributeId); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,536 @@ |
|||||||
|
package de.superx.bianalysis; |
||||||
|
|
||||||
|
import java.sql.Connection; |
||||||
|
import java.sql.ResultSet; |
||||||
|
import java.sql.SQLException; |
||||||
|
import java.sql.Statement; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.TreeMap; |
||||||
|
|
||||||
|
import javax.sql.DataSource; |
||||||
|
|
||||||
|
import org.apache.log4j.Logger; |
||||||
|
import org.springframework.jdbc.core.JdbcTemplate; |
||||||
|
import org.springframework.jdbc.core.RowMapper; |
||||||
|
|
||||||
|
import de.superx.bianalysis.models.DimensionAttribute; |
||||||
|
import de.superx.bianalysis.models.InfoItem; |
||||||
|
import de.superx.bianalysis.models.Measure; |
||||||
|
import de.superx.rest.model.Column; |
||||||
|
import de.superx.rest.model.ColumnType; |
||||||
|
import de.superx.rest.model.Item; |
||||||
|
import de.superx.rest.model.Result; |
||||||
|
import de.superx.rest.model.ResultType; |
||||||
|
import de.superx.rest.model.Row; |
||||||
|
|
||||||
|
public class ResultBuilder { |
||||||
|
|
||||||
|
private static final boolean IGNORE_SELF_LOOPS = true; |
||||||
|
|
||||||
|
private DataSource dataSource; |
||||||
|
|
||||||
|
private ReportMetadata reportMetadata; |
||||||
|
private List<ColumnElement> columnElements; |
||||||
|
|
||||||
|
Logger logger = Logger.getLogger(ResultBuilder.class); |
||||||
|
|
||||||
|
public ResultBuilder() {} |
||||||
|
|
||||||
|
// used for testing
|
||||||
|
public ResultBuilder(ReportMetadata metadata, List<ColumnElement> columns) { |
||||||
|
this.reportMetadata = metadata; |
||||||
|
this.columnElements = columns; |
||||||
|
} |
||||||
|
|
||||||
|
public ResultBuilder(DataSource dataSource) { |
||||||
|
this.dataSource = dataSource; |
||||||
|
} |
||||||
|
|
||||||
|
public void setReportMetadata(ReportMetadata reportMetadata) { |
||||||
|
this.reportMetadata = reportMetadata; |
||||||
|
} |
||||||
|
|
||||||
|
public void setColumnElements(List<ColumnElement> columnElements) { |
||||||
|
this.columnElements = columnElements; |
||||||
|
} |
||||||
|
|
||||||
|
private Row buildRowCells(ResultSet rs) { |
||||||
|
Row row = new Row(); |
||||||
|
Map<String, Object> cells = new TreeMap<String, Object>(); |
||||||
|
if (reportMetadata.leftDimensionAttributes != null && !reportMetadata.leftDimensionAttributes.isEmpty()) { |
||||||
|
int aggregationLvl = reportMetadata.leftDimensionAttributes.size() -1; |
||||||
|
for (DimensionAttribute dimensionAttribute : reportMetadata.leftDimensionAttributes) { |
||||||
|
if(dimensionAttribute.isHierarchy()) { |
||||||
|
try { |
||||||
|
String prevLbl = ""; |
||||||
|
int countLvl = 0; |
||||||
|
aggregationLvl += reportMetadata.maxBridgeLvl - reportMetadata.minBridgeLvl - 1; |
||||||
|
for (int i = reportMetadata.minBridgeLvl; i < reportMetadata.maxBridgeLvl; i++) { |
||||||
|
Object cell = rs.getObject("col" + i); |
||||||
|
String curLbl = (String) cell; |
||||||
|
|
||||||
|
if(cell == null) { |
||||||
|
// An empty cell means a lower aggregation level because
|
||||||
|
// of how the GROUP BY ROLLUP works.
|
||||||
|
aggregationLvl--; |
||||||
|
} |
||||||
|
|
||||||
|
if(IGNORE_SELF_LOOPS && |
||||||
|
curLbl != null && |
||||||
|
curLbl != "" && |
||||||
|
curLbl.equals(prevLbl)) { |
||||||
|
// If the cell label is equal to the previous cell label
|
||||||
|
// then this row contains a self loop, meaning the node is
|
||||||
|
// both its own parent and child. This happens due to the
|
||||||
|
// GROUP BY ROLLUP part of the sql statement, which groups
|
||||||
|
// columns in which the same node can appear right next to
|
||||||
|
// each other in two columns.
|
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
String id = dimensionAttribute.getAttrConformedId(); |
||||||
|
if(id == null) { |
||||||
|
id = dimensionAttribute.getStringId(); |
||||||
|
} |
||||||
|
|
||||||
|
String cellKey = id + " (Ebene " + countLvl + ")"; |
||||||
|
|
||||||
|
if(countLvl == 0) { |
||||||
|
cellKey = dimensionAttribute.getAttrConformedId(); |
||||||
|
} |
||||||
|
|
||||||
|
if(cell != null && cellKey != null) { |
||||||
|
cells.put(cellKey, cell); |
||||||
|
row.rowKey += cellKey + cell; |
||||||
|
countLvl++; |
||||||
|
} |
||||||
|
|
||||||
|
prevLbl = (String) cell; |
||||||
|
} |
||||||
|
} catch (SQLException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} else { |
||||||
|
try { |
||||||
|
Object val = rs.getObject(dimensionAttribute.getDimensionColumnAlias()); |
||||||
|
if(val != null) { |
||||||
|
String id = dimensionAttribute.getAttrConformedId(); |
||||||
|
if(id == null) { |
||||||
|
id = dimensionAttribute.getStringId(); |
||||||
|
} |
||||||
|
cells.put(id, val); |
||||||
|
row.rowKey += id + val; |
||||||
|
} else { |
||||||
|
aggregationLvl--; |
||||||
|
} |
||||||
|
} catch (SQLException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
if(dimensionAttribute.getSortOrderColumn() != null) { |
||||||
|
try { |
||||||
|
String id = dimensionAttribute.getAttrConformedId(); |
||||||
|
if(id == null) { |
||||||
|
id = dimensionAttribute.getStringId(); |
||||||
|
} |
||||||
|
cells.put(id + "_sorting", rs.getObject(dimensionAttribute.getDimensionColumnAlias()+"_"+dimensionAttribute.getSortOrderColumn())); |
||||||
|
} catch (SQLException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
try { |
||||||
|
row.aggregated = aggregationLvl; |
||||||
|
if(row.aggregated == -1) { |
||||||
|
int colNum = this.reportMetadata.maxBridgeLvl + this.columnElements.size() - this.reportMetadata.measures.size(); |
||||||
|
for (Measure measure : reportMetadata.measures) { |
||||||
|
cells.put(getTotalCellHeaderPrefix(reportMetadata) + measure.getId().composedId, rs.getObject("col" + (colNum++))); |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (SQLException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
if (!columnElements.isEmpty()) { |
||||||
|
for (ColumnElement columnElement : columnElements) { |
||||||
|
try { |
||||||
|
cells.put(columnElement.caption, rs.getObject("col" + columnElement.columnNumber)); |
||||||
|
} catch (SQLException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
row.cells = cells; |
||||||
|
return row; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static List<Column> buildColumns(ReportMetadata reportMetadata, List<ColumnElement> columnElements) { |
||||||
|
List<Column> columns = new ArrayList<Column>(); |
||||||
|
if (reportMetadata.leftDimensionAttributes != null) { |
||||||
|
reportMetadata.leftDimensionAttributes.forEach((dimensionAttribute) -> { |
||||||
|
String id = dimensionAttribute.getAttrConformedId(); |
||||||
|
if(id == null) { |
||||||
|
id = dimensionAttribute.getStringId(); |
||||||
|
} |
||||||
|
if(dimensionAttribute.isHierarchy()) { |
||||||
|
int cnt = 0; |
||||||
|
for (int i = reportMetadata.minBridgeLvl; i < reportMetadata.maxBridgeLvl - 1; i++) { |
||||||
|
if(cnt == 0) { |
||||||
|
columns.add(new Column(id, dimensionAttribute.getCaption(), ColumnType.StringColumn, true)); |
||||||
|
} else { |
||||||
|
String caption = id + " (Ebene " + cnt + ")"; |
||||||
|
String header = dimensionAttribute.getCaption() + " (Ebene " + (cnt) + ")"; |
||||||
|
columns.add(new Column(caption, header, ColumnType.HierarchyLevelColumn, true, id, false)); |
||||||
|
} |
||||||
|
cnt += 1; |
||||||
|
} |
||||||
|
} else { |
||||||
|
if(dimensionAttribute.getSortOrderColumn() != null) { |
||||||
|
columns.add(new Column(id, dimensionAttribute.getCaption(), ColumnType.StringColumn, true, dimensionAttribute.getStringId() + "_sorting", false)); |
||||||
|
columns.add(new Column(id + "_sorting", dimensionAttribute.getCaption(), ColumnType.SortOrderColumn, false, dimensionAttribute.getStringId(), true)); |
||||||
|
}else { |
||||||
|
columns.add(new Column(id, dimensionAttribute.getCaption(), ColumnType.StringColumn, true)); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
if (!columnElements.isEmpty()) { |
||||||
|
columnElements.forEach((columnElement) -> { |
||||||
|
Column col = new Column(columnElement.caption, columnElement.header, columnElement.measure.getMeasureType(), false); |
||||||
|
col.aggregation = columnElement.measure.getAggregationType(); |
||||||
|
columns.add(col); |
||||||
|
}); |
||||||
|
} |
||||||
|
return columns; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Row> getRowsForReport(String sqlStatement, Connection con) { |
||||||
|
|
||||||
|
List<Row> rows = null; |
||||||
|
try (Statement stmt = con.createStatement(); |
||||||
|
ResultSet rs = stmt.executeQuery(sqlStatement)) { |
||||||
|
rows = buildRowList(rs); |
||||||
|
} catch (SQLException e) { |
||||||
|
System.out.println(sqlStatement); |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
|
||||||
|
return rows; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Row> buildRowList(ResultSet rs) throws SQLException { |
||||||
|
List<Row> rows = new ArrayList<>(); |
||||||
|
while (rs.next()) { |
||||||
|
Row row = buildRowCells(rs); |
||||||
|
rows.add(row); |
||||||
|
} |
||||||
|
List<Row> result = new ArrayList<>(); |
||||||
|
if (reportMetadata.getHierarchyAttributes().size() > 0) { |
||||||
|
HashMap<String, Row> keys = new HashMap<>(); |
||||||
|
for (Row row : rows) { |
||||||
|
if (keys.containsKey(row.rowKey)) { |
||||||
|
Row currentRow = keys.get(row.rowKey ); |
||||||
|
if (currentRow.aggregated > row.aggregated) { |
||||||
|
keys.put(currentRow.rowKey , row); |
||||||
|
} |
||||||
|
// workaround: fix multiple aggregated rows, take only highest
|
||||||
|
if(currentRow.aggregated == -1 && row.aggregated == -1) { |
||||||
|
for(String cell : currentRow.cells.keySet()) { |
||||||
|
Number currentCellVal = (Number) currentRow.cells.get(cell); |
||||||
|
Number candidateVal = (Number) row.cells.get(cell); |
||||||
|
if(candidateVal.doubleValue() > currentCellVal.doubleValue()) { |
||||||
|
keys.put(currentRow.rowKey, row); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
keys.put(row.rowKey, row); |
||||||
|
} |
||||||
|
} |
||||||
|
rows = new ArrayList<Row>(keys.values()); |
||||||
|
} |
||||||
|
|
||||||
|
for (Row row : rows) { |
||||||
|
if(row != null) { |
||||||
|
result.add(row); |
||||||
|
} |
||||||
|
} |
||||||
|
return rows; |
||||||
|
} |
||||||
|
|
||||||
|
public Result buildReport(List<Item> sqlStatements, boolean isCreateRight) { |
||||||
|
JdbcTemplate jt = new JdbcTemplate(dataSource); |
||||||
|
Result report; |
||||||
|
report = new Result(); |
||||||
|
if(isCreateRight) { |
||||||
|
report.info.setSqlStatements(sqlStatements); |
||||||
|
} |
||||||
|
|
||||||
|
String sql = findByLabel(sqlStatements, "noAggregatesSQL").value; |
||||||
|
String sqlColumnTotal = findByLabel(sqlStatements, "totalsColumnSQL").value; |
||||||
|
|
||||||
|
List<Column> columns = buildColumns(reportMetadata, columnElements); |
||||||
|
List<Row> rows = null; |
||||||
|
List<Row> totalColumns = null; |
||||||
|
|
||||||
|
try (Connection con = jt.getDataSource().getConnection()){ |
||||||
|
rows = getRowsForReport(sql, con); |
||||||
|
} catch (Exception e) { |
||||||
|
logger.error(e); |
||||||
|
e.printStackTrace(); |
||||||
|
report.info.setSegmentCaption(reportMetadata.factTable.getCaption()); |
||||||
|
report.info.setErrorMessage(e.getCause().getMessage()); |
||||||
|
return report; |
||||||
|
} |
||||||
|
|
||||||
|
// add one column for each measure to the report with the total sum
|
||||||
|
if(!reportMetadata.topDimensionAttributes.isEmpty()) { |
||||||
|
try { |
||||||
|
totalColumns = getTotalColumnResult(sqlColumnTotal, jt); |
||||||
|
ResultBuilder.setTotalColumnToColumns(columns, reportMetadata); |
||||||
|
ResultBuilder.setTotalColumnToRows(rows, totalColumns); |
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
report.info.setErrorMessage("Die Gesamtspalte konnte nicht ermittelt werden."); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
setAttributesToReport(report, reportMetadata, rows, columns); |
||||||
|
|
||||||
|
try { |
||||||
|
if(reportMetadata.hideEmptyColumns) { |
||||||
|
removeEmptyColumns(columns, rows); |
||||||
|
} |
||||||
|
} catch(Exception e ) { |
||||||
|
logger.error(e); |
||||||
|
} |
||||||
|
|
||||||
|
return report; |
||||||
|
} |
||||||
|
|
||||||
|
public static void removeEmptyColumns(List<Column> columns, List<Row> rows) { |
||||||
|
HashMap<String, Integer> map = new HashMap<>(); |
||||||
|
for (Column col : columns) { |
||||||
|
if(!map.containsKey(col.field)) { |
||||||
|
map.put(col.field, Integer.valueOf(-1)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
for (Row row : rows) { |
||||||
|
for (String cellKey : row.cells.keySet()) { |
||||||
|
Object value = row.cells.get(cellKey); |
||||||
|
if(value instanceof Number) { |
||||||
|
Number val = (Number) value; |
||||||
|
if(val.intValue() != 0) { |
||||||
|
if(map.containsKey(cellKey)) { |
||||||
|
map.remove(cellKey); |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
if(value == null) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
if(map.containsKey(cellKey)) { |
||||||
|
map.remove(cellKey); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
for (Row row : rows) { |
||||||
|
for(String key : map.keySet()) { |
||||||
|
if(row.cells.containsKey(key)) { |
||||||
|
row.cells.remove(key); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if(rows.size() > 1) { |
||||||
|
for(Iterator<Column> iterator = columns.iterator(); iterator.hasNext(); ) { |
||||||
|
if(map.containsKey(iterator.next().field)) |
||||||
|
iterator.remove(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void setAttributesToReport(Result report, ReportMetadata reportMetadata, List<Row> rows, List<Column> columns) { |
||||||
|
report.setResultType(ResultType.DrilldownTableGroupable); |
||||||
|
report.setRows(rows); |
||||||
|
report.setColumns(columns); |
||||||
|
if(reportMetadata.factTable.getCaption() != null) { |
||||||
|
report.info.setSegmentCaption(reportMetadata.factTable.getCaption()); |
||||||
|
InfoItem facttableInfo = new InfoItem (reportMetadata.factTable.getId().composedId, |
||||||
|
reportMetadata.factTable.getCaption(), |
||||||
|
reportMetadata.factTable.getDescription()); |
||||||
|
report.info.addFacttable(facttableInfo); |
||||||
|
report.info.addSachgebiet(reportMetadata.sachgebiet.name); |
||||||
|
} |
||||||
|
report.info.setMeasures(reportMetadata.getMeasureInfo()); |
||||||
|
report.info.setLeftDimensionAttributes(reportMetadata.getLeftDimAttrAsInfo()); |
||||||
|
report.info.setTopDimensionAttributes(reportMetadata.getTopDimAttrAsInfo()); |
||||||
|
report.info.setFilter(reportMetadata.getFilterAsInfo()); |
||||||
|
report.info.setLastUpdateBiad(reportMetadata.lastBiadUpdate); |
||||||
|
report.info.hideEmptyColumns(reportMetadata.hideEmptyColumns); |
||||||
|
} |
||||||
|
|
||||||
|
private static String getTotalCellHeaderPrefix(ReportMetadata reportMetadata) { |
||||||
|
String totalCellHeaderPrefix = ""; |
||||||
|
for (int i = 0; i < reportMetadata.topDimensionAttributes.size(); i++) { |
||||||
|
DimensionAttribute attr = reportMetadata.topDimensionAttributes.get(i); |
||||||
|
if(i == 0) { |
||||||
|
totalCellHeaderPrefix += ColumnElement.buildField(attr, "Gesamt"); |
||||||
|
} else { |
||||||
|
totalCellHeaderPrefix += ColumnElement.buildField(attr, " "); |
||||||
|
} |
||||||
|
} |
||||||
|
totalCellHeaderPrefix += " || Kennzahl|"; |
||||||
|
return totalCellHeaderPrefix; |
||||||
|
} |
||||||
|
|
||||||
|
private static String getTotalCellHeaderPrefixHeader(ReportMetadata reportMetadata) { |
||||||
|
String totalCellHeaderPrefix = ""; |
||||||
|
for (int i = 0; i < reportMetadata.topDimensionAttributes.size(); i++) { |
||||||
|
DimensionAttribute attr = reportMetadata.topDimensionAttributes.get(i); |
||||||
|
if(i == 0) { |
||||||
|
totalCellHeaderPrefix += attr.getCaption() + ": " + attr.getCaption() + "| Gesamt "; |
||||||
|
} else { |
||||||
|
totalCellHeaderPrefix += " || " + attr.getCaption() + ": " + attr.getCaption() + "| "; |
||||||
|
} |
||||||
|
} |
||||||
|
totalCellHeaderPrefix += " || Kennzahl|"; |
||||||
|
return totalCellHeaderPrefix; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Row> getTotalColumnResult(String sqlStatement, JdbcTemplate jt) { |
||||||
|
if(sqlStatement.isEmpty()) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
List<Row> rows = null; |
||||||
|
rows = jt.query(sqlStatement, new Object[0], new RowMapper<Row>() { |
||||||
|
@Override |
||||||
|
public Row mapRow(ResultSet rs, int rowNum) { |
||||||
|
Row row = new Row(); |
||||||
|
Map<String, Object> cells = new TreeMap<String, Object>(); |
||||||
|
int numCols = reportMetadata.maxBridgeLvl; |
||||||
|
try { |
||||||
|
for (DimensionAttribute attr : reportMetadata.leftDimensionAttributes) { |
||||||
|
if(attr.isHierarchy()) { |
||||||
|
String prevCell = ""; |
||||||
|
for (int i = reportMetadata.minBridgeLvl; i < reportMetadata.maxBridgeLvl; i++) { |
||||||
|
Object cell = rs.getObject("col" + i); |
||||||
|
if(cell == null || cell.equals(prevCell)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
String cellKey = attr.getStringId() + " (Ebene " + i + ")"; |
||||||
|
if(i == 0) { |
||||||
|
cellKey = attr.getStringId(); |
||||||
|
} |
||||||
|
row.rowKey += cellKey + cell; |
||||||
|
prevCell = (String) cell; |
||||||
|
} |
||||||
|
} else { |
||||||
|
Object val = rs.getObject(attr.getDimensionColumnAlias()); |
||||||
|
if(val != null) { |
||||||
|
String id = attr.getAttrConformedId(); |
||||||
|
if(id == null) { |
||||||
|
id = attr.getStringId(); |
||||||
|
} |
||||||
|
cells.put(id, val); |
||||||
|
row.rowKey += id + val; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (SQLException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
for (Measure measure : reportMetadata.measures) { |
||||||
|
try { |
||||||
|
String key = getTotalCellHeaderPrefix(reportMetadata) + measure.getId().composedId; |
||||||
|
Object val = rs.getObject("col" + numCols++); |
||||||
|
cells.put(key, val); |
||||||
|
} catch (SQLException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
row.cells = cells; |
||||||
|
return row; |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
if(reportMetadata.getHierarchyAttributes().size() > 0) { |
||||||
|
HashMap<String, Row> rowKeyValue = new HashMap<>(); |
||||||
|
for (Row row : rows) { |
||||||
|
boolean replace = false; |
||||||
|
if(rowKeyValue.containsKey(row.rowKey)) { |
||||||
|
Row alreadyThere = rowKeyValue.get(row.rowKey); |
||||||
|
for(String key : alreadyThere.cells.keySet()) { |
||||||
|
Number candidateVal = (Number) row.cells.get(key); |
||||||
|
if(candidateVal == null) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
Number alreadyVal = (Number) alreadyThere.cells.get(key); |
||||||
|
if(alreadyVal == null) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
if(candidateVal.doubleValue() > alreadyVal.doubleValue()) { |
||||||
|
replace = true; |
||||||
|
} |
||||||
|
} |
||||||
|
if(replace) { |
||||||
|
rowKeyValue.put(row.rowKey, row); |
||||||
|
replace = false; |
||||||
|
} |
||||||
|
} else { |
||||||
|
rowKeyValue.put(row.rowKey, row); |
||||||
|
} |
||||||
|
} |
||||||
|
return new ArrayList<>(rowKeyValue.values()); |
||||||
|
} |
||||||
|
|
||||||
|
return rows; |
||||||
|
} |
||||||
|
|
||||||
|
public static void setTotalColumnToRows(List<Row> rows, List<Row> result) { |
||||||
|
for (Row row : rows) { |
||||||
|
for (Row r : result) { |
||||||
|
if(r.rowKey.equals(row.rowKey)) { |
||||||
|
row.cells.putAll(r.cells); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
//for (int i = 0; i < rows.size(); i++) {
|
||||||
|
// Row row = rows.get(i);
|
||||||
|
// if(row.aggregated == -1) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// row.cells.putAll(result.get(i).cells);
|
||||||
|
//}
|
||||||
|
} |
||||||
|
|
||||||
|
public static void setTotalColumnToColumns(List<Column> columns, ReportMetadata reportMetadata) { |
||||||
|
for (Measure measure : reportMetadata.measures) { |
||||||
|
String field = getTotalCellHeaderPrefix(reportMetadata) + measure.getId().composedId; |
||||||
|
String header = getTotalCellHeaderPrefixHeader(reportMetadata) + measure.getCaption(); |
||||||
|
Column col = new Column(field, header, measure.getMeasureType(), false); |
||||||
|
col.setHidden(true); |
||||||
|
col.setTotalColumn(true); |
||||||
|
columns.add(col); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private static Item findByLabel(List<Item> items, String label) { |
||||||
|
return items.stream() |
||||||
|
.filter(s -> s.label.equals(label)) |
||||||
|
.findAny() |
||||||
|
.get(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,158 @@ |
|||||||
|
package de.superx.bianalysis; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.StringJoiner; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.models.DimensionAttribute; |
||||||
|
import de.superx.bianalysis.models.FactTable; |
||||||
|
import de.superx.bianalysis.models.Filter; |
||||||
|
import de.superx.bianalysis.models.InfoItem; |
||||||
|
import de.superx.bianalysis.service.DbMetaAdapter; |
||||||
|
import de.superx.jdbc.entity.Sachgebiet; |
||||||
|
import de.superx.rest.model.Column; |
||||||
|
import de.superx.rest.model.Result; |
||||||
|
import de.superx.rest.model.Row; |
||||||
|
|
||||||
|
public class ResultMerger { |
||||||
|
|
||||||
|
private DbMetaAdapter dbAdapter; |
||||||
|
|
||||||
|
public ResultMerger(DbMetaAdapter dbAdapter) { |
||||||
|
this.dbAdapter = dbAdapter; |
||||||
|
} |
||||||
|
|
||||||
|
public Result buildMergedReport(ReportDefinition definition, List<Result> reportResults) { |
||||||
|
|
||||||
|
Result result = new Result(); |
||||||
|
ReportMetadata metadata = new ReportMetadata(definition, null, dbAdapter); |
||||||
|
|
||||||
|
List<ColumnElement> columnElements = ColumnElementBuilder.buildColumnElements(metadata); |
||||||
|
List<Column> columns = ResultBuilder.buildColumns(metadata, columnElements); |
||||||
|
if(!metadata.topDimensionAttributes.isEmpty()) { |
||||||
|
ResultBuilder.setTotalColumnToColumns(columns, metadata); |
||||||
|
} |
||||||
|
|
||||||
|
// create list of merged rows
|
||||||
|
List<List<Row>> allRows = Result.getRowsFromReports(reportResults); |
||||||
|
List<Row> rows = mergeRows(allRows); |
||||||
|
|
||||||
|
if(metadata.hideEmptyColumns) { |
||||||
|
ResultBuilder.removeEmptyColumns(columns, rows); |
||||||
|
} |
||||||
|
|
||||||
|
ResultBuilder.setAttributesToReport(result, metadata, rows, columns); |
||||||
|
|
||||||
|
// override merge report specific attributes
|
||||||
|
result.setSubResults(reportResults); |
||||||
|
List<InfoItem> factTablesInfo = getFactTablesAsInfo(dbAdapter, definition.factTableIds); |
||||||
|
result.info.setSegmentCaption(factTablesInfo.stream().map(f -> f.caption).collect(Collectors.joining(", "))); |
||||||
|
result.info.setSachgebiete(getSachgebieteAsInfo(dbAdapter, definition.factTableIds)); |
||||||
|
result.info.setFacttables(factTablesInfo); |
||||||
|
|
||||||
|
for (Result r : reportResults) { |
||||||
|
if(r.info.error != null && !r.info.error.isBlank()) { |
||||||
|
result.info.setErrorMessage(r.info.error); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
private static List<String> getSachgebieteAsInfo(DbMetaAdapter dbAdapter, List<Identifier> factTableIds) { |
||||||
|
List<String> sachgebiete = new ArrayList<String>(); |
||||||
|
List<Integer> tids = new ArrayList<>(); |
||||||
|
for (Identifier id : factTableIds) { |
||||||
|
FactTable factTable = dbAdapter.getFactTable(id); |
||||||
|
Sachgebiet sachgebiet = dbAdapter.getSachgebietById(factTable.getSachgebiettid()); |
||||||
|
Integer tid = sachgebiet.tid; |
||||||
|
if(!tids.contains(tid)) { |
||||||
|
tids.add(tid); |
||||||
|
sachgebiete.add(sachgebiet.name.trim()); |
||||||
|
} |
||||||
|
} |
||||||
|
return sachgebiete; |
||||||
|
} |
||||||
|
|
||||||
|
private static List<InfoItem> getFactTablesAsInfo(DbMetaAdapter dbAdapter, List<Identifier> factTableIds) { |
||||||
|
List<InfoItem> facttables = new ArrayList<InfoItem>(); |
||||||
|
for (Identifier id : factTableIds) { |
||||||
|
FactTable factTable = dbAdapter.getFactTable(id); |
||||||
|
facttables.add(new InfoItem(factTable.getId().composedId, factTable.getCaption(), factTable.getDescription())); |
||||||
|
} |
||||||
|
return facttables; |
||||||
|
} |
||||||
|
|
||||||
|
public ReportDefinition createFactTableSpecificReportDefinition(ReportDefinition reportDefinition, |
||||||
|
Identifier factTableId) { |
||||||
|
ReportDefinition definition = new ReportDefinition(); |
||||||
|
definition.hideEmptyColumns = reportDefinition.hideEmptyColumns; |
||||||
|
definition.factTableIds.add(factTableId); |
||||||
|
for (int i = 0; i < reportDefinition.leftDimensionAttributeIds.size(); i++) { |
||||||
|
Identifier attr = reportDefinition.leftDimensionAttributeIds.get(i); |
||||||
|
Identifier checkedAttr = dbAdapter.checkIfFactTableHasDimensionAttribute(attr, factTableId); |
||||||
|
if(checkedAttr != null) { |
||||||
|
definition.leftDimensionAttributeIds.add(checkedAttr); |
||||||
|
} |
||||||
|
} |
||||||
|
for (int i = 0; i < reportDefinition.topDimensionAttributeIds.size(); i++) { |
||||||
|
Identifier attr = reportDefinition.topDimensionAttributeIds.get(i); |
||||||
|
Identifier checkedAttr = dbAdapter.checkIfFactTableHasDimensionAttribute(attr, factTableId); |
||||||
|
if(checkedAttr != null) { |
||||||
|
definition.topDimensionAttributeIds.add(checkedAttr); |
||||||
|
} |
||||||
|
} |
||||||
|
for (int i = 0; i < reportDefinition.measureIds.size(); i++) { |
||||||
|
Identifier measure = reportDefinition.measureIds.get(i); |
||||||
|
if(dbAdapter.checkIfFactTableHasMeasure(measure, factTableId)) { |
||||||
|
definition.measureIds.add(measure); |
||||||
|
} |
||||||
|
} |
||||||
|
for (int i = 0; i < reportDefinition.filters.size(); i++) { |
||||||
|
Filter filter = reportDefinition.filters.get(i); |
||||||
|
Identifier checkedAttr = dbAdapter.checkIfFactTableHasDimensionAttribute(filter.dimensionAttributeId, factTableId); |
||||||
|
if(checkedAttr != null) { |
||||||
|
Filter roleFilter = new Filter(filter); |
||||||
|
roleFilter.dimensionAttributeId = checkedAttr; |
||||||
|
definition.filters.add(roleFilter); |
||||||
|
} |
||||||
|
} |
||||||
|
return definition; |
||||||
|
} |
||||||
|
|
||||||
|
public static List<Row> mergeRows(List<List<Row>> rows) { |
||||||
|
List<Row> result = new ArrayList<>(); |
||||||
|
|
||||||
|
for (List<Row> inputRows : rows) { |
||||||
|
for (Row row : inputRows) { |
||||||
|
|
||||||
|
Row rowRepl = new Row(row.aggregated); |
||||||
|
rowRepl.rowKey = row.rowKey; |
||||||
|
|
||||||
|
for(String key : row.cells.keySet()){ |
||||||
|
String newKey = key; |
||||||
|
rowRepl.cells.put(newKey, row.cells.get(key)); |
||||||
|
} |
||||||
|
|
||||||
|
if(!result.contains(rowRepl)) { |
||||||
|
result.add(rowRepl); |
||||||
|
} else { |
||||||
|
// row with the same rowkey exists -> add only cells
|
||||||
|
Row found = result.get(result.indexOf(rowRepl)); |
||||||
|
for(String key : rowRepl.cells.keySet()){ |
||||||
|
if(!found.cells.containsKey(key)) { |
||||||
|
found.cells.put(key, rowRepl.cells.get(key)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,82 @@ |
|||||||
|
package de.superx.bianalysis; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
|
||||||
|
|
||||||
|
import org.springframework.data.annotation.Id; |
||||||
|
import org.springframework.data.annotation.Transient; |
||||||
|
import org.springframework.data.relational.core.mapping.Column; |
||||||
|
import org.springframework.data.relational.core.mapping.Table; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty; |
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException; |
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import com.fasterxml.jackson.databind.ObjectWriter; |
||||||
|
import com.fasterxml.jackson.databind.json.JsonMapper; |
||||||
|
|
||||||
|
import de.superx.rest.model.Result; |
||||||
|
import de.superx.rest.model.TreeNode; |
||||||
|
|
||||||
|
@Table(value ="metadata\".\"rw_report_definitions") |
||||||
|
public class StoredReport { |
||||||
|
|
||||||
|
@Id |
||||||
|
public int id; |
||||||
|
|
||||||
|
public String name; |
||||||
|
|
||||||
|
public String description; |
||||||
|
|
||||||
|
public String definition; |
||||||
|
|
||||||
|
@Column(value = "show_total_column") |
||||||
|
@JsonProperty("show_total_column") |
||||||
|
public int showTotalColumn; |
||||||
|
|
||||||
|
@Transient |
||||||
|
public Boolean isReadOnly = Boolean.FALSE; |
||||||
|
|
||||||
|
@Transient |
||||||
|
public ReportDefinition reportDefinition; |
||||||
|
|
||||||
|
@Transient |
||||||
|
public Result exportedResult; |
||||||
|
|
||||||
|
@Transient |
||||||
|
public ArrayList<TreeNode> hierarchy; |
||||||
|
|
||||||
|
public StoredReport(String name, ReportDefinition reportDefinition, Result exportedResult) { |
||||||
|
super(); |
||||||
|
this.name = name; |
||||||
|
this.reportDefinition = reportDefinition; |
||||||
|
this.exportedResult = exportedResult; |
||||||
|
} |
||||||
|
|
||||||
|
public StoredReport() { |
||||||
|
super(); |
||||||
|
} |
||||||
|
|
||||||
|
public static void setReportDefinitionJson(StoredReport report) { |
||||||
|
ObjectWriter ow = new ObjectMapper().writer(); |
||||||
|
String reportDefinitionJson = null; |
||||||
|
try { |
||||||
|
reportDefinitionJson = ow.writeValueAsString(report.reportDefinition); |
||||||
|
} catch (JsonProcessingException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
report.definition = reportDefinitionJson; |
||||||
|
} |
||||||
|
|
||||||
|
public static void setReportDefinitionFromJson(StoredReport report) { |
||||||
|
ObjectMapper mapper = JsonMapper.builder().findAndAddModules().build(); |
||||||
|
ReportDefinition reportDefinition = null; |
||||||
|
try { |
||||||
|
reportDefinition = mapper.readValue(report.definition, ReportDefinition.class); |
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
report.reportDefinition = reportDefinition; |
||||||
|
report.definition = ""; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,302 @@ |
|||||||
|
package de.superx.bianalysis.bin; |
||||||
|
|
||||||
|
import java.io.BufferedReader; |
||||||
|
import java.io.File; |
||||||
|
import java.io.FileReader; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.PrintWriter; |
||||||
|
import java.nio.file.Path; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.apache.commons.cli.CommandLine; |
||||||
|
import org.apache.commons.cli.CommandLineParser; |
||||||
|
import org.apache.commons.cli.GnuParser; |
||||||
|
import org.apache.commons.cli.HelpFormatter; |
||||||
|
import org.apache.commons.cli.Option; |
||||||
|
import org.apache.commons.cli.OptionBuilder; |
||||||
|
import org.apache.commons.cli.Options; |
||||||
|
import org.apache.commons.cli.ParseException; |
||||||
|
import org.apache.log4j.BasicConfigurator; |
||||||
|
import org.apache.log4j.Level; |
||||||
|
import org.apache.log4j.Logger; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.util.DefaultIndenter; |
||||||
|
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; |
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.metadata.MetaImport; |
||||||
|
import de.superx.bianalysis.metadata.MetaJson; |
||||||
|
import de.superx.bianalysis.metadata.MetadataImporter; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaDimension; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaDimensionAttribute; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaFact; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaMeasure; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaObject; |
||||||
|
import de.superx.bianalysis.metadata.models.yml.MetaYml; |
||||||
|
import de.superx.servlet.SuperXManager; |
||||||
|
import de.superx.util.PathAndFileUtils; |
||||||
|
|
||||||
|
public class BiAnalysisCLI { |
||||||
|
|
||||||
|
private static final String DEFAULT_RELEASE_BRANCH = "2025_12"; |
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException { |
||||||
|
Options options = createOptions(); |
||||||
|
CommandLine parsedArgs = readArgs(args, options); |
||||||
|
if(parsedArgs.hasOption("-i")) { |
||||||
|
addMissingIdsInMetadataDir(parsedArgs); |
||||||
|
} else if(parsedArgs.hasOption("-m")) { |
||||||
|
convertJsonFilesToSql(); |
||||||
|
} else if(parsedArgs.hasOption("-y")) { |
||||||
|
generateYmlForJsonFile(parsedArgs); |
||||||
|
} else if(parsedArgs.hasOption("-d")) { |
||||||
|
generateWikiMarkdown(parsedArgs); |
||||||
|
} else { |
||||||
|
printHelp(options); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void generateWikiMarkdown(CommandLine parsedArgs) throws IOException { |
||||||
|
SuperXManager.setWEB_INFPfad(PathAndFileUtils.getWebinfPath()); |
||||||
|
String facttable = parsedArgs.getOptionValue("d"); |
||||||
|
String filePath = PathAndFileUtils.getReportGeneratorDir("hisinone"); |
||||||
|
String ymlPath = PathAndFileUtils.getDbtTransformDirectory("hisinone") + File.separator + "docs_and_tests"; |
||||||
|
MetadataImporter importer = new MetadataImporter(ymlPath); |
||||||
|
Logger.getLogger(MetadataImporter.class).setLevel(Level.ERROR); |
||||||
|
importer.deserializeMetadataFromJsonFiles(filePath); |
||||||
|
|
||||||
|
String docDirectory = PathAndFileUtils.getModulePath("biad"); |
||||||
|
docDirectory = String.join(File.separator, docDirectory, "conf", "his1", "edustore_doc"); |
||||||
|
|
||||||
|
for(MetaFact fact : importer.getAllFactTables()) { |
||||||
|
if("all".equals(facttable) || fact.getFacttable().equals(facttable)) { |
||||||
|
PrintWriter writer = new PrintWriter(docDirectory + File.separator + fact.getFacttable() + "_mediawiki.txt", "UTF-8"); |
||||||
|
writer.println("===Kennzahlen ==="); |
||||||
|
writer.println(";Kennzahlen " + fact.getCaption()); |
||||||
|
writer.println(); |
||||||
|
writer.println("{| class=\"wikitable\"\n ! Kennzahl !! Beschreibung"); |
||||||
|
writer.println("|-"); |
||||||
|
for(int i = 0; i < fact.getMeasures().size(); i++) { |
||||||
|
MetaMeasure m = fact.getMeasures().get(i); |
||||||
|
writer.println("| "+m.getCaption()); |
||||||
|
writer.println("| "+m.getDescription()); |
||||||
|
if(i != fact.getMeasures().size() - 1) { |
||||||
|
writer.println("|-"); |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
writer.println("|-\n|}"); |
||||||
|
writer.println(); |
||||||
|
writer.println(); |
||||||
|
|
||||||
|
writer.println("===Dimension ==="); |
||||||
|
writer.println(";"+fact.getCaption()); |
||||||
|
writer.println(":"+fact.getDescription()); |
||||||
|
writer.println(); |
||||||
|
writer.println("'''Dimension und Dimensionsattribut'''"); |
||||||
|
writer.println(); |
||||||
|
for(MetaDimension d : fact.getDimensions()) { |
||||||
|
|
||||||
|
String dimCaption = d.getCaption(); |
||||||
|
if((dimCaption == null || dimCaption.isBlank()) && d.getConformedDimension() != null) { |
||||||
|
dimCaption = d.getConformedDimension().getCaption(); |
||||||
|
} |
||||||
|
|
||||||
|
String dimDescription = d.getDescription(); |
||||||
|
if((dimDescription == null || dimDescription.isBlank()) && d.getConformedDimension() != null) { |
||||||
|
dimDescription = d.getConformedDimension().getDescription(); |
||||||
|
} |
||||||
|
|
||||||
|
writer.println(";"+dimCaption); |
||||||
|
writer.println(":"+dimDescription); |
||||||
|
|
||||||
|
List<MetaDimensionAttribute> attributes = d.getAttributes(); |
||||||
|
if(attributes == null || attributes.size() == 0) { |
||||||
|
attributes = d.getConformedDimension().getAttributes(); |
||||||
|
} |
||||||
|
|
||||||
|
for(MetaDimensionAttribute a : attributes) { |
||||||
|
String caption = a.getCaption() == null ? a.getConfDimAttrRef().getCaption() : a.getCaption(); |
||||||
|
writer.println("*"+caption); |
||||||
|
try { |
||||||
|
String desc = a.getDescription() == null ? a.getConfDimAttrRef().getDescription() : a.getDescription(); |
||||||
|
if(!desc.equals("null")) { |
||||||
|
writer.println("*:"+desc); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
// TODO: handle exception
|
||||||
|
} |
||||||
|
} |
||||||
|
writer.println(); |
||||||
|
} |
||||||
|
writer.close(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private static void generateYmlForJsonFile(CommandLine parsedArgs) { |
||||||
|
String file = parsedArgs.getOptionValue("y"); |
||||||
|
if(file == null || !new File(file).exists()) { |
||||||
|
throw new RuntimeException("File " + file +" is not valid."); |
||||||
|
} |
||||||
|
MetadataImporter importer = new MetadataImporter(); |
||||||
|
Logger.getLogger(MetadataImporter.class).setLevel(Level.ERROR); |
||||||
|
importer.setShouldReadYMLDoc(false); |
||||||
|
importer.deserializeMetadataFromJsonFiles(file); |
||||||
|
MetaImport metaImport = importer.getMetaImports().get(0); |
||||||
|
MetaYml yml = importer.createYMLFileForMetaJson(metaImport); |
||||||
|
System.out.println(MetadataImporter.writeYmlToString(yml)); |
||||||
|
} |
||||||
|
|
||||||
|
private static void addMissingIdsInMetadataDir(CommandLine parsedArgs) { |
||||||
|
String[] files = parsedArgs.getOptionValues("i"); |
||||||
|
BasicConfigurator.configure(); // initializes console logging to stdout
|
||||||
|
try { |
||||||
|
MetadataImporter metaImporter = new MetadataImporter(); |
||||||
|
metaImporter.setShouldReadYMLDoc(false); |
||||||
|
metaImporter.deserializeMetadataFromJsonFiles(files); |
||||||
|
for (MetaJson meta : metaImporter.getMetaJsons()) { |
||||||
|
List<Identifier> allIds = meta.getIds(); |
||||||
|
boolean isFileUpdateNecessary = false; |
||||||
|
for (MetaObject obj : meta.getMetaObjects()) { |
||||||
|
if(obj.getId() == null) { |
||||||
|
Identifier id = Identifier.getNewIdentifierValue(allIds, obj.getNamespace()); |
||||||
|
obj.setId(id); |
||||||
|
allIds.add(id); |
||||||
|
isFileUpdateNecessary = true; |
||||||
|
} |
||||||
|
if(obj.getDefaultRelease() == null) { |
||||||
|
obj.setDefaultRelease(DEFAULT_RELEASE_BRANCH); |
||||||
|
isFileUpdateNecessary = true; |
||||||
|
} |
||||||
|
} |
||||||
|
if(isFileUpdateNecessary) { |
||||||
|
writeMetaImportToFile(meta); |
||||||
|
Logger.getRootLogger().info("Updated file " + meta.getFile().getPath()); |
||||||
|
} |
||||||
|
} |
||||||
|
if (!metaImporter.errorMessages.isEmpty()) { |
||||||
|
System.out.println(metaImporter.getPrintableErrorMessages()); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void convertJsonFilesToSql() { |
||||||
|
SuperXManager.setWEB_INFPfad(PathAndFileUtils.getWebinfPath()); |
||||||
|
String filePath = PathAndFileUtils.getReportGeneratorDir("hisinone"); |
||||||
|
String ymlPath = PathAndFileUtils.getDbtTransformDirectory("hisinone"); |
||||||
|
|
||||||
|
String out = |
||||||
|
"DROP TABLE IF EXISTS metadata.facttable; " + |
||||||
|
"DROP TABLE IF EXISTS metadata.measure; " + |
||||||
|
"DROP TABLE IF EXISTS metadata.measure_filter; " + |
||||||
|
"DROP TABLE IF EXISTS metadata.dimension; " + |
||||||
|
"DROP TABLE IF EXISTS metadata.dimension_attribute; "; |
||||||
|
|
||||||
|
Path schemaSqlDir = Path.of("superx", "WEB-INF", "conf", "edustore", "db", "install", "schluesseltabellen"); |
||||||
|
|
||||||
|
out += readLinesWithNewline(new File(schemaSqlDir.toString() + File.separator + "biad_create_meta_tables.sql")); |
||||||
|
out += readLinesWithNewline(new File(schemaSqlDir.toString() + File.separator + "biad_alter_meta_tables.sql")); |
||||||
|
out += readLinesWithNewline(new File(schemaSqlDir.toString() + File.separator + "biad_metadaten_fuellen.sql")); |
||||||
|
|
||||||
|
Logger.getLogger(MetadataImporter.class).setLevel(Level.ERROR); |
||||||
|
MetadataImporter importer = new MetadataImporter(ymlPath); |
||||||
|
importer.deserializeMetadataFromJsonFiles(filePath); |
||||||
|
out += String.join("\n", importer.getAllUpsertStrings(false)); |
||||||
|
|
||||||
|
if(!importer.errorMessages.isEmpty()) { |
||||||
|
System.out.println(importer.getPrintableErrorMessages()); |
||||||
|
System.exit(1); |
||||||
|
} else { |
||||||
|
System.out.println(out); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private static CommandLine readArgs(String[] args, Options options) { |
||||||
|
CommandLineParser parser = new GnuParser(); |
||||||
|
try { |
||||||
|
return parser.parse(options, args, false); |
||||||
|
} catch (ParseException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
private static void printHelp(Options options) { |
||||||
|
HelpFormatter help = new HelpFormatter(); |
||||||
|
help.setOptionComparator(null); |
||||||
|
help.setWidth(200); |
||||||
|
help.printHelp("This tool streamlines common tasks during development for the BIAnalysis.", options); |
||||||
|
} |
||||||
|
|
||||||
|
private static Options createOptions() { |
||||||
|
Options options = new Options(); |
||||||
|
|
||||||
|
OptionBuilder.withDescription("convert metadata directory to sql"); |
||||||
|
OptionBuilder.withLongOpt("convert-metadata"); |
||||||
|
Option outMeta = OptionBuilder.create("m"); |
||||||
|
|
||||||
|
OptionBuilder.withDescription("generate yml documentation for json file"); |
||||||
|
OptionBuilder.withLongOpt("generate-yml"); |
||||||
|
OptionBuilder.withArgName("json-file"); |
||||||
|
OptionBuilder.hasArg(true); |
||||||
|
Option generateYml = OptionBuilder.create("y"); |
||||||
|
|
||||||
|
|
||||||
|
OptionBuilder.withDescription("generate wiki documentation for measures and dimensions"); |
||||||
|
OptionBuilder.withLongOpt("generate-doc"); |
||||||
|
OptionBuilder.withArgName("facttable"); |
||||||
|
OptionBuilder.hasArg(true); |
||||||
|
Option generateDoc = OptionBuilder.create("d"); |
||||||
|
|
||||||
|
OptionBuilder.withLongOpt("add-ids"); |
||||||
|
OptionBuilder.withDescription("add missing ids to json files"); |
||||||
|
OptionBuilder.withArgName("directories"); |
||||||
|
OptionBuilder.hasArgs(); |
||||||
|
Option updateIds = OptionBuilder.create("i"); |
||||||
|
|
||||||
|
options.addOption(updateIds); |
||||||
|
options.addOption(generateYml); |
||||||
|
options.addOption(generateDoc); |
||||||
|
options.addOption(outMeta); |
||||||
|
options.addOption(new Option("h", "help", false, "get help")); |
||||||
|
|
||||||
|
return options; |
||||||
|
} |
||||||
|
|
||||||
|
public static void writeMetaImportToFile(MetaJson meta) { |
||||||
|
ObjectMapper mapper = new ObjectMapper(); |
||||||
|
DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(" ", DefaultIndenter.SYS_LF); |
||||||
|
DefaultPrettyPrinter printer = new DefaultPrettyPrinter(); |
||||||
|
printer.indentObjectsWith(indenter); |
||||||
|
printer.indentArraysWith(indenter); |
||||||
|
try { |
||||||
|
mapper.writer(printer).writeValue(meta.getFile(), meta); |
||||||
|
} catch (Exception e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static String readLinesWithNewline(File file) { |
||||||
|
String result = ""; |
||||||
|
try (BufferedReader br = new BufferedReader(new FileReader(file))) { |
||||||
|
String line; |
||||||
|
while ((line = br.readLine()) != null) { |
||||||
|
result += line; |
||||||
|
} |
||||||
|
} catch (IOException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
return result+"\n"; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,74 @@ |
|||||||
|
package de.superx.bianalysis.metadata; |
||||||
|
|
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
||||||
|
|
||||||
|
@JsonSerialize(using = IdentifierSerializer.class) |
||||||
|
public class Identifier { |
||||||
|
|
||||||
|
private static final String ID_SEPARATOR = ":"; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public Integer value; |
||||||
|
@JsonIgnore |
||||||
|
public String namespace; |
||||||
|
|
||||||
|
public String composedId; |
||||||
|
|
||||||
|
public Identifier(String composedId) { |
||||||
|
this.composedId = composedId; |
||||||
|
String[] result = composedId.split(ID_SEPARATOR); |
||||||
|
this.namespace = result[0]; |
||||||
|
this.value = Integer.valueOf(result[1]); |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier(Identifier id) { |
||||||
|
this.value = id.value; |
||||||
|
this.namespace = id.namespace; |
||||||
|
this.composedId = id.composedId; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public static Identifier getNewIdentifierValue(List<Identifier> list, String namespace) { |
||||||
|
List<Integer> values = list |
||||||
|
.stream() |
||||||
|
.filter(i->i.value!=null) |
||||||
|
.map(i->i.value) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
Integer value; |
||||||
|
if(values.isEmpty()) { |
||||||
|
value = Integer.valueOf(1); |
||||||
|
} else { |
||||||
|
value = Integer.valueOf(Collections.max(values).intValue() + 1); |
||||||
|
} |
||||||
|
return new Identifier(namespace + ID_SEPARATOR + value); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
@JsonIgnore |
||||||
|
public boolean equals(Object obj) { |
||||||
|
if(obj == null || !(obj instanceof Identifier)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
Identifier id = (Identifier) obj; |
||||||
|
return id.composedId.equals(this.composedId); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
@JsonIgnore |
||||||
|
public int hashCode() { |
||||||
|
return this.value.hashCode() + this.namespace.hashCode(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String toString() { |
||||||
|
return composedId; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,27 @@ |
|||||||
|
package de.superx.bianalysis.metadata; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator; |
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException; |
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider; |
||||||
|
import com.fasterxml.jackson.databind.ser.std.StdSerializer; |
||||||
|
|
||||||
|
public class IdentifierSerializer extends StdSerializer<Identifier>{ |
||||||
|
|
||||||
|
public IdentifierSerializer() { |
||||||
|
this(null); |
||||||
|
} |
||||||
|
|
||||||
|
public IdentifierSerializer(Class<Identifier> t) { |
||||||
|
super(t); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void serialize( |
||||||
|
Identifier id, JsonGenerator jgen, SerializerProvider provider) |
||||||
|
throws IOException, JsonProcessingException { |
||||||
|
jgen.writeRawValue('"'+id.composedId+'"'); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,148 @@ |
|||||||
|
package de.superx.bianalysis.metadata; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
import org.apache.log4j.Logger; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||||
|
|
||||||
|
import de.superx.bianalysis.FaultyMetadataException; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaDimension; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaDimensionAttribute; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaFact; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaMeasure; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaMeasureFilter; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaObject; |
||||||
|
|
||||||
|
public class MetaImport extends MetaJson { |
||||||
|
|
||||||
|
public List<MetaFact> facts; |
||||||
|
|
||||||
|
private static Logger log = Logger.getLogger(MetaImport.class); |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private Map<String, MetaDimensionAttribute> keysForMeasureFilter = new HashMap<>(); |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public List<MetaDimension> conformedDimensions; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public void setConformedDimensions(List<MetaDimension> conformedDimensions){ |
||||||
|
this.conformedDimensions = conformedDimensions; |
||||||
|
if(this.conformedDimensions != null) { |
||||||
|
for (MetaDimension dim : this.conformedDimensions) { |
||||||
|
for (MetaDimensionAttribute attr : dim.getAttributes()) { |
||||||
|
attr.setDimension(dim); |
||||||
|
keysForMeasureFilter.put(dim.getDimension()+"."+attr.getDimColumn(), attr); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
@Override |
||||||
|
public void init() { |
||||||
|
this.allMetaObj = new ArrayList<MetaObject>(); |
||||||
|
for (MetaFact fact : this.facts) { |
||||||
|
allMetaObj.add(fact); |
||||||
|
for (MetaDimension dim : fact.getDimensions()) { |
||||||
|
allMetaObj.add(dim); |
||||||
|
if(dim.getRefTo() != null && !dim.getRefTo().isEmpty()) { |
||||||
|
MetaDimension conformedDim = findByRef(dim); |
||||||
|
dim.setConformedDimension(conformedDim); |
||||||
|
} |
||||||
|
for (MetaDimensionAttribute attr : dim.getAttributes()) { |
||||||
|
allMetaObj.add(attr); |
||||||
|
if(attr.getRefTo() != null && !attr.getRefTo().isEmpty()) { |
||||||
|
attr.setConformedDimensionAttribute(findByRefAttr(dim.getConformedDimension().getDimension(), attr)); |
||||||
|
} |
||||||
|
keysForMeasureFilter.put(dim.getDimension()+"."+attr.getDimColumn(), attr); |
||||||
|
} |
||||||
|
} |
||||||
|
if(fact.getMeasures() != null) { |
||||||
|
for (MetaMeasure measure : fact.getMeasures()) { |
||||||
|
allMetaObj.add(measure); |
||||||
|
MetaMeasureFilter filter = measure.getFilter(); |
||||||
|
if(filter != null) { |
||||||
|
if(filter.getDimensionRef() != null && !filter.getDimensionRef().isBlank()) { |
||||||
|
MetaDimensionAttribute attr = keysForMeasureFilter.get(filter.getDimensionRef()); |
||||||
|
if(attr == null) { |
||||||
|
throw new FaultyMetadataException("Could not resolve dimensionRef '" + filter.getDimensionRef() + |
||||||
|
"' (" + file.getName() + " -> " + fact.getFacttable() + ")"); |
||||||
|
} |
||||||
|
filter.setAttribute(attr); |
||||||
|
allMetaObj.add(filter); |
||||||
|
} else if(filter.getFactColumnRef() != null && !filter.getFactColumnRef().isBlank()) { |
||||||
|
allMetaObj.add(filter); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private MetaDimensionAttribute findByRefAttr(String dimensionTable, MetaDimensionAttribute attribute) { |
||||||
|
String attributeColumn = attribute.getRefTo(); |
||||||
|
MetaDimensionAttribute confAttr = null; |
||||||
|
for (MetaDimension confDim : this.conformedDimensions) { |
||||||
|
if(!confDim.getDimension().equals(dimensionTable)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
for (MetaDimensionAttribute attr : confDim.getAttributes()) { |
||||||
|
if(attr.getDimColumn().equals(attributeColumn)) { |
||||||
|
confAttr = attr; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if(confAttr == null) { |
||||||
|
throw new FaultyMetadataException( |
||||||
|
"Could not resolve attribute reference '" + attributeColumn + "' (" |
||||||
|
+ file.getName() + " -> " |
||||||
|
+ attribute.getDimension().getFact().getFacttable() + " -> " |
||||||
|
+ attribute.getDimension().getRefTo() + ")" |
||||||
|
); |
||||||
|
} |
||||||
|
return confAttr; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private MetaDimension findByRef(MetaDimension dim) { |
||||||
|
String refTo = dim.getRefTo(); |
||||||
|
MetaDimension resolvedRefTo = null; |
||||||
|
for (MetaDimension dimConf : this.conformedDimensions) { |
||||||
|
if (dimConf.getDimension() == null) { |
||||||
|
log.error("Missing dimension attribute for " + dimConf.getCaption()); |
||||||
|
continue; |
||||||
|
} |
||||||
|
if (dimConf.getDimension().equals(refTo)) { |
||||||
|
resolvedRefTo = dimConf; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (resolvedRefTo == null) { |
||||||
|
throw new FaultyMetadataException("Could not resolve dimension reference '" + refTo + "' (" + file.getName() + " -> " + dim.getFact().getFacttable() + ")"); |
||||||
|
} |
||||||
|
return resolvedRefTo; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public List<MetaDimension> getDimensionsWithoutRefTo() { |
||||||
|
List<MetaDimension> dims = new ArrayList<>(); |
||||||
|
for (MetaFact fact : facts) { |
||||||
|
for (MetaDimension dim : fact.getDimensions()) { |
||||||
|
if(dim.getRefTo() == null) { |
||||||
|
dims.add(dim); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return dims; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,38 @@ |
|||||||
|
package de.superx.bianalysis.metadata; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaDimension; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaDimensionAttribute; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaMeasure; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaObject; |
||||||
|
|
||||||
|
public class MetaImportConformedDimensions extends MetaJson { |
||||||
|
|
||||||
|
@JsonProperty("conformed_dimensions") |
||||||
|
public List<MetaDimension> conformedDimensions; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void init() { |
||||||
|
this.allMetaObj = new ArrayList<MetaObject>(); |
||||||
|
for (MetaDimension metaDimension : this.conformedDimensions) { |
||||||
|
metaDimension.setConformed(true); |
||||||
|
this.allMetaObj.add(metaDimension); |
||||||
|
for (MetaDimensionAttribute attr : metaDimension.getAttributes()) { |
||||||
|
attr.setDimension(metaDimension); |
||||||
|
this.allMetaObj.add(attr); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
for (MetaObject metaObject : allMetaObj) { |
||||||
|
metaObject.setNamespace(this.namespace); |
||||||
|
if(metaObject.getId() != null) { |
||||||
|
metaObject.getId().namespace = this.namespace; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,58 @@ |
|||||||
|
package de.superx.bianalysis.metadata; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.util.List; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaObject; |
||||||
|
|
||||||
|
public abstract class MetaJson { |
||||||
|
|
||||||
|
public String namespace; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
protected File file; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
protected List<MetaObject> allMetaObj; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public abstract void init(); |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public File getFile() { |
||||||
|
return this.file; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public List<MetaObject> getMetaObjects() { |
||||||
|
return this.allMetaObj; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public void setFile(File file) { |
||||||
|
this.file = file; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public List<Identifier> getIds() { |
||||||
|
return this.getMetaObjects() |
||||||
|
.stream() |
||||||
|
.map(o -> o.getId()) |
||||||
|
.filter(i -> i != null && i.composedId != null) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public void setNamespaceToMetaObjects() { |
||||||
|
for (MetaObject metaObject : allMetaObj) { |
||||||
|
metaObject.setNamespace(this.namespace); |
||||||
|
if(metaObject.getId() != null) { |
||||||
|
metaObject.getId().namespace = this.namespace; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,593 @@ |
|||||||
|
package de.superx.bianalysis.metadata; |
||||||
|
|
||||||
|
import java.io.BufferedReader; |
||||||
|
import java.io.File; |
||||||
|
import java.io.FileReader; |
||||||
|
import java.io.FilenameFilter; |
||||||
|
import java.sql.Connection; |
||||||
|
import java.sql.ResultSet; |
||||||
|
import java.sql.Statement; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Optional; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
import javax.sql.DataSource; |
||||||
|
|
||||||
|
import org.apache.commons.lang.exception.ExceptionUtils; |
||||||
|
import org.apache.log4j.Logger; |
||||||
|
import org.springframework.jdbc.core.JdbcTemplate; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.util.DefaultIndenter; |
||||||
|
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; |
||||||
|
import com.fasterxml.jackson.databind.JsonMappingException; |
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import com.fasterxml.jackson.databind.json.JsonMapper; |
||||||
|
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; |
||||||
|
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; |
||||||
|
|
||||||
|
import de.superx.bianalysis.StoredReport; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaDimension; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaDimensionAttribute; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaFact; |
||||||
|
import de.superx.bianalysis.metadata.models.json.MetaObject; |
||||||
|
import de.superx.bianalysis.metadata.models.yml.MetaYml; |
||||||
|
import de.superx.bianalysis.metadata.models.yml.MetaYmlModel; |
||||||
|
import de.superx.bianalysis.metadata.models.yml.MetaYmlModelColumns; |
||||||
|
import de.superx.util.PathAndFileUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Provides functionality for updating the tables in the metadata schema. |
||||||
|
* The tables are updated by reading the metadata information from various |
||||||
|
* metaimport.json files and transforming that information into executable sql. |
||||||
|
* |
||||||
|
* The BIAnalysis Tool uses the tables to read information about the different |
||||||
|
* meta objects and more importantly to figure out their relationships, e.g. what |
||||||
|
* dimension is part of which facttable or which attribute belongs to which |
||||||
|
* dimension. |
||||||
|
* |
||||||
|
* To learn more about the metadata concept for the BIAnalysis Tool see: |
||||||
|
* doc\bi_analysis\report_wizard\metadaten.adoc |
||||||
|
* |
||||||
|
*/ |
||||||
|
public final class MetadataImporter { |
||||||
|
|
||||||
|
/** |
||||||
|
* Each file containing metadata information must have the following file suffix. |
||||||
|
*/ |
||||||
|
private static final String METAIMPORT_FILE_SUFFIX = "_metaimport.json"; |
||||||
|
|
||||||
|
protected static final String CONFORMED_DIMENSIONS_FILE_SUFFIX = "conformed_dimensions" + METAIMPORT_FILE_SUFFIX; |
||||||
|
|
||||||
|
/** |
||||||
|
* Holds all Metaimport objects with which this instance was initalized. |
||||||
|
* (One MetaImport object corresponds to exactly one deserialized json file) |
||||||
|
*/ |
||||||
|
private List<MetaJson> metaImports = new ArrayList<>(); |
||||||
|
|
||||||
|
public List<String> errorMessages = new ArrayList<>(); |
||||||
|
|
||||||
|
/** |
||||||
|
* SQL String for deleting from all metadata tables except 'custom' releases. |
||||||
|
*/ |
||||||
|
public static final String TRUNCATE_METADATA_SQL = |
||||||
|
"DELETE FROM metadata.facttable WHERE default_release != 'custom' or default_release is null; " + |
||||||
|
"DELETE FROM metadata.measure WHERE default_release != 'custom' or default_release is null; " + |
||||||
|
"DELETE FROM metadata.measure_filter WHERE default_release != 'custom' or default_release is null; " + |
||||||
|
"DELETE FROM metadata.dimension WHERE default_release != 'custom' or default_release is null; " + |
||||||
|
"DELETE FROM metadata.dimension_attribute WHERE default_release != 'custom' or default_release is null; "; |
||||||
|
|
||||||
|
private static Logger log = Logger.getLogger(MetadataImporter.class); |
||||||
|
|
||||||
|
private boolean shouldReadYMLDoc = true; |
||||||
|
|
||||||
|
private String ymlDir = ""; |
||||||
|
|
||||||
|
public MetadataImporter() {} |
||||||
|
|
||||||
|
public MetadataImporter(String ymlDir) {this.ymlDir = ymlDir;} |
||||||
|
|
||||||
|
/** |
||||||
|
* Calling this method initalizes the MetadataImporter by deserializing all unique meta objects |
||||||
|
* from the provided json files. Faulty json files are ignored. |
||||||
|
* |
||||||
|
* @param paths Path(s) to the metadata file(s). A path can point to a directory or a file. |
||||||
|
* Multiple paths and/or directories can be provided. |
||||||
|
*/ |
||||||
|
public void deserializeMetadataFromJsonFiles(String... paths) { |
||||||
|
|
||||||
|
ObjectMapper mapper = JsonMapper.builder().findAndAddModules().build(); |
||||||
|
List<MetaImportConformedDimensions> conformedDimension = new ArrayList<>(); |
||||||
|
List<MetaDimension> conformedDims = new ArrayList<>(); |
||||||
|
|
||||||
|
for (String path : paths) { |
||||||
|
List<File> metaFiles = readMetaImportFiles(path); |
||||||
|
for (File file : metaFiles) { |
||||||
|
MetaJson meta = null; |
||||||
|
try{ |
||||||
|
if(file.getName().endsWith(CONFORMED_DIMENSIONS_FILE_SUFFIX)) { |
||||||
|
meta = mapper.readValue(file, MetaImportConformedDimensions.class); |
||||||
|
conformedDimension.add((MetaImportConformedDimensions) meta); |
||||||
|
} else { |
||||||
|
meta = mapper.readValue(file, MetaImport.class); |
||||||
|
conformedDims.addAll(((MetaImport) meta).getDimensionsWithoutRefTo()); |
||||||
|
} |
||||||
|
|
||||||
|
} catch(JsonMappingException e) { |
||||||
|
String message = "Could not deserialize metadata from file: " + file.getName() + "\n"; |
||||||
|
message += e.getMessage(); |
||||||
|
errorMessages.add(message); |
||||||
|
} catch(Exception e) { |
||||||
|
errorMessages.add(ExceptionUtils.getFullStackTrace(e)); |
||||||
|
} |
||||||
|
if(meta != null) { |
||||||
|
log.info("Read metadata from file: " + file.getName()); |
||||||
|
meta.setFile(file); |
||||||
|
metaImports.add(meta); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// gather all conformed dimensions
|
||||||
|
List<MetaDimension> confDims = new ArrayList<>(); |
||||||
|
confDims.addAll(conformedDims); |
||||||
|
for (MetaImportConformedDimensions conf : conformedDimension) { |
||||||
|
confDims.addAll(conf.conformedDimensions); |
||||||
|
} |
||||||
|
|
||||||
|
// resolve conformed references ('ref_to' attributes)
|
||||||
|
for (MetaJson metaJson : metaImports) { |
||||||
|
if (conformedDimension.size() > 0 && metaJson instanceof MetaImport) { |
||||||
|
((MetaImport) metaJson).setConformedDimensions(confDims); |
||||||
|
} |
||||||
|
try { |
||||||
|
metaJson.init(); |
||||||
|
metaJson.setNamespaceToMetaObjects(); |
||||||
|
} catch (Exception e) { |
||||||
|
errorMessages.add(ExceptionUtils.getFullStackTrace(e)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if(shouldReadYMLDoc) { |
||||||
|
addDescriptionsFromYMLFiles(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public List<String> readStoredReports() { |
||||||
|
List<String> result = new ArrayList<>(); |
||||||
|
try { |
||||||
|
String dir = PathAndFileUtils.getStoredReportDir("hisinone"); |
||||||
|
File[] files = new File(dir).listFiles(); |
||||||
|
if(files == null) { |
||||||
|
return result; |
||||||
|
} |
||||||
|
for (File file : files) { |
||||||
|
try { |
||||||
|
ObjectMapper mapper = JsonMapper.builder().findAndAddModules().build(); |
||||||
|
StoredReport report = mapper.readValue(file, StoredReport.class); |
||||||
|
UpsertStringBuilder builder = new UpsertStringBuilder() |
||||||
|
.forTable("metadata", "rw_report_definitions") |
||||||
|
.withIntCol("id", Integer.valueOf(report.id)) |
||||||
|
.withStringCol("name", report.name) |
||||||
|
.withStringCol("definition", report.definition) |
||||||
|
.withIntCol("show_total_column", Integer.valueOf(report.showTotalColumn)); |
||||||
|
result.add(builder.build(true)); |
||||||
|
} catch (JsonMappingException e) { |
||||||
|
String message = "Could not deserialize stored report from file: " + file.getName() + "\n"; |
||||||
|
message += e.getMessage(); |
||||||
|
errorMessages.add(message); |
||||||
|
} |
||||||
|
} |
||||||
|
// After inserting the stored reports with a fixed id we need to re-sync the
|
||||||
|
// id column of the rw_report_definitions table
|
||||||
|
if(result.size() != 0) { |
||||||
|
result.add("SELECT setval(pg_get_serial_sequence('metadata.rw_report_definitions', 'id')," |
||||||
|
+ "(SELECT max(id) FROM metadata.rw_report_definitions ));"); |
||||||
|
} |
||||||
|
} catch(Exception e) { |
||||||
|
errorMessages.add("Unable to read stored report:\n"); |
||||||
|
errorMessages.add(ExceptionUtils.getFullStackTrace(e)); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public void addDescriptionsFromYMLFiles() { |
||||||
|
String dir = ymlDir; |
||||||
|
if(ymlDir == null || ymlDir.isBlank()) { |
||||||
|
dir = PathAndFileUtils.getDbtTransformDirectory("hisinone"); |
||||||
|
} |
||||||
|
HashMap<String, String> map = getMarkdownDefinitions(dir); |
||||||
|
addYMLDescriptionsToMetaObjects(dir, map); |
||||||
|
} |
||||||
|
|
||||||
|
public void addYMLDescriptionsToMetaObjects(String ymlDir, HashMap<String, String> mdDefs){ |
||||||
|
log.info("Adding descriptions from yml files"); |
||||||
|
HashMap<String, String> descriptions = createDescriptions(new File(ymlDir), mdDefs); |
||||||
|
List<MetaObject> objs = getAllMetaObjectsWithConformed(); |
||||||
|
for (MetaObject metaObj : objs ) { |
||||||
|
String docIdentifier = metaObj.getDocIdentifier(); |
||||||
|
if(docIdentifier == null || docIdentifier.isBlank()) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
// only use yml doc if json description does not exist
|
||||||
|
if(metaObj.getDescription() == null || metaObj.getDescription().isBlank()) { |
||||||
|
String desc = descriptions.get(docIdentifier); |
||||||
|
if(desc == null) { |
||||||
|
log.warn("Missing yml description for: " + docIdentifier); |
||||||
|
} else { |
||||||
|
metaObj.setDescription(desc); |
||||||
|
if(desc.isBlank()) { |
||||||
|
log.warn("Empty yml description for MetaObject: " + docIdentifier); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public MetaYml createYMLFileForMetaJson(MetaJson metaJson) { |
||||||
|
|
||||||
|
MetaYml newYml = new MetaYml(); |
||||||
|
List<MetaYmlModel> newYmlModels = new ArrayList<>(); |
||||||
|
newYml.setVersion(1); |
||||||
|
newYml.setModels(newYmlModels); |
||||||
|
|
||||||
|
if(metaJson instanceof MetaImport) { |
||||||
|
MetaImport metaimport = (MetaImport) metaJson; |
||||||
|
for (MetaFact fact : metaimport.facts) { |
||||||
|
MetaYmlModel factModel = new MetaYmlModel(fact.getFacttable(), " "); |
||||||
|
newYmlModels.add(factModel); |
||||||
|
List<MetaYmlModelColumns> factCols = new ArrayList<>(); |
||||||
|
for(MetaDimension dim : fact.getDimensions()) { |
||||||
|
if(dim.getRefTo() == null) { |
||||||
|
factCols.add(new MetaYmlModelColumns(dim.getFactColumn(), " ", "not_null")); |
||||||
|
MetaYmlModel dimModel = new MetaYmlModel(dim.getDimension(), " "); |
||||||
|
newYmlModels.add(dimModel); |
||||||
|
List<MetaYmlModelColumns> dimCols = new ArrayList<>(); |
||||||
|
for(MetaDimensionAttribute attr : dim.getAttributes()) { |
||||||
|
dimCols.add(new MetaYmlModelColumns(attr.getDimColumn(), " ", "not_null")); |
||||||
|
} |
||||||
|
dimModel.setColumns(dimCols); |
||||||
|
} |
||||||
|
} |
||||||
|
factModel.setColumns(factCols); |
||||||
|
} |
||||||
|
} else { |
||||||
|
MetaImportConformedDimensions metaimport = (MetaImportConformedDimensions) metaJson; |
||||||
|
for(MetaDimension dim : metaimport.conformedDimensions) { |
||||||
|
MetaYmlModel dimModel = new MetaYmlModel(dim.getDimension(), " "); |
||||||
|
newYmlModels.add(dimModel); |
||||||
|
List<MetaYmlModelColumns> dimCols = new ArrayList<>(); |
||||||
|
for(MetaDimensionAttribute attr : dim.getAttributes()) { |
||||||
|
dimCols.add(new MetaYmlModelColumns(attr.getDimColumn(), " ", "not_null")); |
||||||
|
} |
||||||
|
dimModel.setColumns(dimCols); |
||||||
|
} |
||||||
|
} |
||||||
|
return newYml; |
||||||
|
} |
||||||
|
|
||||||
|
private HashMap<String, String> createDescriptions(File startDir, HashMap<String, String> mdDefs){ |
||||||
|
HashMap<String, String> result = new HashMap<>(); |
||||||
|
for (MetaYml yml : getDescriptionYMLs(startDir)) { |
||||||
|
for (MetaYmlModel model : yml.getModels()) { |
||||||
|
String modelName = model.getName(); |
||||||
|
String modelDesc = model.getDescription(); |
||||||
|
result.put(modelName, getDescription(modelDesc, mdDefs)); |
||||||
|
for (MetaYmlModelColumns column : model.getColumns()) { |
||||||
|
String colName = column.getName(); |
||||||
|
String colDesc = column.getDescription(); |
||||||
|
result.put(modelName + "." + colName, getDescription(colDesc, mdDefs)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
private static String getDescription(String desc, HashMap<String, String> mdDefs) { |
||||||
|
if(desc == null) { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
if(desc.startsWith("{{")) { |
||||||
|
String[] parts = desc.split("\""); |
||||||
|
String docRef = parts[1]; |
||||||
|
return mdDefs.get(docRef); |
||||||
|
} |
||||||
|
return desc; |
||||||
|
} |
||||||
|
|
||||||
|
private List<MetaYml> getDescriptionYMLs(File startDir){ |
||||||
|
List<MetaYml> ymls = new ArrayList<>(); |
||||||
|
List<String> files = getFiles(startDir, "", ".yml"); |
||||||
|
ObjectMapper mapperYml = new ObjectMapper(new YAMLFactory()); |
||||||
|
for (String f : files) { |
||||||
|
File file = new File(startDir + File.separator + f); |
||||||
|
MetaYml doc = null; |
||||||
|
try { |
||||||
|
doc = mapperYml.readValue(file, MetaYml.class); |
||||||
|
} catch (Exception e) { |
||||||
|
String message = "Could not read documentation from file: " + file.getName() + "\n"; |
||||||
|
errorMessages.add(message); |
||||||
|
errorMessages.add(ExceptionUtils.getFullStackTrace(e)); |
||||||
|
} |
||||||
|
if(doc != null) { |
||||||
|
log.info("Read documentation from file: " + file.getName()); |
||||||
|
ymls.add(doc); |
||||||
|
} |
||||||
|
} |
||||||
|
return ymls; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Gathers all metadata json files. |
||||||
|
* |
||||||
|
* @param path A path to a metadata json file or a directory containing metadata json files. |
||||||
|
* @return A list of files matching the metadata json suffix. |
||||||
|
*/ |
||||||
|
private static List<File> readMetaImportFiles(String path) { |
||||||
|
File metaimportPath = new File(PathAndFileUtils.getDbtJsonPath(path)); |
||||||
|
List<File> metaimportFiles = new ArrayList<>(); |
||||||
|
if (metaimportPath.isDirectory()) { |
||||||
|
metaimportPath.list(new FilenameFilter() { |
||||||
|
@Override |
||||||
|
public boolean accept(File dir, String name) { |
||||||
|
if (name.endsWith(METAIMPORT_FILE_SUFFIX)) { |
||||||
|
File file = new File(dir.getAbsolutePath() + File.separator + name); |
||||||
|
metaimportFiles.add(file); |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
}); |
||||||
|
} else { |
||||||
|
metaimportFiles.add(metaimportPath); |
||||||
|
} |
||||||
|
return metaimportFiles; |
||||||
|
} |
||||||
|
|
||||||
|
private static List<String> getFiles(File startDir, String subDir, String extension) { |
||||||
|
List<String> filtered = new ArrayList<String>(); |
||||||
|
for (File file : startDir.listFiles()) { |
||||||
|
String name = file.getName(); |
||||||
|
if(file.isDirectory()) { |
||||||
|
filtered.addAll(getFiles(file, subDir + File.separator + name, extension)); |
||||||
|
} |
||||||
|
String filename = name.strip().toLowerCase(); |
||||||
|
if(filename.endsWith(extension)) { |
||||||
|
filtered.add(subDir + File.separator + name); |
||||||
|
} |
||||||
|
} |
||||||
|
return filtered; |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
|
||||||
|
/** |
||||||
|
* Generates the sql upsert strings for all unique, deserialized MetaObjects. |
||||||
|
* |
||||||
|
* @param hasOnConflictConstruct If set to true generates upsert strings with the postgres-specific "ON CONFLICT" clause. |
||||||
|
* @return All the generated upserts from the metadata files. |
||||||
|
*/ |
||||||
|
public List<String> getAllUpsertStrings(boolean hasOnConflictConstruct) { |
||||||
|
|
||||||
|
List<String> upsertStmts = new ArrayList<>(); |
||||||
|
List<Identifier> ids = new ArrayList<>(); |
||||||
|
|
||||||
|
for (MetaJson meta : metaImports) { |
||||||
|
for(MetaObject obj: meta.getMetaObjects()) { |
||||||
|
Identifier id = obj.getId(); |
||||||
|
if(id == null) { |
||||||
|
String message = String.format("Missing ID for Element '%s' in file: %s.", obj.getCaption(), meta.getFile().getAbsolutePath()); |
||||||
|
errorMessages.add(message); |
||||||
|
continue; |
||||||
|
} |
||||||
|
if(ids.contains(id)) { |
||||||
|
String message = String.format("Duplicate ID '%s'. Ignoring Element '%s'.", obj.getCaption(), obj.getId().composedId); |
||||||
|
errorMessages.add(message); |
||||||
|
continue; |
||||||
|
} |
||||||
|
ids.add(obj.getId()); |
||||||
|
String stmt = obj.getUpsertBuilder().build(hasOnConflictConstruct); |
||||||
|
upsertStmts.add(stmt); |
||||||
|
} |
||||||
|
} |
||||||
|
return upsertStmts; |
||||||
|
} |
||||||
|
|
||||||
|
public void updateMetadataForH2Database(DataSource dataSource) throws Exception { |
||||||
|
String metaFilesDir = String.join(File.separator, new String[] {"test", "resources", "db", "fixtures", "reportwizard", "metadata"}); |
||||||
|
deserializeMetadataFromJsonFiles(metaFilesDir); |
||||||
|
JdbcTemplate jt = new JdbcTemplate(dataSource); |
||||||
|
String upserts = String.join("\n", getAllUpsertStrings(false).toString()); |
||||||
|
jt.execute(upserts); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Updates tables in the metadata schema. |
||||||
|
* |
||||||
|
* @param metaPath Location of the metadata file or directory. |
||||||
|
* @param dataSource The datasource on which the sql is executed. |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
public void updateMetadataSchema(String project, DataSource dataSource) throws Exception { |
||||||
|
String metaFilesDir = PathAndFileUtils.getReportGeneratorDir(project); |
||||||
|
deserializeMetadataFromJsonFiles(metaFilesDir); |
||||||
|
|
||||||
|
try (Connection con = dataSource.getConnection()) { |
||||||
|
try (Statement st = con.createStatement()) { |
||||||
|
log.info("Update Metadata for BIAnalysis."); |
||||||
|
st.execute(TRUNCATE_METADATA_SQL); |
||||||
|
List<String> upserts = getAllUpsertStrings(true); |
||||||
|
upserts.addAll(readStoredReports()); |
||||||
|
for (String sql : upserts) { |
||||||
|
log.info(sql); |
||||||
|
try (Statement stUpsert = con.createStatement()) { |
||||||
|
stUpsert.execute(sql); |
||||||
|
} catch (Exception e) { |
||||||
|
throw e; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// execute sql in "attributes_sql" in metadata files to build the attributes
|
||||||
|
// dynamically
|
||||||
|
for (MetaJson i : this.metaImports) { |
||||||
|
for (MetaObject obj : i.getMetaObjects()) { |
||||||
|
if (!(obj instanceof MetaDimension)) continue; |
||||||
|
MetaDimension dim = (MetaDimension) obj; |
||||||
|
if (dim.getAttributesSql() == null) continue; |
||||||
|
|
||||||
|
String sqlDone = ""; |
||||||
|
String sql = "select param_val from unload_params where param_id = '" + dim.getAttributesSql() + "';"; |
||||||
|
try (Statement stAttr = con.createStatement(); ResultSet rs = stAttr.executeQuery(sql)) { |
||||||
|
if(rs.next()) { |
||||||
|
sqlDone = rs.getString("param_val"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
try (Statement stAttr = con.createStatement(); ResultSet rs = stAttr.executeQuery(sqlDone)) { |
||||||
|
int numAttributes = 0; |
||||||
|
while (rs.next()) { |
||||||
|
|
||||||
|
MetaDimensionAttribute attribute = new MetaDimensionAttribute(); |
||||||
|
attribute.setDimension(dim); |
||||||
|
attribute.setCaption(rs.getString("caption")); |
||||||
|
attribute.setDimColumn(rs.getString("dim_column")); |
||||||
|
|
||||||
|
// create a new 'on the fly' identifier for the new metadata
|
||||||
|
// attribute
|
||||||
|
Identifier id = Identifier.getNewIdentifierValue(i.getIds(), dim.getNamespace()); |
||||||
|
Integer val = Integer.valueOf(id.value.intValue() + numAttributes); |
||||||
|
attribute.setId(new Identifier(dim.getNamespace() + ":" +val)); |
||||||
|
numAttributes++; |
||||||
|
|
||||||
|
String stmt = attribute.getUpsertBuilder().build(true); |
||||||
|
try (Statement stUpsert = con.createStatement()) { |
||||||
|
stUpsert.execute(stmt); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static String writeYmlToString(MetaYml yml) { |
||||||
|
YAMLFactory yf = new YAMLFactory() |
||||||
|
.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES) |
||||||
|
.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER); |
||||||
|
ObjectMapper mapper = new ObjectMapper(yf); |
||||||
|
DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(" ", DefaultIndenter.SYS_LF); |
||||||
|
DefaultPrettyPrinter printer = new DefaultPrettyPrinter(); |
||||||
|
printer.indentObjectsWith(indenter); |
||||||
|
printer.indentArraysWith(indenter); |
||||||
|
try { |
||||||
|
//mapper.writer(printer).writeValue(file, yml);
|
||||||
|
return mapper.writer(printer).writeValueAsString(yml); |
||||||
|
} catch (Exception e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public String getPrintableErrorMessages() { |
||||||
|
String output = ""; |
||||||
|
if(!errorMessages.isEmpty()) { |
||||||
|
output += "The following errors occured:\n"; |
||||||
|
for (String message : errorMessages) { |
||||||
|
output += message + "\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
return output; |
||||||
|
} |
||||||
|
|
||||||
|
public HashMap<String, String> getMarkdownDefinitions(String ymlDir) { |
||||||
|
List<String> files = getFiles(new File(ymlDir), "", ".md"); |
||||||
|
HashMap<String, String> map = new HashMap<>(); |
||||||
|
for (String file : files) { |
||||||
|
try { |
||||||
|
try (BufferedReader br = new BufferedReader(new FileReader(ymlDir + File.separator + file))) { |
||||||
|
String line; |
||||||
|
String key = null; |
||||||
|
boolean readHeading = false; |
||||||
|
while ((line = br.readLine()) != null) { |
||||||
|
if (line.startsWith("{% docs ")) { |
||||||
|
key = line.split(" ")[2]; |
||||||
|
map.put(key, ""); |
||||||
|
} else if(key != null && line.startsWith("# ")) { |
||||||
|
readHeading = true; |
||||||
|
} else { |
||||||
|
if(readHeading && !line.isBlank()) { |
||||||
|
map.put(key, line); |
||||||
|
key = null; |
||||||
|
readHeading = false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
String message = "ERROR getting markdown definitions from file: " + file + "\n"; |
||||||
|
errorMessages.add(message); |
||||||
|
errorMessages.add(ExceptionUtils.getFullStackTrace(e)); |
||||||
|
} |
||||||
|
} |
||||||
|
return map; |
||||||
|
} |
||||||
|
|
||||||
|
public Optional<MetaImport> getMetaImport(String fileName) { |
||||||
|
return metaImports.stream() |
||||||
|
.filter(json -> (json instanceof MetaImport) && json.file.getName().equals(fileName)) |
||||||
|
.map(json -> (MetaImport) json) |
||||||
|
.findFirst(); |
||||||
|
} |
||||||
|
|
||||||
|
public Optional<MetaJson> getMetaJson(String fileName) { |
||||||
|
return metaImports.stream() |
||||||
|
.filter(json -> json.file.getName().equals(fileName)) |
||||||
|
.findFirst(); |
||||||
|
} |
||||||
|
|
||||||
|
public List<MetaImport> getMetaImports() { |
||||||
|
return metaImports.stream() |
||||||
|
.filter(json -> (json instanceof MetaImport)) |
||||||
|
.map(json -> (MetaImport) json) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
} |
||||||
|
|
||||||
|
public List<MetaJson> getMetaJsons() { |
||||||
|
return metaImports.stream().collect(Collectors.toList()); |
||||||
|
} |
||||||
|
|
||||||
|
public List<MetaObject> getAllMetaObjects(){ |
||||||
|
return metaImports.stream() |
||||||
|
.filter(json -> (json instanceof MetaImport)) |
||||||
|
.map(meta -> ((MetaImport) meta).getMetaObjects()) |
||||||
|
.flatMap(List::stream) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
} |
||||||
|
|
||||||
|
public List<MetaObject> getAllMetaObjectsWithConformed(){ |
||||||
|
return metaImports.stream() |
||||||
|
.map(meta -> meta.getMetaObjects()) |
||||||
|
.flatMap(List::stream) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
} |
||||||
|
|
||||||
|
public List<MetaFact> getAllFactTables(){ |
||||||
|
return metaImports.stream() |
||||||
|
.filter(json -> (json instanceof MetaImport)) |
||||||
|
.map(meta -> ((MetaImport) meta).facts) |
||||||
|
.flatMap(List::stream) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
} |
||||||
|
|
||||||
|
public void setShouldReadYMLDoc(boolean shouldReadYMLDoc) { |
||||||
|
this.shouldReadYMLDoc = shouldReadYMLDoc; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,99 @@ |
|||||||
|
package de.superx.bianalysis.metadata; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.StringJoiner; |
||||||
|
|
||||||
|
public class UpsertStringBuilder { |
||||||
|
|
||||||
|
private StringJoiner values; |
||||||
|
private StringJoiner columns; |
||||||
|
private StringJoiner onConflict; |
||||||
|
private String schema; |
||||||
|
private String tablename; |
||||||
|
|
||||||
|
private List<UpsertStringBuilder> builders = new ArrayList<>(); |
||||||
|
|
||||||
|
public UpsertStringBuilder() { |
||||||
|
values = new StringJoiner(", "); |
||||||
|
columns = new StringJoiner(", "); |
||||||
|
onConflict = new StringJoiner(", "); |
||||||
|
} |
||||||
|
|
||||||
|
public void addUpsertStringBuilder(UpsertStringBuilder builder) { |
||||||
|
this.builders.add(builder); |
||||||
|
} |
||||||
|
|
||||||
|
public UpsertStringBuilder forTable(String schema, String tablename) { |
||||||
|
this.tablename = tablename; |
||||||
|
this.schema = schema; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public UpsertStringBuilder withStringCol(String colName, String value) { |
||||||
|
appendToSelection(colName); |
||||||
|
if(value == null) { |
||||||
|
values.add("null"); |
||||||
|
} else { |
||||||
|
values.add("'"+value+"'"); |
||||||
|
} |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public UpsertStringBuilder withStringCol(String colName, Object value) { |
||||||
|
if(value != null) { |
||||||
|
return this.withStringCol(colName, value.toString()); |
||||||
|
} |
||||||
|
return this.withStringCol(colName, "unknown"); |
||||||
|
} |
||||||
|
|
||||||
|
public UpsertStringBuilder withStringCol(String colName, String value, String defaultVal) { |
||||||
|
if(value != null) { |
||||||
|
return this.withStringCol(colName, value); |
||||||
|
} |
||||||
|
return this.withStringCol(colName, defaultVal); |
||||||
|
} |
||||||
|
|
||||||
|
public UpsertStringBuilder withStringCol(String colName, Object value, Object defaultVal) { |
||||||
|
if(value != null) { |
||||||
|
return this.withStringCol(colName, value); |
||||||
|
} |
||||||
|
return this.withStringCol(colName, defaultVal); |
||||||
|
} |
||||||
|
|
||||||
|
public UpsertStringBuilder withIntCol(String colName, Integer value) { |
||||||
|
appendToSelection(colName); |
||||||
|
values.add(String.valueOf(value)); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public UpsertStringBuilder withIdCol(String colName, Identifier id) { |
||||||
|
if(id != null) { |
||||||
|
return this.withStringCol(colName, id.composedId); |
||||||
|
} |
||||||
|
return this.withStringCol(colName, null); |
||||||
|
} |
||||||
|
|
||||||
|
private void appendToSelection(String colName) { |
||||||
|
onConflict.add(String.format("%s = EXCLUDED.%s", colName, colName)); |
||||||
|
columns.add(colName); |
||||||
|
} |
||||||
|
|
||||||
|
public String build(boolean hasOnConflictConstruct) { |
||||||
|
String result = "INSERT INTO %s.%s(%s) VALUES(%s)"; |
||||||
|
result = String.format(result, this.schema, this.tablename, this.columns, this.values); |
||||||
|
if(hasOnConflictConstruct) { |
||||||
|
// TODO: log message for on id conflict
|
||||||
|
//result += " ON CONFLICT(id) DO UPDATE SET " + this.onConflict;
|
||||||
|
result += " ON CONFLICT(id) DO NOTHING"; |
||||||
|
} |
||||||
|
result += ";\n"; |
||||||
|
if(this.builders.size() > 0) { |
||||||
|
for (UpsertStringBuilder upsertStringBuilder : builders) { |
||||||
|
result += upsertStringBuilder.build(hasOnConflictConstruct); |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,269 @@ |
|||||||
|
package de.superx.bianalysis.metadata.models.json; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude.Include; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.metadata.UpsertStringBuilder; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude; |
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty; |
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyOrder; |
||||||
|
|
||||||
|
@JsonInclude(Include.NON_DEFAULT) |
||||||
|
@JsonPropertyOrder({ "id", "default_release", "ref_to", "caption", "dimension", "fact_column", "alias", "bridge", "attributes"}) |
||||||
|
public class MetaDimension extends MetaObject { |
||||||
|
|
||||||
|
@JsonProperty("ref_to") |
||||||
|
private String refTo; |
||||||
|
private String dimension; |
||||||
|
@JsonProperty("fact_column") |
||||||
|
private String factColumn; |
||||||
|
private String alias; |
||||||
|
private String view; |
||||||
|
@JsonProperty("id_column") |
||||||
|
private String idColumn; |
||||||
|
private List<MetaDimensionAttribute> attributes; |
||||||
|
|
||||||
|
@JsonProperty("is_hierarchy") |
||||||
|
private boolean isHierarchy; |
||||||
|
@JsonProperty("is_historical") |
||||||
|
private boolean isHistorical; |
||||||
|
|
||||||
|
@JsonProperty("attributes_sql") |
||||||
|
private String attributesSql; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private MetaFact fact; |
||||||
|
|
||||||
|
// true if dimension is from the conformed_dimensions_metaimport.json
|
||||||
|
@JsonIgnore |
||||||
|
private boolean isConformed = false; |
||||||
|
|
||||||
|
// isConformed must be false
|
||||||
|
// the correpsonding dimension from the conformed_dimensions_metaimport.json
|
||||||
|
// referenced by 'ref_to'
|
||||||
|
@JsonIgnore |
||||||
|
private MetaDimension conformedDimension; |
||||||
|
|
||||||
|
public MetaDimension() { |
||||||
|
super("dimension"); |
||||||
|
} |
||||||
|
|
||||||
|
public void setConformedDimension(MetaDimension dimension) { |
||||||
|
this.conformedDimension = dimension; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public UpsertStringBuilder getUpsertBuilder() { |
||||||
|
Identifier factId = (isConformed) ? null : this.fact.id; |
||||||
|
UpsertStringBuilder builder = new UpsertStringBuilder(); |
||||||
|
if(conformedDimension == null) { |
||||||
|
builder = super.getUpsert() |
||||||
|
.withIdCol("facttable_id", factId) |
||||||
|
.withStringCol("joincolumn", this.factColumn) |
||||||
|
.withStringCol("alias", this.alias) |
||||||
|
.withStringCol("is_hierarchy", String.valueOf(this.isHierarchy)) |
||||||
|
.withStringCol("is_historical", String.valueOf(this.isHistorical)) |
||||||
|
//.withStringCol("attributes_sql", this.attributesSql)
|
||||||
|
.withStringCol("tablename", this.dimension) |
||||||
|
.withStringCol("id_column", this.idColumn); |
||||||
|
} else { |
||||||
|
builder = new UpsertStringBuilder() |
||||||
|
.forTable("metadata", this.sourceTable) |
||||||
|
.withStringCol("namespace", this.namespace) |
||||||
|
.withIdCol("id", this.id) |
||||||
|
.withIntCol("default_release", Integer.valueOf(1)); |
||||||
|
builder = builder.withIdCol("facttable_id", factId); |
||||||
|
|
||||||
|
if(this.idColumn != null && !this.idColumn.isBlank()) { |
||||||
|
builder = builder.withStringCol("id_column", idColumn); |
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("id_column", this.conformedDimension.getIdColumn()); |
||||||
|
} |
||||||
|
|
||||||
|
if(this.caption != null && !this.caption.isBlank()) { |
||||||
|
builder = builder.withStringCol("caption", caption); |
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("caption", this.conformedDimension.getCaption()); |
||||||
|
} |
||||||
|
|
||||||
|
if(this.factColumn != null && !this.factColumn.isBlank()) { |
||||||
|
builder = builder.withStringCol("joincolumn", this.factColumn); |
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("joincolumn", this.conformedDimension.getFactColumn()); |
||||||
|
} |
||||||
|
|
||||||
|
if(this.alias != null && !this.factColumn.isBlank()) { |
||||||
|
builder = builder.withStringCol("alias", this.alias); |
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("alias", this.conformedDimension.getAlias()); |
||||||
|
} |
||||||
|
|
||||||
|
if(this.isHierarchy) { |
||||||
|
builder = builder.withStringCol("is_hierarchy", String.valueOf(isHierarchy)); |
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("is_hierarchy", String.valueOf(conformedDimension.isHierarchy)); |
||||||
|
} |
||||||
|
|
||||||
|
if(this.isHistorical) { |
||||||
|
builder = builder.withStringCol("is_historical", String.valueOf(isHistorical)); |
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("is_historical", String.valueOf(conformedDimension.isHistorical)); |
||||||
|
} |
||||||
|
|
||||||
|
if(this.conformedDimension.getDimension() != null && !this.conformedDimension.getDimension().isBlank()) { |
||||||
|
|
||||||
|
if(view != null && !view.isBlank()) { |
||||||
|
builder = builder.withStringCol("tablename", this.view); |
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("tablename", this.conformedDimension.getDimension()); |
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("tablename", this.dimension); |
||||||
|
} |
||||||
|
builder = builder.withIdCol("conformed", this.conformedDimension.id); |
||||||
|
} |
||||||
|
|
||||||
|
if(this.description != null && !this.description.isBlank()) { |
||||||
|
builder = builder.withStringCol("description", this.description); |
||||||
|
} else { |
||||||
|
if(conformedDimension != null) { |
||||||
|
builder = builder.withStringCol("description", conformedDimension.getDescription()); |
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("description", ""); |
||||||
|
} |
||||||
|
} |
||||||
|
return builder; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRefTo() { |
||||||
|
return refTo; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRefTo(String refTo) { |
||||||
|
this.refTo = refTo; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDimension() { |
||||||
|
return dimension; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimension(String dimension) { |
||||||
|
this.dimension = dimension; |
||||||
|
} |
||||||
|
|
||||||
|
public String getAlias() { |
||||||
|
return alias; |
||||||
|
} |
||||||
|
|
||||||
|
public void setAlias(String alias) { |
||||||
|
this.alias = alias; |
||||||
|
} |
||||||
|
|
||||||
|
public List<MetaDimensionAttribute> getAttributes() { |
||||||
|
if(this.attributes == null) { |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
return attributes; |
||||||
|
} |
||||||
|
|
||||||
|
public void setAttributes(List<MetaDimensionAttribute> attributes) { |
||||||
|
for (MetaDimensionAttribute metaDimensionAttribute : attributes) { |
||||||
|
metaDimensionAttribute.setDimension(this); |
||||||
|
} |
||||||
|
this.attributes = attributes; |
||||||
|
} |
||||||
|
|
||||||
|
public MetaFact getFact() { |
||||||
|
return fact; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFact(MetaFact fact) { |
||||||
|
this.fact = fact; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public boolean isConformed() { |
||||||
|
return isConformed; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public void setConformed(boolean isConformed) { |
||||||
|
this.isConformed = isConformed; |
||||||
|
} |
||||||
|
|
||||||
|
public MetaDimension getConformedDimension() { |
||||||
|
return conformedDimension; |
||||||
|
} |
||||||
|
|
||||||
|
public String getFactColumn() { |
||||||
|
return factColumn; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFactColumn(String factColumn) { |
||||||
|
this.factColumn = factColumn; |
||||||
|
} |
||||||
|
|
||||||
|
public void addAttribute(MetaDimensionAttribute metaDimensionAttribute) { |
||||||
|
if(this.attributes == null) { |
||||||
|
this.attributes = new ArrayList<>(); |
||||||
|
} |
||||||
|
this.attributes.add(metaDimensionAttribute); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
@JsonIgnore |
||||||
|
public String getDocIdentifier() { |
||||||
|
if(this.conformedDimension != null) { |
||||||
|
return conformedDimension.getDocIdentifier(); |
||||||
|
} |
||||||
|
return this.dimension; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isHierarchy() { |
||||||
|
return isHierarchy; |
||||||
|
} |
||||||
|
|
||||||
|
public void setHierarchy(boolean isHierarchy) { |
||||||
|
this.isHierarchy = isHierarchy; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isHistorical() { |
||||||
|
return isHistorical; |
||||||
|
} |
||||||
|
|
||||||
|
public void setHistorical(boolean isHistorical) { |
||||||
|
this.isHistorical = isHistorical; |
||||||
|
} |
||||||
|
|
||||||
|
public String getView() { |
||||||
|
return view; |
||||||
|
} |
||||||
|
|
||||||
|
public void setView(String view) { |
||||||
|
this.view = view; |
||||||
|
} |
||||||
|
|
||||||
|
public String getIdColumn() { |
||||||
|
return idColumn; |
||||||
|
} |
||||||
|
|
||||||
|
public void setIdColumn(String idColumn) { |
||||||
|
this.idColumn = idColumn; |
||||||
|
} |
||||||
|
|
||||||
|
public String getAttributesSql() { |
||||||
|
return attributesSql; |
||||||
|
} |
||||||
|
|
||||||
|
public void setAttributesSql(String attributesSql) { |
||||||
|
this.attributesSql = attributesSql; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,179 @@ |
|||||||
|
package de.superx.bianalysis.metadata.models.json; |
||||||
|
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude; |
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty; |
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyOrder; |
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude.Include; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.UpsertStringBuilder; |
||||||
|
|
||||||
|
@JsonInclude(Include.NON_DEFAULT) |
||||||
|
@JsonPropertyOrder({ "id", "default_release", "ref", "caption", "dim_column"}) |
||||||
|
public class MetaDimensionAttribute extends MetaObject { |
||||||
|
|
||||||
|
@JsonProperty("dim_column") |
||||||
|
private String dimColumn; |
||||||
|
|
||||||
|
@JsonProperty("sort_order_column") |
||||||
|
private String sortOrderColumn; |
||||||
|
|
||||||
|
@JsonProperty("hierarchical_filter") |
||||||
|
private boolean hierarchicalFilter; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private MetaDimension dimension; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private MetaDimensionAttribute confDimAttrRef; |
||||||
|
|
||||||
|
@JsonProperty("ref_to") |
||||||
|
private String refTo; |
||||||
|
|
||||||
|
@JsonProperty("filter_selection") |
||||||
|
private String filterSelection; |
||||||
|
|
||||||
|
public MetaDimensionAttribute() { |
||||||
|
super("dimension_attribute"); |
||||||
|
} |
||||||
|
|
||||||
|
public MetaDimensionAttribute(String attrColumn) { |
||||||
|
super("dimension_attribute"); |
||||||
|
this.refTo = attrColumn; |
||||||
|
//this.refTo = dimensionTable + "." + attrColumn;
|
||||||
|
} |
||||||
|
|
||||||
|
public void setConformedDimensionAttribute(MetaDimensionAttribute attribute) { |
||||||
|
this.confDimAttrRef = attribute; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public UpsertStringBuilder getUpsertBuilder() { |
||||||
|
UpsertStringBuilder builder = new UpsertStringBuilder(); |
||||||
|
if(confDimAttrRef == null) { |
||||||
|
builder = super.getUpsert() |
||||||
|
.withIdCol("dimension_id", this.dimension.id) |
||||||
|
.withStringCol("columnname", this.dimColumn) |
||||||
|
.withStringCol("sort_order_column", this.sortOrderColumn) |
||||||
|
.withStringCol("filter_selection", this.filterSelection); |
||||||
|
} else { |
||||||
|
builder = new UpsertStringBuilder() |
||||||
|
.forTable("metadata", this.sourceTable) |
||||||
|
.withStringCol("namespace", this.namespace) |
||||||
|
.withIdCol("id", this.id) |
||||||
|
.withIntCol("default_release", Integer.valueOf(1)); |
||||||
|
|
||||||
|
if(getCaption() != null && !getCaption().isBlank()) { |
||||||
|
builder = builder.withStringCol("caption", caption); |
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("caption", confDimAttrRef.getCaption()); |
||||||
|
} |
||||||
|
|
||||||
|
if(getDimColumn() != null && !getDimColumn().isBlank()) { |
||||||
|
builder = builder.withStringCol("columnname", this.dimColumn); |
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("columnname", confDimAttrRef.getDimColumn()); |
||||||
|
} |
||||||
|
|
||||||
|
if(getFilterSelection() != null && !getFilterSelection().isBlank()) { |
||||||
|
builder = builder.withStringCol("filter_selection", this.filterSelection); |
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("filter_selection", confDimAttrRef.getFilterSelection()); |
||||||
|
} |
||||||
|
|
||||||
|
if(getSortOrderColumn() != null && !getSortOrderColumn().isBlank()) { |
||||||
|
builder = builder.withStringCol("sort_order_column", this.sortOrderColumn); |
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("sort_order_column", confDimAttrRef.getSortOrderColumn()); |
||||||
|
} |
||||||
|
|
||||||
|
builder = builder.withIdCol("dimension_id", this.dimension.id); |
||||||
|
builder = builder.withIdCol("conformed", this.confDimAttrRef.id); |
||||||
|
} |
||||||
|
|
||||||
|
if(confDimAttrRef != null && confDimAttrRef.hierarchicalFilter) { |
||||||
|
builder = builder.withStringCol("hierarchical_filter", String.valueOf(confDimAttrRef.hierarchicalFilter)); |
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("hierarchical_filter", String.valueOf(hierarchicalFilter)); |
||||||
|
} |
||||||
|
|
||||||
|
if(this.description != null && !this.description.isBlank()) { |
||||||
|
builder = builder.withStringCol("description", this.description); |
||||||
|
} else { |
||||||
|
if(confDimAttrRef != null) { |
||||||
|
builder = builder.withStringCol("description", confDimAttrRef.getDescription()); |
||||||
|
} else { |
||||||
|
builder = builder.withStringCol("description", ""); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return builder; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDimColumn() { |
||||||
|
return dimColumn; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimColumn(String dimColumn) { |
||||||
|
this.dimColumn = dimColumn; |
||||||
|
} |
||||||
|
|
||||||
|
public String getSortOrderColumn() { |
||||||
|
return sortOrderColumn; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSortOrderColumn(String sortOrderColumn) { |
||||||
|
this.sortOrderColumn = sortOrderColumn; |
||||||
|
} |
||||||
|
|
||||||
|
public String getFilterSelection() { |
||||||
|
return filterSelection; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFilterSelection(String filterSelection) { |
||||||
|
this.filterSelection = filterSelection; |
||||||
|
} |
||||||
|
|
||||||
|
public MetaDimension getDimension() { |
||||||
|
return dimension; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimension(MetaDimension dimension) { |
||||||
|
this.dimension = dimension; |
||||||
|
} |
||||||
|
|
||||||
|
public MetaDimensionAttribute getConfDimAttrRef() { |
||||||
|
return confDimAttrRef; |
||||||
|
} |
||||||
|
|
||||||
|
public void setConfDimAttrRef(MetaDimensionAttribute confDimAttrRef) { |
||||||
|
this.confDimAttrRef = confDimAttrRef; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRefTo() { |
||||||
|
return refTo; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRefTo(String refTo) { |
||||||
|
this.refTo = refTo; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
@Override |
||||||
|
public String getDocIdentifier() { |
||||||
|
if(refTo != null) { |
||||||
|
return this.confDimAttrRef.getDocIdentifier(); |
||||||
|
} |
||||||
|
return this.dimension.getDocIdentifier()+"."+this.dimColumn; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isHierarchicalFilter() { |
||||||
|
return hierarchicalFilter; |
||||||
|
} |
||||||
|
|
||||||
|
public void setHierarchicalFilter(boolean hierarchicalFilter) { |
||||||
|
this.hierarchicalFilter = hierarchicalFilter; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,77 @@ |
|||||||
|
package de.superx.bianalysis.metadata.models.json; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyOrder; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.metadata.UpsertStringBuilder; |
||||||
|
|
||||||
|
@JsonPropertyOrder({ "id", "default_release", "caption", "sachgebiettid", "facttable", "conformed_dimensions", "dimensions", "measures" }) |
||||||
|
public class MetaFact extends MetaObject { |
||||||
|
|
||||||
|
private Integer sachgebiettid; |
||||||
|
private String facttable; |
||||||
|
private List<MetaDimension> dimensions; |
||||||
|
private List<MetaMeasure> measures; |
||||||
|
|
||||||
|
public MetaFact() { |
||||||
|
super("facttable"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public UpsertStringBuilder getUpsertBuilder() { |
||||||
|
UpsertStringBuilder builder = super.getUpsert() |
||||||
|
.withIntCol("sachgebiettid", this.sachgebiettid) |
||||||
|
.withStringCol("tablename", this.facttable) |
||||||
|
.withStringCol("description", super.getDescription()); |
||||||
|
|
||||||
|
return builder; |
||||||
|
} |
||||||
|
|
||||||
|
public Integer getSachgebiettid() { |
||||||
|
return sachgebiettid; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSachgebiettid(Integer sachgebiettid) { |
||||||
|
this.sachgebiettid = sachgebiettid; |
||||||
|
} |
||||||
|
|
||||||
|
public String getFacttable() { |
||||||
|
return facttable; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFacttable(String facttable) { |
||||||
|
this.facttable = facttable; |
||||||
|
} |
||||||
|
|
||||||
|
public List<MetaDimension> getDimensions() { |
||||||
|
return dimensions; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimensions(List<MetaDimension> dimensions) { |
||||||
|
for (MetaDimension metaDimension : dimensions) { |
||||||
|
metaDimension.setFact(this); |
||||||
|
} |
||||||
|
this.dimensions = dimensions; |
||||||
|
} |
||||||
|
|
||||||
|
public List<MetaMeasure> getMeasures() { |
||||||
|
return measures; |
||||||
|
} |
||||||
|
|
||||||
|
public void setMeasures(List<MetaMeasure> measures) { |
||||||
|
for (MetaMeasure metaMeasure : measures) { |
||||||
|
metaMeasure.setFact(this); |
||||||
|
} |
||||||
|
this.measures = measures; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
@Override |
||||||
|
public String getDocIdentifier() { |
||||||
|
return this.facttable; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,82 @@ |
|||||||
|
package de.superx.bianalysis.metadata.models.json; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyOrder; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.UpsertStringBuilder; |
||||||
|
import de.superx.rest.model.ColumnType; |
||||||
|
|
||||||
|
@JsonPropertyOrder({ "id", "default_release"} ) |
||||||
|
public class MetaMeasure extends MetaObject { |
||||||
|
|
||||||
|
private String factcolumn; |
||||||
|
private String aggregation; |
||||||
|
private ColumnType type; |
||||||
|
private MetaMeasureFilter filter; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private MetaFact fact; |
||||||
|
|
||||||
|
public MetaMeasure() { |
||||||
|
super("measure"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public UpsertStringBuilder getUpsertBuilder() { |
||||||
|
return super.getUpsert() |
||||||
|
.withIdCol("facttable_id", (this.fact != null) ? this.fact.id : null) |
||||||
|
.withIdCol("measure_filter_id", (this.filter != null) ? this.filter.id : null) |
||||||
|
.withStringCol("columnname", this.factcolumn) |
||||||
|
.withStringCol("aggregation_type", this.aggregation) |
||||||
|
.withStringCol("description", this.description) |
||||||
|
.withStringCol("measure_type", this.type, ColumnType.IntegerColumn); |
||||||
|
} |
||||||
|
|
||||||
|
public String getFactcolumn() { |
||||||
|
return factcolumn; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFactcolumn(String factcolumn) { |
||||||
|
this.factcolumn = factcolumn; |
||||||
|
} |
||||||
|
|
||||||
|
public String getAggregation() { |
||||||
|
return aggregation; |
||||||
|
} |
||||||
|
|
||||||
|
public void setAggregation(String aggregation) { |
||||||
|
this.aggregation = aggregation; |
||||||
|
} |
||||||
|
|
||||||
|
public ColumnType getType() { |
||||||
|
return type; |
||||||
|
} |
||||||
|
|
||||||
|
public void setType(ColumnType type) { |
||||||
|
this.type = type; |
||||||
|
} |
||||||
|
|
||||||
|
public MetaMeasureFilter getFilter() { |
||||||
|
return filter; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFilter(MetaMeasureFilter filter) { |
||||||
|
this.filter = filter; |
||||||
|
} |
||||||
|
|
||||||
|
public MetaFact getFact() { |
||||||
|
return fact; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFact(MetaFact fact) { |
||||||
|
this.fact = fact; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
@Override |
||||||
|
public String getDocIdentifier() { |
||||||
|
return this.factcolumn; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
@ -0,0 +1,106 @@ |
|||||||
|
package de.superx.bianalysis.metadata.models.json; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat; |
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyOrder; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.UpsertStringBuilder; |
||||||
|
|
||||||
|
@JsonPropertyOrder({ "id", "default_release"} ) |
||||||
|
public class MetaMeasureFilter extends MetaObject { |
||||||
|
|
||||||
|
private String dimensionRef; |
||||||
|
|
||||||
|
private String factColumnRef; |
||||||
|
|
||||||
|
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) |
||||||
|
private List<String> included; |
||||||
|
|
||||||
|
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) |
||||||
|
private List<String> excluded; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private MetaDimensionAttribute attribute; |
||||||
|
|
||||||
|
public MetaMeasureFilter() { |
||||||
|
super("measure_filter"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public UpsertStringBuilder getUpsertBuilder() { |
||||||
|
|
||||||
|
UpsertStringBuilder builder = super.getUpsert(); |
||||||
|
builder.withStringCol("included_values", concatValues(included)); |
||||||
|
builder.withStringCol("excluded_values", concatValues(excluded)); |
||||||
|
|
||||||
|
if(this.dimensionRef != null) { |
||||||
|
builder.withIdCol("dimension_attribute_id", this.attribute.id); |
||||||
|
} else if(this.factColumnRef != null){ |
||||||
|
builder.withStringCol("fact_column_filter", this.factColumnRef); |
||||||
|
} |
||||||
|
|
||||||
|
return builder; |
||||||
|
} |
||||||
|
|
||||||
|
private static String concatValues(List<String> values) { |
||||||
|
if (values == null || values.isEmpty()) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
String result = ""; |
||||||
|
int size = values.size(); |
||||||
|
for (int i = 0; i < size - 1; i++) { |
||||||
|
result += "''" + values.get(i) + "'', "; |
||||||
|
} |
||||||
|
result += "''" + values.get(size - 1) + "''"; |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDimensionRef() { |
||||||
|
return dimensionRef; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimensionRef(String dimensionRef) { |
||||||
|
this.dimensionRef = dimensionRef; |
||||||
|
} |
||||||
|
|
||||||
|
public List<String> getIncluded() { |
||||||
|
return included; |
||||||
|
} |
||||||
|
|
||||||
|
public void setIncluded(List<String> included) { |
||||||
|
this.included = included; |
||||||
|
} |
||||||
|
|
||||||
|
public List<String> getExcluded() { |
||||||
|
return excluded; |
||||||
|
} |
||||||
|
|
||||||
|
public void setExcluded(List<String> excluded) { |
||||||
|
this.excluded = excluded; |
||||||
|
} |
||||||
|
|
||||||
|
public MetaDimensionAttribute getAttribute() { |
||||||
|
return attribute; |
||||||
|
} |
||||||
|
|
||||||
|
public void setAttribute(MetaDimensionAttribute attribute) { |
||||||
|
this.attribute = attribute; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
@Override |
||||||
|
public String getDocIdentifier() { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
|
||||||
|
public String getFactColumnRef() { |
||||||
|
return factColumnRef; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFactColumnRef(String factColumnRef) { |
||||||
|
this.factColumnRef = factColumnRef; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,112 @@ |
|||||||
|
package de.superx.bianalysis.metadata.models.json; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude; |
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude.Include; |
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.metadata.UpsertStringBuilder; |
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true) |
||||||
|
@JsonInclude(Include.NON_NULL) |
||||||
|
public abstract class MetaObject { |
||||||
|
|
||||||
|
protected Identifier id; |
||||||
|
protected String caption; |
||||||
|
protected String description; |
||||||
|
|
||||||
|
@JsonProperty("default_release") |
||||||
|
protected String defaultRelease; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
protected String sourceTable; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
protected String namespace; |
||||||
|
|
||||||
|
protected MetaObject(String sourceTable) { |
||||||
|
this.sourceTable = sourceTable; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the documentation identifier for a specific meta object. |
||||||
|
* The Identifier is used in a *.md file and is referenced in the yml |
||||||
|
* file like the following: '{{ doc("<identifier>") }}'. |
||||||
|
*/ |
||||||
|
@JsonIgnore |
||||||
|
public abstract String getDocIdentifier(); |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public abstract UpsertStringBuilder getUpsertBuilder(); |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
protected UpsertStringBuilder getUpsert() { |
||||||
|
return new UpsertStringBuilder() |
||||||
|
.forTable("metadata", this.sourceTable) |
||||||
|
.withStringCol("namespace", this.namespace) |
||||||
|
.withIdCol("id", this.id) |
||||||
|
.withStringCol("default_release", this.defaultRelease) |
||||||
|
.withStringCol("caption", this.caption); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean equals(Object obj) { |
||||||
|
if(!(obj instanceof MetaObject)) { |
||||||
|
return false; |
||||||
|
} else if(((MetaObject)obj).id == null) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
return this.id.equals(((MetaObject)obj).id); |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier getId() { |
||||||
|
return id; |
||||||
|
} |
||||||
|
|
||||||
|
public void setId(Identifier id) { |
||||||
|
this.id = id; |
||||||
|
} |
||||||
|
|
||||||
|
public String getCaption() { |
||||||
|
return caption; |
||||||
|
} |
||||||
|
|
||||||
|
public void setCaption(String caption) { |
||||||
|
this.caption = caption; |
||||||
|
} |
||||||
|
|
||||||
|
public String getSourceTable() { |
||||||
|
return sourceTable; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSourceTable(String sourceTable) { |
||||||
|
this.sourceTable = sourceTable; |
||||||
|
} |
||||||
|
|
||||||
|
public String getNamespace() { |
||||||
|
return namespace; |
||||||
|
} |
||||||
|
|
||||||
|
public void setNamespace(String namespace) { |
||||||
|
this.namespace = namespace; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDescription() { |
||||||
|
return description; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDescription(String description) { |
||||||
|
this.description = description; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDefaultRelease() { |
||||||
|
return defaultRelease; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDefaultRelease(String defaultRelease) { |
||||||
|
this.defaultRelease = defaultRelease; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,32 @@ |
|||||||
|
package de.superx.bianalysis.metadata.models.yml; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true) |
||||||
|
public class MetaYml { |
||||||
|
|
||||||
|
private int version; |
||||||
|
private List<MetaYmlModel> models; |
||||||
|
|
||||||
|
public int getVersion() { |
||||||
|
return version; |
||||||
|
} |
||||||
|
|
||||||
|
public void setVersion(int version) { |
||||||
|
this.version = version; |
||||||
|
} |
||||||
|
|
||||||
|
public List<MetaYmlModel> getModels() { |
||||||
|
if(this.models == null) { |
||||||
|
return new ArrayList<MetaYmlModel>(); |
||||||
|
} |
||||||
|
return models; |
||||||
|
} |
||||||
|
|
||||||
|
public void setModels(List<MetaYmlModel> models) { |
||||||
|
this.models = models; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,49 @@ |
|||||||
|
package de.superx.bianalysis.metadata.models.yml; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true) |
||||||
|
public class MetaYmlModel { |
||||||
|
|
||||||
|
private String name; |
||||||
|
private String description; |
||||||
|
private List<MetaYmlModelColumns> columns; |
||||||
|
|
||||||
|
public MetaYmlModel() { } |
||||||
|
|
||||||
|
public MetaYmlModel(String name, String description) { |
||||||
|
super(); |
||||||
|
this.name = name; |
||||||
|
this.description = description; |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return name; |
||||||
|
} |
||||||
|
|
||||||
|
public void setName(String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDescription() { |
||||||
|
return description; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDescription(String description) { |
||||||
|
this.description = description; |
||||||
|
} |
||||||
|
|
||||||
|
public List<MetaYmlModelColumns> getColumns() { |
||||||
|
if(this.columns == null) { |
||||||
|
return new ArrayList<MetaYmlModelColumns>(); |
||||||
|
} |
||||||
|
return columns; |
||||||
|
} |
||||||
|
|
||||||
|
public void setColumns(List<MetaYmlModelColumns> columns) { |
||||||
|
this.columns = columns; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,52 @@ |
|||||||
|
package de.superx.bianalysis.metadata.models.yml; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true) |
||||||
|
public class MetaYmlModelColumns { |
||||||
|
|
||||||
|
private String name; |
||||||
|
private String description; |
||||||
|
private List<Object> tests; |
||||||
|
|
||||||
|
public MetaYmlModelColumns() {} |
||||||
|
|
||||||
|
public MetaYmlModelColumns(String name, String description, String test) { |
||||||
|
super(); |
||||||
|
this.name = name; |
||||||
|
this.description = description; |
||||||
|
this.tests = new ArrayList<Object>(); |
||||||
|
this.tests.add(test); |
||||||
|
} |
||||||
|
|
||||||
|
public MetaYmlModelColumns(String name, String description) { |
||||||
|
super(); |
||||||
|
this.name = name; |
||||||
|
this.description = description; |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return name; |
||||||
|
} |
||||||
|
public void setName(String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
public String getDescription() { |
||||||
|
return description; |
||||||
|
} |
||||||
|
public void setDescription(String description) { |
||||||
|
this.description = description; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Object> getTests() { |
||||||
|
return tests; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTests(List<Object> tests) { |
||||||
|
this.tests = tests; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,94 @@ |
|||||||
|
package de.superx.bianalysis.models; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.springframework.data.annotation.Transient; |
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.repository.dto.DimensionDto; |
||||||
|
|
||||||
|
public class Dimension { |
||||||
|
|
||||||
|
private DimensionDto dimensionDto; |
||||||
|
|
||||||
|
@Transient |
||||||
|
public String conformedCaption; |
||||||
|
|
||||||
|
@Transient |
||||||
|
public String conformedDescription; |
||||||
|
|
||||||
|
@Transient |
||||||
|
public List<DimensionAttribute> dimensionAttributes; |
||||||
|
|
||||||
|
public Dimension(DimensionDto dimDto) { |
||||||
|
this.setDimensionDto(dimDto); |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimensionAttributes(List<DimensionAttribute> lda) { |
||||||
|
for (DimensionAttribute dimensionAttribute : lda) { |
||||||
|
dimensionAttribute.setDimensionColumnAlias(dimensionAttribute.getColumnname() + "_" + getId().value); |
||||||
|
} |
||||||
|
this.dimensionAttributes = lda; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isHidden() { |
||||||
|
if(this.dimensionDto.isHidden == null) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
return this.dimensionDto.isHidden.booleanValue(); |
||||||
|
} |
||||||
|
|
||||||
|
public DimensionDto getDimensionDto() { |
||||||
|
return dimensionDto; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimensionDto(DimensionDto dimensionDto) { |
||||||
|
this.dimensionDto = dimensionDto; |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier getId() { |
||||||
|
return this.dimensionDto.id; |
||||||
|
} |
||||||
|
|
||||||
|
public String getCaption() { |
||||||
|
return this.dimensionDto.caption; |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier getFactTableId() { |
||||||
|
return this.dimensionDto.factTableId; |
||||||
|
} |
||||||
|
|
||||||
|
public String getTablename() { |
||||||
|
return this.dimensionDto.tablename; |
||||||
|
} |
||||||
|
|
||||||
|
public String getJoincolumn() { |
||||||
|
return this.dimensionDto.joincolumn; |
||||||
|
} |
||||||
|
|
||||||
|
public String getAlias() { |
||||||
|
return this.dimensionDto.alias; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDescription() { |
||||||
|
return this.dimensionDto.description; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isHierarchy() { |
||||||
|
if(this.dimensionDto.isHierarchy == null) return false; |
||||||
|
return this.dimensionDto.isHierarchy.booleanValue(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isHistorical() { |
||||||
|
if(this.dimensionDto.isHistorical == null) return false; |
||||||
|
return this.dimensionDto.isHistorical.booleanValue(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getConformed() { |
||||||
|
return this.dimensionDto.conformed; |
||||||
|
} |
||||||
|
|
||||||
|
public String getIdColumn() { |
||||||
|
return this.dimensionDto.idColumn; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,276 @@ |
|||||||
|
package de.superx.bianalysis.models; |
||||||
|
|
||||||
|
import java.util.Comparator; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.repository.dto.AttributeDto; |
||||||
|
|
||||||
|
public class DimensionAttribute { |
||||||
|
|
||||||
|
public static final List<String> SPECIAL_VALUES = List.of("n. v.", "k.A.", "k.a.", "unbekannt", "Unbekannt", "ungültig", "Ungültig"); |
||||||
|
|
||||||
|
public static final Comparator<String> SPECIAL_VALUE_COMPARATOR = (a1, a2) -> { |
||||||
|
if (a1.equals(a2)) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
if (DimensionAttribute.SPECIAL_VALUES.contains(a1)) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
if (DimensionAttribute.SPECIAL_VALUES.contains(a2)) { |
||||||
|
return 1; |
||||||
|
} |
||||||
|
return a1.compareTo(a2); |
||||||
|
}; |
||||||
|
|
||||||
|
public static String specialValueListForSql() { |
||||||
|
String result = String.join("', '", SPECIAL_VALUES); |
||||||
|
return "'" + result + "'"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private String conformedCaption; |
||||||
|
|
||||||
|
private String conformedDescription; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private AttributeDto attributeTable; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private String dimCaption; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private String dimId; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private String dimConformedId; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private String tablename; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private String joincolumn; |
||||||
|
|
||||||
|
private boolean isHierarchy; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private boolean isHistorical; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private String dimensionTableAlias; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private String dimensionColumnAlias; |
||||||
|
|
||||||
|
private List<String> dimensionAttributeValues; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
private String dimIdJoinColumn; |
||||||
|
|
||||||
|
public DimensionAttribute() { |
||||||
|
super(); |
||||||
|
} |
||||||
|
|
||||||
|
public DimensionAttribute(AttributeDto attributeTable) { |
||||||
|
this.attributeTable = attributeTable; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimension(Dimension dim) { |
||||||
|
this.dimCaption = dim.getCaption(); |
||||||
|
this.dimId = dim.getId().composedId; |
||||||
|
this.tablename = dim.getTablename(); |
||||||
|
this.joincolumn = dim.getJoincolumn(); |
||||||
|
this.isHierarchy = dim.isHierarchy(); |
||||||
|
this.isHistorical = dim.isHistorical(); |
||||||
|
this.dimIdJoinColumn = dim.getIdColumn(); |
||||||
|
if(dim.getAlias() != null){ |
||||||
|
this.dimensionTableAlias = dim.getAlias(); |
||||||
|
} else { |
||||||
|
this.dimensionTableAlias = generateDimensionTableAlias(joincolumn); |
||||||
|
} |
||||||
|
this.dimensionColumnAlias = getColumnname() + "_" + getId().value; |
||||||
|
} |
||||||
|
|
||||||
|
public static String generateDimensionTableAlias(String joincolumn) { |
||||||
|
if (joincolumn != null) { |
||||||
|
return joincolumn.replaceFirst("_id$", ""); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int hashCode() { |
||||||
|
return Objects.hash(getId()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean equals(Object obj) { |
||||||
|
if (this == obj) return true; |
||||||
|
if (obj == null) return false; |
||||||
|
if (getClass() != obj.getClass()) return false; |
||||||
|
DimensionAttribute other = (DimensionAttribute) obj; |
||||||
|
return Objects.equals(this.getId(), other.getId()); |
||||||
|
} |
||||||
|
|
||||||
|
public String getCaption() { |
||||||
|
return this.attributeTable.caption; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isHidden() { |
||||||
|
if(this.attributeTable.isHidden == null) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
return this.attributeTable.isHidden.booleanValue(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getColumnname() { |
||||||
|
return this.attributeTable.columnname; |
||||||
|
} |
||||||
|
|
||||||
|
public String getSortOrderColumn() { |
||||||
|
return this.attributeTable.sortOrderColumn; |
||||||
|
} |
||||||
|
|
||||||
|
public String getFilterSelection() { |
||||||
|
return this.attributeTable.filterSelection; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDimId() { |
||||||
|
return dimId; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimId(String dimId) { |
||||||
|
this.dimId = dimId; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDimConformedId() { |
||||||
|
return dimConformedId; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimConformedId(String dimConformedId) { |
||||||
|
this.dimConformedId = dimConformedId; |
||||||
|
} |
||||||
|
|
||||||
|
public String getAttrConformedId() { |
||||||
|
return this.attributeTable.attrConformedId; |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier getId() { |
||||||
|
return this.attributeTable.id; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public String getStringId() { |
||||||
|
return this.attributeTable.id.composedId; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDimCaption() { |
||||||
|
return dimCaption; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimCaption(String dimCaption) { |
||||||
|
this.dimCaption = dimCaption; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDimensionTableAlias() { |
||||||
|
return dimensionTableAlias; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimensionTableAlias(String dimensionTableAlias) { |
||||||
|
this.dimensionTableAlias = dimensionTableAlias; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDimensionColumnAlias() { |
||||||
|
return dimensionColumnAlias; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimensionColumnAlias(String dimensionColumnAlias) { |
||||||
|
this.dimensionColumnAlias = dimensionColumnAlias; |
||||||
|
} |
||||||
|
|
||||||
|
public String getConformedCaption() { |
||||||
|
return conformedCaption; |
||||||
|
} |
||||||
|
|
||||||
|
public void setConformedCaption(String conformedCaption) { |
||||||
|
this.conformedCaption = conformedCaption; |
||||||
|
} |
||||||
|
|
||||||
|
public String getConformedDescription() { |
||||||
|
return conformedDescription; |
||||||
|
} |
||||||
|
|
||||||
|
public void setConformedDescription(String conformedDescription) { |
||||||
|
this.conformedDescription = conformedDescription; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDescription() { |
||||||
|
return this.attributeTable.description; |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier getDimensionId() { |
||||||
|
return this.attributeTable.dimensionId; |
||||||
|
} |
||||||
|
|
||||||
|
public String getTablename() { |
||||||
|
return tablename; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTablename(String tablename) { |
||||||
|
this.tablename = tablename; |
||||||
|
} |
||||||
|
|
||||||
|
public String getJoincolumn() { |
||||||
|
return joincolumn; |
||||||
|
} |
||||||
|
|
||||||
|
public void setJoincolumn(String joincolumn) { |
||||||
|
this.joincolumn = joincolumn; |
||||||
|
} |
||||||
|
|
||||||
|
@JsonProperty(value="isHierarchy") |
||||||
|
public boolean isHierarchy() { |
||||||
|
return isHierarchy; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isHistorical() { |
||||||
|
return isHistorical; |
||||||
|
} |
||||||
|
|
||||||
|
public void setHierarchy(boolean isHierarchy) { |
||||||
|
this.isHierarchy = isHierarchy; |
||||||
|
} |
||||||
|
|
||||||
|
public void setHistorical(boolean isHistorical) { |
||||||
|
this.isHistorical = isHistorical; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isHierarchicalFilter() { |
||||||
|
return this.attributeTable.hierarchicalFilter.booleanValue(); |
||||||
|
} |
||||||
|
|
||||||
|
public List<String> getDimensionAttributeValues() { |
||||||
|
return dimensionAttributeValues; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimensionAttributeValues(List<String> dimensionAttributeValues) { |
||||||
|
this.dimensionAttributeValues = dimensionAttributeValues; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimIdJoinColumn(String idColumn) { |
||||||
|
this.dimIdJoinColumn = idColumn; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDimIdJoinColumn() { |
||||||
|
return this.dimIdJoinColumn; |
||||||
|
} |
||||||
|
|
||||||
|
public void setAttrConformedId(String stringId) { |
||||||
|
this.attributeTable.attrConformedId = stringId; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,71 @@ |
|||||||
|
package de.superx.bianalysis.models; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.springframework.data.annotation.Id; |
||||||
|
import org.springframework.data.annotation.Transient; |
||||||
|
import org.springframework.data.relational.core.mapping.Table; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.repository.dto.FactDto; |
||||||
|
import de.superx.jdbc.entity.Sachgebiet; |
||||||
|
|
||||||
|
@Table(value ="metadata\".\"facttable") |
||||||
|
public class FactTable { |
||||||
|
|
||||||
|
private FactDto factDto; |
||||||
|
|
||||||
|
@Transient |
||||||
|
private Sachgebiet sachgebiet; |
||||||
|
|
||||||
|
@Transient |
||||||
|
private List<Dimension> conformedDimensions; |
||||||
|
|
||||||
|
public FactTable() {} |
||||||
|
|
||||||
|
public FactTable(FactDto factDto) { |
||||||
|
this.factDto = factDto; |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier getId() { |
||||||
|
return this.factDto.id; |
||||||
|
} |
||||||
|
|
||||||
|
public String getCaption() { |
||||||
|
if(this.factDto != null) { |
||||||
|
return this.factDto.caption; |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public int getSachgebiettid() { |
||||||
|
return this.factDto.sachgebiettid.intValue(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getDescription() { |
||||||
|
return this.factDto.description; |
||||||
|
} |
||||||
|
|
||||||
|
public String getTablename() { |
||||||
|
return this.factDto.tablename; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Dimension> getConformedDimensions() { |
||||||
|
return conformedDimensions; |
||||||
|
} |
||||||
|
|
||||||
|
public void setConformedDimensions(List<Dimension> conformedDimensions) { |
||||||
|
this.conformedDimensions = conformedDimensions; |
||||||
|
} |
||||||
|
|
||||||
|
public Sachgebiet getSachgebiet() { |
||||||
|
return sachgebiet; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSachgebiet(Sachgebiet sachgebiet) { |
||||||
|
this.sachgebiet = sachgebiet; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,89 @@ |
|||||||
|
package de.superx.bianalysis.models; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.StringJoiner; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||||
|
|
||||||
|
import de.superx.bianalysis.ReportMetadata; |
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
|
||||||
|
public class Filter { |
||||||
|
|
||||||
|
public Identifier dimensionAttributeId; |
||||||
|
public List<String> filterValues; |
||||||
|
public String columnname; |
||||||
|
public String tablename; |
||||||
|
public String joincolumn; |
||||||
|
public String dimensionTableAlias; |
||||||
|
|
||||||
|
public Filter() { |
||||||
|
super(); |
||||||
|
} |
||||||
|
|
||||||
|
public Filter(List<String> values, Identifier dimAttrId) { |
||||||
|
this.filterValues = values; |
||||||
|
this.dimensionAttributeId = dimAttrId; |
||||||
|
} |
||||||
|
|
||||||
|
public Filter(Filter filter) { |
||||||
|
this.dimensionAttributeId = filter.dimensionAttributeId; |
||||||
|
this.filterValues = filter.filterValues; |
||||||
|
this.columnname = filter.columnname; |
||||||
|
this.tablename = filter.tablename; |
||||||
|
this.joincolumn = filter.joincolumn; |
||||||
|
this.dimensionTableAlias = filter.dimensionTableAlias; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimensionAttribute(DimensionAttribute attr) { |
||||||
|
this.columnname = attr.getColumnname(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setDimension(Dimension dim) { |
||||||
|
this.tablename = dim.getTablename(); |
||||||
|
this.joincolumn = dim.getJoincolumn(); |
||||||
|
if(dim.getAlias() != null) { |
||||||
|
this.dimensionTableAlias = dim.getAlias(); |
||||||
|
} else { |
||||||
|
this.dimensionTableAlias = joincolumn.replaceFirst("_id$", ""); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public DimensionAttribute getDimAttribute(ReportMetadata reportMetadata) { |
||||||
|
return reportMetadata.getDimAttrById(this.dimensionAttributeId); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String toString() { |
||||||
|
return String.valueOf(this.dimensionAttributeId); |
||||||
|
} |
||||||
|
|
||||||
|
public static Filter findFilterById(List<Filter> filters, Identifier id) { |
||||||
|
return filters |
||||||
|
.stream() |
||||||
|
.filter(f -> f.dimensionAttributeId.equals(id)) |
||||||
|
.findFirst() |
||||||
|
.orElse(null); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public String getValuesAsString() { |
||||||
|
if(this.filterValues == null || this.filterValues.isEmpty()) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
return String.join(", ", this.filterValues); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public String getValues() { |
||||||
|
if(this.filterValues == null || this.filterValues.isEmpty()) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
StringJoiner joiner = new StringJoiner(", "); |
||||||
|
for (String value : filterValues) { |
||||||
|
joiner.add("'"+value+"'"); |
||||||
|
} |
||||||
|
return joiner.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,89 @@ |
|||||||
|
package de.superx.bianalysis.models; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import de.superx.rest.model.Item; |
||||||
|
|
||||||
|
public class Info { |
||||||
|
|
||||||
|
public String segmentCaption; |
||||||
|
public String lastUpdateBiad; |
||||||
|
|
||||||
|
|
||||||
|
public List<String> sachgebiete = new ArrayList<String>(); |
||||||
|
public List<InfoItem> facttables = new ArrayList<InfoItem>(); |
||||||
|
public List<InfoItem> measures = new ArrayList<InfoItem>(); |
||||||
|
public List<InfoItem> leftDimensionAttributes = new ArrayList<InfoItem>(); |
||||||
|
public List<InfoItem> topDimensionAttributes = new ArrayList<InfoItem>(); |
||||||
|
public List<String> filter = new ArrayList<String>(); |
||||||
|
public String hideEmptyColumns; |
||||||
|
|
||||||
|
public List<Item> sqlStatements = new ArrayList<Item>(); |
||||||
|
|
||||||
|
public String error; |
||||||
|
|
||||||
|
|
||||||
|
public void addSachgebiet(String sachgebiet) { |
||||||
|
sachgebiete.add(sachgebiet); |
||||||
|
} |
||||||
|
|
||||||
|
public void addFacttable(InfoItem facttable) { |
||||||
|
facttables.add(facttable); |
||||||
|
} |
||||||
|
|
||||||
|
public void setMeasures(List<InfoItem> measures) { |
||||||
|
this.measures = measures; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLeftDimensionAttributes(List<InfoItem> leftDimensionAttributes) { |
||||||
|
this.leftDimensionAttributes = leftDimensionAttributes; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTopDimensionAttributes(List<InfoItem> topDimensionAttributes) { |
||||||
|
this.topDimensionAttributes = topDimensionAttributes; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSachgebiete(List<String> sachgebiete) { |
||||||
|
this.sachgebiete = sachgebiete; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFacttables(List<InfoItem> facttables) { |
||||||
|
this.facttables = facttables; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFilter(List<String> filter) { |
||||||
|
this.filter = filter; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSqlStatements(List<Item> sqlStatements) { |
||||||
|
this.sqlStatements = sqlStatements; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLastUpdateBiad(String lastUpdateBiad) { |
||||||
|
this.lastUpdateBiad = lastUpdateBiad; |
||||||
|
} |
||||||
|
|
||||||
|
public void setErrorMessage(String error) { |
||||||
|
this.error = error; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSegmentCaption(String segmentCaption) { |
||||||
|
this.segmentCaption = segmentCaption; |
||||||
|
} |
||||||
|
|
||||||
|
public void hideEmptyColumns(boolean hideEmptyColumns) { |
||||||
|
if(hideEmptyColumns) { |
||||||
|
this.hideEmptyColumns = "Ja"; |
||||||
|
} else { |
||||||
|
this.hideEmptyColumns = "Nein"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setHideEmptyColumns(String hideEmptyColumns) { |
||||||
|
this.hideEmptyColumns = hideEmptyColumns; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
@ -0,0 +1,19 @@ |
|||||||
|
package de.superx.bianalysis.models; |
||||||
|
|
||||||
|
public class InfoItem { |
||||||
|
|
||||||
|
public String id; |
||||||
|
public String caption; |
||||||
|
public String description; |
||||||
|
|
||||||
|
public InfoItem(String id, String caption, String description) { |
||||||
|
this.id = id; |
||||||
|
this.caption = caption; |
||||||
|
this.description = description; |
||||||
|
} |
||||||
|
|
||||||
|
public InfoItem() { |
||||||
|
super(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,130 @@ |
|||||||
|
package de.superx.bianalysis.models; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.repository.dto.MeasureDto; |
||||||
|
import de.superx.bianalysis.repository.dto.MeasureFilterDto; |
||||||
|
import de.superx.rest.model.ColumnType; |
||||||
|
|
||||||
|
public class Measure { |
||||||
|
|
||||||
|
private MeasureDto measureDto; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public String filterTablename; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public String filterJoincolumn; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public String filterColumnname; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public String filterInclude; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public String filterExclude; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public String filterDimensionTableAlias; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public String filterCondition; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public String factColumnFilter; |
||||||
|
|
||||||
|
@JsonIgnore |
||||||
|
public Identifier filterAttributeId; |
||||||
|
|
||||||
|
public Measure() { |
||||||
|
super(); |
||||||
|
} |
||||||
|
|
||||||
|
public Measure(MeasureDto measureDTO) { |
||||||
|
this.measureDto = measureDTO; |
||||||
|
} |
||||||
|
|
||||||
|
public void setMeasureFilterAttributes(MeasureFilterDto filter, DimensionAttribute attribute, Dimension dimension) { |
||||||
|
this.filterInclude = filter.includedValues; |
||||||
|
this.filterExclude = filter.excludedValues; |
||||||
|
this.filterTablename = dimension.getTablename(); |
||||||
|
this.filterJoincolumn = dimension.getJoincolumn(); |
||||||
|
this.filterColumnname = attribute.getColumnname(); |
||||||
|
this.filterAttributeId = attribute.getId(); |
||||||
|
if (dimension.getAlias() != null) { |
||||||
|
this.filterDimensionTableAlias = dimension.getAlias(); |
||||||
|
} else { |
||||||
|
this.filterDimensionTableAlias = generatefilterDimensionTableAlias(filterJoincolumn); |
||||||
|
} |
||||||
|
this.filterCondition = generateFilterCondition(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setFactColumnFilter(MeasureFilterDto filter) { |
||||||
|
this.factColumnFilter = filter.factColumnFilter; |
||||||
|
this.filterInclude = filter.includedValues; |
||||||
|
this.filterExclude = filter.excludedValues; |
||||||
|
this.filterCondition = generateFilterCondition(); |
||||||
|
} |
||||||
|
|
||||||
|
private static String generatefilterDimensionTableAlias(String filterJoincolumn) { |
||||||
|
if (filterJoincolumn != null) { |
||||||
|
return filterJoincolumn.replaceFirst("_id$", ""); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
private String generateFilterCondition() { |
||||||
|
if (this.measureDto.measureFilterId.value != null) { |
||||||
|
StringBuilder filterConditionStatement = new StringBuilder(); |
||||||
|
String tableDotColumn = this.filterDimensionTableAlias + "." + this.filterColumnname; |
||||||
|
if(factColumnFilter != null && !factColumnFilter.isBlank()) { |
||||||
|
tableDotColumn = factColumnFilter; |
||||||
|
} |
||||||
|
if (this.filterInclude != null) { |
||||||
|
filterConditionStatement.append(tableDotColumn + " IN (" |
||||||
|
+ this.filterInclude + ")"); |
||||||
|
} |
||||||
|
if (this.filterInclude != null && this.filterExclude != null) { |
||||||
|
filterConditionStatement.append(" AND "); |
||||||
|
} |
||||||
|
if (this.filterExclude != null) { |
||||||
|
filterConditionStatement.append(tableDotColumn |
||||||
|
+ " NOT IN (" + this.filterExclude + ")"); |
||||||
|
} |
||||||
|
return filterConditionStatement.toString(); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier getId() { |
||||||
|
return this.measureDto.id; |
||||||
|
} |
||||||
|
|
||||||
|
public String getCaption() { |
||||||
|
return this.measureDto.caption; |
||||||
|
} |
||||||
|
|
||||||
|
public String getColumnname() { |
||||||
|
return this.measureDto.columnname; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDescription() { |
||||||
|
return this.measureDto.description; |
||||||
|
} |
||||||
|
|
||||||
|
public String getAggregationType() { |
||||||
|
return this.measureDto.aggregationType; |
||||||
|
} |
||||||
|
|
||||||
|
public ColumnType getMeasureType() { |
||||||
|
return this.measureDto.measureType; |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier getMeasureFilterId() { |
||||||
|
return this.measureDto.measureFilterId; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,29 @@ |
|||||||
|
package de.superx.bianalysis.models; |
||||||
|
|
||||||
|
public enum Right { |
||||||
|
|
||||||
|
VIEW_REPORT("RIGHT_CS_BIA_ANALYSIS_VIEW_ANALYSIS_TABLE"), |
||||||
|
CREATE_ANALYSIS("RIGHT_CS_BIA_ANALYSIS_CREATE_ANALYSIS"); |
||||||
|
|
||||||
|
private String string; |
||||||
|
|
||||||
|
Right(String string) { |
||||||
|
this.setString(string); |
||||||
|
} |
||||||
|
|
||||||
|
public String getString() { |
||||||
|
return string; |
||||||
|
} |
||||||
|
|
||||||
|
public void setString(String string) { |
||||||
|
this.string = string; |
||||||
|
} |
||||||
|
|
||||||
|
public static String getPrintableRights(Right... rights) { |
||||||
|
String out = ""; |
||||||
|
for (Right right : rights) { |
||||||
|
out += right.toString(); |
||||||
|
} |
||||||
|
return out; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,21 @@ |
|||||||
|
package de.superx.bianalysis.models; |
||||||
|
|
||||||
|
public enum RightParam { |
||||||
|
|
||||||
|
TOPIC_AREA("bianalysis.topic_area"), |
||||||
|
TOPIC("bianalysis.topic"); |
||||||
|
|
||||||
|
private String string; |
||||||
|
|
||||||
|
RightParam(String string) { |
||||||
|
this.setString(string); |
||||||
|
} |
||||||
|
|
||||||
|
public String getString() { |
||||||
|
return string; |
||||||
|
} |
||||||
|
|
||||||
|
public void setString(String string) { |
||||||
|
this.string = string; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,42 @@ |
|||||||
|
package de.superx.bianalysis.repository; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
import org.springframework.data.jdbc.repository.query.Query; |
||||||
|
import org.springframework.data.repository.CrudRepository; |
||||||
|
import org.springframework.data.repository.RepositoryDefinition; |
||||||
|
import org.springframework.data.repository.query.Param; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.repository.dto.AttributeDto; |
||||||
|
import de.superx.jdbc.repository.BiaAdminCrudRepository; |
||||||
|
|
||||||
|
@RepositoryDefinition(domainClass = AttributeDto.class, idClass = Identifier.class) |
||||||
|
public interface DimensionAttributeRepository extends BiaAdminCrudRepository<AttributeDto> { |
||||||
|
|
||||||
|
List<AttributeDto> findByDimensionId(Identifier dimensionId); |
||||||
|
|
||||||
|
Optional<AttributeDto> findById(Identifier id); |
||||||
|
|
||||||
|
@Query( |
||||||
|
"SELECT da.id" |
||||||
|
+ " FROM metadata.dimension_attribute da" |
||||||
|
+ " LEFT JOIN metadata.dimension d" |
||||||
|
+ " ON d.id = da.dimension_id" |
||||||
|
+ " WHERE da.conformed = :confAttrId" |
||||||
|
+ " AND facttable_id = :factId" |
||||||
|
) |
||||||
|
List<Identifier> findAttributesByConformedAttributeAndFactTable(@Param("confAttrId") String confAttrId, @Param("factId") String factId); |
||||||
|
|
||||||
|
@Query( |
||||||
|
"SELECT da.id" |
||||||
|
+ " FROM metadata.dimension_attribute da" |
||||||
|
+ " LEFT JOIN metadata.dimension d" |
||||||
|
+ " ON d.id = da.dimension_id" |
||||||
|
+ " WHERE da.id = :attrId" |
||||||
|
+ " AND d.facttable_id = :factId" |
||||||
|
) |
||||||
|
Identifier findAttributesByIdAndFactTable(@Param("attrId") String confAttrId, @Param("factId") String factId); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,50 @@ |
|||||||
|
package de.superx.bianalysis.repository; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
import org.springframework.data.jdbc.repository.query.Query; |
||||||
|
import org.springframework.data.repository.CrudRepository; |
||||||
|
import org.springframework.data.repository.RepositoryDefinition; |
||||||
|
import org.springframework.data.repository.query.Param; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.repository.dto.DimensionDto; |
||||||
|
import de.superx.jdbc.repository.BiaAdminCrudRepository; |
||||||
|
|
||||||
|
@RepositoryDefinition(domainClass = DimensionDto.class, idClass = Identifier.class) |
||||||
|
public interface DimensionRepository extends BiaAdminCrudRepository<DimensionDto> { |
||||||
|
|
||||||
|
List<DimensionDto> findByFactTableId(Identifier factTableId); |
||||||
|
|
||||||
|
Optional<DimensionDto> findById(Identifier id); |
||||||
|
|
||||||
|
@Override |
||||||
|
List<DimensionDto> findAll(); |
||||||
|
|
||||||
|
@Query( |
||||||
|
" SELECT d.id" |
||||||
|
+ " FROM metadata.dimension d" |
||||||
|
+ " LEFT JOIN metadata.dimension_attribute da" |
||||||
|
+ " ON da.dimension_id = d.id" |
||||||
|
+ " WHERE da.id is null" |
||||||
|
+ " AND d.conformed = :confDim" |
||||||
|
+ " AND d.facttable_id = :factId" |
||||||
|
) |
||||||
|
List<Identifier> getRolePlayingIds(@Param("confDim") String confDim, @Param("factId") String factId); |
||||||
|
|
||||||
|
@Query( |
||||||
|
"SELECT dimension_id " |
||||||
|
+ "FROM metadata.dimension_attribute da " |
||||||
|
+ "WHERE id = :attrId" |
||||||
|
) |
||||||
|
Identifier findDimensionIdForAttribute(@Param("attrId") String attrId); |
||||||
|
|
||||||
|
@Query( |
||||||
|
"SELECT conformed" |
||||||
|
+ " FROM metadata.dimension" |
||||||
|
+ " WHERE facttable_id = :factId" |
||||||
|
+ " AND conformed IS NOT NULL" |
||||||
|
) |
||||||
|
List<Identifier> getUsedConformedDimensionsByFactTable(@Param("factId") String factId); |
||||||
|
} |
||||||
@ -0,0 +1,47 @@ |
|||||||
|
package de.superx.bianalysis.repository; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.Optional; |
||||||
|
import org.springframework.data.jdbc.repository.query.Query; |
||||||
|
import org.springframework.data.repository.CrudRepository; |
||||||
|
import org.springframework.data.repository.RepositoryDefinition; |
||||||
|
import org.springframework.data.repository.query.Param; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.repository.dto.FactDto; |
||||||
|
import de.superx.jdbc.repository.BiaAdminCrudRepository; |
||||||
|
|
||||||
|
@RepositoryDefinition(domainClass = FactDto.class, idClass = Identifier.class) |
||||||
|
public interface FactRepository extends BiaAdminCrudRepository<FactDto> { |
||||||
|
|
||||||
|
@Override |
||||||
|
List<FactDto> findAll(); |
||||||
|
|
||||||
|
Optional<FactDto> findById(Identifier id); |
||||||
|
|
||||||
|
Optional<FactDto> findByTablename(String tablename); |
||||||
|
|
||||||
|
@Query( |
||||||
|
"SELECT COUNT(*) > 0" |
||||||
|
+ " FROM metadata.facttable f" |
||||||
|
+ " LEFT JOIN metadata.measure m" |
||||||
|
+ " ON m.facttable_id = f.id" |
||||||
|
+ " WHERE f.id = :factId" |
||||||
|
+ " AND m.id = :measureId" |
||||||
|
) |
||||||
|
boolean hasFactTableMeasure(@Param("factId") String factId, @Param("measureId") String measureId); |
||||||
|
|
||||||
|
@Query( |
||||||
|
"SELECT f.tablename" |
||||||
|
+ " FROM metadata.dimension_attribute da" |
||||||
|
+ " LEFT JOIN metadata.dimension d" |
||||||
|
+ " ON d.id = da.dimension_id" |
||||||
|
+ " LEFT JOIN metadata.facttable f" |
||||||
|
+ " ON f.id = d.facttable_id" |
||||||
|
+ " WHERE f.id = :factId" |
||||||
|
+ " AND (da.conformed = :attrId OR da.id = :attrId)" |
||||||
|
) |
||||||
|
String getFactTableNameForAttribute(@Param("factId") String factId, @Param("attrId") String attrId); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
@ -0,0 +1,13 @@ |
|||||||
|
package de.superx.bianalysis.repository; |
||||||
|
|
||||||
|
import org.springframework.data.repository.CrudRepository; |
||||||
|
import org.springframework.data.repository.RepositoryDefinition; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.repository.dto.MeasureFilterDto; |
||||||
|
import de.superx.jdbc.repository.BiaAdminCrudRepository; |
||||||
|
|
||||||
|
@RepositoryDefinition(domainClass = MeasureFilterDto.class, idClass = Identifier.class) |
||||||
|
public interface MeasureFilterRepository extends BiaAdminCrudRepository<MeasureFilterDto> { |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,17 @@ |
|||||||
|
package de.superx.bianalysis.repository; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.springframework.data.repository.CrudRepository; |
||||||
|
import org.springframework.data.repository.RepositoryDefinition; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.repository.dto.MeasureDto; |
||||||
|
import de.superx.jdbc.repository.BiaAdminCrudRepository; |
||||||
|
|
||||||
|
@RepositoryDefinition(domainClass = MeasureDto.class, idClass = Identifier.class) |
||||||
|
public interface MeasureRepository extends BiaAdminCrudRepository<MeasureDto> { |
||||||
|
|
||||||
|
List<MeasureDto> findByFactTableId(Identifier id); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,23 @@ |
|||||||
|
package de.superx.bianalysis.repository; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
import org.springframework.data.repository.CrudRepository; |
||||||
|
import org.springframework.data.repository.RepositoryDefinition; |
||||||
|
|
||||||
|
import de.superx.bianalysis.StoredReport; |
||||||
|
|
||||||
|
@RepositoryDefinition(domainClass = StoredReport.class, idClass = Integer.class) |
||||||
|
public interface StoredReportRepository extends CrudRepository<StoredReport, Integer> { |
||||||
|
|
||||||
|
Optional<StoredReport> findByName(String name); |
||||||
|
|
||||||
|
Optional<StoredReport> findById(int id); |
||||||
|
|
||||||
|
void deleteById(int id); |
||||||
|
|
||||||
|
@Override |
||||||
|
List<StoredReport> findAll(); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,74 @@ |
|||||||
|
package de.superx.bianalysis.repository.dto; |
||||||
|
|
||||||
|
import org.springframework.data.annotation.Id; |
||||||
|
import org.springframework.data.relational.core.mapping.Column; |
||||||
|
import org.springframework.data.relational.core.mapping.Table; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.jdbc.entity.EntityBase; |
||||||
|
import de.superx.jdbc.model.DynamicFieldType; |
||||||
|
import de.superx.jdbc.model.EntityDescriptor; |
||||||
|
import de.superx.jdbc.model.TableRef; |
||||||
|
import de.superx.rest.model.ColumnType; |
||||||
|
import de.superx.rest.model.FieldType; |
||||||
|
|
||||||
|
@Table(schema = "metadata", value = "dimension_attribute") |
||||||
|
public class AttributeDto extends EntityBase { |
||||||
|
|
||||||
|
@Id |
||||||
|
@DynamicFieldType(label="ID", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
public Identifier id; |
||||||
|
|
||||||
|
@EntityDescriptor |
||||||
|
@DynamicFieldType(label="Titel") |
||||||
|
public String caption; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Beschreibung", editControlType=FieldType.TextArea) |
||||||
|
public String description; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Dimension", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
@TableRef(schema = "metadata", table = "dimension", keyField = "id", labelField = "caption") |
||||||
|
@Column(value = "dimension_id") |
||||||
|
public Identifier dimensionId; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Spaltenname", readOnly = true) |
||||||
|
public String columnname; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Sortierspalte", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
@Column(value = "sort_order_column") |
||||||
|
public String sortOrderColumn; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Filter-Auswahl", visibleInSimplifiedForm = false) |
||||||
|
@Column(value = "filter_selection") |
||||||
|
public String filterSelection; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Hierarchie", editControlType=FieldType.Select, columnType = ColumnType.BooleanColumnBiAnalysis, readOnly = true) |
||||||
|
@Column(value = "hierarchical_filter") |
||||||
|
public Boolean hierarchicalFilter; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Ausgeblendet", editControlType=FieldType.Select, columnType = ColumnType.BooleanColumnBiAnalysis) |
||||||
|
@Column(value = "is_hidden") |
||||||
|
public Boolean isHidden; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Conformed Attribute", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
@TableRef(schema = "metadata", table = "dimension_attribute", keyField = "id", labelField = "caption") |
||||||
|
@Column(value = "conformed") |
||||||
|
public String attrConformedId; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Auslieferungsversion", visibleInSimplifiedForm = false) |
||||||
|
@Column(value = "default_release") |
||||||
|
public String defaultRelease; |
||||||
|
|
||||||
|
public AttributeDto() {} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canBeCreatedByUser() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canBeDeletedByUser() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,79 @@ |
|||||||
|
package de.superx.bianalysis.repository.dto; |
||||||
|
|
||||||
|
import org.springframework.data.annotation.Id; |
||||||
|
import org.springframework.data.relational.core.mapping.Column; |
||||||
|
import org.springframework.data.relational.core.mapping.Table; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.jdbc.entity.EntityBase; |
||||||
|
import de.superx.jdbc.model.DynamicFieldType; |
||||||
|
import de.superx.jdbc.model.EntityDescriptor; |
||||||
|
import de.superx.rest.model.ColumnType; |
||||||
|
import de.superx.rest.model.FieldType; |
||||||
|
import de.superx.jdbc.model.TableRef; |
||||||
|
|
||||||
|
@Table(schema="metadata", value = "dimension") |
||||||
|
public class DimensionDto extends EntityBase{ |
||||||
|
|
||||||
|
@Id |
||||||
|
@DynamicFieldType(label="ID", readOnly = true) |
||||||
|
public Identifier id; |
||||||
|
|
||||||
|
@EntityDescriptor |
||||||
|
@DynamicFieldType(label="Titel") |
||||||
|
public String caption; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Beschreibung", editControlType=FieldType.TextArea) |
||||||
|
public String description; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Faktentabelle", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
@TableRef(schema = "metadata", table = "facttable", keyField = "id", labelField = "caption") |
||||||
|
@Column(value = "facttable_id") |
||||||
|
public Identifier factTableId; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Tabellenname", readOnly = true) |
||||||
|
public String tablename; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Join-Spalte", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
public String joincolumn; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Join-Alias", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
public String alias; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Hierarchie", editControlType=FieldType.Select, columnType = ColumnType.BooleanColumnBiAnalysis, readOnly = true) |
||||||
|
@Column(value = "is_hierarchy") |
||||||
|
public Boolean isHierarchy; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Historisch", editControlType=FieldType.Select, columnType = ColumnType.BooleanColumnBiAnalysis, readOnly = true) |
||||||
|
@Column(value = "is_historical") |
||||||
|
public Boolean isHistorical; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Conformed Dimension", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
@TableRef(schema = "metadata", table = "dimension", keyField = "id", labelField = "caption") |
||||||
|
public String conformed; |
||||||
|
|
||||||
|
@DynamicFieldType(label="ID Spalte", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
@Column(value = "id_column") |
||||||
|
public String idColumn; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Auslieferungsversion", visibleInSimplifiedForm = false) |
||||||
|
@Column(value = "default_release") |
||||||
|
public String defaultRelease; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Ausgeblendet", editControlType=FieldType.Select, columnType = ColumnType.BooleanColumnBiAnalysis) |
||||||
|
@Column(value = "is_hidden") |
||||||
|
public Boolean isHidden; |
||||||
|
|
||||||
|
public DimensionDto() {} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canBeCreatedByUser() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canBeDeletedByUser() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,50 @@ |
|||||||
|
package de.superx.bianalysis.repository.dto; |
||||||
|
|
||||||
|
import org.springframework.data.annotation.Id; |
||||||
|
import org.springframework.data.relational.core.mapping.Column; |
||||||
|
import org.springframework.data.relational.core.mapping.Table; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.jdbc.entity.EntityBase; |
||||||
|
import de.superx.jdbc.model.DynamicFieldType; |
||||||
|
import de.superx.jdbc.model.EntityDescriptor; |
||||||
|
import de.superx.jdbc.model.TableRef; |
||||||
|
import de.superx.rest.model.FieldType; |
||||||
|
|
||||||
|
@Table(schema = "metadata", value = "facttable") |
||||||
|
public class FactDto extends EntityBase { |
||||||
|
|
||||||
|
@Id |
||||||
|
@DynamicFieldType(label="ID", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
public Identifier id; |
||||||
|
|
||||||
|
@EntityDescriptor |
||||||
|
@DynamicFieldType(label="Titel") |
||||||
|
public String caption; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Beschreibung", editControlType=FieldType.TextArea) |
||||||
|
public String description; |
||||||
|
|
||||||
|
@DynamicFieldType(label = "Sachgebiet", editControlType = FieldType.Select) |
||||||
|
@TableRef(table = "sachgebiete", keyField = "tid", labelField = "name") |
||||||
|
public Integer sachgebiettid; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Tabellenname", readOnly = true) |
||||||
|
public String tablename; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Auslieferungsversion", visibleInSimplifiedForm = false) |
||||||
|
@Column(value = "default_release") |
||||||
|
public String defaultRelease; |
||||||
|
|
||||||
|
public FactDto() {} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canBeCreatedByUser() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canBeDeletedByUser() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,66 @@ |
|||||||
|
package de.superx.bianalysis.repository.dto; |
||||||
|
|
||||||
|
import org.springframework.data.annotation.Id; |
||||||
|
import org.springframework.data.relational.core.mapping.Column; |
||||||
|
import org.springframework.data.relational.core.mapping.Table; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.jdbc.entity.EntityBase; |
||||||
|
import de.superx.jdbc.model.DynamicFieldType; |
||||||
|
import de.superx.jdbc.model.EntityDescriptor; |
||||||
|
import de.superx.rest.model.ColumnType; |
||||||
|
import de.superx.rest.model.FieldType; |
||||||
|
import de.superx.jdbc.model.TableRef; |
||||||
|
|
||||||
|
@Table(schema = "metadata", value = "measure") |
||||||
|
public class MeasureDto extends EntityBase { |
||||||
|
|
||||||
|
@Id |
||||||
|
@DynamicFieldType(label="ID", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
public Identifier id; |
||||||
|
|
||||||
|
@EntityDescriptor |
||||||
|
@DynamicFieldType(label="Titel") |
||||||
|
public String caption; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Beschreibung", editControlType=FieldType.TextArea) |
||||||
|
public String description; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Spaltenname") |
||||||
|
public String columnname; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Faktentabelle", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
@TableRef(schema = "metadata", table = "facttable", keyField = "id", labelField = "caption") |
||||||
|
@Column(value = "facttable_id") |
||||||
|
public Identifier factTableId; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Filter", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
@TableRef(schema = "metadata", table = "measure_filter", keyField = "id", labelField = "caption") |
||||||
|
@Column(value = "measure_filter_id") |
||||||
|
public Identifier measureFilterId; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Aggregationstyp") |
||||||
|
@Column(value = "aggregation_type") |
||||||
|
public String aggregationType; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Datentyp", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
@Column(value = "measure_type") |
||||||
|
public ColumnType measureType; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Auslieferungsversion", visibleInSimplifiedForm = false) |
||||||
|
@Column(value = "default_release") |
||||||
|
public String defaultRelease; |
||||||
|
|
||||||
|
public MeasureDto() {}; |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canBeCreatedByUser() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canBeDeletedByUser() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,61 @@ |
|||||||
|
package de.superx.bianalysis.repository.dto; |
||||||
|
|
||||||
|
import org.springframework.data.annotation.Id; |
||||||
|
import org.springframework.data.relational.core.mapping.Column; |
||||||
|
import org.springframework.data.relational.core.mapping.Table; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.jdbc.entity.EntityBase; |
||||||
|
import de.superx.jdbc.model.DynamicFieldType; |
||||||
|
import de.superx.jdbc.model.EntityDescriptor; |
||||||
|
import de.superx.rest.model.FieldType; |
||||||
|
import de.superx.jdbc.model.TableRef; |
||||||
|
|
||||||
|
@Table(schema = "metadata", value = "measure_filter") |
||||||
|
public class MeasureFilterDto extends EntityBase { |
||||||
|
|
||||||
|
@Id |
||||||
|
@DynamicFieldType(label="ID", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
public Identifier id; |
||||||
|
|
||||||
|
@EntityDescriptor |
||||||
|
@DynamicFieldType(label="Titel") |
||||||
|
public String caption; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Beschreibung", editControlType=FieldType.TextArea) |
||||||
|
public String description; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Attribute", readOnly = true, visibleInSimplifiedForm = false) |
||||||
|
@TableRef(schema = "metadata", table = "dimension_attribute", keyField = "id", labelField = "caption") |
||||||
|
@Column(value = "dimension_attribute_id") |
||||||
|
public Identifier dimensionAttributeId; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Faktenspalte Filter", readOnly = true) |
||||||
|
@Column(value = "fact_column_filter") |
||||||
|
public String factColumnFilter; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Einbezogene Werte", readOnly = true) |
||||||
|
@Column(value = "included_values") |
||||||
|
public String includedValues; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Ausgeschlossene Werte", readOnly = true) |
||||||
|
@Column(value = "excluded_values") |
||||||
|
public String excludedValues; |
||||||
|
|
||||||
|
@DynamicFieldType(label="Auslieferungsversion", visibleInSimplifiedForm = false) |
||||||
|
@Column(value = "default_release") |
||||||
|
public String defaultRelease; |
||||||
|
|
||||||
|
public MeasureFilterDto() {} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canBeCreatedByUser() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean canBeDeletedByUser() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,277 @@ |
|||||||
|
package de.superx.bianalysis.rest; |
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream; |
||||||
|
import java.text.SimpleDateFormat; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Optional; |
||||||
|
import java.util.Base64; |
||||||
|
import java.util.Date; |
||||||
|
import org.apache.log4j.Logger; |
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.web.bind.annotation.RequestBody; |
||||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||||
|
import org.springframework.web.bind.annotation.RequestMethod; |
||||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||||
|
import org.springframework.web.bind.annotation.RestController; |
||||||
|
|
||||||
|
import de.superx.bianalysis.ExcelSheetBuilder; |
||||||
|
import de.superx.bianalysis.ReportDefinition; |
||||||
|
import de.superx.bianalysis.StoredReport; |
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.models.Dimension; |
||||||
|
import de.superx.bianalysis.models.DimensionAttribute; |
||||||
|
import de.superx.bianalysis.models.FactTable; |
||||||
|
import de.superx.bianalysis.models.Measure; |
||||||
|
import de.superx.bianalysis.models.Right; |
||||||
|
import de.superx.bianalysis.service.BiAnalysisManager; |
||||||
|
import de.superx.bianalysis.service.BiAnalysisRightService; |
||||||
|
import de.superx.bianalysis.service.DbMetaAdapter; |
||||||
|
import de.superx.common.NotYetImplementedException; |
||||||
|
import de.superx.rest.RestControllerBase; |
||||||
|
import de.superx.rest.model.Download; |
||||||
|
import de.superx.rest.model.Result; |
||||||
|
import de.superx.rest.model.ResultType; |
||||||
|
import de.superx.rest.model.Row; |
||||||
|
|
||||||
|
@RestController |
||||||
|
@RequestMapping("/api/reportwizard") |
||||||
|
public class BiAnalysisApi extends RestControllerBase { |
||||||
|
|
||||||
|
/* Autor: Robin Wübbeling |
||||||
|
* Achtung: Code ist schnell und unschön zusammengestellt, für einen ersten Entwurf |
||||||
|
* TODO: Filter |
||||||
|
* TODO: Berechnete Kennzahlen |
||||||
|
* TODO: Kennzahlenfilter momentan nur über 1 Dimensionsattribut möglich |
||||||
|
* TODO: Strings schöner durch "Platzhalter" |
||||||
|
* */ |
||||||
|
|
||||||
|
static Logger logger = Logger.getLogger(BiAnalysisApi.class); |
||||||
|
|
||||||
|
@Autowired |
||||||
|
DbMetaAdapter dbAdapter; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
BiAnalysisRightService rightsService; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
BiAnalysisManager biAnalysisManager; |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Logger getLogger() { |
||||||
|
return logger; |
||||||
|
} |
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, path = "/facttables") |
||||||
|
public List<FactTable> listFactTables() throws NotYetImplementedException { |
||||||
|
List<Integer> sachgebiete = rightsService.getSachgebiete(Right.CREATE_ANALYSIS, Right.VIEW_REPORT); |
||||||
|
List<Identifier> factTables = rightsService.getFactTables(Right.CREATE_ANALYSIS, Right.VIEW_REPORT); |
||||||
|
List<FactTable> facts = dbAdapter.getFactTables(sachgebiete, factTables); |
||||||
|
return facts; |
||||||
|
} |
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, path = "/dimensions") |
||||||
|
public List<Dimension> listDimensions(@RequestParam(value = "facttable_id") String facttable_id) { |
||||||
|
int sachgebietTid = dbAdapter.getSachgebietByFactTableId(facttable_id); |
||||||
|
rightsService.checkSachgebiet(sachgebietTid, Right.CREATE_ANALYSIS); |
||||||
|
rightsService.checkFactTable(new Identifier(facttable_id), Right.CREATE_ANALYSIS); |
||||||
|
return dbAdapter.getDimensions(new Identifier(facttable_id)); |
||||||
|
} |
||||||
|
|
||||||
|
// TODO: zeig in benamung does es sich vllt. um eine reduzierte liste handelt
|
||||||
|
// granted vs allowed
|
||||||
|
// umstellen auf camel case
|
||||||
|
@RequestMapping(method = RequestMethod.GET, path = "/dimensionAttributeValues") |
||||||
|
public List<String> listAttributeValues (@RequestParam(value = "attribute_id") List<Identifier> attribute_id, @RequestParam(value = "facts") List<Identifier> facts) { |
||||||
|
List<Integer> tids = rightsService.getSachgebiete(Right.CREATE_ANALYSIS); |
||||||
|
List<Identifier> factTables = rightsService.getFactTables(Right.CREATE_ANALYSIS); |
||||||
|
List<DimensionAttribute> attributes = dbAdapter.getAllowedDimensionAttributes(attribute_id, tids, factTables); |
||||||
|
return dbAdapter.getDimensionAttributeValues(attributes, facts); |
||||||
|
} |
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, path = "/dimensionAttributeValuesHierarchy") |
||||||
|
public List<List<Object>> listAttributeValuesHierarchy(@RequestParam(value = "attribute_id") String attribute_id) { |
||||||
|
rightsService.checkCreateRights(); |
||||||
|
return dbAdapter.getDimensionAttributeValuesHierarchy(new Identifier(attribute_id)); |
||||||
|
} |
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, path = "/measures") |
||||||
|
public List<Measure> listMeasures(@RequestParam(value = "facttable_id") String facttable_id) { |
||||||
|
rightsService.checkSachgebiet(dbAdapter.getSachgebietByFactTableId(facttable_id), Right.CREATE_ANALYSIS, Right.VIEW_REPORT); |
||||||
|
rightsService.checkFactTable(new Identifier(facttable_id), Right.CREATE_ANALYSIS, Right.VIEW_REPORT); |
||||||
|
return dbAdapter.getMeasures(new Identifier(facttable_id)); |
||||||
|
} |
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, path = "/findReportDefinition") |
||||||
|
public List<StoredReport> findReportDefinition( |
||||||
|
@RequestParam(value = "title") Optional<String> title, |
||||||
|
@RequestParam(value = "sach") Optional<Integer> sach, |
||||||
|
@RequestParam(value = "facts") Optional<List<String>> facts) { |
||||||
|
|
||||||
|
List<Integer> allowedSachgebiete = rightsService.getSachgebiete(Right.CREATE_ANALYSIS, Right.VIEW_REPORT); |
||||||
|
List<Identifier> allowedFacts = rightsService.getFactTables(Right.CREATE_ANALYSIS, Right.VIEW_REPORT); |
||||||
|
|
||||||
|
List<StoredReport> result = new ArrayList<>(); |
||||||
|
for (StoredReport report : dbAdapter.findAllStoredReports()) { |
||||||
|
|
||||||
|
List<Integer> sachgebieteOfReport = dbAdapter.getSachgebieteForReport(report.reportDefinition); |
||||||
|
if (!allowedSachgebiete.isEmpty() && !allowedSachgebiete.containsAll(sachgebieteOfReport)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
if (title.isPresent()) { |
||||||
|
if (!report.name.toLowerCase().contains(title.get().toLowerCase())) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (sach.isPresent()) { |
||||||
|
if (!sachgebieteOfReport.contains(sach.get())) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if(allowedFacts != null && allowedFacts.size() > 0) { |
||||||
|
boolean isFactAllowed = true; |
||||||
|
for (Identifier reportFactId : report.reportDefinition.factTableIds) { |
||||||
|
if(!allowedFacts.isEmpty() && !allowedFacts.contains(reportFactId)) { |
||||||
|
isFactAllowed = false; |
||||||
|
} |
||||||
|
} |
||||||
|
if (!isFactAllowed) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (facts.isPresent()) { |
||||||
|
boolean isFactMissing = false; |
||||||
|
for (Identifier reportFactId : report.reportDefinition.factTableIds) { |
||||||
|
if (!facts.get().contains(reportFactId.composedId)) { |
||||||
|
isFactMissing = true; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (isFactMissing) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
result.add(report); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, path = "/getStoredReport") |
||||||
|
public StoredReport getStoredReport(@RequestParam(value = "id") int id) { |
||||||
|
Optional<StoredReport> storedReportOpt = dbAdapter.findById(id); |
||||||
|
if(storedReportOpt.isPresent()) { |
||||||
|
StoredReport storedReport = storedReportOpt.get(); |
||||||
|
checkCreateOrViewRightForFactTables(storedReport.reportDefinition.factTableIds); |
||||||
|
try { |
||||||
|
storedReport.exportedResult = biAnalysisManager.createResult(storedReport.reportDefinition, dbAdapter); |
||||||
|
} catch (Exception e) { |
||||||
|
logger.error("Couldn't create report", e); |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
|
||||||
|
storedReport.isReadOnly = Boolean.valueOf(!this.rightsService.isCreateRight()); |
||||||
|
return storedReport; |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.POST, path = "/report") |
||||||
|
public Result getReport(@RequestBody final ReportDefinition reportDefinition) throws Exception { |
||||||
|
List<Identifier> factTableIds = reportDefinition.factTableIds; |
||||||
|
checkCreateRightForFactTables(factTableIds); |
||||||
|
return biAnalysisManager.createResult(reportDefinition, dbAdapter); |
||||||
|
} |
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.POST, path = "/persistReportDefinition") |
||||||
|
public int persistReportDefinition(@RequestBody final StoredReport storedReport) throws Exception { |
||||||
|
StoredReport.setReportDefinitionJson(storedReport); |
||||||
|
List<Identifier> factTableIds = storedReport.reportDefinition.factTableIds; |
||||||
|
checkCreateRightForFactTables(factTableIds); |
||||||
|
return dbAdapter.saveReportDefinition(storedReport); |
||||||
|
} |
||||||
|
|
||||||
|
@RequestMapping(value = "/report/download", method = RequestMethod.POST) |
||||||
|
public Download getFile(@RequestBody final StoredReport storedReport) throws Exception { |
||||||
|
checkCreateOrViewRightForFactTables(storedReport.reportDefinition.factTableIds); |
||||||
|
Date date = new Date(); |
||||||
|
String fileName = "BI-Analyse_"; |
||||||
|
if(storedReport.id != 0) { |
||||||
|
fileName += dbAdapter.findById(storedReport.id).get().name + "_"; |
||||||
|
if(fileName.length() > 206) { |
||||||
|
fileName = fileName.substring(0, 160); |
||||||
|
} |
||||||
|
fileName = fileName.replaceAll("[^a-zA-Z0-9äöüÄÖÜß_]+", "_"); |
||||||
|
} |
||||||
|
fileName += new SimpleDateFormat("yyyyMMdd_HHmmss").format(date); |
||||||
|
if(!storedReport.exportedResult.resultType.equals(ResultType.FlatTable)) { |
||||||
|
Row totalRow = storedReport.exportedResult.getTotalRow(); |
||||||
|
storedReport.exportedResult.rows = (BiAnalysisManager.hierarchyToRows(storedReport.hierarchy)); |
||||||
|
storedReport.exportedResult.rows.add(totalRow); |
||||||
|
} |
||||||
|
XSSFWorkbook workbook = new ExcelSheetBuilder(storedReport.exportedResult) |
||||||
|
.withFileName(fileName) |
||||||
|
.withReportName(storedReport.name) |
||||||
|
.withDescription(storedReport.description) |
||||||
|
.withDate(date) |
||||||
|
.build(); |
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
||||||
|
workbook.write(bos); |
||||||
|
String base64String = Base64.getEncoder().encodeToString(bos.toByteArray()); |
||||||
|
String contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; |
||||||
|
return new Download(fileName, contentType, base64String); |
||||||
|
} |
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.POST, path = "/deleteReportDefinition") |
||||||
|
public boolean deleteReportDefinition(@RequestBody final int id) throws Exception { |
||||||
|
try { |
||||||
|
Optional<StoredReport> reportOpt = dbAdapter.findById(id); |
||||||
|
if(reportOpt.isEmpty()) { |
||||||
|
throw new Exception("FEHLER: Berichtskonfiguration konnte nicht gefunden werden."); |
||||||
|
} |
||||||
|
checkCreateRightForFactTables(reportOpt.get().reportDefinition.factTableIds); |
||||||
|
dbAdapter.deleteById(id); |
||||||
|
return true; |
||||||
|
} catch(Exception e) { |
||||||
|
throw new Exception("FEHLER: Berichtskonfiguration konnte nicht gelöscht werden.", e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, path = "/reportDefinitions") |
||||||
|
public List<StoredReport> listReportDefinitions() throws Exception { |
||||||
|
rightsService.checkCreateOrViewRights(); |
||||||
|
List<StoredReport> storedReports = null; |
||||||
|
try { |
||||||
|
storedReports = dbAdapter.findAllStoredReports(); |
||||||
|
// TODO mit Marnie abklären, für überschreiben notwendig?
|
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
if (e.getCause().getMessage().contains("FEHLER: Relation »metadata.rw_report_definitions« existiert nicht")) { |
||||||
|
throw new NotYetImplementedException("Bitte installieren Sie zuerst die Komponente 'BI-Analyse-Daten' und führen Sie anschließend den Konnektor aus."); |
||||||
|
} |
||||||
|
throw e; |
||||||
|
} |
||||||
|
return storedReports; |
||||||
|
} |
||||||
|
|
||||||
|
private void checkCreateOrViewRightForFactTables(List<Identifier> factTableIds) { |
||||||
|
for (Identifier factId : factTableIds) { |
||||||
|
int sachgebiet = dbAdapter.getSachgebietByFactTableId(factId.composedId); |
||||||
|
rightsService.checkSachgebiet(sachgebiet, Right.CREATE_ANALYSIS, Right.VIEW_REPORT); |
||||||
|
rightsService.checkFactTable(factId, Right.CREATE_ANALYSIS, Right.VIEW_REPORT); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void checkCreateRightForFactTables(List<Identifier> factTableIds) { |
||||||
|
for (Identifier factId : factTableIds) { |
||||||
|
int sachgebiet = dbAdapter.getSachgebietByFactTableId(factId.composedId); |
||||||
|
rightsService.checkSachgebiet(sachgebiet, Right.CREATE_ANALYSIS); |
||||||
|
rightsService.checkFactTable(factId, Right.CREATE_ANALYSIS); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,141 @@ |
|||||||
|
package de.superx.bianalysis.service; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import org.apache.log4j.Logger; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import de.superx.bianalysis.ColumnElement; |
||||||
|
import de.superx.bianalysis.ColumnElementBuilder; |
||||||
|
import de.superx.bianalysis.ReportDefinition; |
||||||
|
import de.superx.bianalysis.ReportMetadata; |
||||||
|
import de.superx.bianalysis.ResultBuilder; |
||||||
|
import de.superx.bianalysis.ResultMerger; |
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.sqlgeneration.SQLGenerator; |
||||||
|
import de.superx.bianalysis.sqlgeneration.SQLGeneratorTotals; |
||||||
|
import de.superx.common.NotYetImplementedException; |
||||||
|
import de.superx.rest.model.Item; |
||||||
|
import de.superx.rest.model.Result; |
||||||
|
import de.superx.rest.model.Row; |
||||||
|
import de.superx.rest.model.TreeNode; |
||||||
|
|
||||||
|
@Service |
||||||
|
public class BiAnalysisManager { |
||||||
|
|
||||||
|
static Logger logger = Logger.getLogger(BiAnalysisManager.class); |
||||||
|
|
||||||
|
@Autowired |
||||||
|
BiAnalysisRightService biAnalysisRightService; |
||||||
|
|
||||||
|
public Result createResult(ReportDefinition reportDefinition, DbMetaAdapter dbAdapter) throws Exception { |
||||||
|
|
||||||
|
List<Result> results = new ArrayList<>(); |
||||||
|
ResultMerger resultMerger = new ResultMerger(dbAdapter); |
||||||
|
|
||||||
|
for (Identifier factTableId : reportDefinition.factTableIds) { |
||||||
|
ReportDefinition definition = resultMerger.createFactTableSpecificReportDefinition(reportDefinition, factTableId); |
||||||
|
if(definition.leftDimensionAttributeIds.isEmpty() || |
||||||
|
definition.measureIds.isEmpty()) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
try { |
||||||
|
biAnalysisRightService.checkCreateOrViewRights(); |
||||||
|
ReportMetadata metadata = new ReportMetadata(definition, factTableId, dbAdapter); |
||||||
|
checkColLimit(reportDefinition, dbAdapter, metadata); |
||||||
|
Result reportSegment = getReportData(metadata, dbAdapter); |
||||||
|
results.add(reportSegment); |
||||||
|
} catch (Exception e) { |
||||||
|
logger.error("Couldn't create report", e); |
||||||
|
throw e; |
||||||
|
} |
||||||
|
} |
||||||
|
Result result; |
||||||
|
if(reportDefinition.factTableIds.size() > 1) { |
||||||
|
result = resultMerger.buildMergedReport(reportDefinition, results); |
||||||
|
} else { |
||||||
|
result = results.get(0); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
private static void checkColLimit(ReportDefinition reportDefinition, DbMetaAdapter dbAdapter, ReportMetadata metadata) throws NotYetImplementedException { |
||||||
|
final int POSTGRES_MAX_COL_LIMIT = 1664; |
||||||
|
int resultCols = dbAdapter.getColNumbers(metadata.topDimensionAttributes, metadata.filters); |
||||||
|
resultCols *= reportDefinition.measureIds.size(); |
||||||
|
if(resultCols > POSTGRES_MAX_COL_LIMIT - 1) { |
||||||
|
throw new NotYetImplementedException("FEHLER: Ihre Anfrage überschreitet das Spaltenlimit. " |
||||||
|
+ "Bitte wählen Sie eine andere Kombination an Attributen."); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static String getSqlStatement(ReportDefinition definition, DbMetaAdapter dbAdapter) { |
||||||
|
String sqlStatement = ""; |
||||||
|
ReportMetadata reportMetadata = definition.getReportMetadata(dbAdapter, definition.factTableIds.get(0)); |
||||||
|
List<ColumnElement> columnElements = ColumnElementBuilder.buildColumnElements(reportMetadata); |
||||||
|
SQLGenerator sqlGenerator = new SQLGenerator(reportMetadata, columnElements); |
||||||
|
sqlStatement = sqlGenerator.buildSqlStatement(); |
||||||
|
return sqlStatement; |
||||||
|
} |
||||||
|
|
||||||
|
private Result getReportData(ReportMetadata metadata, DbMetaAdapter dbAdapter) throws Exception { |
||||||
|
List<ColumnElement> columnElements = ColumnElementBuilder.buildColumnElements(metadata); |
||||||
|
|
||||||
|
List<Item> sqlStatements = new ArrayList<>(); |
||||||
|
String reportSQL = new SQLGenerator(metadata, columnElements).buildFormattedSqlStatement(); |
||||||
|
String totalsColumnSQL = SQLGeneratorTotals.generateTotalsColumnSQL(metadata); |
||||||
|
sqlStatements.add(new Item("noAggregatesSQL", reportSQL)); |
||||||
|
sqlStatements.add(new Item("totalsColumnSQL", totalsColumnSQL)); |
||||||
|
|
||||||
|
ResultBuilder resultBuilder = new ResultBuilder(dbAdapter.getDataSource()); |
||||||
|
resultBuilder.setColumnElements(columnElements); |
||||||
|
resultBuilder.setReportMetadata(metadata); |
||||||
|
|
||||||
|
Result report = resultBuilder.buildReport(sqlStatements, biAnalysisRightService.isCreateRight()); |
||||||
|
return report; |
||||||
|
} |
||||||
|
|
||||||
|
public static List<Row> hierarchyToRows(ArrayList<TreeNode> hierarchy) { |
||||||
|
List<Row> rows = new ArrayList<Row>(); |
||||||
|
for (TreeNode treeNode : hierarchy) { |
||||||
|
nodeToRow(treeNode, rows); |
||||||
|
} |
||||||
|
return rows; |
||||||
|
} |
||||||
|
|
||||||
|
private static List<Row> nodeToRow(TreeNode<Map<String, Object>> treeNode, List<Row> rows) { |
||||||
|
splitHierarchyColumn(treeNode); |
||||||
|
rows.add(new Row(treeNode.data, true)); |
||||||
|
for (TreeNode child: treeNode.children) { |
||||||
|
List<Row> childRows = nodeToRow(child, rows); |
||||||
|
for (Row row : childRows) { |
||||||
|
if (!rows.contains(row)){ |
||||||
|
rows.add(row); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return rows; |
||||||
|
} |
||||||
|
|
||||||
|
//Im Treenode wird die Hierarchie in einer Spalte abgebildet, diese muss wieder auf die ursprünglichen Spalten aufgeuteilt werden
|
||||||
|
private static void splitHierarchyColumn(TreeNode<Map<String, Object>> node) { |
||||||
|
String realColumn = node.data.get("column").toString(); |
||||||
|
if( realColumn.contains(" (Ebene ")) { |
||||||
|
String[] splittedString = realColumn.split(" \\(Ebene "); |
||||||
|
String mainColumn = splittedString[0]; |
||||||
|
node.data.put(realColumn, node.data.get(mainColumn)); |
||||||
|
node.data.put(mainColumn, ""); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static String getTotalsColumnSqlStatement(ReportDefinition definition, DbMetaAdapter dbAdapter) { |
||||||
|
String sqlStatement = ""; |
||||||
|
ReportMetadata metadata = new ReportMetadata(definition, definition.factTableIds.get(0), dbAdapter); |
||||||
|
sqlStatement = SQLGeneratorTotals.generateTotalsColumnSQL(metadata); |
||||||
|
return sqlStatement; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,135 @@ |
|||||||
|
package de.superx.bianalysis.service; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.models.Right; |
||||||
|
import de.superx.bianalysis.models.RightParam; |
||||||
|
import de.superx.common.AccessDeniedException; |
||||||
|
import de.superx.common.SxUser; |
||||||
|
import de.superx.spring.service.UserService; |
||||||
|
|
||||||
|
@Service() |
||||||
|
public class BiAnalysisRightService { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
DbMetaAdapter dbAdapter; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
UserService userService; |
||||||
|
|
||||||
|
public void checkCreateRights() { |
||||||
|
SxUser user = (SxUser) userService.currentUserDetails(); |
||||||
|
if ( user != null && !user.getHis1Rights().contains("RIGHT_CS_BIA_ANALYSIS_CREATE_ANALYSIS") ) { |
||||||
|
throw new AccessDeniedException("No right to access Create functions"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isCreateRight() { |
||||||
|
SxUser user = (SxUser) userService.currentUserDetails(); |
||||||
|
if ( user != null && !user.getHis1Rights().contains("RIGHT_CS_BIA_ANALYSIS_CREATE_ANALYSIS") ) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public void checkCreateOrViewRights() { |
||||||
|
SxUser user = (SxUser) userService.currentUserDetails(); |
||||||
|
if ( user != null && !user.getHis1Rights().contains("RIGHT_CS_BIA_ANALYSIS_CREATE_ANALYSIS") && |
||||||
|
!user.getHis1Rights().contains("RIGHT_CS_BIA_ANALYSIS_VIEW_ANALYSIS_TABLE") ) { |
||||||
|
throw new AccessDeniedException("No right to access Create and View functions"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public List<Integer> getSachgebiete(Right... rights) { |
||||||
|
List<String> values = getRightParamValues(RightParam.TOPIC_AREA, rights); |
||||||
|
List<String> valuesForTopics = dbAdapter.getSachgebieteForFactTables(getRightParamValues(RightParam.TOPIC, rights)); |
||||||
|
values.addAll(valuesForTopics); |
||||||
|
if (values.isEmpty()) { |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
List<Integer> sachgebietValues = values.stream() |
||||||
|
.map(Integer::parseInt).collect(Collectors.toList()); |
||||||
|
return sachgebietValues; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Identifier> getFactTables(Right... rights) { |
||||||
|
List<String> values = getRightParamValues(RightParam.TOPIC, rights); |
||||||
|
if (values.isEmpty()) { |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
List<Identifier> factsValues = values.stream() |
||||||
|
.map(value -> new Identifier(value)).collect(Collectors.toList()); |
||||||
|
return factsValues; |
||||||
|
} |
||||||
|
|
||||||
|
public void checkSachgebiet(int sachgebiet, Right... rights) { |
||||||
|
List<Integer> sachgebiete = getSachgebiete(rights); |
||||||
|
if (sachgebiete.isEmpty()) { |
||||||
|
return; |
||||||
|
} else if (!sachgebiete.contains(Integer.valueOf(sachgebiet))){ |
||||||
|
throw new AccessDeniedException("No right to access Sachgebiet " + sachgebiet); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void checkFactTable(Identifier fact, Right... rights) { |
||||||
|
List<Identifier> factTables = getFactTables(rights); |
||||||
|
if (factTables.isEmpty()) { |
||||||
|
return; |
||||||
|
} else if (!factTables.contains(fact)){ |
||||||
|
throw new AccessDeniedException("No right to access Fact Table " + fact.composedId); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the values of a RightParam for a given array of Rights. |
||||||
|
* @param param RightParam which can be assigned to multiple Rights. |
||||||
|
* @param rights Rights which may or may not contain the RightParam. |
||||||
|
* @return List of values for the RightParam (first occurrence for multiple Rights). |
||||||
|
*/ |
||||||
|
public List<String> getRightParamValues(RightParam param, Right... rights) { |
||||||
|
SxUser user = (SxUser) userService.currentUserDetails(); |
||||||
|
if(user == null) { |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
Map<String, Map<String,String>> rightsMap = user.getRightsMap(); |
||||||
|
Map<String, String> rightParamMap = null; |
||||||
|
boolean noRights = true; |
||||||
|
for (Right right : rights) { |
||||||
|
if(rightsMap.containsKey(right.getString())) { |
||||||
|
rightParamMap = rightsMap.get(right.getString()); |
||||||
|
noRights = false; |
||||||
|
if(rightParamMap != null) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if(noRights) { |
||||||
|
throw new AccessDeniedException("Missing rights: " + Right.getPrintableRights(rights)); |
||||||
|
} |
||||||
|
|
||||||
|
if(rightParamMap == null || rightParamMap.isEmpty()) { |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
String paramValues = rightParamMap.get(param.getString()); |
||||||
|
if (paramValues != null) { |
||||||
|
List<String> paramValuesResult = new ArrayList<>(); |
||||||
|
for (String string : StringUtils.split(paramValues, ',')) { |
||||||
|
paramValuesResult.add(string); |
||||||
|
} |
||||||
|
return paramValuesResult; |
||||||
|
} |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,637 @@ |
|||||||
|
package de.superx.bianalysis.service; |
||||||
|
|
||||||
|
import java.sql.ResultSet; |
||||||
|
import java.sql.SQLException; |
||||||
|
import java.text.SimpleDateFormat; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Date; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Optional; |
||||||
|
import java.util.StringJoiner; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
import javax.sql.DataSource; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.InitializingBean; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.jdbc.core.JdbcTemplate; |
||||||
|
import org.springframework.jdbc.core.RowMapper; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import de.superx.bianalysis.FaultyMetadataException; |
||||||
|
import de.superx.bianalysis.ReportDefinition; |
||||||
|
import de.superx.bianalysis.ReportMetadata; |
||||||
|
import de.superx.bianalysis.StoredReport; |
||||||
|
import de.superx.bianalysis.metadata.Identifier; |
||||||
|
import de.superx.bianalysis.models.Dimension; |
||||||
|
import de.superx.bianalysis.models.DimensionAttribute; |
||||||
|
import de.superx.bianalysis.models.FactTable; |
||||||
|
import de.superx.bianalysis.models.Filter; |
||||||
|
import de.superx.bianalysis.models.Measure; |
||||||
|
import de.superx.bianalysis.repository.DimensionAttributeRepository; |
||||||
|
import de.superx.bianalysis.repository.DimensionRepository; |
||||||
|
import de.superx.bianalysis.repository.FactRepository; |
||||||
|
import de.superx.bianalysis.repository.MeasureFilterRepository; |
||||||
|
import de.superx.bianalysis.repository.MeasureRepository; |
||||||
|
import de.superx.bianalysis.repository.StoredReportRepository; |
||||||
|
import de.superx.bianalysis.repository.dto.AttributeDto; |
||||||
|
import de.superx.bianalysis.repository.dto.DimensionDto; |
||||||
|
import de.superx.bianalysis.repository.dto.FactDto; |
||||||
|
import de.superx.bianalysis.repository.dto.MeasureDto; |
||||||
|
import de.superx.bianalysis.repository.dto.MeasureFilterDto; |
||||||
|
import de.superx.common.NotYetImplementedException; |
||||||
|
import de.superx.jdbc.entity.Sachgebiet; |
||||||
|
import de.superx.jdbc.entity.Systeminfo; |
||||||
|
import de.superx.jdbc.repository.SachgebieteRepository; |
||||||
|
import de.superx.jdbc.repository.SysteminfoRepository; |
||||||
|
|
||||||
|
@Service() |
||||||
|
public class DbMetaAdapter implements InitializingBean { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
FactRepository factRepository; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
MeasureRepository measureRepository; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
DimensionRepository dimensionRepository; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
DimensionAttributeRepository dimensionAttrRepo; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
MeasureFilterRepository measureFilterRepo; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
StoredReportRepository storedReportRepository; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
SachgebieteRepository sachgebieterepository; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
SysteminfoRepository systeminfoRepository; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
DataSource dataSource; |
||||||
|
|
||||||
|
private JdbcTemplate jt; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void afterPropertiesSet() throws Exception { |
||||||
|
this.jt = new JdbcTemplate(dataSource); |
||||||
|
} |
||||||
|
|
||||||
|
public List<FactTable> getFactTables(List<Integer> sachgebieteTids, List<Identifier> facts) throws NotYetImplementedException { |
||||||
|
try { |
||||||
|
List<FactTable> factTables = this.factRepository.findAll() |
||||||
|
.stream() |
||||||
|
.filter(f -> getSachgebietForFacttable(f.sachgebiettid.intValue()).tid.intValue() != -1) |
||||||
|
.filter(f -> sachgebieteTids.isEmpty() || sachgebieteTids.contains(Integer.valueOf(f.sachgebiettid.intValue()))) |
||||||
|
.filter(f -> facts.isEmpty() || facts.contains(f.id) || !hasSachgebietTopicRestrictions(facts, f.sachgebiettid.intValue()) ) |
||||||
|
.map(f -> { |
||||||
|
FactTable fact = new FactTable(f); |
||||||
|
fact.setSachgebiet(getSachgebietForFacttable(f.sachgebiettid.intValue())); |
||||||
|
fact.setConformedDimensions(getConformedDimensionsForFacttable(f.id)); |
||||||
|
return fact; |
||||||
|
}) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
return factTables; |
||||||
|
} catch (Exception e) { |
||||||
|
|
||||||
|
e.printStackTrace(); |
||||||
|
if (e.getCause().getMessage().contains("FEHLER: Relation »metadata.facttable« existiert nicht")) { |
||||||
|
throw new NotYetImplementedException("Bitte installieren Sie zuerst die Komponente 'BI-Analyse-Daten' und führen Sie anschließend den Konnektor aus."); |
||||||
|
} |
||||||
|
throw e; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private boolean hasSachgebietTopicRestrictions(List<Identifier> facts, int tid) { |
||||||
|
for (Identifier factId : facts) { |
||||||
|
if(getFactTable(factId).getSachgebiettid() == tid) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Dimension> getConformedDimensionsForFacttable(Identifier factId){ |
||||||
|
List<Dimension> conformedDimension = new ArrayList<>(); |
||||||
|
List<Identifier> ids = dimensionRepository.getUsedConformedDimensionsByFactTable(factId.composedId); |
||||||
|
for (Identifier id : ids) { |
||||||
|
Dimension dimension = getDimension(id); |
||||||
|
List<DimensionAttribute> attributes = getAttributesOfDimension(dimension.getId()); |
||||||
|
|
||||||
|
dimension.setDimensionAttributes(attributes); |
||||||
|
for(DimensionAttribute a : attributes) { |
||||||
|
a.setDimension(dimension); |
||||||
|
} |
||||||
|
conformedDimension.add(getDimension(id)); |
||||||
|
} |
||||||
|
return conformedDimension; |
||||||
|
} |
||||||
|
|
||||||
|
public List<DimensionAttribute> getDimensionAttributeMetadata(List<Identifier> attributeIds, Identifier factId) { |
||||||
|
|
||||||
|
if (attributeIds == null || attributeIds.size() <= 0 ) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
List<DimensionAttribute> result = new ArrayList<DimensionAttribute>(); |
||||||
|
for (Identifier id : attributeIds) { |
||||||
|
Optional<AttributeDto> optAttribute = dimensionAttrRepo.findById(id); |
||||||
|
if(optAttribute.isEmpty()) { |
||||||
|
throw new FaultyMetadataException(id, "Attribute"); |
||||||
|
} |
||||||
|
|
||||||
|
DimensionAttribute attr = new DimensionAttribute(optAttribute.get()); |
||||||
|
Dimension dim = null; |
||||||
|
|
||||||
|
if(factId != null) { |
||||||
|
// case 1: id is role playing -> rpId is null because the attribute array of the conf dim is not empty
|
||||||
|
// case 2: id is NOT role playing because the attribute array of the conf dim is empty
|
||||||
|
Identifier rpId = getRolePlayingDimensionWithNoAttributes(id.composedId, factId.composedId); |
||||||
|
if(rpId != null) { |
||||||
|
dim = getDimension(rpId); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if(dim == null) { |
||||||
|
dim = getDimension(attr.getDimensionId()); |
||||||
|
} |
||||||
|
|
||||||
|
attr.setDimension(dim); |
||||||
|
|
||||||
|
if(attr.getAttrConformedId() != null) { |
||||||
|
Optional<AttributeDto> optAttributeConf = dimensionAttrRepo.findById(new Identifier(attr.getAttrConformedId())); |
||||||
|
if(optAttributeConf.isPresent()) { |
||||||
|
Dimension dimConf = getDimension(optAttributeConf.get().dimensionId); |
||||||
|
attr.setDimConformedId(dimConf.getId().composedId); |
||||||
|
} |
||||||
|
} |
||||||
|
result.add(attr); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Measure> getMeasureMetadata(List<Identifier> measureIds) { |
||||||
|
if (measureIds != null && measureIds.size() > 0 ) { |
||||||
|
List<Measure> result = new ArrayList<Measure>(); |
||||||
|
for (Identifier id : measureIds) { |
||||||
|
Measure measure = getMeasure(id); |
||||||
|
if(measure.getMeasureFilterId() != null) { |
||||||
|
MeasureFilterDto filter = measureFilterRepo.findById(measure.getMeasureFilterId()).get(); |
||||||
|
if(filter.dimensionAttributeId != null) { |
||||||
|
DimensionAttribute attribute = getDimensionAttributeById(filter.dimensionAttributeId); |
||||||
|
Dimension dimension = getDimension(attribute.getDimensionId()); |
||||||
|
measure.setMeasureFilterAttributes(filter, attribute, dimension); |
||||||
|
} else if(filter.factColumnFilter != null) { |
||||||
|
measure.setFactColumnFilter(filter); |
||||||
|
} |
||||||
|
} |
||||||
|
result.add(measure); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public List<Dimension> getDimensions(Identifier factTableId) { |
||||||
|
List<Dimension> dimensions = new ArrayList<>(); |
||||||
|
for (DimensionDto dimensionDto : dimensionRepository.findByFactTableId(factTableId)) { |
||||||
|
if(dimensionDto.isHidden != null && dimensionDto.isHidden.booleanValue() == true) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
Dimension dimension = new Dimension(dimensionDto); |
||||||
|
dimensions.add(dimension); |
||||||
|
List<DimensionAttribute> attr = getAttributesOfDimension(dimension.getId()); |
||||||
|
dimension.setDimensionAttributes(attr); |
||||||
|
if(dimension.getConformed() != null) { |
||||||
|
Dimension dimConf = getDimension(new Identifier(dimension.getConformed())); |
||||||
|
dimension.conformedCaption = dimConf.getCaption(); |
||||||
|
dimension.conformedDescription = dimConf.getDescription(); |
||||||
|
if(attr.isEmpty() && !dimension.getConformed().isEmpty()) { |
||||||
|
attr = getAttributesOfDimension(new Identifier(dimension.getConformed())); |
||||||
|
for( DimensionAttribute a : attr) { |
||||||
|
a.setAttrConformedId(a.getStringId()); |
||||||
|
a.setHierarchy(dimConf.isHierarchy()); |
||||||
|
} |
||||||
|
dimension.setDimensionAttributes(attr); |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
for(DimensionAttribute a : attr) { |
||||||
|
if(a.getAttrConformedId() != null) { |
||||||
|
DimensionAttribute attribute = getDimensionAttributeById(new Identifier(a.getAttrConformedId())); |
||||||
|
a.setConformedCaption(attribute.getCaption()); |
||||||
|
a.setConformedDescription(attribute.getDescription()); |
||||||
|
} |
||||||
|
a.setDimension(dimension); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return dimensions; |
||||||
|
} |
||||||
|
|
||||||
|
public List<DimensionAttribute> getAllowedDimensionAttributes(List<Identifier> ids, List<Integer> sachgebietTids, List<Identifier> factTables){ |
||||||
|
List<DimensionAttribute> attributes = new ArrayList<>(); |
||||||
|
for (Identifier id : ids) { |
||||||
|
DimensionAttribute attr = getDimensionAttributeById(id); |
||||||
|
Dimension dim = getDimension(attr.getDimensionId()); |
||||||
|
attr.setDimension(dim); |
||||||
|
Optional<FactDto> factOpt = factRepository.findById(dim.getId()); |
||||||
|
if(factOpt.isPresent()) { |
||||||
|
if(!factTables.contains(factOpt.get().id)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
Integer sachgebiettsTid = Integer.valueOf(factOpt.get().sachgebiettid.intValue()); |
||||||
|
if(!sachgebietTids.isEmpty() && !sachgebietTids.contains(sachgebiettsTid)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
attributes.add(attr); |
||||||
|
} |
||||||
|
return attributes; |
||||||
|
} |
||||||
|
|
||||||
|
public List<String> getDimensionAttributeValues(List<DimensionAttribute> attributes, List<Identifier> factTables) { |
||||||
|
List<String> result = new ArrayList<String>(); |
||||||
|
List<String> tables = new ArrayList<String>(); |
||||||
|
for (DimensionAttribute attr : attributes) { |
||||||
|
if(tables.contains(attr.getTablename())) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
tables.add(attr.getTablename()); |
||||||
|
for(Identifier factId : factTables) { |
||||||
|
FactTable fact = getFactTable(factId); |
||||||
|
Dimension dim = getDimension(attr.getDimensionId()); |
||||||
|
List<String> values = getDimensionAttributeValues(attr, dim, fact); |
||||||
|
result.addAll(values); |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public List<List<Object>> getDimensionAttributeValuesHierarchy(Identifier attribute_id) { |
||||||
|
DimensionAttribute attr = getDimensionAttributeById(attribute_id); |
||||||
|
Dimension dim = getDimension(attr.getDimensionId()); |
||||||
|
return getDimensionAttributeValuesHierarchy(attr.getColumnname(), dim.getTablename()); |
||||||
|
} |
||||||
|
|
||||||
|
public List<Filter> getFilterMetadata(List<Filter> filters) { |
||||||
|
for (Filter filter : filters) { |
||||||
|
DimensionAttribute attr = getDimensionAttributeById(filter.dimensionAttributeId); |
||||||
|
Dimension dim = getDimension(attr.getDimensionId()); |
||||||
|
attr.setDimension(dim); |
||||||
|
filter.setDimension(dim); |
||||||
|
filter.setDimensionAttribute(attr); |
||||||
|
} |
||||||
|
return filters; |
||||||
|
} |
||||||
|
|
||||||
|
public List<String> getDimensionAttributeValues(DimensionAttribute attr, Dimension dim, FactTable factTable) { |
||||||
|
String sortOrderColumnName = attr.getSortOrderColumn() != null ? attr.getSortOrderColumn(): attr.getColumnname(); |
||||||
|
|
||||||
|
String templateSql = |
||||||
|
"SELECT DISTINCT d.%s AS value, d.%s, " + |
||||||
|
"array_position(array[%s], d.%s::text) " + |
||||||
|
"FROM presentation.%s d"; |
||||||
|
|
||||||
|
if(dim != null |
||||||
|
&& attr.getFilterSelection() != null |
||||||
|
&& attr.getFilterSelection().equals("show_existing_only")) { |
||||||
|
|
||||||
|
templateSql += " INNER JOIN presentation." + factTable.getTablename() |
||||||
|
+ " f ON d.id = f." + dim.getJoincolumn(); |
||||||
|
} |
||||||
|
|
||||||
|
templateSql += " WHERE d.%s IS NOT NULL "; |
||||||
|
|
||||||
|
if(dim != null |
||||||
|
&& attr.getFilterSelection() != null |
||||||
|
&& attr.getFilterSelection().equals("show_range")) { |
||||||
|
|
||||||
|
templateSql += " AND d.id BETWEEN (" |
||||||
|
+ "SELECT MIN(" + dim.getJoincolumn() + ")" |
||||||
|
+ " FROM presentation." + factTable.getTablename() |
||||||
|
+ ") AND (" |
||||||
|
+ "SELECT MAX(" + dim.getJoincolumn() |
||||||
|
+ " FROM presentation." + factTable.getTablename() + ")"; |
||||||
|
} |
||||||
|
|
||||||
|
// TODO: sometimes we need DESC
|
||||||
|
templateSql += " ORDER BY 3, 2 ASC;"; |
||||||
|
|
||||||
|
String query = String.format( |
||||||
|
templateSql, |
||||||
|
attr.getColumnname(), |
||||||
|
sortOrderColumnName, |
||||||
|
DimensionAttribute.specialValueListForSql(), |
||||||
|
attr.getColumnname(), |
||||||
|
attr.getTablename(), |
||||||
|
attr.getColumnname() |
||||||
|
); |
||||||
|
|
||||||
|
List<String> values = jt.query(query, (rs, rowNum) -> rs.getString("value")) |
||||||
|
.stream().distinct().collect(Collectors.toList()); |
||||||
|
|
||||||
|
return values; |
||||||
|
} |
||||||
|
|
||||||
|
public List<List<Object>> getDimensionAttributeValuesHierarchy(String columname, String tablename) { |
||||||
|
String query = "select distinct id, parent_id, "+columname+" from presentation." + tablename; |
||||||
|
List<List<Object>> values = jt.query(query, |
||||||
|
new Object[0], |
||||||
|
new RowMapper<List<Object>>() { |
||||||
|
@Override |
||||||
|
public List<Object> mapRow(ResultSet rs, int rowNum) throws SQLException { |
||||||
|
List<Object> result = new ArrayList<>(); |
||||||
|
result.add(Integer.valueOf(rs.getInt("id"))); |
||||||
|
result.add(Integer.valueOf(rs.getInt("parent_id"))); |
||||||
|
result.add(rs.getString(columname)); |
||||||
|
return result; |
||||||
|
} |
||||||
|
} |
||||||
|
); |
||||||
|
|
||||||
|
return values; |
||||||
|
} |
||||||
|
|
||||||
|
public DimensionAttribute getDimensionAttributeMetadataById(Identifier id) { |
||||||
|
DimensionAttribute attr = getDimensionAttributeById(id); |
||||||
|
Dimension dim = getDimension(attr.getDimensionId()); |
||||||
|
attr.setDimension(dim); |
||||||
|
return attr; |
||||||
|
} |
||||||
|
|
||||||
|
public Sachgebiet getSachgebietById(int sachgebietId) { |
||||||
|
return this.sachgebieterepository.findById(Integer.valueOf(sachgebietId)).get(); |
||||||
|
} |
||||||
|
|
||||||
|
public int saveReportDefinition(StoredReport report) { |
||||||
|
StoredReport savedStoredReport = this.storedReportRepository.save(report); |
||||||
|
return savedStoredReport.id; |
||||||
|
} |
||||||
|
|
||||||
|
public int getBridgeMaxLevel(DimensionAttribute bridgeAttr, ReportMetadata metadata) { |
||||||
|
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); |
||||||
|
String sql = buildMaxHierarchyLvlSQL(bridgeAttr, metadata.factTable.getTablename(), metadata.getFilterNoHierarchy(), bridgeAttr.getTablename()); |
||||||
|
int value = jdbcTemplate.queryForObject(sql, Integer.class).intValue() + 1; |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
public int getBridgeMaxLevel(DimensionAttribute bridgeAttr, ReportMetadata metadata, String factTableName) { |
||||||
|
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); |
||||||
|
String sql = buildMaxHierarchyLvlSQL(bridgeAttr, factTableName, metadata.getFilterNoHierarchy(), bridgeAttr.getTablename()); |
||||||
|
int value = jdbcTemplate.queryForObject(sql, Integer.class).intValue() + 1; |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
public int getBridgeMinLevel(List<Filter> filters, int maxLvl, String dimTable) { |
||||||
|
if(filters == null || filters.isEmpty() ) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); |
||||||
|
List<String> filterValues = new ArrayList<>(); |
||||||
|
|
||||||
|
for (Filter filter : filters) { |
||||||
|
filterValues.add("ancestor_" + filter.columnname + "[%s] IN ( " + filter.getValues() + " )"); |
||||||
|
} |
||||||
|
|
||||||
|
for (int i = 0; i < maxLvl; i++) { |
||||||
|
String sql = "select count(*) from presentation." + dimTable + "_hierarchy" |
||||||
|
+ " where "; |
||||||
|
StringJoiner filterJoiner = new StringJoiner(" OR "); |
||||||
|
|
||||||
|
for (String string : filterValues) { |
||||||
|
filterJoiner.add(String.format(string, Integer.valueOf(i+1))); |
||||||
|
} |
||||||
|
|
||||||
|
sql += filterJoiner.toString(); |
||||||
|
int value = jdbcTemplate.queryForObject(sql, Integer.class).intValue(); |
||||||
|
if(value > 0) { |
||||||
|
return i; |
||||||
|
} |
||||||
|
} |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isAttributeHierarchyBridge(Identifier leftDimensionAttributeId) { |
||||||
|
Optional<AttributeDto> dimAttrOpt = this.dimensionAttrRepo.findById(leftDimensionAttributeId); |
||||||
|
if(dimAttrOpt.isEmpty()) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
Optional<DimensionDto> dimOpt = this.dimensionRepository.findById(dimAttrOpt.get().dimensionId); |
||||||
|
if(dimOpt.isEmpty()) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if(dimOpt.get().isHierarchy == null) return false; |
||||||
|
return dimOpt.get().isHierarchy.booleanValue(); |
||||||
|
} |
||||||
|
|
||||||
|
public int getColNumbers(List<DimensionAttribute> topDimensionAttributes, List<Filter> filters) { |
||||||
|
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); |
||||||
|
int num = 1; |
||||||
|
for (DimensionAttribute dimensionAttribute : topDimensionAttributes) { |
||||||
|
if(filters != null && filters.size() > 0) { |
||||||
|
Filter filter = Filter.findFilterById(filters, dimensionAttribute.getId()); |
||||||
|
if(filter != null && filter.filterValues.size() > 0) { |
||||||
|
num *= filter.filterValues.size(); |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
String sql = String.format("SELECT count(DISTINCT %s) FROM presentation.%s WHERE %s IS NOT NULL", dimensionAttribute.getColumnname(), dimensionAttribute.getTablename(), dimensionAttribute.getColumnname()); |
||||||
|
int value = jdbcTemplate.queryForObject(sql, new Object[] {}, Integer.class).intValue(); |
||||||
|
num *= value; |
||||||
|
} |
||||||
|
return num; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Given a conformed attribute and a facttable this function determines the following: |
||||||
|
* |
||||||
|
* Does this conformed attribute belong to a role playing dimension with no attributes ? |
||||||
|
* |
||||||
|
* If it is the case: return the id of the rp dimension |
||||||
|
*/ |
||||||
|
public Identifier getRolePlayingDimensionWithNoAttributes(String attrId, String factId) { |
||||||
|
Identifier confDimId = dimensionRepository.findDimensionIdForAttribute(attrId); |
||||||
|
System.out.println(attrId); |
||||||
|
List<Identifier> preids = dimensionRepository.getRolePlayingIds(confDimId.composedId, factId); |
||||||
|
if(preids.size() == 1) { |
||||||
|
return preids.get(0); |
||||||
|
} else if (preids.size() > 1) { |
||||||
|
throw new RuntimeException("Not yet implemented: Can't use conformed dimension " |
||||||
|
+ "more than once for the same facttable."); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier checkIfFactTableHasDimensionAttribute(Identifier conformedAttrId, Identifier fact) { |
||||||
|
Identifier rpId = getRolePlayingDimensionWithNoAttributes(conformedAttrId.composedId, fact.composedId); |
||||||
|
|
||||||
|
if(rpId != null) { |
||||||
|
return conformedAttrId; |
||||||
|
} |
||||||
|
List<Identifier> ids = dimensionAttrRepo |
||||||
|
.findAttributesByConformedAttributeAndFactTable(conformedAttrId.composedId, fact.composedId); |
||||||
|
if (ids.size() == 1) { |
||||||
|
return ids.get(0); |
||||||
|
} else if (ids.size() > 1) { |
||||||
|
throw new FaultyMetadataException("Für die Faktentabelle mit der ID '" + fact.composedId |
||||||
|
+ "' existieren zwei Role-Playing Dimensions " + "zugehörig zu der Conformed Dimension mit der ID '" |
||||||
|
+ conformedAttrId.composedId + "'. " + "Dieser Fall ist zurzeit noch nicht umgesetzt."); |
||||||
|
} else { |
||||||
|
Identifier id = dimensionAttrRepo.findAttributesByIdAndFactTable(conformedAttrId.composedId, fact.composedId); |
||||||
|
return id; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public boolean checkIfFactTableHasMeasure(Identifier measure, Identifier fact) { |
||||||
|
return factRepository.hasFactTableMeasure(fact.composedId, measure.composedId); |
||||||
|
} |
||||||
|
|
||||||
|
public String getLastUpdate(int tid) { |
||||||
|
Optional<Systeminfo> systeminfoOpt = systeminfoRepository.findById(Integer.valueOf(tid)); |
||||||
|
if(systeminfoOpt.isPresent()) { |
||||||
|
Date lastUpdate = systeminfoOpt.get().datum; |
||||||
|
return new SimpleDateFormat("dd.MM.yyyy hh:mm").format(lastUpdate); |
||||||
|
} |
||||||
|
return "Unknown"; |
||||||
|
} |
||||||
|
|
||||||
|
public String getFactTableNameMaxBridgeLvl(Identifier fact, Identifier attr) { |
||||||
|
return factRepository.getFactTableNameForAttribute(fact.composedId, attr.composedId); |
||||||
|
} |
||||||
|
|
||||||
|
public DataSource getDataSource() { |
||||||
|
return this.dataSource; |
||||||
|
} |
||||||
|
|
||||||
|
public int getSachgebietByFactTableId(String factTableId) { |
||||||
|
Optional<FactDto> fact = this.factRepository.findById(new Identifier(factTableId)); |
||||||
|
if(fact.isPresent()) { |
||||||
|
return fact.get().sachgebiettid.intValue(); |
||||||
|
} |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Integer> getSachgebieteForReport(ReportDefinition reportDefinition) { |
||||||
|
List<Integer> result = new ArrayList<>(); |
||||||
|
for (Identifier factTableId : reportDefinition.factTableIds) { |
||||||
|
int sachgebiet = getSachgebietByFactTableId(factTableId.composedId); |
||||||
|
result.add(Integer.valueOf(sachgebiet)); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public List<StoredReport> findAllStoredReports(){ |
||||||
|
List<StoredReport> reports = new ArrayList<>(); |
||||||
|
for (StoredReport report : this.storedReportRepository.findAll()) { |
||||||
|
StoredReport.setReportDefinitionFromJson(report); |
||||||
|
reports.add(report); |
||||||
|
} |
||||||
|
return reports; |
||||||
|
} |
||||||
|
|
||||||
|
public Optional<StoredReport> findById(int id) { |
||||||
|
Optional<StoredReport> report = storedReportRepository.findById(id); |
||||||
|
if(report.isPresent()) { |
||||||
|
StoredReport.setReportDefinitionFromJson(report.get()); |
||||||
|
} |
||||||
|
return report; |
||||||
|
} |
||||||
|
|
||||||
|
public void deleteById(int id) { |
||||||
|
storedReportRepository.deleteById(id); |
||||||
|
} |
||||||
|
|
||||||
|
private Sachgebiet getSachgebietForFacttable(int sachgebiettid) { |
||||||
|
Optional<Sachgebiet> sachgebiet = sachgebieterepository |
||||||
|
.findById(Integer.valueOf(sachgebiettid)); |
||||||
|
if(sachgebiet.isPresent()) { |
||||||
|
return sachgebiet.get(); |
||||||
|
} |
||||||
|
return new Sachgebiet(Integer.valueOf(-1), "Unknown", null); |
||||||
|
} |
||||||
|
|
||||||
|
public List<String> getSachgebieteForFactTables(List<String> rightParamValues) { |
||||||
|
List<String> result = new ArrayList<>(); |
||||||
|
for (String id : rightParamValues) { |
||||||
|
int sachgebiet = getSachgebietByFactTableId(id); |
||||||
|
if(sachgebiet != -1) { |
||||||
|
result.add(String.valueOf(sachgebiet)); |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public List<DimensionAttribute> getAttributesOfDimension(Identifier dimId){ |
||||||
|
List<AttributeDto> attr = dimensionAttrRepo.findByDimensionId(dimId); |
||||||
|
List<DimensionAttribute> attributes = attr.stream() |
||||||
|
.map(a -> new DimensionAttribute(a)) |
||||||
|
.filter(a -> !a.isHidden()) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
return attributes; |
||||||
|
} |
||||||
|
|
||||||
|
public Dimension getDimension(Identifier id) { |
||||||
|
Optional<DimensionDto> dimOpt = dimensionRepository.findById(id); |
||||||
|
if(dimOpt.isEmpty()) { |
||||||
|
throw new FaultyMetadataException(id, "Dimension"); |
||||||
|
} |
||||||
|
Dimension dimension = new Dimension(dimOpt.get()); |
||||||
|
return dimension; |
||||||
|
} |
||||||
|
|
||||||
|
public Measure getMeasure(Identifier id) { |
||||||
|
Optional<MeasureDto> measureOpt = measureRepository.findById(id); |
||||||
|
if(measureOpt.isEmpty()) { |
||||||
|
throw new FaultyMetadataException(id, "Measure"); |
||||||
|
} |
||||||
|
Measure measure = new Measure(measureOpt.get()); |
||||||
|
return measure; |
||||||
|
} |
||||||
|
|
||||||
|
public DimensionAttribute getDimensionAttributeById(Identifier dimAttrId) { |
||||||
|
Optional<AttributeDto> optAttr = this.dimensionAttrRepo.findById(dimAttrId); |
||||||
|
if(optAttr.isEmpty()) { |
||||||
|
throw new FaultyMetadataException(dimAttrId, "Attribute"); |
||||||
|
} |
||||||
|
return new DimensionAttribute(optAttr.get()); |
||||||
|
} |
||||||
|
|
||||||
|
public List<Measure> getMeasures(Identifier factTableId) { |
||||||
|
List<Measure> measures = new ArrayList<>(); |
||||||
|
for (MeasureDto measureDto : measureRepository.findByFactTableId(factTableId)) { |
||||||
|
measures.add(new Measure(measureDto)); |
||||||
|
} |
||||||
|
return measures; |
||||||
|
} |
||||||
|
|
||||||
|
public FactTable getFactTable(Identifier factTableId) { |
||||||
|
Optional<FactDto> optFact = factRepository.findById(factTableId); |
||||||
|
if(optFact.isEmpty()) { |
||||||
|
throw new FaultyMetadataException(factTableId, "Fact"); |
||||||
|
} |
||||||
|
return new FactTable(optFact.get()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Generates the SQL which returns the max depth for a hierarchy. |
||||||
|
* (Unfortunately i can't think of a better way to achieve this without relying on additional SQL) |
||||||
|
*/ |
||||||
|
private static String buildMaxHierarchyLvlSQL(DimensionAttribute bridgeAttr, String factTable, List<Filter> filters, String dimTab) { |
||||||
|
// TODO: filters
|
||||||
|
String sql = "SELECT MAX(lvl) " |
||||||
|
+ "FROM presentation."+ factTable + " fw " |
||||||
|
+ "LEFT JOIN presentation."+dimTab+"_hierarchy h " |
||||||
|
+ "ON h." + bridgeAttr.getDimIdJoinColumn() +" = fw."+bridgeAttr.getJoincolumn(); |
||||||
|
return sql; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,378 @@ |
|||||||
|
package de.superx.bianalysis.sqlgeneration; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.StringJoiner; |
||||||
|
|
||||||
|
import de.superx.bianalysis.ColumnElement; |
||||||
|
import de.superx.bianalysis.ReportMetadata; |
||||||
|
import de.superx.bianalysis.models.DimensionAttribute; |
||||||
|
import de.superx.bianalysis.models.Filter; |
||||||
|
import de.superx.bianalysis.models.Measure; |
||||||
|
|
||||||
|
/** |
||||||
|
* Lets consider the following example for the SQL Generation: |
||||||
|
* |
||||||
|
* Dimensions: X, Y, Z with one attribute each |
||||||
|
* Attributes |
||||||
|
* - X: DA |
||||||
|
* - values: DA1, DA1 |
||||||
|
* - Y: DB |
||||||
|
* - values: DB1, DB1 |
||||||
|
* - Z: DC |
||||||
|
* - values: DC1, DC1 |
||||||
|
* Measures: |
||||||
|
* - M1: count on col_a |
||||||
|
* - M2: sum on col_b |
||||||
|
* |
||||||
|
* For the simplest use case (all attributes and measures selected without any |
||||||
|
* filters or bridge tables) the generated table would look like this: |
||||||
|
* |
||||||
|
* +---------+-----------------------+----------------------+ |
||||||
|
* | | DA1 | DA2 | |
||||||
|
* | |-----------+-----------+-----------+----------+ |
||||||
|
* | DC | DB1 | DB2 | DB1 | DB2 | |
||||||
|
* | |-----+-----+-----+-----+-----+-----+-----+----+ |
||||||
|
* | | M1 | M2 | M1 | M2 | M1 | M2 | M1 | M2 | |
||||||
|
* +=========+=====+=====+=====+=====+=====+=====+=====+====+ |
||||||
|
* | DC1 | | | | | | | | | |
||||||
|
* +---------+-----+-----+-----+-----+-----+-----+-----+----+ |
||||||
|
* | DC2 | | | | | | | | | |
||||||
|
* +---------+-----+-----+-----+-----+-----+-----+-----+----+ |
||||||
|
* |
||||||
|
* and the generated SQL would look like this: |
||||||
|
* |
||||||
|
* SELECT |
||||||
|
* DC, |
||||||
|
* COUNT(col_a) FILTER (WHERE DA = 'DA1' AND DB = 'DB1') as "col0", |
||||||
|
* SUM(col_b) FILTER (WHERE DA = 'DA1' AND DB = 'DB1') as "col1", |
||||||
|
* COUNT(col_a) FILTER (WHERE DA = 'DA1' AND DB = 'DB2') as "col2", |
||||||
|
* SUM(col_b) FILTER (WHERE DA = 'DA1' AND DB = 'DB2') as "col3", |
||||||
|
* COUNT(col_a) FILTER (WHERE DA = 'DA2' AND DB = 'DB1') as "col4", |
||||||
|
* SUM(col_b) FILTER (WHERE DA = 'DA2' AND DB = 'DB1') as "col5", |
||||||
|
* COUNT(col_a) FILTER (WHERE DA = 'DA2' AND DB = 'DB2') as "col6", |
||||||
|
* SUM(col_b) FILTER (WHERE DA = 'DA2' AND DB = 'DB2') as "col7" |
||||||
|
* FROM |
||||||
|
* presentation.fact_table |
||||||
|
* JOIN presentation.dim_a |
||||||
|
* ON fact_table.dim_a = dim_a.id |
||||||
|
* JOIN presentation.dim_b |
||||||
|
* ON fact_table.dim_b = dim_b.id |
||||||
|
* JOIN presentation.dim_a |
||||||
|
* ON fact_table.dim_c = dim_c.id |
||||||
|
* GROUP BY dim_c.DC |
||||||
|
* |
||||||
|
* |
||||||
|
* !! Special Cases: |
||||||
|
* |
||||||
|
* 1. Filtering Attributes |
||||||
|
* User Filtered to see only DA with values DA1. |
||||||
|
* In this case the select section would shrink to the following four columns: |
||||||
|
* |
||||||
|
* COUNT(col_a) FILTER (WHERE DA = 'DA1' AND DB = 'DB1') as "col0", |
||||||
|
* SUM(col_b) FILTER (WHERE DA = 'DA1' AND DB = 'DB1') as "col1", |
||||||
|
* COUNT(col_a) FILTER (WHERE DA = 'DA1' AND DB = 'DB2') as "col2", |
||||||
|
* SUM(col_b) FILTER (WHERE DA = 'DA1' AND DB = 'DB2') as "col3", |
||||||
|
* COUNT(col_a) FILTER (WHERE DA = 'DA2' AND DB = 'DB1') as "col4" |
||||||
|
* |
||||||
|
* and the following where clause would be appended: |
||||||
|
* |
||||||
|
* WHERE dim_a.DA IN ('DA1') |
||||||
|
* |
||||||
|
* 2. Measures with Build-In-Filter |
||||||
|
* Consider the measure M1 should only count the values DA1 of attribute DA. |
||||||
|
* In this case the filter condition is prepended to the selection section |
||||||
|
* of the specific columns for this measure: |
||||||
|
* |
||||||
|
* COUNT(col_a) FILTER (WHERE col_a IN ('DA1') AND DA = 'DA1' AND DB = 'DB1') as "col0", |
||||||
|
* ... |
||||||
|
* COUNT(col_a) FILTER (WHERE col_a IN ('DA1') AND DA = 'DA1' AND DB = 'DB2') as "col2", |
||||||
|
* ... |
||||||
|
* COUNT(col_a) FILTER (WHERE col_a IN ('DA1') AND DA = 'DA2' AND DB = 'DB1') as "col4", |
||||||
|
* ... |
||||||
|
* COUNT(col_a) FILTER (WHERE col_a IN ('DA1') AND DA = 'DA2' AND DB = 'DB2') as "col6", |
||||||
|
* ... |
||||||
|
* |
||||||
|
* The filter condition for a measure can be either an IN or NOT IN condition. |
||||||
|
* |
||||||
|
*/ |
||||||
|
public class SQLGenerator { |
||||||
|
|
||||||
|
public ReportMetadata reportMetadata; |
||||||
|
public List<ColumnElement> columnElements; |
||||||
|
public char formatSql = ' '; |
||||||
|
private final static String HIERARCHY_MODEL_SUFFIX = "_hierarchy"; |
||||||
|
|
||||||
|
public SQLGenerator(ReportMetadata reportMetadata, List<ColumnElement> columnElements) { |
||||||
|
this.reportMetadata = reportMetadata; |
||||||
|
this.columnElements = columnElements; |
||||||
|
} |
||||||
|
|
||||||
|
public SQLGenerator(ReportMetadata reportMetadata) { |
||||||
|
this.reportMetadata = reportMetadata; |
||||||
|
} |
||||||
|
|
||||||
|
public String buildFormattedSqlStatement() { |
||||||
|
formatSql = '\n'; |
||||||
|
return buildSqlStatement(); |
||||||
|
} |
||||||
|
|
||||||
|
public String buildSqlStatement() { |
||||||
|
StringBuilder statement = new StringBuilder(); |
||||||
|
statement.append("SELECT "); |
||||||
|
statement.append(buildSelectSection()); |
||||||
|
statement.append(formatSql + "FROM presentation." + reportMetadata.factTable.getTablename() ); |
||||||
|
statement.append(buildJoinSection()); |
||||||
|
statement.append(buildFilterSection()); |
||||||
|
statement.append(buildGroupBySection()); |
||||||
|
statement.append(buildOrderBySection()); |
||||||
|
return statement.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public String buildSelectSection() { |
||||||
|
StringJoiner columns = new StringJoiner(", "); |
||||||
|
String dimensionAttributesStatement = selectDimensionAttributes(); |
||||||
|
if (dimensionAttributesStatement != null && !dimensionAttributesStatement.isBlank() ) { |
||||||
|
columns.add(dimensionAttributesStatement); |
||||||
|
} |
||||||
|
StringJoiner measuresStatementJoiner = new StringJoiner(", "); |
||||||
|
columnElements.forEach((columnElement) -> { |
||||||
|
measuresStatementJoiner.add(selectMeasure(columnElement)); |
||||||
|
}); |
||||||
|
String measuresStatement = measuresStatementJoiner.toString(); |
||||||
|
if (measuresStatement != null && !measuresStatement.isBlank()) { |
||||||
|
columns.add(measuresStatement); |
||||||
|
} |
||||||
|
return columns.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public String selectDimensionAttributes() { |
||||||
|
if (reportMetadata.leftDimensionAttributes == null) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
StringJoiner columns = new StringJoiner(", "); |
||||||
|
for (DimensionAttribute attribute : reportMetadata.leftDimensionAttributes) { |
||||||
|
|
||||||
|
String columnName = attribute.getColumnname(); |
||||||
|
String tableAlias = attribute.getDimensionTableAlias(); |
||||||
|
String columnAlias = attribute.getDimensionColumnAlias(); |
||||||
|
|
||||||
|
if(attribute.isHierarchy()) { |
||||||
|
|
||||||
|
// Build select expressions for each hierarchy level (ancestor node),
|
||||||
|
// assigning aliases col0, col1, etc.
|
||||||
|
StringBuilder resultBuilder = new StringBuilder(); |
||||||
|
for (int i = reportMetadata.minBridgeLvl; i < reportMetadata.maxBridgeLvl; i++) { |
||||||
|
resultBuilder |
||||||
|
.append(attribute.getDimensionTableAlias()) |
||||||
|
.append(".ancestor_") |
||||||
|
.append(columnName) |
||||||
|
.append('[').append(i + 1).append(']') |
||||||
|
.append(" AS \"col").append(i).append("\""); |
||||||
|
|
||||||
|
if (i < reportMetadata.maxBridgeLvl - 1) { |
||||||
|
resultBuilder.append(", "); |
||||||
|
} |
||||||
|
} |
||||||
|
columns.add(resultBuilder.toString()); |
||||||
|
|
||||||
|
} else { |
||||||
|
columns.add(String.format("%s.%s AS %s", tableAlias, columnName, columnAlias)); |
||||||
|
|
||||||
|
String sortOrderColumn = attribute.getSortOrderColumn(); |
||||||
|
if (sortOrderColumn != null) { |
||||||
|
columns.add(String.format("%s.%s AS %s_%s", |
||||||
|
tableAlias, sortOrderColumn, columnAlias, sortOrderColumn)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return columns.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getMeasureTablePart(String factTableTablename, Measure measure, List<DimensionAttribute> dimensionAttributes) { |
||||||
|
String result = ""; |
||||||
|
String tableCol = factTableTablename + "." + measure.getColumnname(); |
||||||
|
if(measure.getAggregationType().equals("sum")) { |
||||||
|
result = "SUM(" + tableCol + ")"; |
||||||
|
} else if (measure.getAggregationType().equals("count")) { |
||||||
|
result = "COUNT(" + tableCol + ")"; |
||||||
|
} else if (measure.getAggregationType().equals("distinct-count")) { |
||||||
|
result = "COUNT(distinct(" + tableCol + "))"; |
||||||
|
} else if (measure.getAggregationType().equals("avg")) { |
||||||
|
result = "AVG(" + tableCol + ")"; |
||||||
|
} else if (measure.getAggregationType().equals("min")) { |
||||||
|
result = "MIN(" + tableCol + ")"; |
||||||
|
} else if (measure.getAggregationType().equals("max")) { |
||||||
|
result = "MAX(" + tableCol + ")"; |
||||||
|
} else if (measure.getAggregationType().equals("std")) { |
||||||
|
result = "STDDEV_SAMP(" + tableCol + ")"; |
||||||
|
} else if (measure.getAggregationType().equals("var")) { |
||||||
|
result = "VAR_SAMP(" + tableCol + ")"; |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public String selectMeasure(ColumnElement columnElement) { |
||||||
|
String factTableTablename = reportMetadata.factTable.getTablename(); |
||||||
|
StringBuilder measureSelect = new StringBuilder(); |
||||||
|
Measure measure = columnElement.measure; |
||||||
|
measureSelect.append(getMeasureTablePart(factTableTablename, measure, reportMetadata.leftDimensionAttributes));//todo topdimen hinzufügen
|
||||||
|
if ( measure.filterCondition != null ) { |
||||||
|
// if there exists a filter condition for a specific measure, prepend it to the column filter condition
|
||||||
|
measureSelect.append(formatSql+ "FILTER (WHERE " + measure.filterCondition); |
||||||
|
if (columnElement.dimensionAttributeFilter != null) { |
||||||
|
measureSelect.append(" AND " + columnElement.dimensionAttributeFilter); |
||||||
|
} |
||||||
|
measureSelect.append(")"); |
||||||
|
} else if (columnElement.dimensionAttributeFilter != null) { |
||||||
|
measureSelect.append(formatSql + "FILTER (WHERE " + columnElement.dimensionAttributeFilter + ")"); |
||||||
|
} |
||||||
|
if (measureSelect.length() != 0) { |
||||||
|
measureSelect.append(" AS \"col" + columnElement.columnNumber + "\""); |
||||||
|
} |
||||||
|
return measureSelect.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public String buildJoinSection() { |
||||||
|
StringBuilder statement = new StringBuilder(); |
||||||
|
for (DimensionAttribute attr : reportMetadata.getUniqueDimensionAttributes()) { |
||||||
|
|
||||||
|
String joinColumn = "id"; |
||||||
|
if( attr.getDimIdJoinColumn() != null |
||||||
|
&& !attr.getDimIdJoinColumn().isBlank()) { |
||||||
|
// Hierarchy dimension models must always be joined on an id column.
|
||||||
|
// See the "hierarchy_dim.sql" dbt macro for implementation details.
|
||||||
|
// For other models, the default join column can be customized in the metadata JSON files
|
||||||
|
// using the "id_column" attribute.
|
||||||
|
joinColumn = attr.getDimIdJoinColumn(); |
||||||
|
} |
||||||
|
|
||||||
|
String dimensionTable = attr.getTablename(); |
||||||
|
boolean isTopAttribute = reportMetadata.topDimensionAttributes.contains(attr); |
||||||
|
if(attr.isHierarchy() && !isTopAttribute) { |
||||||
|
// Hierarchy dimension tables use a dedicated join suffix.
|
||||||
|
// For example, dim_orgunit is joined as dim_orgunit_hierarchy.
|
||||||
|
// This hierarchy table contains all node paths in the hierarchy tree.
|
||||||
|
// For additional details, see the "hierarchy_dim.sql" macro.
|
||||||
|
dimensionTable += HIERARCHY_MODEL_SUFFIX; |
||||||
|
} |
||||||
|
|
||||||
|
String join = String.format( |
||||||
|
" JOIN presentation.%s AS %s ON %s.%s = %s.%s", |
||||||
|
dimensionTable, |
||||||
|
attr.getDimensionTableAlias(), |
||||||
|
reportMetadata.factTable.getTablename(), |
||||||
|
attr.getJoincolumn(), |
||||||
|
attr.getDimensionTableAlias(), |
||||||
|
joinColumn |
||||||
|
); |
||||||
|
statement.append(join); |
||||||
|
/* TODO userinput for histroical keys: |
||||||
|
1. is_current |
||||||
|
2. last_known |
||||||
|
3. specific date: (ANY_DATE BETWEEN %s.valid_from AND %s.valid_to) |
||||||
|
*/ |
||||||
|
if(attr.isHistorical()) { |
||||||
|
String currentFilter = String.format( |
||||||
|
" AND %s.is_current = true ", |
||||||
|
attr.getDimensionTableAlias() |
||||||
|
); |
||||||
|
statement.append(currentFilter); |
||||||
|
} |
||||||
|
} |
||||||
|
return statement.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public String buildFilterSection() { |
||||||
|
if (reportMetadata.filters == null || reportMetadata.filters.size() <= 0) { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
StringBuilder statement = new StringBuilder(" WHERE "); |
||||||
|
StringJoiner groups = new StringJoiner(" AND "); |
||||||
|
|
||||||
|
for (Filter filter : reportMetadata.filters) { |
||||||
|
|
||||||
|
if(reportMetadata.isHierarchyFilter(filter)) { |
||||||
|
StringBuilder resultBuilder = new StringBuilder(); |
||||||
|
|
||||||
|
for (int i = reportMetadata.minBridgeLvl; i < reportMetadata.maxBridgeLvl; i++) { |
||||||
|
resultBuilder |
||||||
|
.append(filter.joincolumn) |
||||||
|
.append(".ancestor_") |
||||||
|
.append(filter.columnname) |
||||||
|
.append('[').append(i).append("] IN (") |
||||||
|
.append(filter.getValues()) |
||||||
|
.append(')'); |
||||||
|
|
||||||
|
if (i < reportMetadata.maxBridgeLvl - 1) { |
||||||
|
resultBuilder.append(" OR "); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
groups.add(resultBuilder.toString()); |
||||||
|
|
||||||
|
} else { |
||||||
|
groups.add(filter.dimensionTableAlias + "." + filter.columnname + " IN (" + filter.getValues() + ")"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
statement.append(groups.toString()); |
||||||
|
if(groups.length() == 0) { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
return statement.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public String buildGroupBySection() { |
||||||
|
if(reportMetadata.leftDimensionAttributes == null || reportMetadata.leftDimensionAttributes.size() <= 0) { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
StringBuilder statement = new StringBuilder("GROUP BY ROLLUP ("); |
||||||
|
StringJoiner groups = new StringJoiner(", "); |
||||||
|
for (DimensionAttribute attr : reportMetadata.leftDimensionAttributes) { |
||||||
|
if(attr.isHierarchy()) { |
||||||
|
// TODO: what is happening here?
|
||||||
|
int numOfHierarchyAttributes = reportMetadata.getHierarchyAttributes().size(); |
||||||
|
for (int i = 0; i < numOfHierarchyAttributes; i++) { |
||||||
|
for (int j = 0; j < reportMetadata.maxBridgeLvl; j++) { |
||||||
|
if(j < reportMetadata.minBridgeLvl) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
groups.add("col"+(j + (i * reportMetadata.maxBridgeLvl))); |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
groups.add(attr.getDimensionTableAlias() + "." + attr.getColumnname()); |
||||||
|
if(attr.getSortOrderColumn() != null) { |
||||||
|
groups.add(attr.getDimensionTableAlias() + "." + attr.getSortOrderColumn()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
statement.append(groups.toString()); |
||||||
|
if(groups.length() == 0) { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
statement.append(")"); |
||||||
|
return formatSql + statement.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public StringJoiner buildOrderBySection() { |
||||||
|
StringJoiner orderCols = new StringJoiner(", ", " ORDER BY ", ""); |
||||||
|
orderCols.setEmptyValue(""); |
||||||
|
for (DimensionAttribute attr : reportMetadata.leftDimensionAttributes) { |
||||||
|
if(attr.isHierarchy()) { |
||||||
|
for (int i = reportMetadata.minBridgeLvl; i < reportMetadata.maxBridgeLvl; i++) { |
||||||
|
orderCols.add("col" + i); |
||||||
|
} |
||||||
|
continue; |
||||||
|
} |
||||||
|
if(attr.getSortOrderColumn() != null) { |
||||||
|
orderCols.add(attr.getDimensionTableAlias() + "." + attr.getSortOrderColumn()); |
||||||
|
} else { |
||||||
|
orderCols.add(attr.getDimensionColumnAlias()); |
||||||
|
} |
||||||
|
} |
||||||
|
return orderCols; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,82 @@ |
|||||||
|
package de.superx.bianalysis.sqlgeneration; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.StringJoiner; |
||||||
|
|
||||||
|
import de.superx.bianalysis.ReportMetadata; |
||||||
|
import de.superx.bianalysis.models.DimensionAttribute; |
||||||
|
import de.superx.bianalysis.models.Filter; |
||||||
|
import de.superx.bianalysis.models.Measure; |
||||||
|
|
||||||
|
public class SQLGeneratorTotals { |
||||||
|
|
||||||
|
public SQLGeneratorTotals() {} |
||||||
|
|
||||||
|
public static String buildTotalsColumnSQL(SQLGenerator generator, int maxBridgeLvlOfReport) { |
||||||
|
ReportMetadata metadata = generator.reportMetadata; |
||||||
|
StringBuilder statement = new StringBuilder(); |
||||||
|
statement.append("SELECT "); |
||||||
|
statement.append(buildSelectSectionForTotalsCol(generator, metadata, maxBridgeLvlOfReport)); |
||||||
|
statement.append(generator.formatSql + "FROM presentation." + metadata.factTable.getTablename() ); |
||||||
|
statement.append(generator.buildJoinSection()); |
||||||
|
statement.append(buildFilterSectionForTotalsCol(generator, metadata)); |
||||||
|
statement.append(generator.buildGroupBySection()); |
||||||
|
return statement.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
private static String buildFilterSectionForTotalsCol(SQLGenerator generator, ReportMetadata metadata) { |
||||||
|
if(metadata.topDimensionAttributes.size() == 0 && metadata.filters.size() == 0) { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
StringBuilder where = new StringBuilder(" WHERE "); |
||||||
|
StringJoiner groups = new StringJoiner(" AND "); |
||||||
|
for (DimensionAttribute attribute : metadata.topDimensionAttributes) { |
||||||
|
groups.add(attribute.getDimensionTableAlias() + "." + attribute.getColumnname() + " IN (" + getValues(attribute.getDimensionAttributeValues()) + ")"); |
||||||
|
} |
||||||
|
for (Filter filter : generator.reportMetadata.filters) { |
||||||
|
groups.add(filter.dimensionTableAlias + "." + filter.columnname + " IN (" + filter.getValues() + ")"); |
||||||
|
} |
||||||
|
where.append(groups); |
||||||
|
return where.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
private static String buildSelectSectionForTotalsCol(SQLGenerator generator, ReportMetadata metadata, int maxBridgeLvlOfReport) { |
||||||
|
StringJoiner columns = new StringJoiner(", "); |
||||||
|
columns.add(generator.selectDimensionAttributes()); |
||||||
|
//columns.add(metadata.aggregationLvl + " AS aggregationLvl");
|
||||||
|
int numCols = generator.reportMetadata.maxBridgeLvl; |
||||||
|
for (Measure measure : metadata.measures) { |
||||||
|
String value = generator.getMeasureTablePart(metadata.factTable.getTablename(), measure, metadata.leftDimensionAttributes); |
||||||
|
if ( measure.filterCondition != null ) { |
||||||
|
value += " FILTER (WHERE " + measure.filterCondition +")"; |
||||||
|
} |
||||||
|
value += " AS \"col" + (numCols++) + "\""; |
||||||
|
columns.add(value); |
||||||
|
} |
||||||
|
String selectSection = columns.toString(); |
||||||
|
return selectSection; |
||||||
|
} |
||||||
|
|
||||||
|
private static String getValues(List<String> values) { |
||||||
|
if(values == null || values.isEmpty()) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
StringJoiner joiner = new StringJoiner(", "); |
||||||
|
for (String value : values) { |
||||||
|
joiner.add("'"+value+"'"); |
||||||
|
} |
||||||
|
return joiner.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public static String generateTotalsColumnSQL(ReportMetadata metadata) { |
||||||
|
if(metadata.topDimensionAttributes.isEmpty()) { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
|
||||||
|
SQLGenerator generator = new SQLGenerator(metadata); |
||||||
|
String finalSQL = buildTotalsColumnSQL(generator, metadata.maxBridgeLvl) |
||||||
|
+ generator.buildOrderBySection(); |
||||||
|
return finalSQL; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,510 @@ |
|||||||
|
package de.superx.bin; |
||||||
|
|
||||||
|
import static de.superx.servlet.SxSQL_Server.DEFAULT_MANDANTEN_ID; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
import javax.sql.DataSource; |
||||||
|
|
||||||
|
import org.apache.commons.cli.CommandLine; |
||||||
|
import org.apache.commons.cli.CommandLineParser; |
||||||
|
import org.apache.commons.cli.GnuParser; |
||||||
|
import org.apache.commons.cli.HelpFormatter; |
||||||
|
import org.apache.commons.cli.Option; |
||||||
|
import org.apache.commons.cli.Options; |
||||||
|
import org.apache.commons.cli.ParseException; |
||||||
|
import org.apache.log4j.BasicConfigurator; |
||||||
|
import org.apache.log4j.Level; |
||||||
|
import org.apache.log4j.Logger; |
||||||
|
import org.springframework.batch.core.ExitStatus; |
||||||
|
import org.springframework.beans.BeansException; |
||||||
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
||||||
|
import org.springframework.context.support.GenericApplicationContext; |
||||||
|
import de.superx.job.ContainerNode; |
||||||
|
import de.superx.rest.EtlJobApi; |
||||||
|
import de.superx.rest.model.job.Component; |
||||||
|
import de.superx.rest.model.job.JobExecutionStatus; |
||||||
|
import de.superx.rest.model.job.StepExecutionStatus; |
||||||
|
import de.superx.servlet.SuperXManager; |
||||||
|
import de.superx.servlet.SxPools; |
||||||
|
import de.superx.spring.HisInOneConfiguration; |
||||||
|
import de.superx.spring.batch.His1DataSources; |
||||||
|
import de.superx.spring.cli.config.CLIConfig; |
||||||
|
import de.superx.spring.config.BatchConfig; |
||||||
|
import de.superx.spring.config.DataJdbcConfiguration; |
||||||
|
import de.superx.spring.config.ServiceConfig; |
||||||
|
import de.superx.spring.service.BatchJobDescriptionAdapter; |
||||||
|
import de.superx.spring.service.EntityJobDescriptionSource; |
||||||
|
import de.superx.util.PathAndFileUtils; |
||||||
|
|
||||||
|
/*** |
||||||
|
* This class provides functionality to run the component actions of the |
||||||
|
* 'modernized component administration' |
||||||
|
* of the HISinOne-BI via command line. That includes |
||||||
|
* - listing ETL jobs |
||||||
|
* - installing components |
||||||
|
* - updating components |
||||||
|
* - deinstalling components |
||||||
|
* - running "Hauptladeroutine" ETL jobs |
||||||
|
* - running "Unterladeroutine" ETL jobs |
||||||
|
* The class is just meant to be a frontend, so it uses the same implementation as the web application |
||||||
|
* (which happens to be the "EtlJobApi" bean) |
||||||
|
* However, there are to be some things to be considered: |
||||||
|
* - The "jobLauncher" bean from the "BatchConfig" class works asynchronously, which is fine for the |
||||||
|
* web application context, but in the CLI context, it is overridden by a synchronous implementation |
||||||
|
* (in fact the tweaks to get the configurations ready for the CLI context, are placed in the |
||||||
|
* "CLIConfig" class). |
||||||
|
* - In the web application context, the HISinOne-BI code in the HISinOne web application writes the |
||||||
|
* database configuration to a file, which is then consumed by the "superx" application (the actual |
||||||
|
* HISinOne-BI application). The command line application needs this file too, so before using it, you |
||||||
|
* should start the web application one time, in order to have the file in place. |
||||||
|
* @author witt |
||||||
|
* |
||||||
|
*/ |
||||||
|
public class ComponentAdminCLI { |
||||||
|
|
||||||
|
private static GenericApplicationContext APPLICATION_CONTEXT = null; |
||||||
|
|
||||||
|
private static String HELP_STRING = "Use this tool to run component actions via command line. " |
||||||
|
+ "It needs the config file 'his1_databases.properties' inside the classpath; " |
||||||
|
+ "this file gets written automatically when starting the web application."; |
||||||
|
|
||||||
|
private static boolean FILESYSTEM = false; |
||||||
|
|
||||||
|
static Logger logger = Logger.getLogger(ComponentAdminCLI.class); |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
BasicConfigurator.configure(); // initializes console logging to stdout
|
||||||
|
System.setProperty(SuperXManager.SUPER_X_HISINONE_VERSION, "non-empty-value"); |
||||||
|
Options options = createOptions(); |
||||||
|
CommandLine parsedArgs = parseArgs(args, options); |
||||||
|
logOptions(parsedArgs); |
||||||
|
if (parsedArgs.hasOption("h")) { |
||||||
|
printHelp(options); |
||||||
|
System.exit(0); |
||||||
|
} |
||||||
|
if(parsedArgs.hasOption("f")) { |
||||||
|
FILESYSTEM = true; |
||||||
|
} |
||||||
|
initSuperXManager(); |
||||||
|
if(parsedArgs.hasOption("s")) { |
||||||
|
initTablesForEmptyDB(); |
||||||
|
} |
||||||
|
if(parsedArgs.hasOption("lg")) { |
||||||
|
setBatchLoggerToOneFile(); |
||||||
|
} |
||||||
|
SuperXManager.initKettleEnv(createContext()); |
||||||
|
if (parsedArgs.hasOption("la")) { |
||||||
|
printAllJobs(); |
||||||
|
} else if (parsedArgs.hasOption("li")) { |
||||||
|
printInstallableJobs(); |
||||||
|
} else if (parsedArgs.hasOption("le")) { |
||||||
|
printEtlJobs(); |
||||||
|
} else if (parsedArgs.hasOption("i")) { |
||||||
|
installComponents(parsedArgs); |
||||||
|
} else if (parsedArgs.hasOption("d")) { |
||||||
|
deinstallComponent(parsedArgs); |
||||||
|
} else if (parsedArgs.hasOption("u")) { |
||||||
|
upgradeComponents(parsedArgs); |
||||||
|
} else if (parsedArgs.hasOption("ua")) { |
||||||
|
upgradeAll(); |
||||||
|
} else if (parsedArgs.hasOption("e")) { |
||||||
|
etlJobs(parsedArgs); |
||||||
|
} else if (parsedArgs.hasOption("r")) { |
||||||
|
reloadModule(); |
||||||
|
} else if (parsedArgs.hasOption("if")) { |
||||||
|
installFunctions(parsedArgs); |
||||||
|
} else { |
||||||
|
printHelp(options); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void logOptions(CommandLine parsedArgs) { |
||||||
|
logger.info("Starting with the following options:"); |
||||||
|
for (Option opt : parsedArgs.getOptions()) { |
||||||
|
logger.info(opt); |
||||||
|
if(opt.getValues() != null && opt.getValues().length > 0) { |
||||||
|
logger.info("Values for option " + opt.getOpt() + ": " + Arrays.asList(opt.getValues())); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void initTablesForEmptyDB() { |
||||||
|
try { |
||||||
|
GenericApplicationContext context = createContext(); |
||||||
|
EtlJobApi componentApi = context.getBean(EtlJobApi.class); |
||||||
|
ContainerNode root = EntityJobDescriptionSource.getPreKernInstallJob(); |
||||||
|
componentApi.executeJob("eduetl", root); |
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void setBatchLoggerToOneFile() { |
||||||
|
try { |
||||||
|
GenericApplicationContext context = createContext(); |
||||||
|
BatchJobDescriptionAdapter bjda = context.getBean(BatchJobDescriptionAdapter.class); |
||||||
|
bjda.setLogJobToFile(false); |
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void installComponents(CommandLine parsedArgs) { |
||||||
|
String[] components = parsedArgs.getOptionValues("i"); |
||||||
|
String currentComp = null; |
||||||
|
try (GenericApplicationContext context = createContext()) { |
||||||
|
initSxPools(); |
||||||
|
EtlJobApi componentApi = context.getBean(EtlJobApi.class); |
||||||
|
for (String comp : components) { |
||||||
|
try { |
||||||
|
currentComp = comp; |
||||||
|
Long jobStartStatus = Long.valueOf(-1); |
||||||
|
if(!FILESYSTEM) { |
||||||
|
logger.info("EXECUTING: install job from database"); |
||||||
|
jobStartStatus = componentApi.executeInstall(comp); |
||||||
|
} else { |
||||||
|
// disable mondrian step
|
||||||
|
logger.info("EXECUTING: install job from filesystem for " + currentComp); |
||||||
|
jobStartStatus = componentApi.executeInstallForQAMuster(comp); |
||||||
|
logger.info("EXECUTING: workaround upgrade job from filesystem for " + currentComp); |
||||||
|
jobStartStatus = componentApi.executeUpgradeForQAMuster(comp); |
||||||
|
} |
||||||
|
handleStartResult(jobStartStatus, componentApi); |
||||||
|
if(comp.equals("kern") && FILESYSTEM) { |
||||||
|
DataSource dataSource = context.getBean(His1DataSources.class).get("eduetl"); |
||||||
|
SuperXManager.setWebInfFilePath(dataSource); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
logger.error("ERROR installing component " + comp, e); |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (BeansException be) { |
||||||
|
handleBeansException(be); |
||||||
|
} catch (Exception e) { |
||||||
|
handleJobException(e, currentComp); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void reloadModule() { |
||||||
|
try (GenericApplicationContext context = createContext()){ |
||||||
|
initSxPools(); |
||||||
|
initSuperXManager(); |
||||||
|
EtlJobApi componentApi = context.getBean(EtlJobApi.class); |
||||||
|
componentApi.writeJobsToDb(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void printHelp(Options options) { |
||||||
|
HelpFormatter help = new HelpFormatter(); |
||||||
|
help.printHelp(HELP_STRING, options); |
||||||
|
} |
||||||
|
|
||||||
|
private static void printInstallableJobs() { |
||||||
|
try (GenericApplicationContext context = createContext()) { |
||||||
|
EtlJobApi componentApi = context.getBean(EtlJobApi.class); |
||||||
|
List<Component> installJobs = componentApi.getInstallJobs(); |
||||||
|
for (Component comp : installJobs) { |
||||||
|
printDetails(comp); |
||||||
|
System.out.println(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void printEtlJobs() { |
||||||
|
try (GenericApplicationContext context = createContext()) { |
||||||
|
EtlJobApi componentApi = context.getBean(EtlJobApi.class); |
||||||
|
List<Component> etlJobs = componentApi.getEtlJobs(); |
||||||
|
for (Component etlJob : etlJobs) { |
||||||
|
printDetails(etlJob); |
||||||
|
System.out.println(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void printDetails(Component comp) { |
||||||
|
System.out.println("abbrev: " + comp.getAbbreviation()); |
||||||
|
System.out.println("name: " + comp.getName()); |
||||||
|
System.out.println("database: " + comp.getDatabase()); |
||||||
|
System.out.println("systeminfo_id: " + comp.getSysteminfoId()); |
||||||
|
System.out.println("installed: " + comp.isInstalled()); |
||||||
|
} |
||||||
|
|
||||||
|
private static void deinstallComponent(CommandLine parsedArgs) { |
||||||
|
String comp = parsedArgs.getOptionValue("d"); |
||||||
|
System.out.println(comp); |
||||||
|
try (GenericApplicationContext context = createContext()) { |
||||||
|
initSxPools(); |
||||||
|
EtlJobApi componentApi = context.getBean(EtlJobApi.class); |
||||||
|
Long jobStartStatus = componentApi.executeUninstall(comp); |
||||||
|
handleStartResult(jobStartStatus, componentApi); |
||||||
|
} catch (BeansException be) { |
||||||
|
handleBeansException(be); |
||||||
|
} catch (Exception e) { |
||||||
|
handleJobException(e, comp); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void upgradeComponents(CommandLine parsedArgs) { |
||||||
|
String[] components = parsedArgs.getOptionValues("u"); |
||||||
|
String currentComp = null; |
||||||
|
try (GenericApplicationContext context = createContext()) { |
||||||
|
initSxPools(); |
||||||
|
EtlJobApi componentApi = context.getBean(EtlJobApi.class); |
||||||
|
for (String comp : components) { |
||||||
|
currentComp = comp; |
||||||
|
Long jobStartStatus = componentApi.executeUpgrade(comp); |
||||||
|
if (jobStartStatus.longValue() == -1) { |
||||||
|
logger.warn(comp + " not installed. Skipping upgrade."); |
||||||
|
continue; |
||||||
|
} |
||||||
|
handleStartResult(jobStartStatus, componentApi); |
||||||
|
} |
||||||
|
} catch (BeansException be) { |
||||||
|
handleBeansException(be); |
||||||
|
} catch (Exception e) { |
||||||
|
handleJobException(e, currentComp); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void installFunctions(CommandLine parsedArgs) { |
||||||
|
String[] components = parsedArgs.getOptionValues("if"); |
||||||
|
try (GenericApplicationContext context = createContext()) { |
||||||
|
initSxPools(); |
||||||
|
EtlJobApi componentApi = context.getBean(EtlJobApi.class); |
||||||
|
// No components given: install
|
||||||
|
// functions for all installed components
|
||||||
|
if (components.length == 1 && "all".equals(components[0])) { |
||||||
|
List<Component> installedComponents = componentApi.getInstallJobs(); |
||||||
|
components = installedComponents.stream().map( |
||||||
|
c -> c.getAbbreviation()).collect(Collectors.toList()).toArray(new String[] {}); |
||||||
|
} |
||||||
|
boolean exitFailure = false; |
||||||
|
for (String comp : components) { |
||||||
|
componentApi.installModuleFunctions(comp); |
||||||
|
} |
||||||
|
if(exitFailure) { |
||||||
|
System.out.println(("Beim Ausführen einer Aktion ist ein Fehler aufgetreten:")); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
} catch (BeansException be) { |
||||||
|
handleBeansException(be); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void upgradeAll() { |
||||||
|
try (GenericApplicationContext context = createContext()) { |
||||||
|
initSxPools(); |
||||||
|
EtlJobApi componentApi = context.getBean(EtlJobApi.class); |
||||||
|
Long jobStartStatus = componentApi.executeUpgradeAll(); |
||||||
|
handleStartResult(jobStartStatus, componentApi); |
||||||
|
} catch (BeansException be) { |
||||||
|
handleBeansException(be); |
||||||
|
} catch (Exception e) { |
||||||
|
handleJobException(e, null); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void etlJobs(CommandLine parsedArgs) { |
||||||
|
String[] jobIds = parsedArgs.getOptionValues("e"); |
||||||
|
String currentJobId = null; |
||||||
|
try (GenericApplicationContext context = createContext()) { |
||||||
|
initSxPools(); |
||||||
|
EtlJobApi componentApi = context.getBean(EtlJobApi.class); |
||||||
|
Long jobStartStatus; |
||||||
|
for (String jobId : jobIds) { |
||||||
|
try { |
||||||
|
currentJobId = jobId; |
||||||
|
if (isHauptladeroutine(jobId, componentApi)) { |
||||||
|
jobStartStatus = componentApi.complete(jobId); |
||||||
|
} else if (isLoadTransform(jobId, componentApi)) { |
||||||
|
jobStartStatus = componentApi.load(jobId); |
||||||
|
} else { |
||||||
|
jobStartStatus = componentApi.executeJob(null, jobId); |
||||||
|
} |
||||||
|
handleStartResult(jobStartStatus, componentApi); |
||||||
|
} catch (Exception e) { |
||||||
|
logger.error("ERROR executing job " + jobId, e); |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (BeansException be) { |
||||||
|
handleBeansException(be); |
||||||
|
} catch (Exception e) { |
||||||
|
handleJobException(e, currentJobId); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void handleStartResult(Long jobStartStatus, EtlJobApi componentApi) { |
||||||
|
if (jobStartStatus.intValue() == -1) { |
||||||
|
System.err.println("Aktion konnte nicht gestartet werden: Es läuft bereits eine Aktion"); |
||||||
|
} |
||||||
|
try { |
||||||
|
JobExecutionStatus es = componentApi.getStatus(jobStartStatus); |
||||||
|
if ("FAILED".equals(es.exitStatus.getExitCode())) { |
||||||
|
EtlJobApi.outputErrorSummary(es, System.err); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
System.err.println(("Beim Ausführen der Aktion ist ein Fehler aufgetreten:")); |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void handleJobException(Exception e, String jobName) { |
||||||
|
System.err.println("error while executing the job '" + jobName + "'"); |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
|
||||||
|
private static void handleBeansException(BeansException be) { |
||||||
|
System.err.println("configuration error or error with resolving the bean '" + EtlJobApi.class.getCanonicalName() + "'"); |
||||||
|
be.printStackTrace(); |
||||||
|
} |
||||||
|
|
||||||
|
private static boolean isHauptladeroutine(String comp, EtlJobApi etlJob) { |
||||||
|
List<Component> installJobs = etlJob.getEtlJobs(); |
||||||
|
for (Component comp_meta : installJobs) { |
||||||
|
if (comp_meta != null && comp_meta.getAbbreviation().equals(comp) && comp_meta.isDatabaseConnected()) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
private static boolean isLoadTransform(String comp, EtlJobApi etlJob) { |
||||||
|
List<Component> installJobs = etlJob.getEtlJobs(); |
||||||
|
for (Component comp_meta : installJobs) { |
||||||
|
if (comp_meta != null && comp_meta.getAbbreviation().equals(comp) && !comp_meta.isDatabaseConnected()) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
private static void printAllJobs() { |
||||||
|
try (GenericApplicationContext context = createContext()) { |
||||||
|
EtlJobApi etlJob = context.getBean(EtlJobApi.class); |
||||||
|
List<ContainerNode> allJobs = etlJob.getAllJobs(); |
||||||
|
for (ContainerNode cn : allJobs) { |
||||||
|
printDetails(cn); |
||||||
|
System.out.println(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static GenericApplicationContext createContext() { |
||||||
|
/* |
||||||
|
* https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/AnnotationConfigApplicationContext.html
|
||||||
|
* quote: |
||||||
|
* "In case of multiple @Configuration classes, @Bean methods defined in later classes will override those defined in earlier classes. |
||||||
|
* This can be leveraged to deliberately override certain bean definitions via an extra @Configuration class." |
||||||
|
* - so it's alright to override some beans via "CLIConfig" |
||||||
|
*/ |
||||||
|
if (APPLICATION_CONTEXT == null) { |
||||||
|
APPLICATION_CONTEXT = new AnnotationConfigApplicationContext(BatchConfig.class, DataJdbcConfiguration.class, CLIConfig.class, ServiceConfig.class); |
||||||
|
HisInOneConfiguration.configSuperXDbformsXML("pg", SuperXManager.getWEB_INFPfad() + File.separator + ".."); |
||||||
|
} |
||||||
|
// Override the JobDescriptionSource Bean if the -f flag is passed.
|
||||||
|
if(FILESYSTEM) { |
||||||
|
EtlJobApi etlJob = APPLICATION_CONTEXT.getBean(EtlJobApi.class); |
||||||
|
EntityJobDescriptionSource entityJobDescriptionSource = APPLICATION_CONTEXT.getBean(EntityJobDescriptionSource.class); |
||||||
|
etlJob.setJobDescriptionSource(entityJobDescriptionSource); |
||||||
|
} |
||||||
|
return APPLICATION_CONTEXT; |
||||||
|
} |
||||||
|
|
||||||
|
private static void printDetails(ContainerNode cn) { |
||||||
|
System.out.println("id: " + cn.id); |
||||||
|
System.out.println("name: " + cn.name); |
||||||
|
System.out.println("systeminfo_id: " + cn.systemInfoId); |
||||||
|
System.out.println("tid: " + cn.tid); |
||||||
|
System.out.println("type: " + cn.type); |
||||||
|
} |
||||||
|
|
||||||
|
private static Options createOptions() { |
||||||
|
Options options = new Options(); |
||||||
|
Option opt; |
||||||
|
opt = new Option("h", "help", false, "get help"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("f", "filesystem", false, "load jobs from filesystem"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("s", "setup", false, "setup minimal list of tables necessary for kern install"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("la", "list-all", false, "list all available components"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("li", "list-installables", false, "list all installable components"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("le", "list-etl", false, "list all etl components"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("i", "install", true, "install components"); |
||||||
|
opt.setArgs(Option.UNLIMITED_VALUES); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("if", "install-functions", true, "install database functions for components (use 'all' to install functions for all installed components)"); |
||||||
|
options.addOption(opt); |
||||||
|
opt.setArgs(Option.UNLIMITED_VALUES); |
||||||
|
opt = new Option("d", "deinstall", true, "de-/uninstall component"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("u", "upgrade", true, "upgrade components"); |
||||||
|
opt.setArgs(Option.UNLIMITED_VALUES); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("ua", "upgrade-all", false, "upgrade all installed components"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("e", "etl", true, "run etl jobs"); |
||||||
|
opt.setArgs(Option.UNLIMITED_VALUES); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("r", "reload-modules", false, "reload modules"); |
||||||
|
options.addOption(opt); |
||||||
|
//opt = new Option("re", "reload-module-etl", true, "reload module etl");
|
||||||
|
//options.addOption(opt);
|
||||||
|
opt = new Option("db", "database", true, "database system"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("lg", "log-to-stdout", false, "log only to stdout and not to individual job files"); |
||||||
|
options.addOption(opt); |
||||||
|
return options; |
||||||
|
} |
||||||
|
|
||||||
|
private static CommandLine parseArgs(String[] args, Options options) { |
||||||
|
CommandLineParser parser = new GnuParser(); |
||||||
|
try { |
||||||
|
return parser.parse(options, args, false); |
||||||
|
} catch (ParseException e) { |
||||||
|
System.out.println("error while reading the command line parameters:"); |
||||||
|
e.printStackTrace(); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
// some actions require the SuperXManager, this is the place for initializing its static class attributes when needed
|
||||||
|
private static void initSuperXManager() { |
||||||
|
try { |
||||||
|
SuperXManager.setWEB_INFPfad(PathAndFileUtils.getWebinfPath()); |
||||||
|
SuperXManager.setModuleDir(PathAndFileUtils.getWebinfPath() + File.separator + PathAndFileUtils.MODULE_PATH); |
||||||
|
} catch(Exception e) { |
||||||
|
System.out.println("error while initialising the SuperXManger:"); |
||||||
|
e.printStackTrace(); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// sxPools need to be initialized, because spring batch ETL uses them to look up the database connections
|
||||||
|
private static void initSxPools() { |
||||||
|
try { |
||||||
|
List<String> mandantenNamen = new LinkedList<String>(); |
||||||
|
mandantenNamen.add(DEFAULT_MANDANTEN_ID); |
||||||
|
SxPools.closeAll(); |
||||||
|
SxPools.init(mandantenNamen); |
||||||
|
SxPools.get(DEFAULT_MANDANTEN_ID).init(); |
||||||
|
SxPools.get(DEFAULT_MANDANTEN_ID).initLogging(true, Level.DEBUG); |
||||||
|
// also init kettle env, set plugin dir
|
||||||
|
SuperXManager.initKettleEnv(APPLICATION_CONTEXT); |
||||||
|
} catch (Exception e) { |
||||||
|
System.out.println("error while initialising the SuperX pools:"); |
||||||
|
e.printStackTrace(); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,674 @@ |
|||||||
|
package de.superx.bin; |
||||||
|
|
||||||
|
import static de.superx.servlet.SxSQL_Server.DEFAULT_MANDANTEN_ID; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.FileOutputStream; |
||||||
|
import java.io.IOException; |
||||||
|
import java.sql.Connection; |
||||||
|
import java.sql.DatabaseMetaData; |
||||||
|
import java.sql.JDBCType; |
||||||
|
import java.sql.ResultSet; |
||||||
|
import java.sql.SQLException; |
||||||
|
import java.sql.Time; |
||||||
|
import java.sql.Timestamp; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.Date; |
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
import javax.sql.DataSource; |
||||||
|
|
||||||
|
import org.apache.commons.cli.CommandLine; |
||||||
|
import org.apache.commons.cli.CommandLineParser; |
||||||
|
import org.apache.commons.cli.GnuParser; |
||||||
|
import org.apache.commons.cli.HelpFormatter; |
||||||
|
import org.apache.commons.cli.Option; |
||||||
|
import org.apache.commons.cli.Options; |
||||||
|
import org.apache.commons.cli.ParseException; |
||||||
|
import org.apache.log4j.Level; |
||||||
|
import org.apache.log4j.Logger; |
||||||
|
import org.apache.poi.xssf.usermodel.XSSFCell; |
||||||
|
import org.apache.poi.xssf.usermodel.XSSFCellStyle; |
||||||
|
import org.apache.poi.xssf.usermodel.XSSFDataFormat; |
||||||
|
import org.apache.poi.xssf.usermodel.XSSFFont; |
||||||
|
import org.apache.poi.xssf.usermodel.XSSFRow; |
||||||
|
import org.apache.poi.xssf.usermodel.XSSFSheet; |
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
||||||
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
||||||
|
import org.springframework.context.support.GenericApplicationContext; |
||||||
|
import org.springframework.jdbc.core.JdbcTemplate; |
||||||
|
import org.springframework.jdbc.core.RowCallbackHandler; |
||||||
|
import org.springframework.jdbc.core.RowMapper; |
||||||
|
|
||||||
|
import de.superx.servlet.SuperXManager; |
||||||
|
import de.superx.servlet.SxPools; |
||||||
|
import de.superx.spring.batch.His1DataSources; |
||||||
|
import de.superx.spring.cli.config.CLIConfig; |
||||||
|
import de.superx.spring.config.BatchConfig; |
||||||
|
import de.superx.spring.config.DataJdbcConfiguration; |
||||||
|
import de.superx.spring.config.ServiceConfig; |
||||||
|
|
||||||
|
/** |
||||||
|
* A utility for creating data profiling statistics for tables in a database |
||||||
|
* to be used in Data Warehouse Design. |
||||||
|
* This can be used as a command line utility or embedded in an application. |
||||||
|
*/ |
||||||
|
public class DataProfiler { |
||||||
|
|
||||||
|
private final static String SQL_COUNT_NULL = "select count(*) from %s where %s is null"; |
||||||
|
private final static String SQL_PERCENT_UNIQUE = "select\n" |
||||||
|
+ " count(distinct %s) as unique_anz,\n" |
||||||
|
+ " count(distinct %s)::float / count(*) * 100 as unique_percentage\n" |
||||||
|
+ "from\n" |
||||||
|
+ " %s;"; |
||||||
|
private final static String SQL_RANKING = "select %s, count(*) as anz from %s where %s is not null group by %s order by 2 desc limit 10;"; |
||||||
|
private final static String SQL_MIN_MAX_LEN = "select min(length(%s)) as min_length, max(length(%s)) as max_length\n" |
||||||
|
+ "from %s\n" |
||||||
|
+ "where %s is not null"; |
||||||
|
private final static String SQL_COUNT_VALUE = "select count(*) from %s where %s = %s"; |
||||||
|
private final static String SQL_MIN_MAX_AVG = "select min(%s), max(%s), avg(%s) from %s where %s is not null;"; |
||||||
|
private final static String SQL_START_END = "select min(%s), max(%s) from %s where %s is not null"; |
||||||
|
|
||||||
|
private static GenericApplicationContext APPLICATION_CONTEXT = null; |
||||||
|
|
||||||
|
private static String HELP_STRING = "Use this tool to profile database tables for dwh design. " |
||||||
|
+ "It needs the config file 'his1_databases.properties' inside the classpath; " |
||||||
|
+ "this file gets written automatically when starting the web application."; |
||||||
|
|
||||||
|
|
||||||
|
static Logger logger = Logger.getLogger(DataProfiler.class); |
||||||
|
|
||||||
|
private DataSource dataSource; |
||||||
|
private String database; |
||||||
|
private String schema; |
||||||
|
private String[] tables; |
||||||
|
|
||||||
|
/** |
||||||
|
* Instantiate a new DataProfiler. |
||||||
|
* @param dataSource The DataSource from which to read the table statistics. |
||||||
|
* @param schema The schema from which to read. If null public is assumed. |
||||||
|
* @param tables An Array of the names of the tables for which statistics should be created. |
||||||
|
*/ |
||||||
|
public DataProfiler(DataSource dataSource, String schema, String[] tables) { |
||||||
|
try (Connection con = dataSource.getConnection()) { |
||||||
|
this.database = con.getCatalog(); |
||||||
|
} catch (SQLException e) { |
||||||
|
logger.error("Couldn't read catalog", e); |
||||||
|
} |
||||||
|
this.schema = schema != null ? schema : "public"; |
||||||
|
List<String> tableList = Arrays.asList(tables); |
||||||
|
// TODO: Make sorting configurable?
|
||||||
|
tableList.sort(null); |
||||||
|
this.tables = tableList.toArray(new String[] {}); |
||||||
|
this.dataSource = dataSource; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
System.setProperty(SuperXManager.SUPER_X_HISINONE_VERSION, "non-empty-value"); |
||||||
|
Options options = createOptions(); |
||||||
|
CommandLine parsedArgs = parseArgs(args, options); |
||||||
|
if (parsedArgs.hasOption("h")) { |
||||||
|
printHelp(options); |
||||||
|
System.exit(0); |
||||||
|
} |
||||||
|
|
||||||
|
String database = null; |
||||||
|
String schema = "public"; |
||||||
|
String[] tables = null; |
||||||
|
|
||||||
|
if (parsedArgs.hasOption("d")) { |
||||||
|
database = parsedArgs.getOptionValue('d'); |
||||||
|
} |
||||||
|
if (parsedArgs.hasOption("s")) { |
||||||
|
schema = parsedArgs.getOptionValue('s'); |
||||||
|
} |
||||||
|
if (parsedArgs.hasOption("t")) { |
||||||
|
tables = parsedArgs.getOptionValues('t'); |
||||||
|
} |
||||||
|
if (!parsedArgs.hasOption('d') || !parsedArgs.hasOption('t')) { |
||||||
|
printHelp(options); |
||||||
|
System.exit(0); |
||||||
|
} |
||||||
|
try (GenericApplicationContext context = createContext()) { |
||||||
|
initSxPools(); |
||||||
|
DataSource dataSource = context.getBean(His1DataSources.class).get(database); |
||||||
|
DataProfiler profiler = new DataProfiler(dataSource, schema, tables); |
||||||
|
profiler.outputExcel(profiler.createStatistics(), null); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create the List of TableStatistics. |
||||||
|
* @return List of TableStatistics. |
||||||
|
*/ |
||||||
|
public List<TableStatistic> createStatistics() { |
||||||
|
List<TableStatistic> tableStats = new ArrayList<>(); |
||||||
|
try { |
||||||
|
JdbcTemplate jt = new JdbcTemplate(dataSource); |
||||||
|
logger.info("Database: " + database); |
||||||
|
logger.info("Schema: " + schema); |
||||||
|
logger.info("Tables: " + Arrays.asList(tables)); |
||||||
|
try (Connection con = dataSource.getConnection()) { |
||||||
|
jt.execute("set search_path to " + schema); |
||||||
|
DatabaseMetaData meta = con.getMetaData(); |
||||||
|
for (String table : tables) { |
||||||
|
long rowCount = jt.queryForObject("select count(*) from " + table, Long.class).longValue(); |
||||||
|
TableStatistic tableStat = new TableStatistic(table, rowCount); |
||||||
|
logger.info("Table " + table); |
||||||
|
try(ResultSet columns = meta.getColumns(null, schema, table, null); |
||||||
|
ResultSet exported = meta.getExportedKeys(null, schema, table); |
||||||
|
ResultSet imported = meta.getImportedKeys(null, schema, table); |
||||||
|
ResultSet pks = meta.getPrimaryKeys(null, schema, table)) { |
||||||
|
while(columns.next()) { |
||||||
|
ColumnStatistic columnStat = new ColumnStatistic(); |
||||||
|
columnStat.name = columns.getString("COLUMN_NAME"); |
||||||
|
columnStat.size = columns.getInt("COLUMN_SIZE"); |
||||||
|
columnStat.decimalDigits = columns.getInt("DECIMAL_DIGITS"); |
||||||
|
columnStat.type = JDBCType.valueOf(columns.getInt("DATA_TYPE")); |
||||||
|
columnStat.comment = columns.getString("REMARKS"); |
||||||
|
columnStat.isNullable = columns.getString("IS_NULLABLE").equalsIgnoreCase("yes"); |
||||||
|
columnStat.isAutoincrement = columns.getString("IS_AUTOINCREMENT").equalsIgnoreCase("yes"); |
||||||
|
columnStat.countNull = jt.queryForObject(String.format(SQL_COUNT_NULL, tableStat.name, columnStat.name), Long.class).longValue(); |
||||||
|
columnStat.percentNull = (double) columnStat.countNull / (double) tableStat.rowCount * 100.0; |
||||||
|
jt.query(String.format(SQL_PERCENT_UNIQUE, columnStat.name, columnStat.name, tableStat.name), new RowCallbackHandler() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void processRow(ResultSet rs) throws SQLException { |
||||||
|
columnStat.uniqueCount = rs.getLong(1); |
||||||
|
columnStat.uniquePercent = rs.getDouble(2); |
||||||
|
|
||||||
|
} |
||||||
|
}); |
||||||
|
columnStat.ranking = jt.query(String.format(SQL_RANKING, columnStat.name, tableStat.name, columnStat.name, columnStat.name), new RowMapper<RankingEntry>() { |
||||||
|
@Override |
||||||
|
public RankingEntry mapRow(ResultSet rs, int rowNum) throws SQLException { |
||||||
|
return new RankingEntry(rs.getString(1), rs.getInt(2)); |
||||||
|
} |
||||||
|
|
||||||
|
}); |
||||||
|
switch (columnStat.type) { |
||||||
|
case CHAR: |
||||||
|
case NCHAR: |
||||||
|
case VARCHAR: |
||||||
|
case NVARCHAR: |
||||||
|
case LONGVARCHAR: |
||||||
|
case LONGNVARCHAR: |
||||||
|
jt.query(String.format(SQL_MIN_MAX_LEN, columnStat.name, columnStat.name, tableStat.name, columnStat.name), new RowCallbackHandler() { |
||||||
|
@Override |
||||||
|
public void processRow(ResultSet rs) throws SQLException { |
||||||
|
columnStat.minLen = Optional.of(Integer.valueOf(rs.getInt(1))); |
||||||
|
columnStat.maxLen = Optional.of(Integer.valueOf(rs.getInt(2))); |
||||||
|
} |
||||||
|
}); |
||||||
|
columnStat.min_count = Optional.of(jt.queryForObject(String.format(SQL_COUNT_VALUE, tableStat.name, |
||||||
|
"length(" + columnStat.name + ")", columnStat.minLen.get()), Integer.class)); |
||||||
|
columnStat.max_count = Optional.of(jt.queryForObject(String.format(SQL_COUNT_VALUE, tableStat.name, |
||||||
|
"length(" + columnStat.name + ")", columnStat.maxLen.get()), Integer.class)); |
||||||
|
break; |
||||||
|
case BIGINT: |
||||||
|
case DECIMAL: |
||||||
|
case DOUBLE: |
||||||
|
case FLOAT: |
||||||
|
case INTEGER: |
||||||
|
case REAL: |
||||||
|
case NUMERIC: |
||||||
|
case SMALLINT: |
||||||
|
case TINYINT: |
||||||
|
jt.query(String.format(SQL_MIN_MAX_AVG, columnStat.name, columnStat.name, columnStat.name, tableStat.name, columnStat.name), new RowCallbackHandler() { |
||||||
|
@Override |
||||||
|
public void processRow(ResultSet rs) throws SQLException { |
||||||
|
columnStat.min = Optional.of(Double.valueOf(rs.getDouble(1))); |
||||||
|
columnStat.max = Optional.of(Double.valueOf(rs.getDouble(2))); |
||||||
|
columnStat.avg = Optional.of(Double.valueOf(rs.getDouble(3))); |
||||||
|
} |
||||||
|
}); |
||||||
|
columnStat.min_count = Optional.of(jt.queryForObject(String.format(SQL_COUNT_VALUE, tableStat.name, columnStat.name, columnStat.min.get()), Integer.class)); |
||||||
|
columnStat.max_count = Optional.of(jt.queryForObject(String.format(SQL_COUNT_VALUE, tableStat.name, columnStat.name, columnStat.max.get()), Integer.class)); |
||||||
|
break; |
||||||
|
case DATE: |
||||||
|
jt.query(String.format(SQL_START_END, columnStat.name, columnStat.name, tableStat.name, columnStat.name), new RowCallbackHandler() { |
||||||
|
@Override |
||||||
|
public void processRow(ResultSet rs) throws SQLException { |
||||||
|
columnStat.earliestDate = Optional.ofNullable(rs.getDate(1)); |
||||||
|
columnStat.latestDate = Optional.ofNullable(rs.getDate(2)); |
||||||
|
} |
||||||
|
}); |
||||||
|
if (columnStat.earliestDate.isPresent()) { |
||||||
|
columnStat.min_count = Optional.of(jt.queryForObject(String.format(SQL_COUNT_VALUE, tableStat.name, columnStat.name, quote(columnStat.earliestDate.get())), Integer.class)); |
||||||
|
} |
||||||
|
if (columnStat.latestDate.isPresent()) { |
||||||
|
columnStat.max_count = Optional.of(jt.queryForObject(String.format(SQL_COUNT_VALUE, tableStat.name, columnStat.name, quote(columnStat.latestDate.get())), Integer.class)); |
||||||
|
} |
||||||
|
break; |
||||||
|
case TIMESTAMP: |
||||||
|
case TIMESTAMP_WITH_TIMEZONE: |
||||||
|
jt.query(String.format(SQL_START_END, columnStat.name, columnStat.name, tableStat.name, columnStat.name), new RowCallbackHandler() { |
||||||
|
@Override |
||||||
|
public void processRow(ResultSet rs) throws SQLException { |
||||||
|
columnStat.earliestTimestamp = Optional.ofNullable(rs.getTimestamp(1)); |
||||||
|
columnStat.latestTimestamp = Optional.ofNullable(rs.getTimestamp(2)); |
||||||
|
} |
||||||
|
}); |
||||||
|
if (columnStat.earliestTimestamp.isPresent()) { |
||||||
|
columnStat.min_count = Optional.of(jt.queryForObject(String.format(SQL_COUNT_VALUE, tableStat.name, columnStat.name, quote(columnStat.earliestTimestamp.get())), Integer.class)); |
||||||
|
} |
||||||
|
if (columnStat.latestTimestamp.isPresent()) { |
||||||
|
columnStat.max_count = Optional.of(jt.queryForObject(String.format(SQL_COUNT_VALUE, tableStat.name, columnStat.name, quote(columnStat.latestTimestamp.get())), Integer.class)); |
||||||
|
} |
||||||
|
break; |
||||||
|
case TIME: |
||||||
|
case TIME_WITH_TIMEZONE: |
||||||
|
jt.query(String.format(SQL_START_END, columnStat.name, columnStat.name, tableStat.name, columnStat.name), new RowCallbackHandler() { |
||||||
|
@Override |
||||||
|
public void processRow(ResultSet rs) throws SQLException { |
||||||
|
columnStat.earliestTime = Optional.ofNullable(rs.getTime(1)); |
||||||
|
columnStat.latestTime = Optional.ofNullable(rs.getTime(2)); |
||||||
|
} |
||||||
|
}); |
||||||
|
if (columnStat.earliestTime.isPresent()) { |
||||||
|
columnStat.min_count = Optional.of(jt.queryForObject(String.format(SQL_COUNT_VALUE, tableStat.name, columnStat.name, quote(columnStat.earliestTime.get())), Integer.class)); |
||||||
|
} |
||||||
|
if (columnStat.latestTime.isPresent()) { |
||||||
|
columnStat.max_count = Optional.of(jt.queryForObject(String.format(SQL_COUNT_VALUE, tableStat.name, columnStat.name, quote(columnStat.latestTime.get())), Integer.class)); |
||||||
|
} |
||||||
|
break; |
||||||
|
default: |
||||||
|
} |
||||||
|
tableStat.columns.add(columnStat); |
||||||
|
} |
||||||
|
while (exported.next()) { |
||||||
|
String fromColumn = exported.getString("PKCOLUMN_NAME"); |
||||||
|
String toTable = exported.getString("FKTABLE_NAME"); |
||||||
|
String toColumn = exported .getString("FKCOLUMN_NAME"); |
||||||
|
tableStat.exportedKeys.add(new ForeignKey(fromColumn, toTable, toColumn)); |
||||||
|
|
||||||
|
} |
||||||
|
while (imported.next()) { |
||||||
|
String fromColumn = imported.getString("FKCOLUMN_NAME"); |
||||||
|
String toTable = imported.getString("PKTABLE_NAME"); |
||||||
|
String toColumn = imported .getString("PKCOLUMN_NAME"); |
||||||
|
tableStat.importedKeys.add(new ForeignKey(fromColumn, toTable, toColumn)); |
||||||
|
|
||||||
|
} |
||||||
|
while (pks.next()) { |
||||||
|
String column = pks.getString("COLUMN_NAME"); |
||||||
|
tableStat.primaryKeys.add(column); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
tableStats.add(tableStat); |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (SQLException e) { |
||||||
|
logger.error("SQL Fehler", e); |
||||||
|
} |
||||||
|
return tableStats; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Output statistic for a list of tables to an Excel file. |
||||||
|
* The statistics of each table are written to a separate sheet. |
||||||
|
* @param tableStats The list of TableStats |
||||||
|
* @param outputFile The File to output to. If null output to current dir with a default file name. |
||||||
|
*/ |
||||||
|
public void outputExcel(List<TableStatistic> tableStats, File outputFile) { |
||||||
|
XSSFWorkbook workbook = new XSSFWorkbook(); |
||||||
|
XSSFDataFormat dataFormat = workbook.createDataFormat(); |
||||||
|
XSSFCellStyle cellStyleDouble = workbook.createCellStyle(); |
||||||
|
cellStyleDouble.setDataFormat(dataFormat.getFormat("0.##")); |
||||||
|
XSSFCellStyle headerStyle = workbook.createCellStyle(); |
||||||
|
XSSFFont bold = workbook.createFont(); |
||||||
|
bold.setBold(true); |
||||||
|
headerStyle.setFont(bold); |
||||||
|
for (TableStatistic tableStat : tableStats) { |
||||||
|
XSSFSheet sheet = workbook.createSheet("Table " + tableStat.name); |
||||||
|
XSSFRow header = sheet.createRow(0); |
||||||
|
XSSFCell cell = header.createCell(0); |
||||||
|
cell.setCellValue("Database: " + database); |
||||||
|
cell.setCellStyle(headerStyle); |
||||||
|
cell = header.createCell(1); |
||||||
|
cell.setCellStyle(headerStyle); |
||||||
|
cell.setCellValue("Schema: " + schema); |
||||||
|
XSSFRow first = sheet.createRow(2); |
||||||
|
first.createCell(0).setCellValue("Table"); |
||||||
|
first.getCell(0).setCellStyle(headerStyle); |
||||||
|
first.createCell(1).setCellValue("Row Count"); |
||||||
|
first.getCell(1).setCellStyle(headerStyle); |
||||||
|
first.createCell(2).setCellValue("Column"); |
||||||
|
first.getCell(2).setCellStyle(headerStyle); |
||||||
|
first.createCell(3).setCellValue("Type"); |
||||||
|
first.getCell(3).setCellStyle(headerStyle); |
||||||
|
first.createCell(4).setCellValue("Size"); |
||||||
|
first.getCell(4).setCellStyle(headerStyle); |
||||||
|
first.createCell(5).setCellValue("Not Null"); |
||||||
|
first.getCell(5).setCellStyle(headerStyle); |
||||||
|
first.createCell(6).setCellValue("Autoincrement"); |
||||||
|
first.getCell(6).setCellStyle(headerStyle); |
||||||
|
first.createCell(7).setCellValue("Count NULL"); |
||||||
|
first.getCell(7).setCellStyle(headerStyle); |
||||||
|
first.createCell(8).setCellValue("% NULL"); |
||||||
|
first.getCell(8).setCellStyle(headerStyle); |
||||||
|
first.createCell(9).setCellValue("Count Unique"); |
||||||
|
first.getCell(9).setCellStyle(headerStyle); |
||||||
|
first.createCell(10).setCellValue("% Unique"); |
||||||
|
first.getCell(10).setCellStyle(headerStyle); |
||||||
|
first.createCell(11).setCellValue("Min Len"); |
||||||
|
first.getCell(11).setCellStyle(headerStyle); |
||||||
|
first.createCell(12).setCellValue("Max Len"); |
||||||
|
first.getCell(12).setCellStyle(headerStyle); |
||||||
|
first.createCell(13).setCellValue("Min"); |
||||||
|
first.getCell(13).setCellStyle(headerStyle); |
||||||
|
first.createCell(14).setCellValue("Max"); |
||||||
|
first.getCell(14).setCellStyle(headerStyle); |
||||||
|
first.createCell(15).setCellValue("Avg"); |
||||||
|
first.getCell(15).setCellStyle(headerStyle); |
||||||
|
first.createCell(16).setCellValue("Min Count"); |
||||||
|
first.getCell(16).setCellStyle(headerStyle); |
||||||
|
first.createCell(17).setCellValue("Max Count"); |
||||||
|
first.getCell(17).setCellStyle(headerStyle); |
||||||
|
first.createCell(18).setCellValue("Earliest"); |
||||||
|
first.getCell(18).setCellStyle(headerStyle); |
||||||
|
first.createCell(19).setCellValue("Latest"); |
||||||
|
first.getCell(19).setCellStyle(headerStyle); |
||||||
|
first.createCell(20).setCellValue("Comment"); |
||||||
|
first.getCell(20).setCellStyle(headerStyle); |
||||||
|
int row = 3; |
||||||
|
XSSFRow tableRow = sheet.createRow(row); |
||||||
|
tableRow.createCell(0).setCellValue(tableStat.name); |
||||||
|
tableRow.getCell(0).setCellStyle(headerStyle); |
||||||
|
tableRow.createCell(1).setCellValue(tableStat.rowCount); |
||||||
|
tableRow.getCell(1).setCellStyle(headerStyle); |
||||||
|
for (ColumnStatistic columnStat : tableStat.columns) { |
||||||
|
row += 1; |
||||||
|
XSSFRow descRow = sheet.createRow(row); |
||||||
|
descRow.createCell(2).setCellValue(columnStat.name); |
||||||
|
if (tableStat.primaryKeys.contains(columnStat.name)) { |
||||||
|
descRow.getCell(2).setCellValue(columnStat.name + " (PK)"); |
||||||
|
descRow.getCell(2).setCellStyle(headerStyle); |
||||||
|
} |
||||||
|
descRow.createCell(3).setCellValue(columnStat.type.getName()); |
||||||
|
descRow.createCell(4).setCellValue(columnStat.size); |
||||||
|
if (columnStat.decimalDigits != 0) { |
||||||
|
descRow.getCell(4).setCellValue( |
||||||
|
Double.valueOf(columnStat.size + "." + columnStat.decimalDigits).doubleValue() |
||||||
|
); |
||||||
|
descRow.getCell(4).setCellStyle(cellStyleDouble); |
||||||
|
} |
||||||
|
descRow.createCell(5).setCellValue(!columnStat.isNullable); |
||||||
|
descRow.createCell(6).setCellValue(columnStat.isAutoincrement); |
||||||
|
descRow.createCell(7).setCellValue(columnStat.countNull); |
||||||
|
descRow.createCell(8).setCellValue(columnStat.percentNull); |
||||||
|
descRow.getCell(8).setCellStyle(cellStyleDouble); |
||||||
|
descRow.createCell(9).setCellValue(columnStat.uniqueCount); |
||||||
|
descRow.createCell(10).setCellValue(columnStat.uniquePercent); |
||||||
|
descRow.getCell(10).setCellStyle(cellStyleDouble); |
||||||
|
if (columnStat.minLen.isPresent()) { |
||||||
|
descRow.createCell(11).setCellValue(columnStat.minLen.get().doubleValue()); |
||||||
|
} |
||||||
|
if (columnStat.maxLen.isPresent()) { |
||||||
|
descRow.createCell(12).setCellValue(columnStat.maxLen.get().doubleValue()); |
||||||
|
} |
||||||
|
if (columnStat.min.isPresent()) { |
||||||
|
descRow.createCell(13).setCellValue(columnStat.min.get().doubleValue()); |
||||||
|
descRow.getCell(13).setCellStyle(cellStyleDouble); |
||||||
|
} |
||||||
|
if (columnStat.max.isPresent()) { |
||||||
|
descRow.createCell(14).setCellValue(columnStat.max.get().doubleValue()); |
||||||
|
descRow.getCell(14).setCellStyle(cellStyleDouble); |
||||||
|
} |
||||||
|
if (columnStat.avg.isPresent()) { |
||||||
|
descRow.createCell(15).setCellValue(columnStat.avg.get().doubleValue()); |
||||||
|
descRow.getCell(15).setCellStyle(cellStyleDouble); |
||||||
|
} |
||||||
|
if (columnStat.min_count.isPresent()) { |
||||||
|
descRow.createCell(16).setCellValue(columnStat.min_count.get().doubleValue()); |
||||||
|
descRow.getCell(16).setCellStyle(cellStyleDouble); |
||||||
|
} |
||||||
|
if (columnStat.max_count.isPresent()) { |
||||||
|
descRow.createCell(17).setCellValue(columnStat.max_count.get().doubleValue()); |
||||||
|
descRow.getCell(17).setCellStyle(cellStyleDouble); |
||||||
|
} |
||||||
|
if (columnStat.earliestDate.isPresent()) { |
||||||
|
descRow.createCell(18).setCellValue(columnStat.earliestDate.get().toString()); |
||||||
|
} |
||||||
|
if (columnStat.latestDate.isPresent()) { |
||||||
|
descRow.createCell(19).setCellValue(columnStat.latestDate.get().toString()); |
||||||
|
} |
||||||
|
if (columnStat.earliestTime.isPresent()) { |
||||||
|
descRow.createCell(18).setCellValue(columnStat.earliestTime.get().toString()); |
||||||
|
} |
||||||
|
if (columnStat.latestTime.isPresent()) { |
||||||
|
descRow.createCell(19).setCellValue(columnStat.latestTime.get().toString()); |
||||||
|
} |
||||||
|
if (columnStat.earliestTimestamp.isPresent()) { |
||||||
|
descRow.createCell(18).setCellValue(columnStat.earliestTimestamp.get().toString()); |
||||||
|
} |
||||||
|
if (columnStat.latestTimestamp.isPresent()) { |
||||||
|
descRow.createCell(19).setCellValue(columnStat.latestTimestamp.get().toString()); |
||||||
|
} |
||||||
|
descRow.createCell(20).setCellValue(columnStat.comment); |
||||||
|
} |
||||||
|
for (int i = 0; i < 20; i++) { |
||||||
|
sheet.autoSizeColumn(i); |
||||||
|
} |
||||||
|
XSSFRow frequHeader1 = sheet.createRow(row + 2); |
||||||
|
XSSFRow frequHeader2 = sheet.createRow(row + 3); |
||||||
|
frequHeader1.createCell(0).setCellValue("Frequency"); |
||||||
|
frequHeader1.getCell(0).setCellStyle(headerStyle); |
||||||
|
frequHeader2.createCell(0).setCellValue("Column"); |
||||||
|
frequHeader2.getCell(0).setCellStyle(headerStyle); |
||||||
|
for (int n = 1; n <= 10; n++) { |
||||||
|
frequHeader1.createCell(n).setCellValue(n); |
||||||
|
frequHeader1.getCell(n).setCellStyle(headerStyle); |
||||||
|
} |
||||||
|
for (int colNr = 0; colNr < tableStat.columns.size(); colNr++) { |
||||||
|
XSSFRow frequRowLabel = sheet.createRow(row + 4 + 2 * colNr); |
||||||
|
XSSFRow frequRowCount = sheet.createRow(row + 5 + 2 * colNr); |
||||||
|
frequRowLabel.createCell(0).setCellValue(tableStat.columns.get(colNr).name); |
||||||
|
for (int rankNr = 0; rankNr < tableStat.columns.get(colNr).ranking.size(); rankNr++) { |
||||||
|
frequRowLabel.createCell(rankNr + 1).setCellValue(tableStat.columns.get(colNr).ranking.get(rankNr).label); |
||||||
|
frequRowCount.createCell(rankNr + 1).setCellValue(tableStat.columns.get(colNr).ranking.get(rankNr).count); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
row = row + 2 * tableStat.columns.size() + 5; |
||||||
|
XSSFRow exHeader1 = sheet.createRow(row); |
||||||
|
exHeader1.createCell(0).setCellValue("Exported Keys"); |
||||||
|
exHeader1.getCell(0).setCellStyle(headerStyle); |
||||||
|
XSSFRow exHeader2 = sheet.createRow(row + 1); |
||||||
|
exHeader2.createCell(0).setCellValue("From Column"); |
||||||
|
exHeader2.getCell(0).setCellStyle(headerStyle); |
||||||
|
exHeader2.createCell(1).setCellValue("To Table"); |
||||||
|
exHeader2.getCell(1).setCellStyle(headerStyle); |
||||||
|
exHeader2.createCell(2).setCellValue("To Column"); |
||||||
|
exHeader2.getCell(2).setCellStyle(headerStyle); |
||||||
|
for (int fkNr = 0; fkNr < tableStat.exportedKeys.size(); fkNr++) { |
||||||
|
XSSFRow fkRow = sheet.createRow(row + 2 + fkNr); |
||||||
|
fkRow.createCell(0).setCellValue(tableStat.exportedKeys.get(fkNr).fromColumn); |
||||||
|
fkRow.createCell(1).setCellValue(tableStat.exportedKeys.get(fkNr).toTable); |
||||||
|
fkRow.createCell(2).setCellValue(tableStat.exportedKeys.get(fkNr).toColumn); |
||||||
|
} |
||||||
|
row = row + 3 + tableStat.exportedKeys.size(); |
||||||
|
XSSFRow imHeader1 = sheet.createRow(row); |
||||||
|
imHeader1.createCell(0).setCellValue("Imported Keys"); |
||||||
|
imHeader1.getCell(0).setCellStyle(headerStyle); |
||||||
|
XSSFRow imHeader2 = sheet.createRow(row + 1); |
||||||
|
imHeader2.createCell(0).setCellValue("From Table"); |
||||||
|
imHeader2.getCell(0).setCellStyle(headerStyle); |
||||||
|
imHeader2.createCell(1).setCellValue("From Column"); |
||||||
|
imHeader2.getCell(1).setCellStyle(headerStyle); |
||||||
|
imHeader2.createCell(2).setCellValue("To Column"); |
||||||
|
imHeader2.getCell(2).setCellStyle(headerStyle); |
||||||
|
for (int fkNr = 0; fkNr < tableStat.importedKeys.size(); fkNr++) { |
||||||
|
XSSFRow fkRow = sheet.createRow(row + 2 + fkNr); |
||||||
|
fkRow.createCell(0).setCellValue(tableStat.importedKeys.get(fkNr).toTable); |
||||||
|
fkRow.createCell(1).setCellValue(tableStat.importedKeys.get(fkNr).toColumn); |
||||||
|
fkRow.createCell(2).setCellValue(tableStat.importedKeys.get(fkNr).fromColumn); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
File currDir = new File("."); |
||||||
|
String path = currDir.getAbsolutePath(); |
||||||
|
String fileLocation = path.substring(0, path.length() - 1) + "db_profile_" + database + ".xlsx"; |
||||||
|
if (outputFile != null) { |
||||||
|
fileLocation = outputFile.getAbsolutePath(); |
||||||
|
} |
||||||
|
logger.info("Writing to " + fileLocation); |
||||||
|
|
||||||
|
FileOutputStream outputStream; |
||||||
|
try { |
||||||
|
outputStream = new FileOutputStream(fileLocation); |
||||||
|
workbook.write(outputStream); |
||||||
|
workbook.close(); |
||||||
|
} catch (IOException e) { |
||||||
|
logger.error("Couldn't write excel file", e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static Options createOptions() { |
||||||
|
Options options = new Options(); |
||||||
|
Option opt; |
||||||
|
opt = new Option("h", "help", false, "get help"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("t", "tables", true, "tables"); |
||||||
|
opt.setArgs(Option.UNLIMITED_VALUES); |
||||||
|
// opt.setRequired(true);
|
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("s", "schema", true, "schema"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("d", "database", true, "database"); |
||||||
|
// opt.setRequired(true);
|
||||||
|
options.addOption(opt); |
||||||
|
return options; |
||||||
|
} |
||||||
|
|
||||||
|
private static CommandLine parseArgs(String[] args, Options options) { |
||||||
|
CommandLineParser parser = new GnuParser(); |
||||||
|
try { |
||||||
|
return parser.parse(options, args, false); |
||||||
|
} catch (ParseException e) { |
||||||
|
System.out.println("error while reading the command line parameters:"); |
||||||
|
e.printStackTrace(); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
private static void initSxPools() { |
||||||
|
try { |
||||||
|
List<String> mandantenNamen = new LinkedList<String>(); |
||||||
|
mandantenNamen.add(DEFAULT_MANDANTEN_ID); |
||||||
|
SxPools.closeAll(); |
||||||
|
SxPools.init(mandantenNamen); |
||||||
|
SxPools.get(DEFAULT_MANDANTEN_ID).init(); |
||||||
|
SxPools.get(DEFAULT_MANDANTEN_ID).initLogging(true, Level.DEBUG); |
||||||
|
// also init kettle env, set plugin dir
|
||||||
|
SuperXManager.initKettleEnv(APPLICATION_CONTEXT); |
||||||
|
} catch (Exception e) { |
||||||
|
System.out.println("error while initialising the SuperX pools:"); |
||||||
|
e.printStackTrace(); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void printHelp(Options options) { |
||||||
|
HelpFormatter help = new HelpFormatter(); |
||||||
|
help.printHelp(HELP_STRING, options); |
||||||
|
} |
||||||
|
|
||||||
|
private static GenericApplicationContext createContext() { |
||||||
|
/* |
||||||
|
* https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/AnnotationConfigApplicationContext.html
|
||||||
|
* quote: |
||||||
|
* "In case of multiple @Configuration classes, @Bean methods defined in later classes will override those defined in earlier classes. |
||||||
|
* This can be leveraged to deliberately override certain bean definitions via an extra @Configuration class." |
||||||
|
* - so it's alright to override some beans via "CLIConfig" |
||||||
|
*/ |
||||||
|
if (APPLICATION_CONTEXT == null) { |
||||||
|
APPLICATION_CONTEXT = new AnnotationConfigApplicationContext(BatchConfig.class, DataJdbcConfiguration.class, CLIConfig.class, ServiceConfig.class); |
||||||
|
} |
||||||
|
return APPLICATION_CONTEXT; |
||||||
|
} |
||||||
|
|
||||||
|
private static String quote(Object o) { |
||||||
|
return "'" + o + "'"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class TableStatistic { |
||||||
|
|
||||||
|
public String name; |
||||||
|
public long rowCount; |
||||||
|
public List<ColumnStatistic> columns; |
||||||
|
public List<ForeignKey> exportedKeys; |
||||||
|
public List<ForeignKey> importedKeys; |
||||||
|
public List<String> primaryKeys; |
||||||
|
|
||||||
|
public TableStatistic(String name, long rowCount) { |
||||||
|
this.name = name; |
||||||
|
this.rowCount = rowCount; |
||||||
|
this.columns = new ArrayList<>(); |
||||||
|
this.exportedKeys = new ArrayList<>(); |
||||||
|
this.importedKeys = new ArrayList<>(); |
||||||
|
this.primaryKeys = new ArrayList<>(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class ColumnStatistic { |
||||||
|
public String name; |
||||||
|
public JDBCType type; |
||||||
|
public int size; |
||||||
|
public int decimalDigits; |
||||||
|
public boolean isNullable; |
||||||
|
public boolean isAutoincrement; |
||||||
|
public String comment; |
||||||
|
public long countNull; |
||||||
|
public double percentNull; |
||||||
|
public long uniqueCount; |
||||||
|
public double uniquePercent; |
||||||
|
public Optional<Integer> max_count = Optional.empty(); |
||||||
|
public Optional<Integer> min_count = Optional.empty(); |
||||||
|
public List<RankingEntry> ranking; |
||||||
|
public Optional<Integer> minLen = Optional.empty(); |
||||||
|
public Optional<Integer> maxLen = Optional.empty(); |
||||||
|
public Optional<Double> min = Optional.empty(); |
||||||
|
public Optional<Double> max = Optional.empty(); |
||||||
|
public Optional<Double> avg = Optional.empty(); |
||||||
|
public Optional<Date> earliestDate = Optional.empty(); |
||||||
|
public Optional<Date> latestDate = Optional.empty(); |
||||||
|
public Optional<Time> earliestTime = Optional.empty(); |
||||||
|
public Optional<Time> latestTime = Optional.empty(); |
||||||
|
public Optional<Timestamp> earliestTimestamp = Optional.empty(); |
||||||
|
public Optional<Timestamp> latestTimestamp = Optional.empty(); |
||||||
|
} |
||||||
|
|
||||||
|
class RankingEntry { |
||||||
|
|
||||||
|
public RankingEntry(String label, int count) { |
||||||
|
this.label = label; |
||||||
|
this.count = count; |
||||||
|
} |
||||||
|
|
||||||
|
public String label; |
||||||
|
public int count; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
class ForeignKey { |
||||||
|
|
||||||
|
public ForeignKey(String fromColumn, String toTable, String toColumn) { |
||||||
|
this.fromColumn = fromColumn; |
||||||
|
this.toTable = toTable; |
||||||
|
this.toColumn = toColumn; |
||||||
|
} |
||||||
|
|
||||||
|
public String fromColumn; |
||||||
|
public String toTable; |
||||||
|
public String toColumn; |
||||||
|
} |
||||||
@ -1,308 +1,277 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
import java.io.BufferedReader; |
|
||||||
import java.io.BufferedWriter; |
import java.io.BufferedReader; |
||||||
import java.io.File; |
import java.io.BufferedWriter; |
||||||
import java.io.FileInputStream; |
import java.io.File; |
||||||
import java.io.FileOutputStream; |
import java.io.FileInputStream; |
||||||
import java.io.IOException; |
import java.io.FileOutputStream; |
||||||
import java.io.InputStreamReader; |
import java.io.IOException; |
||||||
import java.io.OutputStreamWriter; |
import java.io.InputStreamReader; |
||||||
|
import java.io.OutputStreamWriter; |
||||||
import de.memtext.util.GetOpts; |
|
||||||
|
import de.memtext.util.GetOpts; |
||||||
public class DelEndChar { |
import de.memtext.util.GetOpts.Options; |
||||||
|
|
||||||
/* Klassenvariablen */ |
public class DelEndChar { |
||||||
private static String _dateiPfad = ""; |
|
||||||
private static String DELIMITER = "^"; |
/* Klassenvariablen */ |
||||||
private static String _outDateiPfad=""; |
private static String _dateiPfad = ""; |
||||||
private static String _tabelle=""; |
|
||||||
/** |
private static String DELIMITER = "^"; |
||||||
* Diese Klasse bereinigt die Zeilen der angegebenen ASCII-Dateien<br> |
|
||||||
* Es wird der letzte Delimiter-Zeichen aus jeder Zeile entfernt.<br> |
private static String _outDateiPfad = ""; |
||||||
* Parameter:<br> |
|
||||||
* 1. Eingabe-Dateiname mit Pfadangabe <br> |
private static String _tabelle = ""; |
||||||
* 2. Ausgabe-Dateiname mit Pfadangabe<br> |
|
||||||
* 3. Delimiter-Zeichen(optional).<br> |
/** |
||||||
* 4. Tabellenname in der Datenbank, der auf Übereistimmung der Felderanzahl geprüft werden soll (optional).<br> |
* Diese Klasse bereinigt die Zeilen der angegebenen ASCII-Dateien<br> |
||||||
* Defaultwert für Delimiter ist ^. |
* Es wird der letzte Delimiter-Zeichen aus jeder Zeile entfernt.<br> |
||||||
* Aufruf: java -cp .:../lib/superx-db.jar:../lib/<<jdbc-Treiber>>.jar delEndChar <Dateiname> <Zieldateiname> <opt. Delimiter-Zeichen> <opt. Tabellenname> |
* Parameter:<br> |
||||||
* @version 0.1 4.7.2003 |
* 1. Eingabe-Dateiname mit Pfadangabe <br> |
||||||
* @author Eugen Ermantraut */ |
* 2. Ausgabe-Dateiname mit Pfadangabe<br> |
||||||
public DelEndChar() { |
* 3. Delimiter-Zeichen(optional).<br> |
||||||
} |
* 4. Tabellenname in der Datenbank, der auf Übereistimmung der Felderanzahl geprüft werden soll (optional).<br> |
||||||
public static void main(String[] args) |
* Defaultwert für Delimiter ist ^. |
||||||
{ |
* Aufruf: java -cp .:../lib/superx-db.jar:../lib/<<jdbc-Treiber>>.jar delEndChar <Dateiname> <Zieldateiname> <opt. Delimiter-Zeichen> <opt. Tabellenname> |
||||||
DelEndChar r = new DelEndChar(); |
* @version 0.1 4.7.2003 |
||||||
GetOpts.setOpts(args); |
* @author Eugen Ermantraut */ |
||||||
String isdrin= GetOpts.isAllRequiredOptionsPresent("-IN"); |
public DelEndChar() { |
||||||
if(isdrin != null) |
} |
||||||
{ |
|
||||||
System.err.println("Datei-Pfade werden als Parameter erwartet. Folgende Optionen fehlen: " + isdrin); |
public static void main(String[] args) { |
||||||
r.zeige_hilfe(); |
DelEndChar r = new DelEndChar(); |
||||||
System.exit(1); |
GetOpts.setOpts(args); |
||||||
} |
String isdrin = GetOpts.isAllRequiredOptionsPresent(new Options[] {Options.opt_in}); |
||||||
|
if (isdrin != null) { |
||||||
//GetOpts myOpts=new GetOpts();
|
System.err.println("Datei-Pfade werden als Parameter erwartet. Folgende Optionen fehlen: " + isdrin); |
||||||
if (GetOpts.isPresent("-IN")) |
r.zeige_hilfe(); |
||||||
_dateiPfad=GetOpts.getValue("-IN" ); |
System.exit(1); |
||||||
if (GetOpts.isPresent("-OUT")) |
} |
||||||
_outDateiPfad=GetOpts.getValue("-OUT" ); |
|
||||||
if (GetOpts.isPresent("-delim")) |
//GetOpts myOpts=new GetOpts();
|
||||||
DELIMITER=GetOpts.getValue("-delim" ); |
if (GetOpts.isPresent(Options.opt_in)) _dateiPfad = GetOpts.getValue(Options.opt_in); |
||||||
if (GetOpts.isPresent("-table")) |
if (GetOpts.isPresent(Options.opt_out)) _outDateiPfad = GetOpts.getValue(Options.opt_out); |
||||||
_tabelle=GetOpts.getValue("-table" ); |
if (GetOpts.isPresent(Options.opt_delim)) DELIMITER = GetOpts.getValue(Options.opt_delim); |
||||||
if (args[0].toString().equals("?") || |
if (GetOpts.isPresent(Options.opt_table)) _tabelle = GetOpts.getValue(Options.opt_table); |
||||||
args[0].toString().equals("/?") || |
if (args[0].toString().equals("?") || args[0].toString().equals("/?") || args[0].toString().equals("\\?") || args[0].toString().toLowerCase().equals("-h") |
||||||
args[0].toString().equals("\\?") || |
|| args[0].toString().toLowerCase().equals("--h")) { |
||||||
args[0].toString().toLowerCase().equals("-h") || |
r.zeige_hilfe(); |
||||||
args[0].toString().toLowerCase().equals("--h") ) |
System.exit(1); |
||||||
{ |
} |
||||||
r.zeige_hilfe(); |
|
||||||
System.exit(1); |
|
||||||
} |
//if (r.check_param_ok(args))
|
||||||
|
//{
|
||||||
|
try { |
||||||
//if (r.check_param_ok(args))
|
r.updateFile(r._dateiPfad, r._outDateiPfad); |
||||||
//{
|
System.out.println("Datei: " + r._dateiPfad + " nach " + r._outDateiPfad + " umgesetzt"); |
||||||
try |
} catch (Exception e) { |
||||||
{ |
System.err.println(e.toString()); |
||||||
r.updateFile(r._dateiPfad, r._outDateiPfad); |
} |
||||||
System.out.println("Datei: " + r._dateiPfad + " nach " + r._outDateiPfad+ " umgesetzt"); |
//}
|
||||||
} |
|
||||||
catch (Exception e) |
} // Ende der Methode
|
||||||
{ System.err.println(e.toString()); |
|
||||||
} |
|
||||||
//}
|
private void updateFile(String inDateiPfad, String outDateiPfad) throws IOException, Exception { |
||||||
|
File f = new File(inDateiPfad); |
||||||
} // Ende der Methode
|
if (!f.exists()) { |
||||||
|
throw new Exception("Datei nicht gefunden: " + inDateiPfad); |
||||||
|
} |
||||||
private void updateFile(String inDateiPfad, String outDateiPfad) throws IOException, Exception |
BufferedReader in; |
||||||
{ |
BufferedWriter out; |
||||||
File f = new File(inDateiPfad); |
//--- File-Instanz für temporäre Ergebnis-Datei anlegen ---//
|
||||||
if (!f.exists()) |
File out_tmp; |
||||||
{ throw new Exception("Datei nicht gefunden: " + inDateiPfad); |
out_tmp = new File(inDateiPfad + ".tmp2"); |
||||||
} |
//--- IputStream und OutputStream generieren ---//
|
||||||
BufferedReader in; |
in = new BufferedReader(new InputStreamReader(new FileInputStream(f))); |
||||||
BufferedWriter out; |
//--- Output-Stream der tämporere Datei erzeugen ---//
|
||||||
//--- File-Instanz für temporäre Ergebnis-Datei anlegen ---//
|
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(out_tmp))); |
||||||
File out_tmp; |
|
||||||
out_tmp = new File(inDateiPfad+".tmp2"); |
//--- Verarbeiten der Datei ---//
|
||||||
//--- IputStream und OutputStream generieren ---//
|
String text; |
||||||
in = new BufferedReader(new InputStreamReader( |
String tt; |
||||||
new FileInputStream(f) )); |
text = in.readLine(); |
||||||
//--- Output-Stream der tämporere Datei erzeugen ---//
|
if (text != null) { //Datei nicht leer
|
||||||
out = new BufferedWriter( new OutputStreamWriter( |
if (text.endsWith("\\")) { |
||||||
new FileOutputStream(out_tmp) )); |
|
||||||
|
tt = in.readLine(); |
||||||
//--- Verarbeiten der Datei ---//
|
if (tt != null) { |
||||||
String text; |
text += tt; |
||||||
String tt; |
while (tt.endsWith("\\")) { |
||||||
text = in.readLine(); |
tt = in.readLine(); |
||||||
if(text!=null) |
if (tt != null) text += tt + "\n"; //(tt.substring(0,tt.length()));
|
||||||
{ //Datei nicht leer
|
} |
||||||
if(text.endsWith("\\")) |
} |
||||||
{ |
} |
||||||
|
if (!_tabelle.equals("") && !_tabelle.equals("null")) { |
||||||
tt=in.readLine(); |
//Die Datei ist eine entladene Tabelle
|
||||||
if(tt!=null) |
//int start=_dateiPfad.indexOf("_",_dateiPfad.length()-4);
|
||||||
{ |
//if(start <0 )
|
||||||
text+=tt; |
// start=0;
|
||||||
while(tt.endsWith( "\\")) |
// String tabname=_dateiPfad.substring(start,_dateiPfad.length()-4);
|
||||||
{ |
int numFelder = 0; |
||||||
tt= in.readLine(); |
//System.out.println("Tabelle "+_tabelle+ " DELIM " + DELIMITER);
|
||||||
if(tt != null) text +=tt+"\n"; //(tt.substring(0,tt.length()));
|
try { |
||||||
} |
numFelder = SxDBUtils.fieldCount(_tabelle); |
||||||
} |
//System.out.println("Felderanzahl:"+numFelder);
|
||||||
} |
} catch (Exception e) { |
||||||
if(!_tabelle.equals("") && !_tabelle.equals("null") ) |
System.err.println("Fehler beim Abfragen der Tabellen-Metadaten: " + e.toString()); |
||||||
{ |
} |
||||||
//Die Datei ist eine entladene Tabelle
|
int k = 0; |
||||||
//int start=_dateiPfad.indexOf("_",_dateiPfad.length()-4);
|
int i = 0; |
||||||
//if(start <0 )
|
int p = 0; |
||||||
// start=0;
|
do { |
||||||
// String tabname=_dateiPfad.substring(start,_dateiPfad.length()-4);
|
p = text.indexOf(DELIMITER, i); |
||||||
int numFelder=0; |
if (p > 0) { |
||||||
//System.out.println("Tabelle "+_tabelle+ " DELIM " + DELIMITER);
|
k++; |
||||||
try { |
i = p + 1; |
||||||
numFelder= SxDBUtils.fieldCount(_tabelle); |
} |
||||||
//System.out.println("Felderanzahl:"+numFelder);
|
|
||||||
} |
} while (p > 0); |
||||||
catch (Exception e) |
if (k != numFelder) { |
||||||
{ |
throw new Exception("unl-Datei entspricht nicht der Tabelle in der Datenbank;\nDie Tabelle hat " + numFelder + " Felder, die unl-Datei hat " + k + " Felder "); |
||||||
System.err.println("Fehler beim Abfragen der Tabellen-Metadaten: " + e.toString()); |
} |
||||||
} |
|
||||||
int k=0; |
} //Wenn Tabelle gecheckt werden sollte
|
||||||
int i=0; |
do { |
||||||
int p=0; |
if (text == null) break; |
||||||
do |
if (text.endsWith("\\")) { |
||||||
{ |
|
||||||
p=text.indexOf(DELIMITER,i); |
tt = in.readLine(); |
||||||
if(p>0) |
if (tt != null) { |
||||||
{ |
text += tt; |
||||||
k++; |
while (tt != null && tt.endsWith("\\")) { //Umbrüche aus Informix-Lognvarchars abfangen
|
||||||
i=p+1; |
tt = in.readLine(); |
||||||
} |
if (tt != null) text += tt + "\n"; //(tt.substring(0,tt.length()));
|
||||||
|
} |
||||||
} |
} |
||||||
while (p>0); |
} |
||||||
if(k!=numFelder) |
|
||||||
{ throw new Exception("unl-Datei entspricht nicht der Tabelle in der Datenbank;\nDie Tabelle hat "+numFelder+" Felder, die unl-Datei hat "+k +" Felder "); |
text = reorgString(text.trim()); |
||||||
} |
if (text == "-0") // Rohdatendatei Formatfehler
|
||||||
|
{ |
||||||
} //Wenn Tabelle gecheckt werden sollte
|
throw new Exception("Datei: " + inDateiPfad + " hat falsches Format: "); |
||||||
do |
} |
||||||
{ |
out.write(text, 0, text.length()); |
||||||
if (text == null) |
out.write("\n"); // muss NeuLine schreiben das die Zeile ohne eingelesen wird
|
||||||
break; |
out.flush(); |
||||||
if(text.endsWith("\\")) |
|
||||||
{ |
text = in.readLine(); |
||||||
|
|
||||||
tt= in.readLine(); |
} while (text != null); |
||||||
if(tt != null) |
} //Wenn Datei nicht leer war.
|
||||||
{ |
in.close(); |
||||||
text += tt; |
out.close(); |
||||||
while(tt != null && tt.endsWith( "\\")) |
//--- Umbenennen Quell-Dateien ---//
|
||||||
{ //Umbrüche aus Informix-Lognvarchars abfangen
|
/*String alt = inDateiPfad + ".in"; |
||||||
tt= in.readLine(); |
File altFile = new File(alt); |
||||||
if(tt != null) text +=tt+"\n"; //(tt.substring(0,tt.length()));
|
if (altFile.exists()) |
||||||
} |
altFile.delete(); |
||||||
} |
|
||||||
} |
f.renameTo(altFile);*/ |
||||||
|
|
||||||
text = reorgString(text.trim()); |
//--- Umformatierte temporäre Datei unter dem ursprünglichen Namen ablegen ---//
|
||||||
if (text == "-0") // Rohdatendatei Formatfehler
|
File neuFile = new File(outDateiPfad); |
||||||
{ throw new Exception("Datei: " + inDateiPfad + " hat falsches Format: "); |
out_tmp.renameTo(neuFile); |
||||||
} |
|
||||||
out.write(text,0,text.length()); |
//--- Berechtigung für die neu angelegete Datei neu Vergeben ---//
|
||||||
out.write("\n"); // muss NeuLine schreiben das die Zeile ohne eingelesen wird
|
if (!chmode("u=rw,g=rw,o=rw", outDateiPfad)) { |
||||||
out.flush(); |
System.out.println("Kann Berechtigung nicht ändern " + outDateiPfad); |
||||||
|
} |
||||||
text = in.readLine(); |
//--- Schliessen der Streams und Löschen der temporären Datei ---//
|
||||||
|
in.close(); |
||||||
}while (text!=null); |
out.close(); |
||||||
} //Wenn Datei nicht leer war.
|
out_tmp.delete(); |
||||||
in.close(); out.close(); |
|
||||||
//--- Umbenennen Quell-Dateien ---//
|
}//Ende der Methode
|
||||||
/*String alt = inDateiPfad + ".in"; |
|
||||||
File altFile = new File(alt); |
private boolean chmode(String inBerechtigung, String inDat) { |
||||||
if (altFile.exists()) |
String befehl = "chmod " + inBerechtigung + " " + inDat; |
||||||
altFile.delete(); |
try { |
||||||
|
Runtime r = Runtime.getRuntime(); |
||||||
f.renameTo(altFile);*/ |
Process p = r.exec(befehl); |
||||||
|
int exitCode = p.waitFor(); |
||||||
//--- Umformatierte temporäre Datei unter dem ursprünglichen Namen ablegen ---//
|
} catch (Exception e) { |
||||||
File neuFile = new File(outDateiPfad); |
System.out.println("Error: " + e.toString()); |
||||||
out_tmp.renameTo(neuFile); |
return false; |
||||||
|
} |
||||||
//--- Berechtigung für die neu angelegete Datei neu Vergeben ---//
|
|
||||||
if (!chmode("u=rw,g=rw,o=rw", outDateiPfad)) |
return true; |
||||||
{ System.out.println("Kann Berechtigung nicht ändern " + outDateiPfad); |
}//Ende der Methode
|
||||||
} |
|
||||||
//--- Schliessen der Streams und Löschen der temporären Datei ---//
|
/** |
||||||
in.close(); out.close(); |
* Liefert den Teilsstring von 0 bis zu letzten Delimiterzeichen(Exclusive) |
||||||
out_tmp.delete(); |
* @param inS |
||||||
|
* @return String |
||||||
}//Ende der Methode
|
*/ |
||||||
|
private String reorgString(String inS) throws Exception { |
||||||
private boolean chmode(String inBerechtigung,String inDat) |
int ldPos = inS.lastIndexOf(DELIMITER); |
||||||
{ |
//--- Wenn Delimiter-Zeichen nicht letztes Zeichen im String ist,
|
||||||
String befehl = "chmod "+ inBerechtigung + " " + inDat; |
//--- muss die Verarbeitung abgebrochen werden---//
|
||||||
try |
|
||||||
{ |
if ((ldPos + 1) < inS.length() || ldPos == -1) |
||||||
Runtime r = Runtime.getRuntime(); |
//throw new Exception("Datei ist bereits umgesetzt!");
|
||||||
Process p = r.exec(befehl); |
return inS; |
||||||
int exitCode = p.waitFor(); |
else |
||||||
} |
return inS.substring(0, ldPos); |
||||||
catch(Exception e) |
|
||||||
{ System.out.println("Error: " + e.toString()); |
}//Ende der Methode
|
||||||
return false; |
|
||||||
} |
public boolean check_param_ok(String[] inTab) { //--- Anzahl der übergebenen Parameter prüfen ---//
|
||||||
|
//System.out.println(inTab.length);
|
||||||
return true; |
if (inTab.length < 2) { |
||||||
}//Ende der Methode
|
System.out.println("Mindestens 2 Parameter erwartet! Mit -h oder ? rufen sie Hilfe auf."); |
||||||
|
return false; |
||||||
/** |
} |
||||||
* Liefert den Teilsstring von 0 bis zu letzten Delimiterzeichen(Exclusive) |
//--- Dateinpfad übernehmen ---//
|
||||||
* @param inS |
_dateiPfad = inTab[0].trim(); |
||||||
* @return String |
_outDateiPfad = inTab[1].trim(); |
||||||
*/ |
|
||||||
private String reorgString(String inS) throws Exception |
if (inTab.length >= 3) DELIMITER = inTab[2].trim(); |
||||||
{ |
//---Wenn Delimiter-Zeichen übergeben wurde dann übernehmen ---//
|
||||||
int ldPos = inS.lastIndexOf(DELIMITER); |
if (inTab.length > 3) _tabelle = inTab[3].toString().trim(); |
||||||
//--- Wenn Delimiter-Zeichen nicht letztes Zeichen im String ist,
|
|
||||||
//--- muss die Verarbeitung abgebrochen werden---//
|
return true; |
||||||
|
}//Ende der Methode
|
||||||
if ((ldPos + 1) < inS.length() || ldPos== -1) |
|
||||||
//throw new Exception("Datei ist bereits umgesetzt!");
|
/** |
||||||
return inS; |
* Prüfen der Datei auf Vorhandensein und Leseberechrigung |
||||||
else |
* @param inFile |
||||||
return inS.substring(0,ldPos); |
*/ |
||||||
|
private boolean check_Directory(File inFile) { |
||||||
}//Ende der Methode
|
if (inFile.exists()) { |
||||||
|
if (!inFile.isDirectory()) { |
||||||
public boolean check_param_ok(String[] inTab) |
System.out.println(inFile + " ist kein Verzeichnis!"); |
||||||
{ //--- Anzahl der übergebenen Parameter prüfen ---//
|
return false; |
||||||
//System.out.println(inTab.length);
|
} |
||||||
if (inTab.length < 2 ) |
} else { |
||||||
{ System.out.println("Mindestens 2 Parameter erwartet! Mit -h oder ? rufen sie Hilfe auf."); |
System.out.println(inFile + " Verzeichniss nicht gefunden!"); |
||||||
return false; |
return false; |
||||||
} |
} |
||||||
//--- Dateinpfad übernehmen ---//
|
|
||||||
_dateiPfad = inTab[0].trim(); |
return true; |
||||||
_outDateiPfad = inTab[1].trim(); |
}//Ende der Methode
|
||||||
|
|
||||||
if (inTab.length >=3 ) |
private void progEnde() { |
||||||
DELIMITER = inTab[2].trim(); |
System.runFinalization(); |
||||||
//---Wenn Delimiter-Zeichen übergeben wurde dann übernehmen ---//
|
System.exit(0); |
||||||
if (inTab.length >3 ) |
}//Ende der Methode
|
||||||
_tabelle = inTab[3].toString().trim(); |
|
||||||
|
|
||||||
return true; |
private void zeige_hilfe() { |
||||||
}//Ende der Methode
|
System.out.println("\n Diese Klasse bereinigt die Zeilen der angegebenen ASCII-Dateien."); |
||||||
|
System.out.println(" Es wird der letzte Delimeter-Zeichen aus jeder Zeile entfernt."); |
||||||
/** |
System.out.println("\n Parameter: "); |
||||||
* Prüfen der Datei auf Vorhandensein und Leseberechrigung |
System.out.println("1. Eingabe-Dateiname mit Pfadangabe "); |
||||||
* @param inFile |
System.out.println("2. Ausgabe-Dateiname mit Pfadangabe"); |
||||||
*/ |
System.out.println("3. Delimiter-Zeichen(optional)"); |
||||||
private boolean check_Directory(File inFile) |
System.out.println("4. Tabellenname in der Datenbank, der auf Übereistimmung der Felderanzahl geprüft werden soll (optional, wenn keine Überprüfung, dann 'none')."); |
||||||
{ |
//System.out.println(" Wenn in einer Zeile Zeichen hinter dem letzten Delimiter-Zeichen ");
|
||||||
if (inFile.exists()) |
//System.out.println(" wird die Bearbeitung abgebrochen, da es anzunehmen ist daß diese Datei");
|
||||||
{ if (!inFile.isDirectory()) |
//System.out.println(" bereits umgesetzt ist!");
|
||||||
{ System.out.println(inFile + " ist kein Verzeichnis!"); |
System.out.println(" Defaultwert fuer Delimiter ist ^. \n"); |
||||||
return false; |
}// Ende der Methode
|
||||||
} |
|
||||||
} |
|
||||||
else |
|
||||||
{ System.out.println(inFile + " Verzeichniss nicht gefunden!"); |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
return true; |
|
||||||
}//Ende der Methode
|
|
||||||
|
|
||||||
private void progEnde() |
|
||||||
{ |
|
||||||
System.runFinalization(); |
|
||||||
System.exit(0); |
|
||||||
}//Ende der Methode
|
|
||||||
|
|
||||||
|
|
||||||
private void zeige_hilfe() |
|
||||||
{ |
|
||||||
System.out.println("\n Diese Klasse bereinigt die Zeilen der angegebenen ASCII-Dateien."); |
|
||||||
System.out.println(" Es wird der letzte Delimeter-Zeichen aus jeder Zeile entfernt."); |
|
||||||
System.out.println("\n Parameter: "); |
|
||||||
System.out.println("1. Eingabe-Dateiname mit Pfadangabe "); |
|
||||||
System.out.println("2. Ausgabe-Dateiname mit Pfadangabe"); |
|
||||||
System.out.println("3. Delimiter-Zeichen(optional)"); |
|
||||||
System.out.println("4. Tabellenname in der Datenbank, der auf Übereistimmung der Felderanzahl geprüft werden soll (optional, wenn keine Überprüfung, dann 'none')."); |
|
||||||
//System.out.println(" Wenn in einer Zeile Zeichen hinter dem letzten Delimiter-Zeichen ");
|
|
||||||
//System.out.println(" wird die Bearbeitung abgebrochen, da es anzunehmen ist daß diese Datei");
|
|
||||||
//System.out.println(" bereits umgesetzt ist!");
|
|
||||||
System.out.println(" Defaultwert fuer Delimiter ist ^. \n" ); |
|
||||||
}// Ende der Methode
|
|
||||||
|
|
||||||
|
|
||||||
}//Ende der Klasse
|
}//Ende der Klasse
|
||||||
@ -1,74 +1,73 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
|
|
||||||
import java.io.File; |
import java.io.File; |
||||||
import java.io.FileWriter; |
import java.io.FileWriter; |
||||||
import java.io.IOException; |
import java.io.IOException; |
||||||
import java.io.Writer; |
import java.io.Writer; |
||||||
import java.util.HashMap; |
import java.util.HashMap; |
||||||
|
|
||||||
import de.memtext.util.DateUtils; |
import de.memtext.util.DateUtils; |
||||||
import freemarker.template.Configuration; |
import freemarker.template.Configuration; |
||||||
import freemarker.template.Template; |
import freemarker.template.Template; |
||||||
import freemarker.template.TemplateException; |
import freemarker.template.TemplateException; |
||||||
|
|
||||||
public class DialectCreator { |
public class DialectCreator { |
||||||
private static String path, sourceFileName; |
private static String path, sourceFileName; |
||||||
private static String source; |
|
||||||
protected static Configuration cfg = new Configuration(); |
private static String source; |
||||||
private static Template template; |
|
||||||
|
protected static Configuration cfg = new Configuration(); |
||||||
public static void main(String[] args) { |
|
||||||
checkArgs(args); |
private static Template template; |
||||||
try { |
|
||||||
cfg.setDirectoryForTemplateLoading(new File(path)); |
public static void main(String[] args) { |
||||||
template = cfg.getTemplate(sourceFileName); |
checkArgs(args); |
||||||
//source=StringUtils.readFile(f);
|
try { |
||||||
translate("Informix", "_ids"); |
cfg.setDirectoryForTemplateLoading(new File(path)); |
||||||
translate("Postgres", "_pg"); |
template = cfg.getTemplate(sourceFileName); |
||||||
|
//source=StringUtils.readFile(f);
|
||||||
} catch (Exception e) { |
translate("Informix", "_ids"); |
||||||
e.printStackTrace(); |
translate("Postgres", "_pg"); |
||||||
} |
|
||||||
} |
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
private static void checkArgs(String[] args) { |
} |
||||||
if (args.length != 2) { |
} |
||||||
System.out |
|
||||||
.println("Error: use: DialectCreator path sourcefilename"); |
private static void checkArgs(String[] args) { |
||||||
System.exit(1); |
if (args.length != 2) { |
||||||
} |
System.out.println("Error: use: DialectCreator path sourcefilename"); |
||||||
path = args[0]; |
System.exit(1); |
||||||
sourceFileName = args[1]; |
} |
||||||
File f = new File(path + File.separator + sourceFileName); |
path = args[0]; |
||||||
if (!f.exists() || !f.canRead()) { |
sourceFileName = args[1]; |
||||||
System.out.println("Error: can't read source file " + args[1]); |
File f = new File(path + File.separator + sourceFileName); |
||||||
System.exit(1); |
if (!f.exists() || !f.canRead()) { |
||||||
} |
System.out.println("Error: can't read source file " + args[1]); |
||||||
} |
System.exit(1); |
||||||
|
} |
||||||
private static void translatePostgres() { |
} |
||||||
HashMap map = new HashMap(); |
|
||||||
|
private static void translatePostgres() { |
||||||
map.put("SQLdialect", "Postgres"); |
HashMap map = new HashMap(); |
||||||
|
|
||||||
} |
map.put("SQLdialect", "Postgres"); |
||||||
|
|
||||||
private static void translate(String dialect, String fileAppendix) |
} |
||||||
throws TemplateException, IOException { |
|
||||||
HashMap map = new HashMap(); |
private static void translate(String dialect, String fileAppendix) throws TemplateException, IOException { |
||||||
map.put("SQLdialect", dialect); |
HashMap map = new HashMap(); |
||||||
map.put("current", DateUtils.getTodayString() + " um " |
map.put("SQLdialect", dialect); |
||||||
+ DateUtils.getNowString()); |
map.put("current", DateUtils.getTodayString() + " um " + DateUtils.getNowString()); |
||||||
String fname = sourceFileName.substring(0, sourceFileName.length() - 4) |
String fname = sourceFileName.substring(0, sourceFileName.length() - 4) + fileAppendix + ".sql"; |
||||||
+ fileAppendix + ".sql"; |
|
||||||
|
Writer out = new FileWriter(path + File.separator + fname); |
||||||
Writer out = new FileWriter(path + File.separator + fname); |
|
||||||
|
// Merge the data-model and the template
|
||||||
// Merge the data-model and the template
|
template.process(map, out); |
||||||
template.process(map, out); |
out.close(); |
||||||
out.close(); |
System.out.println(" " + dialect + " variant created:" + fname); |
||||||
System.out.println(" " + dialect + " variant created:" + fname); |
} |
||||||
} |
} |
||||||
} |
|
||||||
|
//Created on 19.04.2005 at 10:22:09
|
||||||
//Created on 19.04.2005 at 10:22:09
|
|
||||||
|
|||||||
@ -1,236 +1,217 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
import java.io.BufferedReader; |
|
||||||
import java.io.File; |
import java.io.BufferedReader; |
||||||
import java.io.FileInputStream; |
import java.io.File; |
||||||
import java.io.FileNotFoundException; |
import java.io.FileInputStream; |
||||||
import java.io.FileWriter; |
import java.io.FileWriter; |
||||||
import java.io.IOException; |
import java.io.IOException; |
||||||
import java.io.InputStreamReader; |
import java.io.InputStreamReader; |
||||||
import java.sql.Connection; |
import java.sql.Connection; |
||||||
import java.sql.ResultSet; |
import java.sql.ResultSet; |
||||||
import java.sql.SQLException; |
import java.sql.Statement; |
||||||
import java.sql.Statement; |
import java.util.StringTokenizer; |
||||||
import java.util.StringTokenizer; |
import java.util.logging.LogManager; |
||||||
import java.util.logging.LogManager; |
import java.util.logging.Logger; |
||||||
import java.util.logging.Logger; |
|
||||||
|
import de.memtext.util.GetOpts; |
||||||
import de.memtext.util.ExceptionHandler; |
import de.memtext.util.GetOpts.Options; |
||||||
import de.memtext.util.GetOpts; |
import de.superx.bin.Doschema.Format; |
||||||
|
|
||||||
/** |
/** |
||||||
* @author Daniel Quathamer Projektgruppe SuperX |
* @author Daniel Quathamer Projektgruppe SuperX |
||||||
* Dosql.java |
* Dosql.java |
||||||
* @ |
* @ |
||||||
* Dieses Javaprogramm führt einen oder mehrere SQL-Ausdrück in einer Datei aus und gibt das Ergebnis aus.<br> |
* Dieses Javaprogramm führt einen oder mehrere SQL-Ausdrück in einer Datei aus und gibt das Ergebnis aus.<br> |
||||||
* Gebrauch:<br> java dosql <Pfad zu logger-properties> <pfad zu db.properties> <Datei mit sql-Ausdrücken> <Ausgabeformat (txt | html | xml)>(optional) <delimiter> <mit Spaltenüberschriften (true | false)>(optional) <Ausgabedatei>(optional) |
* Gebrauch:<br> java dosql <Pfad zu logger-properties> <pfad zu db.properties> <Datei mit sql-Ausdrücken> <Ausgabeformat (txt | html | xml)>(optional) <delimiter> <mit Spaltenüberschriften (true | false)>(optional) <Ausgabedatei>(optional) |
||||||
* |
* |
||||||
*/ |
*/ |
||||||
|
|
||||||
/* Änderungen |
/* Änderungen |
||||||
|
|
||||||
15.4.2004 MB wenn keine Ausgabedatei und Ausgabeformat txt, alle selects von SxJdbcClient |
15.4.2004 MB wenn keine Ausgabedatei und Ausgabeformat txt, alle selects von SxJdbcClient |
||||||
loggen lassen |
loggen lassen |
||||||
6.4.2004 MB Code static main verlegt - nach erfolgreicher Durchführung ein system.out |
6.4.2004 MB Code static main verlegt - nach erfolgreicher Durchführung ein system.out |
||||||
|
|
||||||
**/ |
**/ |
||||||
public class Dosql { |
public class Dosql { |
||||||
private static Connection myDb; |
private static Connection myDb; |
||||||
private static Statement st; // Our statement to run queries with
|
|
||||||
private static boolean done = false; // Added by CWJ to permit \q command
|
private static Statement st; // Our statement to run queries with
|
||||||
private static String delim = "^"; |
|
||||||
private static String header = "false"; |
private static boolean done = false; // Added by CWJ to permit \q command
|
||||||
private static String logfile = "../conf/logging.properties"; |
|
||||||
private static String tabelle = ""; |
private static String delim = "^"; |
||||||
private static String dbpropfile = "../conf/db.properties"; |
|
||||||
private static String outfile = ""; |
private static String header = "false"; |
||||||
private static String outFormat = "txt"; |
|
||||||
private static String _dateiPfad = ""; |
private static String logfile = "../conf/logging.properties"; |
||||||
//LogUtils logger=null;
|
|
||||||
private static Logger logger = |
private static String tabelle = ""; |
||||||
(Logger) Logger.getLogger(Dosql.class.toString()); |
|
||||||
//static Logger logger = Logger.getLogger(dosql.class);
|
private static String dbpropfile = "../conf/db.properties"; |
||||||
private static ExceptionHandler exceptionHandler = |
|
||||||
new ExceptionHandler(false); |
private static String outfile = ""; |
||||||
private static String usage = |
|
||||||
"-------------------------------------\n" |
private static Format outFormat = Format.txt; |
||||||
+ "Gebrauch: java de.superx.bin.Dosql -logger=<<Pfad zu logging.properties>> -dbproperties=<<Pfad zu db.properties>> " |
|
||||||
+ "-sqlfile:<Datei mit sql-Ausdrücken> -params:<Parameter, die in sql- oder Script-Dateien ersetzt werden; Syntax:param1=wert1,param2=wert2 etc> -outFormat:<Ausgabeformat (txt | html | xml)>(optional) -delim:<delimiter> -header:<mit Spaltenüberschriften (true | false)>(optional) -outfile:<Ausgabedatei>(optional) \n---------------------------------------------------"; |
private static String _dateiPfad = ""; |
||||||
|
|
||||||
/* |
//LogUtils logger=null;
|
||||||
* Display some instructions on how to run the example |
private static Logger logger = (Logger) Logger.getLogger(Dosql.class.toString()); |
||||||
*/ |
|
||||||
public static void instructions() { |
//static Logger logger = Logger.getLogger(dosql.class);
|
||||||
System.out.println("SuperX @version@\n"); |
|
||||||
System.out.println( |
|
||||||
"\nDieses Javaprogramm führt ein beliebiges sql-Script mit einer oder mehr sql-Anweisungen aus"); |
private static String usage = "-------------------------------------\n" |
||||||
System.out.println( |
+ "Gebrauch: java de.superx.bin.Dosql -logger=<<Pfad zu logging.properties>> -dbproperties=<<Pfad zu db.properties>> " |
||||||
"Im Classpath muss superx@version@.jar sowie der zugehörige jdbc-Treiber sein."); |
+ "-sqlfile:<Datei mit sql-Ausdrücken> -params:<Parameter, die in sql- oder Script-Dateien ersetzt werden; Syntax:param1=wert1,param2=wert2 etc> -outFormat:<Ausgabeformat (txt | html | xml)>(optional) -delim:<delimiter> -header:<mit Spaltenüberschriften (true | false)>(optional) -outfile:<Ausgabedatei>(optional) \n---------------------------------------------------"; |
||||||
System.out.println( |
|
||||||
"Befehl:\n java dosql <Dateipfad sql-Script> <delimiter>(optional) <Ausgabe der Feldüberschriften (optional, true oder false)."); |
/* |
||||||
System.out.println( |
* Display some instructions on how to run the example |
||||||
"Default:\n java dosql <Dateipfad sql-Script> <TAB> true"); |
*/ |
||||||
System.exit(1); |
public static void instructions() { |
||||||
} |
System.out.println("SuperX @version@\n"); |
||||||
|
System.out.println("\nDieses Javaprogramm führt ein beliebiges sql-Script mit einer oder mehr sql-Anweisungen aus"); |
||||||
public static void main(String args[]) { |
System.out.println("Im Classpath muss superx@version@.jar sowie der zugehörige jdbc-Treiber sein."); |
||||||
try { |
System.out.println("Befehl:\n java dosql <Dateipfad sql-Script> <delimiter>(optional) <Ausgabe der Feldüberschriften (optional, true oder false)."); |
||||||
execute(args); |
System.out.println("Default:\n java dosql <Dateipfad sql-Script> <TAB> true"); |
||||||
} catch (Exception e) { |
System.exit(1); |
||||||
logger.severe( |
} |
||||||
"Fehler beim sql-Script: " + _dateiPfad + " " + e.toString()); |
|
||||||
e.printStackTrace(); |
public static void main(String args[]) { |
||||||
System.exit(1); |
try { |
||||||
} |
execute(args); |
||||||
|
} catch (Exception e) { |
||||||
} |
logger.severe("Fehler beim sql-Script: " + _dateiPfad + " " + e.toString()); |
||||||
|
e.printStackTrace(); |
||||||
public static void execute(String[] args) |
System.exit(1); |
||||||
throws Exception { |
} |
||||||
|
|
||||||
String params = ""; |
} |
||||||
GetOpts.setOpts(args); |
|
||||||
String isdrin = |
public static void execute(String[] args) throws Exception { |
||||||
GetOpts.isAllRequiredOptionsPresent( |
|
||||||
"-logger,-dbproperties,-sqlfile"); |
String params = ""; |
||||||
if (isdrin != null) { |
GetOpts.setOpts(args); |
||||||
System.err.println("Folgende Optionen fehlen: " + isdrin); |
String isdrin = GetOpts.isAllRequiredOptionsPresent(new Options[]{Options.opt_logger,Options.opt_dbprops,Options.opt_sql}); |
||||||
System.err.println(usage); |
if (isdrin != null) { |
||||||
System.exit(1); |
System.err.println("Folgende Optionen fehlen: " + isdrin); |
||||||
} |
System.err.println(usage); |
||||||
|
System.exit(1); |
||||||
//GetOpts myOpts=new GetOpts();
|
} |
||||||
if (GetOpts.isPresent("-logger")) |
|
||||||
logfile = GetOpts.getValue("-logger"); |
//GetOpts myOpts=new GetOpts();
|
||||||
if (GetOpts.isPresent("-dbproperties")) |
if (GetOpts.isPresent(Options.opt_logger)) logfile = GetOpts.getValue(Options.opt_logger); |
||||||
dbpropfile = GetOpts.getValue("-dbproperties"); |
if (GetOpts.isPresent(Options.opt_dbprops)) dbpropfile = GetOpts.getValue(Options.opt_dbprops); |
||||||
if (GetOpts.isPresent("-sqlfile")) |
if (GetOpts.isPresent(Options.opt_sql)) _dateiPfad = GetOpts.getValue(Options.opt_sql); |
||||||
_dateiPfad = GetOpts.getValue("-sqlfile"); |
//if (GetOpts.isPresent("-outFormat")) outFormat = GetOpts.getValue("-outFormat");
|
||||||
if (GetOpts.isPresent("-outFormat")) |
if (GetOpts.isPresent(Options.opt_delim)) delim = GetOpts.getValue(Options.opt_delim); |
||||||
outFormat = GetOpts.getValue("-outFormat"); |
if (GetOpts.isPresent(Options.opt_header)) header = GetOpts.getValue(Options.opt_header); |
||||||
if (GetOpts.isPresent("-delim")) |
if (GetOpts.isPresent(Options.opt_outFile)) outfile = GetOpts.getValue(Options.opt_outFile); |
||||||
delim = GetOpts.getValue("-delim"); |
if (GetOpts.isPresent(Options.opt_params)) params = GetOpts.getValue(Options.opt_params); |
||||||
if (GetOpts.isPresent("-header")) |
|
||||||
header = GetOpts.getValue("-header"); |
if(GetOpts.isPresent(Options.opt_outFormat)) { |
||||||
if (GetOpts.isPresent("-outfile")) |
outFormat = Format.valueOf(GetOpts.getValue(Options.opt_outFormat).toLowerCase()); |
||||||
outfile = GetOpts.getValue("-outfile"); |
} |
||||||
if (GetOpts.isPresent("-params")) |
|
||||||
params = GetOpts.getValue("-params"); |
if (delim.equals("")) delim = "^"; //default Delimiter
|
||||||
|
|
||||||
if (delim.equals("")) |
//logger.initRaw(dosql.class)
|
||||||
delim = "^"; //default Delimiter
|
//PropertyConfigurator.configure(logfile);
|
||||||
|
File f = new File(logfile); |
||||||
//logger.initRaw(dosql.class)
|
if (!f.exists()) { |
||||||
//PropertyConfigurator.configure(logfile);
|
throw new IOException("Datei nicht gefunden: " + logfile); |
||||||
File f = new File(logfile); |
} |
||||||
if (!f.exists()) { |
FileInputStream ins = new FileInputStream(logfile); |
||||||
throw new IOException("Datei nicht gefunden: " + logfile); |
LogManager MyLogManager = java.util.logging.LogManager.getLogManager(); |
||||||
} |
MyLogManager.readConfiguration(ins); |
||||||
FileInputStream ins = new FileInputStream(logfile); |
logfile = MyLogManager.getProperty(".level"); |
||||||
LogManager MyLogManager = java.util.logging.LogManager.getLogManager(); |
logger.info("Using Loggging-Level " + logfile); |
||||||
MyLogManager.readConfiguration(ins); |
|
||||||
logfile = MyLogManager.getProperty(".level"); |
f = new File(_dateiPfad); |
||||||
logger.info("Using Loggging-Level " + logfile); |
if (!f.exists()) { |
||||||
|
throw new IOException("Datei nicht gefunden: " + _dateiPfad); |
||||||
f = new File(_dateiPfad); |
} |
||||||
if (!f.exists()) { |
BufferedReader in; |
||||||
throw new IOException("Datei nicht gefunden: " + _dateiPfad); |
//--- InputStream generieren ---//
|
||||||
} |
in = new BufferedReader(new InputStreamReader(new FileInputStream(f))); |
||||||
BufferedReader in; |
|
||||||
//--- InputStream generieren ---//
|
//--- Verarbeiten der Datei ---//
|
||||||
in = new BufferedReader(new InputStreamReader(new FileInputStream(f))); |
String sql = ""; |
||||||
|
String text = ""; |
||||||
//--- Verarbeiten der Datei ---//
|
while ((text = in.readLine()) != null) { |
||||||
String sql = ""; |
//MB auskommentiert 27.4.05
|
||||||
String text = ""; |
//löschte ( in
|
||||||
while ((text = in.readLine()) != null) { |
//insert into
|
||||||
//MB auskommentiert 27.4.05
|
//(
|
||||||
//löschte ( in
|
//tid,...
|
||||||
//insert into
|
//if (text.length() > 1)
|
||||||
//(
|
sql += System.getProperty("line.separator") + text.trim(); |
||||||
//tid,...
|
} |
||||||
//if (text.length() > 1)
|
in.close(); |
||||||
sql += System.getProperty("line.separator") + text.trim(); |
if (sql.toLowerCase().indexOf("<xupdate>") > -1) { |
||||||
} |
SxConnection myConnection = new SxConnection(); |
||||||
in.close(); |
myConnection.setPropfile(dbpropfile); |
||||||
if (sql.toLowerCase().indexOf("<xupdate>")>-1) |
Connection con = myConnection.getConnection(); |
||||||
{ |
|
||||||
SxConnection myConnection = new SxConnection(); |
new XUpdater().execute(con, myConnection.getDatabaseAbbr(), sql, logger); |
||||||
myConnection.setPropfile(dbpropfile); |
} else { |
||||||
Connection con = myConnection.getConnection(); |
if (sql.toLowerCase().indexOf("--freemarker template") > -1) { |
||||||
|
|
||||||
new XUpdater().execute(con, myConnection.getDatabaseAbbr(), sql,logger); |
try { |
||||||
} |
sql = de.superx.bin.FMParser.simpleParser(dbpropfile, sql); |
||||||
else |
} catch (Exception e) { |
||||||
{ |
|
||||||
if(sql.toLowerCase().indexOf("--freemarker template")>-1) |
e.printStackTrace(); |
||||||
{ |
} |
||||||
|
} |
||||||
try { |
sql = sql.trim(); |
||||||
sql=de.superx.bin.FMParser.simpleParser(dbpropfile, sql); |
if (sql.startsWith("\"")) sql = sql.substring(1, sql.length()); |
||||||
} catch (Exception e) { |
if (sql.endsWith("\"")) sql = sql.substring(0, sql.length() - 1); |
||||||
|
|
||||||
e.printStackTrace(); |
logger.config("Inhalt der sql-Datei: \n--" + sql + "--"); |
||||||
} |
//First the params are replaced:
|
||||||
} |
if (!params.equals("")) { |
||||||
sql = sql.trim(); |
if (!params.endsWith("|")) params += "|"; |
||||||
if (sql.startsWith("\"")) |
StringTokenizer st = new StringTokenizer(params, "|"); |
||||||
sql = sql.substring(1, sql.length()); |
for (; st.hasMoreTokens();) { |
||||||
if (sql.endsWith("\"")) |
String param = st.nextToken(); |
||||||
sql = sql.substring(0, sql.length() - 1); |
if (!param.equals("")) { |
||||||
|
String paramname = param.substring(0, param.indexOf("=")); |
||||||
logger.config("Inhalt der sql-Datei: \n--" + sql + "--"); |
String paramvalue = param.substring(param.indexOf("=") + 1, param.length()); |
||||||
//First the params are replaced:
|
sql = de.superx.bin.SxDBUtils.replaceString(sql, paramname, paramvalue); |
||||||
if (!params.equals("")) { |
} |
||||||
if (!params.endsWith("|")) |
} |
||||||
params += "|"; |
} |
||||||
StringTokenizer st = new StringTokenizer(params, "|"); |
SxJdbcClient myClient = new SxJdbcClient(logger, dbpropfile, sql); |
||||||
for (; st.hasMoreTokens();) { |
if (outfile.equals("") && outFormat == Format.txt) myClient.setLogAllResultSetsToConsole(true); |
||||||
String param = st.nextToken(); |
SxTransformer myTransformer = null; |
||||||
if (!param.equals("")) { |
|
||||||
String paramname = param.substring(0, param.indexOf("=")); |
myClient.Rs_executeALL(); |
||||||
String paramvalue = |
ResultSet myrs = myClient.getRs(); |
||||||
param.substring(param.indexOf("=") + 1, param.length()); |
|
||||||
sql = |
if (myrs != null) { |
||||||
de.superx.bin.SxDBUtils.replaceString( |
if (outfile.equals("")) { |
||||||
sql, |
myTransformer = new SxTransformer(logger, System.out); |
||||||
paramname, |
} else |
||||||
paramvalue); |
myTransformer = new SxTransformer(logger, new FileWriter(outfile)); |
||||||
} |
|
||||||
} |
if (!outfile.equals("") || outFormat != Format.txt) { |
||||||
} |
|
||||||
SxJdbcClient myClient = new SxJdbcClient(logger, dbpropfile, sql); |
myTransformer.setDelim(delim); |
||||||
if (outfile.equals("")&&outFormat.equalsIgnoreCase("txt")) |
myTransformer.setHeader(header); |
||||||
myClient.setLogAllResultSetsToConsole(true); |
|
||||||
SxTransformer myTransformer = null; |
myTransformer.setOutrs(myrs); |
||||||
|
myTransformer.setOutrsmd(myClient.getRsmd()); |
||||||
myClient.Rs_executeALL(); |
myTransformer.printResult(outFormat.name()); |
||||||
ResultSet myrs = myClient.getRs(); |
} |
||||||
|
} else |
||||||
if (myrs != null) { |
logger.info("Keine Rückgabewerte aus SQL-Script"); |
||||||
if (outfile.equals("")) { |
myClient.close(); |
||||||
myTransformer = new SxTransformer(logger, System.out); |
} |
||||||
} else |
System.out.println("Dosql hat das Script " + _dateiPfad + " erfolgreich durchgeführt"); |
||||||
myTransformer = |
logger.info("dosql erfolgreich beendet"); |
||||||
new SxTransformer(logger, new FileWriter(outfile)); |
|
||||||
|
} |
||||||
if (!outfile.equals("")||!outFormat.equalsIgnoreCase("txt")) |
} |
||||||
{ |
|
||||||
|
|
||||||
myTransformer.setDelim(delim); |
|
||||||
myTransformer.setHeader(header); |
|
||||||
|
|
||||||
myTransformer.setOutrs(myrs); |
|
||||||
myTransformer.setOutrsmd(myClient.getRsmd()); |
|
||||||
myTransformer.printResult(outFormat); |
|
||||||
} |
|
||||||
} else |
|
||||||
logger.info("Keine Rückgabewerte aus SQL-Script"); |
|
||||||
myClient.close(); |
|
||||||
} |
|
||||||
System.out.println( |
|
||||||
"Dosql hat das Script " + _dateiPfad + " erfolgreich durchgeführt"); |
|
||||||
logger.info("dosql erfolgreich beendet"); |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,927 @@ |
|||||||
|
package de.superx.bin; |
||||||
|
|
||||||
|
import static de.superx.servlet.SxSQL_Server.DEFAULT_MANDANTEN_ID; |
||||||
|
|
||||||
|
import java.sql.ResultSet; |
||||||
|
import java.sql.SQLException; |
||||||
|
import java.sql.Timestamp; |
||||||
|
import java.text.SimpleDateFormat; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Date; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Random; |
||||||
|
import java.util.regex.Matcher; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
import javax.sql.DataSource; |
||||||
|
|
||||||
|
import org.apache.commons.cli.CommandLine; |
||||||
|
import org.apache.commons.cli.CommandLineParser; |
||||||
|
import org.apache.commons.cli.GnuParser; |
||||||
|
import org.apache.commons.cli.HelpFormatter; |
||||||
|
import org.apache.commons.cli.Option; |
||||||
|
import org.apache.commons.cli.Options; |
||||||
|
import org.apache.commons.cli.ParseException; |
||||||
|
import org.apache.log4j.Level; |
||||||
|
import org.apache.log4j.Logger; |
||||||
|
import org.springframework.batch.core.ExitStatus; |
||||||
|
import org.springframework.beans.BeansException; |
||||||
|
import org.springframework.context.ApplicationContext; |
||||||
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
||||||
|
import org.springframework.context.support.GenericApplicationContext; |
||||||
|
import org.springframework.dao.DataIntegrityViolationException; |
||||||
|
import org.springframework.jdbc.BadSqlGrammarException; |
||||||
|
import org.springframework.jdbc.core.JdbcTemplate; |
||||||
|
import org.springframework.jdbc.core.ResultSetExtractor; |
||||||
|
import org.springframework.jdbc.core.RowCallbackHandler; |
||||||
|
|
||||||
|
import de.superx.rest.EtlJobApi; |
||||||
|
import de.superx.rest.model.job.Component; |
||||||
|
import de.superx.rest.model.job.JobExecutionStatus; |
||||||
|
import de.superx.rest.model.job.StepExecutionStatus; |
||||||
|
import de.superx.servlet.SuperXManager; |
||||||
|
import de.superx.servlet.SxPools; |
||||||
|
import de.superx.spring.batch.His1DataSources; |
||||||
|
import de.superx.spring.cli.config.CLIConfig; |
||||||
|
import de.superx.spring.config.BatchConfig; |
||||||
|
import de.superx.spring.config.DataJdbcConfiguration; |
||||||
|
|
||||||
|
|
||||||
|
public class EtlFuzzer { |
||||||
|
|
||||||
|
private static String HELP = "Use this tool to check for problems with incongruencies, " |
||||||
|
+ "which may occur " |
||||||
|
+ "while running etljobs. Note that Tomcat should not be running," |
||||||
|
+ " due to resulting interferences. Additionally, " |
||||||
|
+ "the usage of the latest version of the data sample in the source systems is recommended" |
||||||
|
+ "WARNING: you can only run either all of the mbs modules at once or on of them, before you" |
||||||
|
+ "must reset your mbs database. It will crash otherwise."; |
||||||
|
|
||||||
|
private static Logger log = Logger.getLogger(EtlFuzzer.class.getName()); |
||||||
|
|
||||||
|
private static int EXTREME_INT = 2100000000; |
||||||
|
|
||||||
|
private static Random random = new Random(); |
||||||
|
|
||||||
|
private static final String COLNAME_NULLABLE = "is_nullable"; |
||||||
|
|
||||||
|
private static final String COLNAME_COLUMN = "column_name"; |
||||||
|
|
||||||
|
private static final String COLNAME_DATATYPE = "data_type"; |
||||||
|
|
||||||
|
private static final String COLNAME_CHAR_MAX = "character_maximum_length"; |
||||||
|
|
||||||
|
private static final String COLNAME_PRECISION = "numeric_precision"; |
||||||
|
|
||||||
|
private static final String COLNAME_SCALE = "numeric_scale"; |
||||||
|
|
||||||
|
private static final String COLNAME_TABLE = "table_name"; |
||||||
|
|
||||||
|
private static final String COLNAME_RELNAME = "relname"; |
||||||
|
|
||||||
|
private static final String DB_MBS = "mbs"; |
||||||
|
|
||||||
|
private static final String DB_H1 = "hisinone"; |
||||||
|
|
||||||
|
private static int extreme_int_puffer = 10000; |
||||||
|
|
||||||
|
private static String SQL_GET_ACCESSED_TABLES_H1 = "Select * from pg_stat_all_tables where " |
||||||
|
+ "(seq_scan > 0 or seq_tup_read > 0 or idx_scan > 0) and schemaname = 'hisinone'"; |
||||||
|
|
||||||
|
private static String SQL_GET_ACCESSED_TABLES_MBS = "Select * from pg_stat_all_tables where " |
||||||
|
+ "(seq_scan > 0 or seq_tup_read > 0 or idx_scan > 0) and schemaname = 'mbs'"; |
||||||
|
|
||||||
|
private static String SQL_GET_TABLE_METADATA_BASE = "select column_name, data_type," |
||||||
|
+ " is_nullable, numeric_precision, numeric_scale, character_maximum_length from information_schema.columns where table_name ="; |
||||||
|
|
||||||
|
private static String SQL_RESET_STATISTICS = "Select pg_stat_reset()"; |
||||||
|
|
||||||
|
private static String[] modulesH1 = {"kern", "cob", "prom", "sos", "res", "zul"}; |
||||||
|
|
||||||
|
private static String[] modulesMBS = {"fin","ivs","bau"}; |
||||||
|
|
||||||
|
private static final int MODULES_KERN_INDEX = 0; |
||||||
|
private static final int MODULES_COB_INDEX = 1; |
||||||
|
private static final int MODULES_PROM_INDEX = 2; |
||||||
|
private static final int MODULES_SOS_INDEX = 3; |
||||||
|
private static final int MODULES_RES_INDEX = 4; |
||||||
|
private static final int MODULES_ZUL_INDEX = 5; |
||||||
|
private static final int MODULES_FIN_INDEX = 0; |
||||||
|
private static final int MODULES_IVS_INDEX = 1; |
||||||
|
private static final int MODULES_BAU_INDEX = 2; |
||||||
|
|
||||||
|
private static int next_id = 0; |
||||||
|
|
||||||
|
private static int next_join_nr = 0; |
||||||
|
|
||||||
|
private static ArrayList<String> errors = new ArrayList<>(); |
||||||
|
|
||||||
|
private static void setNext_join_nr(int next_nr) { |
||||||
|
EtlFuzzer.next_join_nr = next_nr; |
||||||
|
} |
||||||
|
|
||||||
|
private static void setNext_id(int next_id) { |
||||||
|
EtlFuzzer.next_id = next_id; |
||||||
|
} |
||||||
|
|
||||||
|
static HashMap<String, String> error_tables_columns = new HashMap<String, String>(); |
||||||
|
|
||||||
|
private static ArrayList<String> error_keys = new ArrayList<>(); |
||||||
|
|
||||||
|
private static ApplicationContext applicationContext; |
||||||
|
|
||||||
|
private static GenericApplicationContext APPLICATION_CONTEXT = null; |
||||||
|
|
||||||
|
/** |
||||||
|
* Generiert einen String, bestehend aus dem Zeichen x, mit einer bestimmten Länge. |
||||||
|
* @param length gewollte Stringlänge |
||||||
|
*/ |
||||||
|
private static String StringGenerator(int length) { |
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
for (int i = 0; i < length; i++) { |
||||||
|
sb.append("x"); |
||||||
|
} |
||||||
|
return sb.toString(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* generiert einen numerischen Wert mit precision Stellen vor dem Komma und scale Nachkommastellen. |
||||||
|
* @param precision |
||||||
|
* @param scale |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private static String NumGen(int precision, int scale) { |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
for (int i = 0; i < precision; i++) { |
||||||
|
sb.append("9"); |
||||||
|
} |
||||||
|
String num = sb.toString(); |
||||||
|
String firstPart = num.substring(0, precision-scale); |
||||||
|
String secondPart = num.substring(precision-scale); |
||||||
|
return firstPart + "." + secondPart; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Gibt alle Tabellen aus, auf die durch ein Entladeskript zugegriffen wurde. |
||||||
|
* @param stmt Statement |
||||||
|
* @param tables ArrayListe, in die die Tabellennamen gespeichert werden sollen. |
||||||
|
* @return ArrayList mit den Tabellennamen |
||||||
|
* @throws SQLException |
||||||
|
*/ |
||||||
|
private static ArrayList<String> getAccessedTablesH1(JdbcTemplate jt, ArrayList<String> tables) throws SQLException { |
||||||
|
|
||||||
|
ResultSetExtractor<Void> extractor = new ResultSetExtractor<Void>() { |
||||||
|
@Override |
||||||
|
public Void extractData(ResultSet rs) throws SQLException { |
||||||
|
while(rs.next()) { |
||||||
|
tables.add(rs.getString(COLNAME_RELNAME)); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
}; |
||||||
|
jt.query(SQL_GET_ACCESSED_TABLES_H1, extractor); |
||||||
|
return tables; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* gibt alle durch ETL Laderoutinen zugegriffenen Tabellen für das mbs Vorsystem aus. |
||||||
|
* @return |
||||||
|
* @throws SQLException |
||||||
|
*/ |
||||||
|
private static ArrayList<String> getAccessedTablesMBS(JdbcTemplate jt, ArrayList<String> tables) throws SQLException { |
||||||
|
|
||||||
|
ResultSetExtractor<Void> extractor = new ResultSetExtractor<Void>() { |
||||||
|
@Override |
||||||
|
public Void extractData(ResultSet rs) throws SQLException { |
||||||
|
while(rs.next()) { |
||||||
|
tables.add(rs.getString(COLNAME_RELNAME)); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
}; |
||||||
|
jt.query(SQL_GET_ACCESSED_TABLES_MBS, extractor); |
||||||
|
return tables; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Gibt den SQL Befehl für die Metadaten einer Tabelle aus dem hisinone Vorsystem zurück. |
||||||
|
* @param table Tabellenname |
||||||
|
* @return SQL Befehl |
||||||
|
*/ |
||||||
|
private static String sqlTableMetaDataH1(String table) { |
||||||
|
return SQL_GET_TABLE_METADATA_BASE + "'" + table + "'"; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Gibt den SQL Befehl für die Metadaten einer Tabelle aus dem mbs Vorsystem zurück. |
||||||
|
* @param table |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private static String sqlTableMetaDataMBS(String table) { |
||||||
|
return String.format("%s '%s' and table_schema='mbs'",SQL_GET_TABLE_METADATA_BASE, table); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* für HLR. |
||||||
|
* @param <T> |
||||||
|
* @param beanName |
||||||
|
* @param requiredType |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static <T> T getBean(String beanName, Class<T> requiredType) { |
||||||
|
if (applicationContext != null) { |
||||||
|
return applicationContext.getBean(beanName, requiredType); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* für HLR. |
||||||
|
*/ |
||||||
|
private static void initSxPools() { |
||||||
|
try { |
||||||
|
List<String> mandantenNamen = new LinkedList<String>(); |
||||||
|
mandantenNamen.add(DEFAULT_MANDANTEN_ID); |
||||||
|
SxPools.closeAll(); |
||||||
|
SxPools.init(mandantenNamen); |
||||||
|
SxPools.get(DEFAULT_MANDANTEN_ID).init(); |
||||||
|
SxPools.get(DEFAULT_MANDANTEN_ID).initLogging(true, Level.DEBUG); |
||||||
|
} catch (Exception e) { |
||||||
|
System.out.println("error while initialising the SuperX pools:"); |
||||||
|
e.printStackTrace(); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* für HLR. |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private static GenericApplicationContext createContext() { |
||||||
|
/* |
||||||
|
* https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/AnnotationConfigApplicationContext.html
|
||||||
|
* quote: |
||||||
|
* "In case of multiple @Configuration classes, @Bean methods defined in later classes will override those defined in earlier classes. |
||||||
|
* This can be leveraged to deliberately override certain bean definitions via an extra @Configuration class." |
||||||
|
* - so it's alright to override some beans via "CLIConfig" |
||||||
|
*/ |
||||||
|
if (APPLICATION_CONTEXT == null) { |
||||||
|
APPLICATION_CONTEXT = new AnnotationConfigApplicationContext(BatchConfig.class, DataJdbcConfiguration.class, CLIConfig.class); |
||||||
|
} |
||||||
|
return APPLICATION_CONTEXT; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* für HLR. |
||||||
|
* @param comp |
||||||
|
* @param etlJob |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private static boolean isHauptladeroutine(String comp, EtlJobApi etlJob) { |
||||||
|
List<Component> installJobs = etlJob.getEtlJobs(); |
||||||
|
for (Component comp_meta : installJobs) { |
||||||
|
if (comp_meta != null && comp_meta.getAbbreviation().equals(comp)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Erstellt einen Timestamp, in einem bestimmten Format. |
||||||
|
* @param d |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private static String timestampMaker(String d) { |
||||||
|
Date date = new Date(); |
||||||
|
Timestamp ts=new Timestamp(date.getTime()); |
||||||
|
SimpleDateFormat formatterNow = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
||||||
|
SimpleDateFormat formatterDay = new SimpleDateFormat("yyyy-MM-dd"); |
||||||
|
String time = ""; |
||||||
|
|
||||||
|
switch(d) { |
||||||
|
case "day": |
||||||
|
time = formatterDay.format(ts); |
||||||
|
break; |
||||||
|
case "now": |
||||||
|
time = formatterNow.format(ts); |
||||||
|
break; |
||||||
|
} |
||||||
|
return time; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* für HLR. |
||||||
|
* @param job_id |
||||||
|
* @param context |
||||||
|
*/ |
||||||
|
private static void etlJob(String job_id, GenericApplicationContext context, String db) { |
||||||
|
System.out.println(job_id); |
||||||
|
try { |
||||||
|
EtlJobApi componentApi = context.getBean(EtlJobApi.class); |
||||||
|
String database = db; |
||||||
|
Long jobStartStatus; |
||||||
|
if (isHauptladeroutine(job_id, componentApi)) { |
||||||
|
jobStartStatus = componentApi.complete(job_id); |
||||||
|
} else { |
||||||
|
jobStartStatus = componentApi.executeJob(database, job_id); |
||||||
|
} |
||||||
|
handleStartResult(jobStartStatus, componentApi); |
||||||
|
} catch (BeansException be) { |
||||||
|
handleBeansException(be); |
||||||
|
} catch (Exception e) { |
||||||
|
handleJobException(e, job_id); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void unload(String job_id, GenericApplicationContext context, String db) { |
||||||
|
System.out.println(job_id); |
||||||
|
try { |
||||||
|
EtlJobApi componentApi = context.getBean(EtlJobApi.class); |
||||||
|
String database = db; |
||||||
|
Long jobStartStatus; |
||||||
|
if (isHauptladeroutine(job_id, componentApi)) { |
||||||
|
jobStartStatus = componentApi.unload(job_id); |
||||||
|
} else { |
||||||
|
jobStartStatus = componentApi.executeJob(database, job_id); |
||||||
|
} |
||||||
|
handleStartResult(jobStartStatus, componentApi); |
||||||
|
} catch (BeansException be) { |
||||||
|
handleBeansException(be); |
||||||
|
} catch (Exception e) { |
||||||
|
handleJobException(e, job_id); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Findet in einem String den ersten Integer Wert der innerhalb dieser Zeichen "»«" liegt. Die Zeichen sind relevant für die Fehlermeldung. |
||||||
|
* @param input |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static String findInt(String input) { |
||||||
|
Pattern pattern = Pattern.compile("»\\d+«"); |
||||||
|
Matcher matcher = pattern.matcher(input); |
||||||
|
if (matcher.find()) { |
||||||
|
String match = matcher.group(); |
||||||
|
return match.substring(1, match.length() - 1); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Gibt die gefundenen fehler aus. |
||||||
|
* @param ses |
||||||
|
*/ |
||||||
|
private static void collectErrors(StepExecutionStatus ses) { |
||||||
|
for (StepExecutionStatus sec : ses.getChildren()) { |
||||||
|
if(sec.getChildren() != null) { |
||||||
|
for(StepExecutionStatus sec2 : sec.getChildren()) { |
||||||
|
if (sec2.getExitStatus().getExitCode().equals("FAILED")) { |
||||||
|
errors.add(sec2.getName()); |
||||||
|
String etl_error = sec2.getExitStatus().getExitDescription(); |
||||||
|
errors.add(etl_error); |
||||||
|
if(error_tables_columns.containsKey(findInt(etl_error))) { |
||||||
|
error_keys.add(findInt(etl_error)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* für HLR. |
||||||
|
* @param jobStartStatus |
||||||
|
* @param componentApi |
||||||
|
*/ |
||||||
|
private static void handleStartResult(Long jobStartStatus, EtlJobApi componentApi) { |
||||||
|
if (jobStartStatus.intValue() == -1) { |
||||||
|
System.out.println("Aktion konnte nicht gestartet werden: Es läuft bereits eine Aktion"); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
try { |
||||||
|
JobExecutionStatus es = componentApi.getStatus(jobStartStatus); |
||||||
|
for(StepExecutionStatus ses : es.getStepExecutions()) { |
||||||
|
collectErrors(ses); |
||||||
|
} |
||||||
|
|
||||||
|
ExitStatus exst = es.exitStatus; |
||||||
|
|
||||||
|
if (exst.equals(ExitStatus.FAILED)) { |
||||||
|
System.out.println(("Beim Ausführen der Aktion ist ein Fehler aufgetreten; Bitte prüfen Sie die Logdatei.")); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
System.out.println(("Beim Ausführen der Aktion ist ein Fehler aufgetreten:")); |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* für HRL. |
||||||
|
* @param e |
||||||
|
* @param jobName |
||||||
|
*/ |
||||||
|
private static void handleJobException(Exception e, String jobName) { |
||||||
|
System.out.println("error while executing the job '" + jobName + "'"); |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* für HLR. |
||||||
|
* @param be |
||||||
|
*/ |
||||||
|
private static void handleBeansException(BeansException be) { |
||||||
|
System.out.println("configuration error or error with resolving the bean '" + EtlJobApi.class.getCanonicalName() + "'"); |
||||||
|
be.printStackTrace(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* gibt den Inhalt einer ArrayList aus. |
||||||
|
* @param list |
||||||
|
*/ |
||||||
|
private static void printList(ArrayList<String> list) { |
||||||
|
for(int i = 0; i<list.size();i++) { |
||||||
|
String text = list.get(i); |
||||||
|
log.info(String.format(" %s", text)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* gibt die Tabellen- und Spaltennamen von den Fehlern aus, die durch die Ints entstehen. |
||||||
|
*/ |
||||||
|
private static void printIntErrors() { |
||||||
|
for(String key : error_keys) { |
||||||
|
String intError = String.format("Der Wert: %s wurde initial in die Tabelle.Spalte: %s eingetragen.", key, error_tables_columns.get(key)); |
||||||
|
log.info(intError); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Findet für ein ID Attribut, den nächstgrößeren Wert. |
||||||
|
* @param jt |
||||||
|
* @param table |
||||||
|
* @param column_name |
||||||
|
*/ |
||||||
|
private static void nextID(JdbcTemplate jt, String table, String column_name, String db) { |
||||||
|
ResultSetExtractor<Void> extractor = new ResultSetExtractor<Void>() { |
||||||
|
@Override |
||||||
|
public Void extractData(ResultSet rs) throws SQLException { |
||||||
|
while(rs.next()) { |
||||||
|
setNext_id(rs.getInt(1)+1); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
}; |
||||||
|
if (db.equals(DB_H1)) { |
||||||
|
String SQL_highest_id = String.format("Select max(%s) from %s", column_name, table); |
||||||
|
jt.query(SQL_highest_id, extractor); |
||||||
|
} else { |
||||||
|
String SQL_highest_id = String.format("Select max(%s) from mbs.%s", column_name, table); |
||||||
|
jt.query(SQL_highest_id, extractor); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void next_nr(JdbcTemplate jt, String table, String column_name) { |
||||||
|
ResultSetExtractor<Void> extractor = new ResultSetExtractor<Void>() { |
||||||
|
@Override |
||||||
|
public Void extractData(ResultSet rs) throws SQLException { |
||||||
|
while(rs.next()) { |
||||||
|
setNext_join_nr(rs.getInt(1)+1); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
}; |
||||||
|
String SQL_highest_nr = String.format("select max(%s) from mbs.%s", column_name, table); |
||||||
|
jt.query(SQL_highest_nr, extractor); |
||||||
|
} |
||||||
|
|
||||||
|
public static String separateWithComma(ArrayList<String> array) { |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
for (int i = 0; i < array.size(); i++) { |
||||||
|
sb.append(array.get(i)); |
||||||
|
if (i < array.size() - 1) { |
||||||
|
sb.append(", "); |
||||||
|
} |
||||||
|
} |
||||||
|
return sb.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Erzeugt ein INSERT SQL Befehl. |
||||||
|
* @param traps |
||||||
|
* @param id |
||||||
|
* @param table |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private static String createTrap(ArrayList<String> traps, String table, String db) { |
||||||
|
String trap = ""; |
||||||
|
ArrayList<String> columns = new ArrayList<>(); |
||||||
|
ArrayList<String> values = new ArrayList<>(); |
||||||
|
for (int i = 0;i<traps.size();i++) { |
||||||
|
if (i % 2 == 0) { |
||||||
|
columns.add(traps.get(i)); |
||||||
|
} else { |
||||||
|
values.add(traps.get(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
if (db.equals(DB_H1)) { |
||||||
|
trap = String.format("Insert into %s (%s) values (%s)", table, separateWithComma(columns), separateWithComma(values)); |
||||||
|
} else if (db.equals(DB_MBS)) { |
||||||
|
trap = String.format("Insert into mbs.%s (%s) values (%s)", table, separateWithComma(columns), separateWithComma(values)); |
||||||
|
} |
||||||
|
return trap; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* fügt die Extremwerte in die Datenbank. |
||||||
|
* @param jt |
||||||
|
* @param table |
||||||
|
*/ |
||||||
|
private static void insertTraps(JdbcTemplate jt, String table, String db) { |
||||||
|
ResultSetExtractor<Void> extractor = new ResultSetExtractor<Void>() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public Void extractData(ResultSet rs) throws SQLException { |
||||||
|
ArrayList<String> traps = new ArrayList<>(); |
||||||
|
while(rs.next()) { |
||||||
|
//firstly, checks if nullable
|
||||||
|
if(rs.getString(COLNAME_NULLABLE).equals("YES")) { |
||||||
|
traps.add(rs.getString(COLNAME_COLUMN)); |
||||||
|
traps.add("null"); |
||||||
|
continue; |
||||||
|
//else generate extreme values
|
||||||
|
} else if (rs.getString(COLNAME_NULLABLE).equals("NO")) { |
||||||
|
//IDs
|
||||||
|
if (rs.getString(COLNAME_COLUMN).equals("id") || rs.getString(COLNAME_COLUMN).endsWith("_id") || |
||||||
|
rs.getString(COLNAME_COLUMN).equals("lid") || rs.getString(COLNAME_COLUMN).endsWith("_lid")) { |
||||||
|
nextID(jt, table, rs.getString(COLNAME_COLUMN), db); |
||||||
|
traps.add(rs.getString(COLNAME_COLUMN)); |
||||||
|
traps.add(String.valueOf(next_id)); |
||||||
|
continue; |
||||||
|
//Join_Nr
|
||||||
|
} else if (rs.getString(COLNAME_COLUMN).equals("join_nr")) { |
||||||
|
next_nr(jt, table, rs.getString(COLNAME_COLUMN)); |
||||||
|
traps.add(rs.getString(COLNAME_COLUMN)); |
||||||
|
traps.add(String.valueOf(next_join_nr)); |
||||||
|
//Int
|
||||||
|
} else if (rs.getString(COLNAME_DATATYPE).equals("integer")) { |
||||||
|
int randomNumber = EXTREME_INT + random.nextInt(extreme_int_puffer); |
||||||
|
//String number = String.format("%d", Integer.valueOf(randomNumber));
|
||||||
|
String number = Integer.toString(randomNumber); |
||||||
|
traps.add(rs.getString(COLNAME_COLUMN)); |
||||||
|
traps.add(number); |
||||||
|
error_tables_columns.put(number, String.format("%s.%s", table, rs.getString(COLNAME_COLUMN))); |
||||||
|
continue; |
||||||
|
//String
|
||||||
|
} else if (rs.getString(COLNAME_DATATYPE).equals("character varying")) { |
||||||
|
int max_length = rs.getInt(COLNAME_CHAR_MAX); |
||||||
|
String col = rs.getString(COLNAME_COLUMN); |
||||||
|
if (rs.getObject(COLNAME_CHAR_MAX) != null) { |
||||||
|
int length = max_length-table.length()-col.length()-2; |
||||||
|
//falls tabelle schon länger als max erlaubt
|
||||||
|
if (max_length <= table.length()) { |
||||||
|
traps.add(rs.getString(COLNAME_COLUMN)); |
||||||
|
traps.add(String.format("'%s'",StringGenerator(max_length))); |
||||||
|
continue; |
||||||
|
} |
||||||
|
//falls tabelle+spalte länger ist als max erlaubt
|
||||||
|
if((table.length() + col.length()) >= max_length) { |
||||||
|
length = max_length-table.length()-1; |
||||||
|
traps.add(rs.getString(COLNAME_COLUMN)); |
||||||
|
traps.add(String.format("'%s:%s'",table, StringGenerator(length))); |
||||||
|
continue; |
||||||
|
} |
||||||
|
String longString = StringGenerator(length); |
||||||
|
traps.add(rs.getString(COLNAME_COLUMN)); |
||||||
|
traps.add(String.format("'%s.%s%s'",table,col, longString)); |
||||||
|
continue; |
||||||
|
} |
||||||
|
int string_length = random.nextInt(501) + 2500; |
||||||
|
String longString = StringGenerator(string_length); |
||||||
|
traps.add(rs.getString(COLNAME_COLUMN)); |
||||||
|
traps.add(String.format("'%s.%s:%s'",table,col, longString)); |
||||||
|
continue; |
||||||
|
//Timestamp
|
||||||
|
} else if (rs.getString(COLNAME_DATATYPE).equals("timestamp without time zone")) { |
||||||
|
traps.add(rs.getString(COLNAME_COLUMN)); |
||||||
|
traps.add("'" + timestampMaker("now") + "'"); |
||||||
|
continue; |
||||||
|
//NUMERIC
|
||||||
|
} else if (rs.getString(COLNAME_DATATYPE).equals("numeric")) { |
||||||
|
int precision = rs.getInt(COLNAME_PRECISION); |
||||||
|
int scale = rs.getInt(COLNAME_SCALE); |
||||||
|
traps.add(rs.getString(COLNAME_COLUMN)); |
||||||
|
traps.add(String.format("%s", NumGen(precision, scale))); |
||||||
|
continue; |
||||||
|
//Timestamp day only
|
||||||
|
} else if (rs.getString(COLNAME_DATATYPE).equals("date")) { |
||||||
|
traps.add(rs.getString(COLNAME_COLUMN)); |
||||||
|
traps.add("'" + timestampMaker("day") + "'"); |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (db.equals(DB_H1)) { |
||||||
|
String trap = createTrap(traps, table, db); |
||||||
|
log.info(trap); |
||||||
|
String disableTrigger = String.format("alter table %s disable trigger all;", table); |
||||||
|
String enableTrigger = String.format("alter table %s enable trigger all;", table); |
||||||
|
jt.update(disableTrigger); |
||||||
|
jt.update(trap); |
||||||
|
jt.update(enableTrigger); |
||||||
|
} else if (db.equals(DB_MBS)) { |
||||||
|
String trap = createTrap(traps, table, db); |
||||||
|
log.info(trap); |
||||||
|
String disableTrigger = String.format("alter table mbs.%s disable trigger all;", table); |
||||||
|
String enableTrigger = String.format("alter table mbs.%s enable trigger all;", table); |
||||||
|
jt.update(disableTrigger); |
||||||
|
jt.update(trap); |
||||||
|
jt.update(enableTrigger); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
}; |
||||||
|
if (db.equals(DB_H1)) { |
||||||
|
String query = sqlTableMetaDataH1(table); |
||||||
|
try { |
||||||
|
jt.query(query, extractor); |
||||||
|
} catch(Exception e) { |
||||||
|
log.error("Fehler bei Statement (Vorbereitung/Setup):\n" + query + "\n" + e.getMessage()); |
||||||
|
} |
||||||
|
} else if (db.equals(DB_MBS)) { |
||||||
|
String query = sqlTableMetaDataMBS(table); |
||||||
|
try { |
||||||
|
jt.query(query, extractor); |
||||||
|
} catch(Exception e) { |
||||||
|
log.error("Fehler bei Statement (Vorbereitung/Setup):\n" + query + "\n" + e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Setzt die Postgres Statistiken zurück. |
||||||
|
* @param jt |
||||||
|
*/ |
||||||
|
private static void resetStats(JdbcTemplate jt) { |
||||||
|
log.info("Zurücksetzung der Statistiken gestartet..."); |
||||||
|
|
||||||
|
RowCallbackHandler handler = new RowCallbackHandler() { |
||||||
|
@Override |
||||||
|
public void processRow(ResultSet rs) throws SQLException { |
||||||
|
//nothing
|
||||||
|
} |
||||||
|
}; |
||||||
|
jt.query(SQL_RESET_STATISTICS, handler); |
||||||
|
log.info("Statistiken erfolgreich zurückgesetzt"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Entfernt die Extremwerte aus der Datenbank. |
||||||
|
* @param jt |
||||||
|
* @param tables |
||||||
|
*/ |
||||||
|
@SuppressWarnings("unused") |
||||||
|
private static void removeTraps(JdbcTemplate jt, ArrayList<String> tables) { |
||||||
|
|
||||||
|
for (int i = 0; i<tables.size();i++){ |
||||||
|
String table = tables.get(i); |
||||||
|
if (!table.startsWith("tmp")) { |
||||||
|
String deleteEntry = String.format("ALTER TABLE %s DISABLE TRIGGER ALL; delete from %s where id in (select max(id) from %s); alter table %s enable trigger all;", table,table,table,table); |
||||||
|
jt.update(deleteEntry); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Findet Inkongruenzen zwischen der hisinone und eduetl Datenbank. |
||||||
|
*/ |
||||||
|
public static void checkH1(String[] checked_modules) { |
||||||
|
ArrayList<String> tables = new ArrayList<>(); |
||||||
|
JdbcTemplate jt = new JdbcTemplate(); |
||||||
|
|
||||||
|
try (GenericApplicationContext context = createContext()){ |
||||||
|
initSxPools(); |
||||||
|
|
||||||
|
//Datenbankzugriff erstellen
|
||||||
|
His1DataSources hds = context.getBean(His1DataSources.class); |
||||||
|
DataSource ds = hds.get(DB_H1); |
||||||
|
jt.setDataSource(ds); |
||||||
|
|
||||||
|
//Statistiken zurücksetzen
|
||||||
|
resetStats(jt); |
||||||
|
|
||||||
|
//Hauptladeroutine durchführen
|
||||||
|
log.info("Unloadscript (Analysedurchlauf) gestartet..."); |
||||||
|
for(String m : checked_modules) { |
||||||
|
unload(m,context, DB_H1); |
||||||
|
} |
||||||
|
|
||||||
|
log.info("Unloadscript (Analysedurchlauf) erfolgreich abgeschlossen."); |
||||||
|
|
||||||
|
//Zugegriffene Tabellen abfangen
|
||||||
|
tables = getAccessedTablesH1(jt, tables); |
||||||
|
printList(tables); |
||||||
|
log.info("zugegriffene Tabellen erfolgreich abgefangen"); |
||||||
|
|
||||||
|
//Extremwerte einfügen
|
||||||
|
log.info("Einfügen von Extremwerten gestartet..."); |
||||||
|
for(int i = 0; i<tables.size();i++) { |
||||||
|
insertTraps(jt, tables.get(i), DB_H1); |
||||||
|
} |
||||||
|
log.info("Extremwerte erfolgreich eingefügt"); |
||||||
|
|
||||||
|
//nochmal Hauptladeroutine durchführen
|
||||||
|
log.info("Hauptladeroutine (Fuzzingtestdurchlauf) gestartet..."); |
||||||
|
for(String m : checked_modules) { |
||||||
|
etlJob(m,context, DB_H1); |
||||||
|
} |
||||||
|
log.info("Hauptladeroutine (Fuzzingtestdurchlauf) erfolgreich."); |
||||||
|
printList(errors); |
||||||
|
printIntErrors(); |
||||||
|
} catch (SQLException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} catch (DataIntegrityViolationException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} catch (BadSqlGrammarException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} catch (Exception e){ |
||||||
|
e.printStackTrace(); |
||||||
|
} finally { |
||||||
|
errors.clear(); |
||||||
|
error_keys.clear(); |
||||||
|
//removeTraps(jt,tables);
|
||||||
|
//log.info("Einträge erfolgreich entfernt.");
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void checkMBS(String[] checked_modules) { |
||||||
|
ArrayList<String> tables = new ArrayList<>(); |
||||||
|
JdbcTemplate jt = new JdbcTemplate(); |
||||||
|
try (GenericApplicationContext context = createContext()){ |
||||||
|
initSxPools(); |
||||||
|
//Datenbankzugriff erstellen
|
||||||
|
His1DataSources hds = context.getBean(His1DataSources.class); |
||||||
|
DataSource ds = hds.get(DB_MBS); |
||||||
|
jt.setDataSource(ds); |
||||||
|
//Statistiken zurücksetzen
|
||||||
|
resetStats(jt); |
||||||
|
//Hauptladeroutine durchführen
|
||||||
|
log.info("Unloadscript (Analysedurchlauf) gestartet..."); |
||||||
|
for(String m : checked_modules) { |
||||||
|
unload(m, context, DB_MBS); |
||||||
|
} |
||||||
|
log.info("Unloadscript (Analysedurchlauf) erfolgreich abgeschlossen."); |
||||||
|
//Zugegriffene Tabellen abfangen
|
||||||
|
tables = getAccessedTablesMBS(jt, tables); |
||||||
|
printList(tables); |
||||||
|
log.info("zugegriffene Tabellen erfolgreich abgefangen"); |
||||||
|
//Extremwerte einfügen
|
||||||
|
log.info("Einfügen von Extremwerten gestartet..."); |
||||||
|
for(int i = 0; i<tables.size();i++) { |
||||||
|
insertTraps(jt, tables.get(i), DB_MBS); |
||||||
|
} |
||||||
|
log.info("Extremwerte erfolgreich eingefügt"); |
||||||
|
//nochmal Hauptladeroutine durchführen
|
||||||
|
log.info("Hauptladeroutine (Fuzzingtestdurchlauf) gestartet..."); |
||||||
|
for(String m : checked_modules) { |
||||||
|
etlJob(m,context, DB_MBS); |
||||||
|
} |
||||||
|
log.info("Hauptladeroutine (Fuzzingtestdurchlauf) erfolgreich."); |
||||||
|
printList(errors); |
||||||
|
printIntErrors(); |
||||||
|
} catch (SQLException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} catch (DataIntegrityViolationException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} catch (BadSqlGrammarException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} catch (Exception e){ |
||||||
|
e.printStackTrace(); |
||||||
|
} finally { |
||||||
|
errors.clear(); |
||||||
|
error_keys.clear(); |
||||||
|
//removeTraps(jt,tables);
|
||||||
|
//log.info("Einträge erfolgreich entfernt.");
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Für CommandLine Skript. |
||||||
|
* @param args |
||||||
|
* @param options |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private static CommandLine parseArgs(String[] args, Options options) { |
||||||
|
CommandLineParser parser = new GnuParser(); |
||||||
|
try { |
||||||
|
return parser.parse(options, args, false); |
||||||
|
} catch (ParseException e) { |
||||||
|
System.out.println("error while reading the command line parameters:"); |
||||||
|
e.printStackTrace(); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Für CommandLine Skript. |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private static Options createOptions() { |
||||||
|
Options options = new Options(); |
||||||
|
Option opt; |
||||||
|
opt = new Option("h", "help", false, "get help"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("rh1", "run-h1", false, "runs the script for all h1 modules"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("rmbs", "run-mbs", false, "runs the script for all mbs modules"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("rk", "run-kern", false, "runs the script for kern module"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("rc", "run-cob", false, "runs the script for cob module"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("rf", "run-fin", false, "runs the script for fin module"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("ri", "run-ivs", false, "runs the script for ivs module"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("rb", "run-bau", false, "runs the script for bau module"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("rs", "run-sos", false, "runs the script for sos module"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("rp", "run-prom", false, "runs the script for prom module"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("rz", "run-zul", false, "runs the script for zul module"); |
||||||
|
options.addOption(opt); |
||||||
|
opt = new Option("rr", "run-res", false, "runs the script for res module"); |
||||||
|
options.addOption(opt); |
||||||
|
return options; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Für CommandLine Skript. |
||||||
|
* @param options |
||||||
|
*/ |
||||||
|
private static void printHelp(Options options) { |
||||||
|
HelpFormatter help = new HelpFormatter(); |
||||||
|
help.printHelp(HELP, options); |
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
System.setProperty(SuperXManager.SUPER_X_HISINONE_VERSION, "non-empty-value"); |
||||||
|
Options options = createOptions(); |
||||||
|
CommandLine parsedArgs = parseArgs(args, options); |
||||||
|
if (parsedArgs.hasOption("h")) { |
||||||
|
printHelp(options); |
||||||
|
} else if (parsedArgs.hasOption("rh1")) { |
||||||
|
checkH1(modulesH1); |
||||||
|
} else if (parsedArgs.hasOption("rmbs")) { |
||||||
|
checkMBS(modulesMBS); |
||||||
|
} else if (parsedArgs.hasOption("rk")) { |
||||||
|
String[] module = new String[1]; |
||||||
|
module[0] = modulesH1[MODULES_KERN_INDEX]; |
||||||
|
checkH1(module); |
||||||
|
} else if (parsedArgs.hasOption("rc")) { |
||||||
|
String[] module = new String[1]; |
||||||
|
module[0] = modulesH1[MODULES_COB_INDEX]; |
||||||
|
checkH1(module); |
||||||
|
} else if (parsedArgs.hasOption("rf")) { |
||||||
|
String[] module = new String[1]; |
||||||
|
module[0] = modulesMBS[MODULES_FIN_INDEX]; |
||||||
|
checkMBS(module); |
||||||
|
} else if (parsedArgs.hasOption("ri")) { |
||||||
|
String[] module = new String[1]; |
||||||
|
module[0] = modulesMBS[MODULES_IVS_INDEX]; |
||||||
|
checkMBS(module); |
||||||
|
} else if (parsedArgs.hasOption("rb")) { |
||||||
|
String[] module = new String[1]; |
||||||
|
module[0] = modulesMBS[MODULES_BAU_INDEX]; |
||||||
|
checkMBS(module); |
||||||
|
} else if (parsedArgs.hasOption("rs")) { |
||||||
|
String[] module = new String[1]; |
||||||
|
module[0] = modulesH1[MODULES_SOS_INDEX]; |
||||||
|
checkH1(module); |
||||||
|
} else if (parsedArgs.hasOption("rp")) { |
||||||
|
String[] module = new String[1]; |
||||||
|
module[0] = modulesH1[MODULES_PROM_INDEX]; |
||||||
|
checkH1(module); |
||||||
|
} else if (parsedArgs.hasOption("rz")) { |
||||||
|
String[] module = new String[1]; |
||||||
|
module[0] = modulesH1[MODULES_ZUL_INDEX]; |
||||||
|
checkH1(module); |
||||||
|
} else if (parsedArgs.hasOption("rr")) { |
||||||
|
String[] module = new String[1]; |
||||||
|
module[0] = modulesH1[MODULES_RES_INDEX]; |
||||||
|
checkH1(module); |
||||||
|
} else { |
||||||
|
printHelp(options); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -1,253 +1,223 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
import static de.superx.servlet.SxSQL_Server.DEFAULT_MANDANTEN_ID; |
|
||||||
import java.io.File; |
import static de.superx.servlet.SxSQL_Server.DEFAULT_MANDANTEN_ID; |
||||||
import java.io.FileNotFoundException; |
|
||||||
import java.io.IOException; |
import java.io.File; |
||||||
import java.sql.Connection; |
import java.io.FileNotFoundException; |
||||||
import java.sql.ResultSet; |
import java.io.IOException; |
||||||
import java.sql.SQLException; |
import java.sql.Connection; |
||||||
import java.sql.Statement; |
import java.sql.ResultSet; |
||||||
import java.sql.DatabaseMetaData; |
import java.sql.SQLException; |
||||||
import java.util.HashMap; |
import java.sql.Statement; |
||||||
import java.util.Hashtable; |
import java.util.HashMap; |
||||||
import java.util.Iterator; |
import java.util.Hashtable; |
||||||
import java.util.Properties; |
import java.util.Iterator; |
||||||
import java.util.StringTokenizer; |
import java.util.Properties; |
||||||
import java.util.logging.Level; |
|
||||||
import java.util.logging.Logger; |
import org.apache.commons.io.FileUtils; |
||||||
|
import org.apache.log4j.Level; |
||||||
import de.memtext.db.ConnectionCreator; |
|
||||||
import de.memtext.util.DateUtils; |
import de.memtext.db.ConnectionCreator; |
||||||
import de.memtext.util.GetOpts; |
import de.memtext.util.DateUtils; |
||||||
import de.memtext.util.StringUtils; |
import de.memtext.util.GetOpts; |
||||||
import de.superx.common.DBServletException; |
import de.memtext.util.GetOpts.Options; |
||||||
import de.superx.common.FieldContainer; |
import de.memtext.util.StringUtils; |
||||||
import de.superx.common.Sichten; |
import de.superx.common.FieldContainer; |
||||||
import de.superx.common.StandaloneSicht; |
import de.superx.common.Sichten; |
||||||
import de.superx.common.SuperX_el; |
import de.superx.common.StandaloneSicht; |
||||||
import de.superx.common.SxResultRow; |
import de.superx.common.SuperX_el; |
||||||
import de.superx.common.SxResultSet; |
import de.superx.common.SxResultRow; |
||||||
import de.superx.common.SxSqlHelper; |
import de.superx.common.SxResultSet; |
||||||
import de.superx.common.SxUser; |
import de.superx.common.SxSqlHelper; |
||||||
import de.superx.common.TableFieldExists; |
import de.superx.common.SxUser; |
||||||
import de.superx.common.TemplateProcessor; |
import de.superx.common.TableFieldExists; |
||||||
import de.superx.servlet.SuperXManager; |
import de.superx.common.TemplateProcessor; |
||||||
import de.superx.servlet.SxPools; |
import de.superx.servlet.SxPools; |
||||||
import de.superx.servlet.SxSQL_Server; |
import de.superx.util.PropsReader; |
||||||
import de.superx.util.PropsReader; |
import de.superx.util.SqlStringUtils; |
||||||
import de.superx.util.SqlStringUtils; |
|
||||||
|
public class FMParser extends TemplateProcessor { |
||||||
public class FMParser extends TemplateProcessor { |
private String dbprop, infile, outfile; |
||||||
private String dbprop, infile, outfile; |
|
||||||
private Properties props; |
private Properties props; |
||||||
|
|
||||||
private Statement stm; |
private Statement stm; |
||||||
private String isSimpleParser; |
|
||||||
private static String sqlDialect; |
private String isSimpleParser; |
||||||
|
|
||||||
FMParser() { |
private static String sqlDialect; |
||||||
super(DEFAULT_MANDANTEN_ID); |
|
||||||
|
public FMParser(String mandantenId, Connection con) throws SQLException { |
||||||
|
super(mandantenId, con); |
||||||
} |
if (con.getMetaData().getDatabaseProductName().toLowerCase().contains("postgres")) { |
||||||
|
sqlDialect = "Postgres"; |
||||||
private void run() throws FileNotFoundException, IOException, Exception { |
} |
||||||
dbprop = GetOpts.getValue("-dbproperties:"); |
} |
||||||
props = PropsReader.prepareProps(new File(dbprop)); |
|
||||||
infile = GetOpts.getValue("-in:"); |
public FMParser(String mandantenId) { |
||||||
outfile = GetOpts.getValue("-out:"); |
super(mandantenId); |
||||||
if (GetOpts.isPresent("-simpleParser")) |
} |
||||||
isSimpleParser = GetOpts.getValue("-simpleParser:"); |
|
||||||
String input = StringUtils.readFile(new File(infile)); |
private void run() throws FileNotFoundException, IOException, Exception { |
||||||
String output = ""; |
dbprop = GetOpts.getValue(Options.opt_dbprops); |
||||||
if (isSimpleParser != null && isSimpleParser.equalsIgnoreCase("true")) { |
props = PropsReader.prepareProps(new File(dbprop)); |
||||||
output = simpleParser(dbprop, input); |
infile = GetOpts.getValue(Options.opt_in); |
||||||
} else { |
outfile = GetOpts.getValue(Options.opt_out); |
||||||
initConAndParser(); |
if (GetOpts.isPresent(Options.opt_simpPars)) |
||||||
|
isSimpleParser = GetOpts.getValue(Options.opt_simpPars); |
||||||
sqlDialect = de.superx.util.SqlStringUtils.getSqlDialect(props |
String input = StringUtils.readFile(new File(infile)); |
||||||
.getProperty("driverName")); |
String output = ""; |
||||||
|
if (isSimpleParser != null && isSimpleParser.equalsIgnoreCase("true")) { |
||||||
HashMap map = new HashMap(); |
output = simpleParser(dbprop, input); |
||||||
map.put("TableFieldExists", new TableFieldExists(con)); |
} else { |
||||||
|
SxPools.initTesting(props); |
||||||
output = "--automatically created by SuperX/Freemarker for " |
initConAndParser(); |
||||||
+ sqlDialect + " (" + DateUtils.getTodayString() + " " |
sqlDialect = de.superx.util.SqlStringUtils.getSqlDialect(props.getProperty("driverName")); |
||||||
+ DateUtils.getNowString() + ")\n" |
HashMap map = new HashMap(); |
||||||
+ process("FM-Parsing " + infile, input, map, sqlDialect); |
map.put("TableFieldExists", new TableFieldExists(con)); |
||||||
stm.close(); |
output = "--automatically created by SuperX/Freemarker for " + sqlDialect + " (" |
||||||
con.close(); |
+ DateUtils.getTodayString() + " " + DateUtils.getNowString() + ")\n" |
||||||
} |
+ process("FM-Parsing " + infile, input, map, sqlDialect); |
||||||
StringUtils.write(new File(outfile), output); |
stm.close(); |
||||||
} |
con.close(); |
||||||
|
} |
||||||
private void initConAndParser() throws IOException, SQLException, |
FileUtils.writeStringToFile(new File(outfile), output); |
||||||
ClassNotFoundException { |
} |
||||||
super.con = ConnectionCreator.getConnectionCryptPassword(dbprop, |
|
||||||
"driverName", "connectionURL", "connectionName", |
private void initConAndParser() throws IOException, SQLException, ClassNotFoundException { |
||||||
"connectionPassword"); |
super.con = ConnectionCreator.getConnectionCryptPassword(dbprop, "driverName", "connectionURL", |
||||||
|
"connectionName", "connectionPassword"); |
||||||
stm = con.createStatement(); |
stm = con.createStatement(); |
||||||
if(SqlStringUtils.tableExists(con,"fm_templates",DEFAULT_MANDANTEN_ID)) |
if (SqlStringUtils.tableExists(con, "fm_templates", mandantenID)) { |
||||||
{ |
setTemplates(readFromDb("select trim(both from id),content from fm_templates")); |
||||||
setTemplates(readFromDb("select trim(both from id),content from fm_templates")); |
repositoryToMap(readFromDb(REPOSITORY_SELECT), repositoryMap); |
||||||
repositoryToMap(readFromDb(REPOSITORY_SELECT), repositoryMap); |
} |
||||||
} |
if (SqlStringUtils.tableExists(con, "konstanten", mandantenID)) { |
||||||
if(SqlStringUtils.tableExists(con,"konstanten",DEFAULT_MANDANTEN_ID)) |
SxResultSet rs = readFromDb("select trim(both from beschreibung),apnr from konstanten"); |
||||||
{ |
for (Iterator it = rs.iterator(); it.hasNext();) { |
||||||
SxResultSet rs = readFromDb("select trim(both from beschreibung),apnr from konstanten"); |
SxResultRow row = (SxResultRow) it.next(); |
||||||
for (Iterator it = rs.iterator(); it.hasNext();) { |
String beschreibung = (String) row.get(0); |
||||||
SxResultRow row = (SxResultRow) it.next(); |
repositoryMap.put("K_" + beschreibung.trim(), row.get(1)); |
||||||
String beschreibung = (String) row.get(0); |
} |
||||||
|
} |
||||||
repositoryMap.put("K_" + beschreibung.trim(), row.get(1)); |
} |
||||||
} |
|
||||||
} |
@Override |
||||||
} |
protected SxResultSet readFromDb(String sql) throws SQLException { |
||||||
|
SuperX_el el = new SuperX_el(); |
||||||
|
SxSqlHelper sh = new SxSqlHelper(); |
||||||
|
sh.execute(sql, this.con, el); |
||||||
protected SxResultSet readFromDb(String sql) throws SQLException { |
if (el.getError_String() != null && !el.getError_String().trim().equals("")) { |
||||||
SuperX_el el = new SuperX_el(); |
throw new SQLException("\nProblem bei:" + "\n\n Meldung:" + el.getError_String() + "\n sql:" + sql); |
||||||
|
} |
||||||
SxSqlHelper sh=new SxSqlHelper(); |
return el.getResultSet(); |
||||||
sh.execute(sql, this.con, el); |
} |
||||||
|
|
||||||
|
/** |
||||||
if (el.getError_String() != null |
* @deprecated |
||||||
&& !el.getError_String().trim().equals("")) |
* @param sql |
||||||
throw new SQLException("\nProblem bei:" + "\n\n Meldung:" |
* @return |
||||||
+ el.getError_String() + "\n sql:" + sql); |
* @throws SQLException |
||||||
|
*/ |
||||||
return el.getResultSet(); |
@Deprecated |
||||||
|
protected SxResultSet readFromDbAlt(String sql) throws SQLException { |
||||||
|
SxResultSet result = new SxResultSet(); |
||||||
} |
ResultSet rs = stm.executeQuery(sql); |
||||||
|
|
||||||
|
result.setColumnNames(rs.getMetaData()); |
||||||
|
int naturalOrder = 0; |
||||||
|
while (rs.next()) { |
||||||
|
SxResultRow row = new SxResultRow(rs.getMetaData().getColumnCount(), naturalOrder++); |
||||||
/** |
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { |
||||||
* @deprecated |
if (rs.getMetaData().getColumnType(i) == java.sql.Types.LONGVARCHAR) |
||||||
* @param sql |
row.add(rs.getString(i)); |
||||||
* @return |
else |
||||||
* @throws SQLException |
row.add(rs.getObject(i)); |
||||||
*/ |
} |
||||||
protected SxResultSet readFromDbAlt(String sql) throws SQLException { |
result.add(row); |
||||||
SxResultSet result = new SxResultSet(); |
} |
||||||
ResultSet rs = stm.executeQuery(sql); |
rs.close(); |
||||||
|
return result; |
||||||
result.setColumnNames(rs.getMetaData()); |
} |
||||||
int naturalOrder = 0; |
|
||||||
while (rs.next()) { |
public static void main(String[] args) { |
||||||
SxResultRow row = new SxResultRow( |
GetOpts.setOpts(args); |
||||||
rs.getMetaData().getColumnCount(), naturalOrder++); |
String isdrin = GetOpts.isAllRequiredOptionsPresent(new Options[]{Options.opt_dbprops, Options.opt_in, Options.opt_out}); |
||||||
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { |
if (isdrin != null) { |
||||||
if (rs.getMetaData().getColumnType(i) == java.sql.Types.LONGVARCHAR) |
System.err.println("-dbproperties: -in: -out:"); |
||||||
row.add(rs.getString(i)); |
System.exit(1); |
||||||
else |
} |
||||||
row.add(rs.getObject(i)); |
try { |
||||||
} |
new FMParser(DEFAULT_MANDANTEN_ID).run(); |
||||||
result.add(row); |
} catch (Exception e) { |
||||||
} |
System.err.println("Fehler beim FM-Parsen "); |
||||||
rs.close(); |
e.printStackTrace(); |
||||||
return result; |
System.exit(1); |
||||||
} |
} |
||||||
|
} |
||||||
public static void main(String[] args) { |
|
||||||
GetOpts.setOpts(args); |
/* |
||||||
String isdrin = GetOpts |
* Einfacher Parser für Fremddatenbanken, nur sqlDialect wird übergeben wird von |
||||||
.isAllRequiredOptionsPresent("-dbproperties,-in,-out"); |
* DOSQL direkt aufgerufen |
||||||
if (isdrin != null) { |
*/ |
||||||
System.err.println("-dbproperties: -in: -out:"); |
public static String simpleParser(String dbprop, String input) |
||||||
System.exit(1); |
throws FileNotFoundException, IOException, Exception { |
||||||
} |
Properties props = PropsReader.prepareProps(new File(dbprop)); |
||||||
try { |
String output = ""; |
||||||
new FMParser().run(); |
sqlDialect = de.superx.util.SqlStringUtils.getSqlDialect(props.getProperty("driverName")); |
||||||
|
HashMap map = new HashMap(); |
||||||
} catch (Exception e) { |
try { |
||||||
System.err.println("Fehler beim FM-Parsen "); |
output = "--automatically created by SuperX/Freemarker for " + sqlDialect + " (" |
||||||
e.printStackTrace(); |
+ DateUtils.getTodayString() + " " + DateUtils.getNowString() + ")\n" |
||||||
System.exit(1); |
+ new FMParser(DEFAULT_MANDANTEN_ID).process("FM-Parsing ", input, map, sqlDialect); |
||||||
} |
} catch (Exception e) { |
||||||
|
System.err.println("Fehler beim FM-Parsen "); |
||||||
} |
e.printStackTrace(); |
||||||
|
System.exit(1); |
||||||
/* |
} |
||||||
* Einfacher Parser für Fremddatenbanken, nur sqlDialect wird übergeben wird |
return output; |
||||||
* von DOSQL direkt aufgerufen |
} |
||||||
*/ |
|
||||||
public static String simpleParser(String dbprop, String input) |
/** |
||||||
throws FileNotFoundException, IOException, Exception { |
* Methode war ursprünglich für direktes Einspielen einer einzelnen konkret mit |
||||||
Properties props = PropsReader.prepareProps(new File(dbprop)); |
* name_intern benannten Sicht. Jetzt erweitert, dass aufgebaute Sicht auch |
||||||
String output = ""; |
* zurückgeliefert wird, damit eine sichtsequence aufgebaut werden kann |
||||||
sqlDialect = de.superx.util.SqlStringUtils.getSqlDialect(props |
*/ |
||||||
.getProperty("driverName")); |
@Override |
||||||
|
protected StandaloneSicht addSqlVarSicht(HashMap hmap, String varname, String name_intern, String gewuenschterStand) |
||||||
HashMap map = new HashMap(); |
throws SQLException { |
||||||
try { |
String sql = "select tid,name,label,'',beschreibung,quelle,standbutton,art \n" |
||||||
output = "--automatically created by SuperX/Freemarker for " |
+ " ,type,alt_hier_id,treecfgtable,treecfgid,gueltig_seit,gueltig_bis,xmlmaxentries,name_intern,attribut1,attribut2,attribut3,cacheapplet,cachexml \n" |
||||||
+ sqlDialect |
+ "from sichten where name_intern='" |
||||||
+ " (" |
+ name_intern |
||||||
+ DateUtils.getTodayString() |
+ "' and aktiv=1 order by type"; |
||||||
+ " " |
SxResultSet roh = new SxResultSet(); |
||||||
+ DateUtils.getNowString() |
StandaloneSicht sicht = null; |
||||||
+ ")\n" |
roh = readFromDb(sql); |
||||||
+ new FMParser().process("FM-Parsing ", input, map, |
Sichten sichten = new Sichten(); |
||||||
sqlDialect); |
SxUser user = new SxUser(); |
||||||
|
user.setAdmin(true); // Adminuser ok weil nur von DOSQL gebraucht
|
||||||
} catch (Exception e) { |
sichten.setUser(user); |
||||||
System.err.println("Fehler beim FM-Parsen "); |
for (Iterator iter = roh.iterator(); iter.hasNext();) { |
||||||
e.printStackTrace(); |
SxResultRow row = (SxResultRow) iter.next(); |
||||||
System.exit(1); |
Integer id = Integer.valueOf(1); |
||||||
} |
try { |
||||||
return output; |
sichten.initNonInternalSicht(DEFAULT_MANDANTEN_ID, StandaloneSicht.class, row, id); |
||||||
|
sicht = (StandaloneSicht) sichten.getById(id); |
||||||
} |
sicht.setConnection(con); |
||||||
/** |
sicht.setSqlDialect(sqlDialect); |
||||||
Methode war ursprünglich für direktes Einspielen einer einzelnen konkret mit name_intern benannten Sicht. |
if (gewuenschterStand.trim().startsWith("today")) { |
||||||
Jetzt erweitert, dass aufgebaute Sicht auch zurückgeliefert wird, damit eine sichtsequence aufgebaut werden kann |
gewuenschterStand = DateUtils.getTodayString(); |
||||||
*/ |
} |
||||||
protected StandaloneSicht addSqlVarSicht(HashMap hmap, String varname, String name_intern,String gewuenschterStand) |
sicht.setStand(new Hashtable(), hmap, new FieldContainer(), gewuenschterStand); |
||||||
throws SQLException { |
hmap.put(varname, sicht); |
||||||
String mandantenID="default"; // package de.superx.bin wird nur von Scripten gebraucht, MandantenID unerheblich
|
} catch (Exception e) { |
||||||
String sql = "select tid,name,label,'',beschreibung,quelle,standbutton,art \n" |
e.printStackTrace(); |
||||||
+ " ,type,alt_hier_id,treecfgtable,treecfgid,gueltig_seit,gueltig_bis,xmlmaxentries,name_intern,attribut1,attribut2,attribut3,cacheapplet,cachexml \n" |
throw new SQLException("Fehler beim Aufbau von Sicht " + name_intern + " " + e); |
||||||
+ "from sichten where name_intern='" |
} |
||||||
+ name_intern |
} |
||||||
+ "' and aktiv=1 order by type"; |
return sicht; |
||||||
SxResultSet roh = new SxResultSet(); |
} |
||||||
StandaloneSicht sicht=null; |
} |
||||||
roh = readFromDb(sql); |
|
||||||
Sichten sichten = new Sichten(); |
// Created on 08.12.2006 at 18:03:46
|
||||||
SxUser user = new SxUser(mandantenID); |
|
||||||
user.setAdmin(true); // Adminuser ok weil nur von DOSQL gebraucht
|
|
||||||
sichten.setUser(user); |
|
||||||
for (Iterator iter = roh.iterator(); iter.hasNext();) { |
|
||||||
SxResultRow row = (SxResultRow) iter.next(); |
|
||||||
Integer id = new Integer(1); // (Integer) row.get(0);
|
|
||||||
|
|
||||||
try { |
|
||||||
sichten.initNonInternalSicht(mandantenID, StandaloneSicht.class, |
|
||||||
row, id); |
|
||||||
sicht = (StandaloneSicht) sichten.getById(id); |
|
||||||
sicht.setConnection(con); |
|
||||||
sicht.setSqlDialect(sqlDialect); |
|
||||||
|
|
||||||
if (gewuenschterStand.trim().startsWith("today")) |
|
||||||
gewuenschterStand = DateUtils.getTodayString(); |
|
||||||
sicht.setStand(new Hashtable(),hmap,new FieldContainer(),gewuenschterStand); |
|
||||||
hmap.put(varname, sicht); |
|
||||||
} catch (Exception e) { |
|
||||||
e.printStackTrace(); |
|
||||||
throw new SQLException("Fehler beim Aufbau von Sicht " |
|
||||||
+ name_intern + " " + e); |
|
||||||
} |
|
||||||
} |
|
||||||
return sicht; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Created on 08.12.2006 at 18:03:46
|
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,745 @@ |
|||||||
|
package de.superx.bin; |
||||||
|
|
||||||
|
|
||||||
|
import java.io.BufferedReader; |
||||||
|
import java.io.ByteArrayInputStream; |
||||||
|
import java.io.File; |
||||||
|
import java.io.FileInputStream; |
||||||
|
import java.io.FileNotFoundException; |
||||||
|
import java.io.FileOutputStream; |
||||||
|
import java.io.FileReader; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
import java.io.PrintStream; |
||||||
|
import java.io.Reader; |
||||||
|
import java.io.UnsupportedEncodingException; |
||||||
|
import java.sql.Connection; |
||||||
|
import java.sql.DatabaseMetaData; |
||||||
|
import java.sql.PreparedStatement; |
||||||
|
import java.sql.ResultSet; |
||||||
|
import java.sql.ResultSetMetaData; |
||||||
|
import java.sql.SQLException; |
||||||
|
import java.sql.Types; |
||||||
|
import java.text.ParseException; |
||||||
|
import java.util.Hashtable; |
||||||
|
import java.util.StringTokenizer; |
||||||
|
|
||||||
|
import org.postgresql.PGConnection; |
||||||
|
import org.postgresql.copy.CopyManager; |
||||||
|
|
||||||
|
import de.memtext.util.DateUtils; |
||||||
|
import de.memtext.util.GetOpts; |
||||||
|
import de.memtext.util.GetOpts.Options; |
||||||
|
import de.superx.bin.SxConnection.DriverClass; |
||||||
|
/* |
||||||
|
* |
||||||
|
* Basierend auf de.superx.common.FileToTableUpload mit Unterstützung für Header |
||||||
|
* |
||||||
|
*/ |
||||||
|
public class GxstageCSVImport { |
||||||
|
private String logfile; |
||||||
|
private String dbpropfile; |
||||||
|
private String mode="stop"; |
||||||
|
private String inFormat; |
||||||
|
private String targetTable; |
||||||
|
private String srcFile; |
||||||
|
private static final boolean header=true; |
||||||
|
|
||||||
|
private String delim="^"; |
||||||
|
private String encoding; |
||||||
|
private String inserts=""; |
||||||
|
private boolean continueAfterError; |
||||||
|
private boolean removeTrailingDelim=true; |
||||||
|
private boolean isPostgres; |
||||||
|
private boolean useBatch=true; |
||||||
|
private static int maxCols=1000; |
||||||
|
private String[] insert_cols = new String[maxCols]; |
||||||
|
private int[] insert_types = new int[maxCols]; |
||||||
|
|
||||||
|
private int numberOfColumns; |
||||||
|
public long numberOfRows; |
||||||
|
private Connection uploadConnection; |
||||||
|
private DatabaseMetaData dbmd; |
||||||
|
private PreparedStatement pst; |
||||||
|
private static String usage = |
||||||
|
"-------------------------------------\n" |
||||||
|
+ "Gebrauch: java de.superx.bin.GxstageCSVImport \n-dbproperties:<Pfad zu db.properties> \n" |
||||||
|
+ "-table:<Tabellenname> \n-unl:<Dateipfad Quelldatei>(optional, default ist Tabellenname.unl) \n-delim:<delimiter>(optional, default ist ^) \n-header:<true|false>(optional, mit Feldüberschriften, default ist false)\n" |
||||||
|
+ "-mode:<stop|exclude-row>(optional, default is stop) #Bei Fehlerhaften Daten kann das Hochladen gestoppt werden, oder der Datensatz wird übersprungen" |
||||||
|
+ "\n-inserts:<false|simple|batch>(optional, default is false) #Bei -inserts:simple und batch werden Die Rohdaten in Insert-sql-Statements übersetzt (nur für Debugging-Zwecke, sehr langsam. Der Modus exclude-field ist darüberhinaus nicht anwendbar)" |
||||||
|
+ "\n-encoding:<utf8,ISO-8859-1, default ist System.file.encoding>" |
||||||
|
+ "\n---------------------------------------------------"; |
||||||
|
|
||||||
|
public Connection getUploadConnection() { |
||||||
|
return uploadConnection; |
||||||
|
} |
||||||
|
public void setUploadConnection(Connection uploadConnection) { |
||||||
|
this.uploadConnection = uploadConnection; |
||||||
|
} |
||||||
|
public boolean isRemoveTrailingDelim() { |
||||||
|
return removeTrailingDelim; |
||||||
|
} |
||||||
|
public void setRemoveTrailingDelim(boolean removeTrailingDelim) { |
||||||
|
this.removeTrailingDelim = removeTrailingDelim; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public String getDbpropfile() { |
||||||
|
return dbpropfile; |
||||||
|
} |
||||||
|
public void setDbpropfile(String dbpropfile) { |
||||||
|
this.dbpropfile = dbpropfile; |
||||||
|
} |
||||||
|
public String getMode() { |
||||||
|
return mode; |
||||||
|
} |
||||||
|
public void setMode(String mode) { |
||||||
|
if (!mode.equals("stop") && !mode.equals("exclude-field")&& !mode.equals("transaction")) |
||||||
|
mode = "exclude-row"; |
||||||
|
this.mode = mode; |
||||||
|
} |
||||||
|
public String getInFormat() { |
||||||
|
return inFormat; |
||||||
|
} |
||||||
|
public void setInFormat(String inFormat) { |
||||||
|
this.inFormat = inFormat; |
||||||
|
} |
||||||
|
public String getTargetTable() { |
||||||
|
return targetTable; |
||||||
|
} |
||||||
|
public void setTargetTable(String targetTable) { |
||||||
|
this.targetTable = targetTable; |
||||||
|
} |
||||||
|
public String getSrcFile() { |
||||||
|
return srcFile; |
||||||
|
} |
||||||
|
public void setSrcFile(String srcFile) { |
||||||
|
this.srcFile = srcFile; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDelim() { |
||||||
|
return delim; |
||||||
|
} |
||||||
|
public void setDelim(String delim) { |
||||||
|
if (delim.equals("tab")) |
||||||
|
delim = "\t"; //Tab
|
||||||
|
if (delim.equals("")) |
||||||
|
delim = "^"; //default Delimiter
|
||||||
|
this.delim = delim; |
||||||
|
} |
||||||
|
public String getEncoding() { |
||||||
|
return encoding; |
||||||
|
} |
||||||
|
public void setEncoding(String encoding) { |
||||||
|
if(encoding==null || encoding.equals("")) |
||||||
|
encoding="UTF-8"; |
||||||
|
this.encoding = encoding; |
||||||
|
} |
||||||
|
public String getInserts() { |
||||||
|
return inserts; |
||||||
|
} |
||||||
|
public void setInserts(String inserts) { |
||||||
|
if(inserts.equalsIgnoreCase("batch")) |
||||||
|
useBatch=true; |
||||||
|
if(inserts.equalsIgnoreCase("simple")) |
||||||
|
useBatch=false; |
||||||
|
|
||||||
|
this.inserts = inserts; |
||||||
|
} |
||||||
|
public boolean isContinueAfterError() { |
||||||
|
return continueAfterError; |
||||||
|
} |
||||||
|
public void setContinueAfterError(boolean continueAfterError) { |
||||||
|
this.continueAfterError = continueAfterError; |
||||||
|
} |
||||||
|
public String uploadFile() throws Exception |
||||||
|
{ |
||||||
|
String protokoll=""; |
||||||
|
if(inFormat!=null&&inFormat.equalsIgnoreCase("xml")) |
||||||
|
{ |
||||||
|
throw new IllegalArgumentException("xml nicht unterstützt"); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
protokoll=uploadCSV(); |
||||||
|
} |
||||||
|
if(protokoll.indexOf("Exception")>-1) |
||||||
|
throw new Exception(protokoll); |
||||||
|
return protokoll; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private String uploadCSV() throws Exception |
||||||
|
{ |
||||||
|
String line; |
||||||
|
String line2; |
||||||
|
File outFile=null; |
||||||
|
String protokoll=""; |
||||||
|
if(isPostgres && !inserts.equalsIgnoreCase("simple") && !inserts.equalsIgnoreCase("batch")) |
||||||
|
{ |
||||||
|
if(removeTrailingDelim) |
||||||
|
srcFile=removeTrailingDelim(srcFile); |
||||||
|
|
||||||
|
protokoll=uploadCSVinPostgres(srcFile,removeTrailingDelim); |
||||||
|
|
||||||
|
} |
||||||
|
else |
||||||
|
protokoll=uploadCSVwithAnsiSQL(srcFile); |
||||||
|
return protokoll; |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
private String removeTrailingDelim(String srcFile) throws UnsupportedEncodingException, FileNotFoundException, IOException { |
||||||
|
String line; |
||||||
|
File outFile; |
||||||
|
String returnSrcFile=srcFile+".tmp"; |
||||||
|
BufferedReader in2 = new BufferedReader(new InputStreamReader(new FileInputStream(srcFile), encoding)); |
||||||
|
|
||||||
|
outFile=new File(srcFile+".tmp"); |
||||||
|
FileOutputStream out = new FileOutputStream(outFile, false); |
||||||
|
PrintStream out2 = new PrintStream(out, true, encoding); |
||||||
|
|
||||||
|
|
||||||
|
while ((line = in2.readLine()) != null) { |
||||||
|
|
||||||
|
if (line.endsWith(delim)) |
||||||
|
line=line.substring(0,line.length()-delim.length()); |
||||||
|
out2.println(line); |
||||||
|
out2.flush(); |
||||||
|
|
||||||
|
} |
||||||
|
return returnSrcFile; |
||||||
|
} |
||||||
|
private String uploadCSVinPostgres(String srcFile, boolean deleteSrcFile) { |
||||||
|
//neues Format für Postgres42-Treiber mit Format csv, geht aber auch mit Postgres9.2 Treiber
|
||||||
|
/*copy target_table (b, a, c) |
||||||
|
from file.csv |
||||||
|
with (delimiter ',', format csv, header)*/ |
||||||
|
// String test=" (hs_nr,gjahr,inst_ext,bund_fachgebiet,asp_akl,rest,rest_vj,zugang,abgang,abschr,histor_ahk,umbuch,zuschr,abschr_ges,datum,extkotr) ";
|
||||||
|
String cols=""; |
||||||
|
String msg=""; |
||||||
|
boolean dataFound=true; |
||||||
|
try |
||||||
|
{ |
||||||
|
if (header) |
||||||
|
{ |
||||||
|
|
||||||
|
String headersInFile = getHeaderString(srcFile); |
||||||
|
if (headersInFile!=null) |
||||||
|
{ |
||||||
|
cols=headersInFile.replace(delim,","); |
||||||
|
cols=" ("+cols+") "; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
//headers ist null, Datei leer
|
||||||
|
dataFound=false; |
||||||
|
numberOfRows=0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
//default quote ist ", kann aber vorkommen, daher quote Zeichen auf nicht erwartetes Backspace Oktal 10 setzen
|
||||||
|
String copySql = "COPY " + targetTable + cols+ " FROM STDIN (FORMAT csv, QUOTE '\b', DELIMITER '"+delim+"',NULL '',ENCODING '"+ encoding+"'"+(header?", HEADER true":"")+")"; |
||||||
|
|
||||||
|
if (dataFound) |
||||||
|
{ |
||||||
|
|
||||||
|
final CopyManager cpm = ((PGConnection) uploadConnection).getCopyAPI(); |
||||||
|
msg = ""; |
||||||
|
FileReader in3 = new FileReader(srcFile); |
||||||
|
Reader in4 = new BufferedReader(in3); |
||||||
|
numberOfRows = cpm.copyIn(copySql, in4); |
||||||
|
} |
||||||
|
if(deleteSrcFile) |
||||||
|
{ |
||||||
|
File outFile=new File(srcFile); |
||||||
|
if(outFile!=null) |
||||||
|
outFile.delete(); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
|
||||||
|
msg=e.toString(); |
||||||
|
} |
||||||
|
return msg; |
||||||
|
} |
||||||
|
protected String getHeaderString(String srcFile) throws FileNotFoundException, UnsupportedEncodingException, IOException { |
||||||
|
FileInputStream fileInputStream = new FileInputStream(srcFile); |
||||||
|
InputStreamReader ir=new InputStreamReader(fileInputStream, encoding); |
||||||
|
BufferedReader br = new BufferedReader(ir); |
||||||
|
String headersInFile=br.readLine(); |
||||||
|
br.close(); |
||||||
|
ir.close(); |
||||||
|
fileInputStream.close(); |
||||||
|
return headersInFile; |
||||||
|
} |
||||||
|
|
||||||
|
private String uploadCSVwithAnsiSQL(String srcFile) throws SQLException, FileNotFoundException, IOException { |
||||||
|
numberOfRows=0; |
||||||
|
String text; |
||||||
|
String text2; |
||||||
|
String msg=""; |
||||||
|
int zeilennr=1; |
||||||
|
int fehlerSaetze=0; |
||||||
|
String headersInFile=null; |
||||||
|
if (header) |
||||||
|
{ headersInFile = getHeaderString(srcFile); |
||||||
|
|
||||||
|
} |
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(srcFile), encoding)); |
||||||
|
initializeColumnSchema(headersInFile); |
||||||
|
String insertHead=createPreparedStatementHead(headersInFile); |
||||||
|
pst = uploadConnection.prepareStatement(insertHead); |
||||||
|
if(useBatch) |
||||||
|
pst.clearBatch(); |
||||||
|
boolean isFirstRow=true; |
||||||
|
while ((text = in.readLine()) != null) { |
||||||
|
if (isFirstRow&&header) { isFirstRow=false; continue;} |
||||||
|
if (text.endsWith("\\")) { |
||||||
|
text=text.substring(0, text.length()-1); |
||||||
|
text2 = in.readLine(); |
||||||
|
if (text2 != null) { |
||||||
|
text += "\n"+ text2; |
||||||
|
while (text2.endsWith("\\")) { |
||||||
|
text=text.substring(0, text.length()-1); |
||||||
|
text2 = in.readLine(); |
||||||
|
if (text2 != null) |
||||||
|
text += "\n"+text2; |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
String prepare = |
||||||
|
createPreparedInsertStatement(zeilennr, |
||||||
|
insertHead, |
||||||
|
text); |
||||||
|
if(!prepare.equals("") && mode.equals("stop")) |
||||||
|
{ |
||||||
|
msg=prepare; |
||||||
|
break; |
||||||
|
} |
||||||
|
if(useBatch) |
||||||
|
pst.addBatch(); |
||||||
|
else |
||||||
|
pst.executeUpdate(); |
||||||
|
numberOfRows++; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
if(useBatch) |
||||||
|
pst.executeBatch(); |
||||||
|
|
||||||
|
return msg; |
||||||
|
} |
||||||
|
|
||||||
|
private String createPreparedInsertStatement( |
||||||
|
int line, |
||||||
|
String insertHead, |
||||||
|
String text) |
||||||
|
throws SQLException { |
||||||
|
int p; |
||||||
|
int i=0; |
||||||
|
int k=0; |
||||||
|
String errmsg = ""; |
||||||
|
String feld_wert; |
||||||
|
//pst.clearParameters();
|
||||||
|
do { |
||||||
|
//ggf. Trennzeichen am Ende hinzufügen:
|
||||||
|
if(!text.endsWith(delim)) |
||||||
|
text+= delim; |
||||||
|
p = text.indexOf(delim, i); |
||||||
|
//logger.config("Type "+types[k]);
|
||||||
|
//maskierte Trennzeichen abfangen:
|
||||||
|
if(p>0 && text.substring(p-1, p).equals("\\")) |
||||||
|
p = text.indexOf(delim, p+1); |
||||||
|
|
||||||
|
if (p > -1 ) { |
||||||
|
if(p==-1) |
||||||
|
feld_wert = text.substring(i); |
||||||
|
else |
||||||
|
feld_wert = text.substring(i, p); |
||||||
|
//wenn der Feldwert zufällig das Zeichen "\\n" enthält, wird es zu "\n"
|
||||||
|
if(feld_wert != null && (feld_wert.indexOf("\\\\n") >0 )) |
||||||
|
{ |
||||||
|
feld_wert=de.memtext.util.StringUtils.replace(feld_wert, "\\\\n", "\\n"); |
||||||
|
} |
||||||
|
//wenn der Feldwert das Zeichen "\Trennzeichen" enthält, wird der \ entfernt
|
||||||
|
if(feld_wert != null && (feld_wert.indexOf("\\"+delim) >0 )) |
||||||
|
{ |
||||||
|
feld_wert=de.memtext.util.StringUtils.replace(feld_wert, "\\", ""); |
||||||
|
} |
||||||
|
//wenn der Feldwert das Zeichen "\\" enthält, wird ein \ entfernt
|
||||||
|
if(feld_wert != null && (feld_wert.indexOf("\\\\") >0 )) |
||||||
|
{ |
||||||
|
feld_wert=de.memtext.util.StringUtils.replace(feld_wert, "\\\\", "\\"); |
||||||
|
} |
||||||
|
|
||||||
|
errmsg = feld_wert_to_pst(line,k, errmsg, feld_wert); |
||||||
|
k++; |
||||||
|
i = p + 1; |
||||||
|
} |
||||||
|
|
||||||
|
} while (p > -1); |
||||||
|
return errmsg; |
||||||
|
} |
||||||
|
private String feld_wert_to_pst(int line, int col, String errmsg, String feld_wert) throws SQLException { |
||||||
|
|
||||||
|
|
||||||
|
if( col >= numberOfColumns) |
||||||
|
errmsg+= "Anzahl Spalten in Datei ist "+col+", aber es sollten nur "+(numberOfColumns-1)+" Spalten sein. Bitte prüfen Sie das Trennzeichen"; |
||||||
|
else |
||||||
|
{ |
||||||
|
if (feld_wert.equals("")) |
||||||
|
try { |
||||||
|
pst.setNull(col + 1, insert_types[col]); |
||||||
|
} catch (SQLException e1) { |
||||||
|
errmsg += e1.toString(); |
||||||
|
} else { |
||||||
|
|
||||||
|
switch (insert_types[col]) { |
||||||
|
case Types.BIGINT : |
||||||
|
case Types.TINYINT : |
||||||
|
case Types.SMALLINT : |
||||||
|
case Types.INTEGER : |
||||||
|
|
||||||
|
try { |
||||||
|
int myInt = (int) Integer.parseInt(feld_wert.trim()); |
||||||
|
pst.setInt(col + 1, myInt); |
||||||
|
} catch (NumberFormatException e1) { |
||||||
|
errmsg += e1.toString(); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} catch (SQLException e1) { |
||||||
|
errmsg += conversionException(line, col, feld_wert,e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} |
||||||
|
break; |
||||||
|
case Types.FLOAT : |
||||||
|
try { |
||||||
|
float myFloat = |
||||||
|
(float) Float.parseFloat(feld_wert.trim()); |
||||||
|
pst.setFloat(col + 1, myFloat); |
||||||
|
} catch (NumberFormatException e1) { |
||||||
|
errmsg += conversionException(line, col, feld_wert,e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} catch (SQLException e1) { |
||||||
|
errmsg += conversionException(line, col, feld_wert,e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} |
||||||
|
break; |
||||||
|
|
||||||
|
case Types.REAL : |
||||||
|
case Types.DOUBLE : |
||||||
|
case Types.NUMERIC : |
||||||
|
case Types.DECIMAL : |
||||||
|
try { |
||||||
|
double myDouble = |
||||||
|
(double) Double.parseDouble(feld_wert.trim()); |
||||||
|
pst.setDouble(col + 1, myDouble); |
||||||
|
} catch (NumberFormatException e1) { |
||||||
|
errmsg += conversionException(line, col, feld_wert,e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} catch (SQLException e1) { |
||||||
|
errmsg += conversionException(line, col, feld_wert, e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} |
||||||
|
break; |
||||||
|
|
||||||
|
case Types.CHAR : |
||||||
|
case Types.VARCHAR : |
||||||
|
default : |
||||||
|
if(feld_wert.equals(" ")) |
||||||
|
feld_wert=""; //Leerzeichen im UNL-File wird zu Leerstring
|
||||||
|
try { |
||||||
|
pst.setString(col + 1, feld_wert); |
||||||
|
} catch (SQLException e1) { |
||||||
|
errmsg += conversionException(line, col, feld_wert,e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} |
||||||
|
break; |
||||||
|
case Types.LONGVARCHAR : |
||||||
|
ByteArrayInputStream by = |
||||||
|
new ByteArrayInputStream(feld_wert.getBytes()); |
||||||
|
pst.setAsciiStream( |
||||||
|
col + 1, |
||||||
|
by, |
||||||
|
feld_wert.length()); |
||||||
|
break; |
||||||
|
case Types.DATE : |
||||||
|
try { |
||||||
|
java.util.Date datum = |
||||||
|
DateUtils.parse(feld_wert.trim()); |
||||||
|
feld_wert = DateUtils.formatUS(datum); |
||||||
|
//Leider ist dieser Schritt wg java.sql.Date nötig
|
||||||
|
pst.setDate( |
||||||
|
col + 1, |
||||||
|
java.sql.Date.valueOf(feld_wert)); |
||||||
|
|
||||||
|
} catch (SQLException e1) { |
||||||
|
errmsg += conversionException(line, col, feld_wert, e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} catch (ParseException e1) { |
||||||
|
errmsg += conversionException(line, col, feld_wert, e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} |
||||||
|
catch (IllegalArgumentException e1) { |
||||||
|
errmsg += conversionException(line, col, feld_wert, e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} |
||||||
|
|
||||||
|
break; |
||||||
|
case Types.TIME : |
||||||
|
|
||||||
|
try { |
||||||
|
//Time zeit = (java.sql.Time)
|
||||||
|
//DateUtils.timeParse(feld_wert);
|
||||||
|
pst.setTime(col + 1, java.sql.Time.valueOf( |
||||||
|
feld_wert.trim())); |
||||||
|
} catch (SQLException e1) { |
||||||
|
errmsg += conversionException(line, col, feld_wert, e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} |
||||||
|
catch (IllegalArgumentException e1) { |
||||||
|
errmsg += conversionException(line, col, feld_wert, e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} |
||||||
|
|
||||||
|
break; |
||||||
|
case Types.TIMESTAMP : |
||||||
|
try { |
||||||
|
java.util.Date datum = |
||||||
|
DateUtils.dateTimeParse(feld_wert.trim()); |
||||||
|
feld_wert = DateUtils.dateTimeFormatUS(datum); |
||||||
|
//Leider ist dieser Schritt wg java.sql.Date nötig
|
||||||
|
pst.setTimestamp( |
||||||
|
col + 1, |
||||||
|
java.sql.Timestamp.valueOf( |
||||||
|
feld_wert + ".0")); |
||||||
|
|
||||||
|
} catch (SQLException e1) { |
||||||
|
errmsg += conversionException(line, col,feld_wert, e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} catch (ParseException e1) { |
||||||
|
errmsg += conversionException(line, col, feld_wert, e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} |
||||||
|
catch (IllegalArgumentException e1) { |
||||||
|
errmsg += conversionException(line, col, feld_wert, e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} |
||||||
|
|
||||||
|
break; |
||||||
|
|
||||||
|
case Types.BIT : |
||||||
|
// Types.BOOLEAN gibt es im jdk 1.3 nicht
|
||||||
|
try { |
||||||
|
boolean wf = |
||||||
|
(boolean) Boolean.getBoolean(feld_wert.trim()); |
||||||
|
pst.setBoolean(col + 1, wf); |
||||||
|
} catch (SQLException e1) { |
||||||
|
errmsg += conversionException(line, col, feld_wert, e1.toString()); |
||||||
|
setFieldToNull(col, insert_types, pst); |
||||||
|
} |
||||||
|
//Boolean wird vom Informix-Treiber als OTHER (1111) erkannt
|
||||||
|
//Da aber default '' ist, klappt es trotzdem
|
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
return errmsg; |
||||||
|
} |
||||||
|
private void setFieldToNull( |
||||||
|
int k, |
||||||
|
int[] insert_types, |
||||||
|
PreparedStatement pst) { |
||||||
|
if (mode.equals("exclude-field")) |
||||||
|
try { |
||||||
|
pst.setNull(k + 1, insert_types[k]); |
||||||
|
} catch (SQLException e3) { |
||||||
|
System.err.println("Invalid Field " + (k + 1) + " could not be set to null"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
private String conversionException(int line,int col, String field_value, String error) { |
||||||
|
String err_msg = ""; |
||||||
|
|
||||||
|
err_msg = "Error in line "+line+" in Column " + (col + 1) + " "+insert_cols[col]+" value "+ field_value+ ": " + error.toString() + "; "; |
||||||
|
|
||||||
|
return err_msg; |
||||||
|
} |
||||||
|
private void initializeColumnSchema(String headersInFile) throws SQLException |
||||||
|
{ |
||||||
|
|
||||||
|
|
||||||
|
ResultSet rs = null; |
||||||
|
ResultSetMetaData rsmd = null; |
||||||
|
String tabelle=targetTable; |
||||||
|
if (!dbmd.storesLowerCaseIdentifiers()) |
||||||
|
tabelle = tabelle.toUpperCase(); |
||||||
|
rs =dbmd.getColumns(uploadConnection.getCatalog(), null, tabelle, null); |
||||||
|
rsmd = rs.getMetaData(); |
||||||
|
Hashtable<String,Integer> fieldtypes=new Hashtable<String,Integer>(); |
||||||
|
while (rs.next()) { |
||||||
|
fieldtypes.put(rs.getObject("COLUMN_NAME").toString(),Integer.valueOf(rs.getInt("DATA_TYPE"))); |
||||||
|
} |
||||||
|
int i=0; |
||||||
|
StringTokenizer st=new StringTokenizer(headersInFile,delim); |
||||||
|
while (st.hasMoreTokens()) |
||||||
|
{ |
||||||
|
String colname=st.nextToken(); |
||||||
|
insert_cols[i]= colname ; |
||||||
|
insert_types[i] = fieldtypes.get(colname).intValue(); |
||||||
|
i++; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
numberOfColumns=i; |
||||||
|
if(!dbmd.supportsBatchUpdates()) |
||||||
|
useBatch=false; |
||||||
|
|
||||||
|
} |
||||||
|
private String createPreparedStatementHeadOld() throws SQLException |
||||||
|
{ |
||||||
|
|
||||||
|
String sql=null; |
||||||
|
|
||||||
|
String insert_head = "insert into " + targetTable+"("; |
||||||
|
String insert_val=""; |
||||||
|
for (int i = 0; i < numberOfColumns; i++) |
||||||
|
{ |
||||||
|
insert_head += insert_cols[i] + ", "; |
||||||
|
insert_val+="?, "; |
||||||
|
} |
||||||
|
insert_head = insert_head.substring(0, insert_head.length() - 2); |
||||||
|
insert_val = insert_val.substring(0, insert_val.length() - 2); |
||||||
|
insert_head +=") values( "; |
||||||
|
sql=insert_head + insert_val+");"; |
||||||
|
return sql; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private String createPreparedStatementHead(String headersInFile) throws SQLException |
||||||
|
{ |
||||||
|
|
||||||
|
String sql=null; |
||||||
|
|
||||||
|
String insert_head = "insert into " + targetTable+"("; |
||||||
|
String insert_val=""; |
||||||
|
if (headersInFile!=null) |
||||||
|
{ |
||||||
|
StringTokenizer st=new StringTokenizer(headersInFile,delim); |
||||||
|
while (st.hasMoreTokens()) |
||||||
|
{ |
||||||
|
String colname=st.nextToken(); |
||||||
|
insert_head += colname + ", "; |
||||||
|
insert_val+="?, "; |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
for (int i = 0; i < numberOfColumns; i++) |
||||||
|
{ |
||||||
|
insert_head += insert_cols[i] + ", "; |
||||||
|
insert_val+="?, "; |
||||||
|
} |
||||||
|
} |
||||||
|
insert_head = insert_head.substring(0, insert_head.length() - 2); |
||||||
|
insert_val = insert_val.substring(0, insert_val.length() - 2); |
||||||
|
insert_head +=") values( "; |
||||||
|
sql=insert_head + insert_val+");"; |
||||||
|
return sql; |
||||||
|
|
||||||
|
} |
||||||
|
public Connection getConnection(Connection myConnection,String propfile) throws Exception { |
||||||
|
|
||||||
|
if(myConnection==null) |
||||||
|
{ |
||||||
|
SxConnection mySxConnection = null; |
||||||
|
mySxConnection = new SxConnection(); |
||||||
|
mySxConnection.setPropfile(propfile); |
||||||
|
|
||||||
|
myConnection = mySxConnection.getConnection(); |
||||||
|
|
||||||
|
String db_driver = mySxConnection.m_DriverClass.stringValue(); |
||||||
|
if(db_driver.equals(DriverClass.dc_postgre.stringValue())) |
||||||
|
isPostgres=true; |
||||||
|
} |
||||||
|
dbmd = myConnection.getMetaData(); |
||||||
|
|
||||||
|
return myConnection; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String args[]) { |
||||||
|
try { |
||||||
|
GetOpts.setOpts(args); |
||||||
|
String isdrin = |
||||||
|
GetOpts.isAllRequiredOptionsPresent(new Options[] {Options.opt_dbprops,Options.opt_table,Options.opt_unl}); |
||||||
|
if (isdrin != null) { |
||||||
|
System.err.println("Folgende Optionen fehlen: " + isdrin); |
||||||
|
System.err.println(usage); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
GxstageCSVImport myUploader=new GxstageCSVImport(); |
||||||
|
//GetOpts myOpts=new GetOpts();
|
||||||
|
if (GetOpts.isPresent(Options.opt_dbprops)) |
||||||
|
myUploader.setDbpropfile(GetOpts.getValue(Options.opt_dbprops)); |
||||||
|
if (GetOpts.isPresent(Options.opt_inFormat)) |
||||||
|
myUploader.setInFormat(GetOpts.getValue(Options.opt_inFormat)); |
||||||
|
if (GetOpts.isPresent(Options.opt_table)) |
||||||
|
myUploader.setTargetTable( GetOpts.getValue(Options.opt_table)); |
||||||
|
|
||||||
|
if (GetOpts.isPresent(Options.opt_unl)) |
||||||
|
myUploader.setSrcFile(GetOpts.getValue(Options.opt_unl)); |
||||||
|
else |
||||||
|
myUploader.setSrcFile(myUploader.getTargetTable() + ".unl"); |
||||||
|
if (GetOpts.isPresent(Options.opt_header)&&!GetOpts.getValue(Options.opt_header).equalsIgnoreCase("true")) |
||||||
|
{ |
||||||
|
throw new IllegalArgumentException("nur header=true unterstützt"); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
if (GetOpts.isPresent(Options.opt_delim)) |
||||||
|
myUploader.setDelim(GetOpts.getValue(Options.opt_delim)); |
||||||
|
if (GetOpts.isPresent(Options.opt_encoding)) |
||||||
|
{ |
||||||
|
String encodingParam=GetOpts.getValue(Options.opt_encoding); |
||||||
|
|
||||||
|
if(encodingParam != null && !encodingParam.equals("") ) |
||||||
|
myUploader.setEncoding(encodingParam); |
||||||
|
} |
||||||
|
else |
||||||
|
myUploader.setEncoding(System.getProperty("file.encoding")); |
||||||
|
if (GetOpts.isPresent(Options.opt_mode)) { |
||||||
|
myUploader.setMode(GetOpts.getValue(Options.opt_mode).toLowerCase()); |
||||||
|
|
||||||
|
} |
||||||
|
if (GetOpts.isPresent(Options.opt_inserts)) |
||||||
|
myUploader.setInserts(GetOpts.getValue(Options.opt_inserts)); |
||||||
|
long jetzt = new java.util.Date().getTime() ; |
||||||
|
myUploader.setUploadConnection(myUploader.getConnection(null,myUploader.getDbpropfile())); |
||||||
|
if (new File(myUploader.getSrcFile()).length()==0) |
||||||
|
{ |
||||||
|
System.out.println("Nichts zu tun, Datei "+myUploader.getSrcFile()+" ist leer"); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
String protokoll=myUploader.uploadFile(); |
||||||
|
long erstrecht = new java.util.Date().getTime() ; |
||||||
|
System.out.println(myUploader.numberOfRows+" lines loaded"); |
||||||
|
System.out.println("File "+myUploader.getSrcFile() +" uploaded"); |
||||||
|
if(protokoll.equals("")) |
||||||
|
protokoll= " in "+(erstrecht-jetzt)/1000 +" Sec."; |
||||||
|
System.out.println(protokoll); |
||||||
|
} |
||||||
|
|
||||||
|
} catch (Exception ex) { |
||||||
|
System.err.println("Upload fehlgeschlagen: " + ex); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -1,54 +1,48 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
|
|
||||||
import java.io.File; |
import java.io.File; |
||||||
import java.sql.Connection; |
import java.sql.Connection; |
||||||
import java.sql.PreparedStatement; |
import java.sql.PreparedStatement; |
||||||
import java.sql.Statement; |
import java.sql.Statement; |
||||||
|
|
||||||
import de.memtext.db.ConnectionCreator; |
import de.memtext.db.ConnectionCreator; |
||||||
import de.memtext.util.DateUtils; |
import de.memtext.util.DateUtils; |
||||||
import de.memtext.util.StringUtils; |
import de.memtext.util.StringUtils; |
||||||
|
|
||||||
public class MaskenSqlUpdater { |
public class MaskenSqlUpdater { |
||||||
|
|
||||||
public static void main(String[] args) { |
public static void main(String[] args) { |
||||||
if (args.length != 3) { |
if (args.length != 3) { |
||||||
System.out |
System.out.println("usage: MaskenSqlUpdater DB_PROPERTIES maskennummer sourcefile"); |
||||||
.println("usage: MaskenSqlUpdater DB_PROPERTIES maskennummer sourcefile"); |
System.exit(1); |
||||||
System.exit(1); |
} |
||||||
} |
Connection con = null; |
||||||
Connection con = null; |
int tid = Integer.parseInt(args[1]); |
||||||
int tid = Integer.parseInt(args[1]); |
try { |
||||||
try { |
con = ConnectionCreator.getConnectionCryptPassword(args[0], "driverName", "connectionURL", "connectionName", "connectionPassword"); |
||||||
con = ConnectionCreator.getConnectionCryptPassword(args[0], |
} catch (Exception e) { |
||||||
"driverName", "connectionURL", "connectionName", |
System.out.println("ERROR: Verbindung konnte nicht aufgebaut werden.\n" + e); |
||||||
"connectionPassword"); |
System.exit(1); |
||||||
} catch (Exception e) { |
} |
||||||
System.out |
try { |
||||||
.println("ERROR: Verbindung konnte nicht aufgebaut werden.\n" |
String sql = StringUtils.readFile(new File(args[2])); |
||||||
+ e); |
|
||||||
System.exit(1); |
Statement stm = con.createStatement(); |
||||||
} |
PreparedStatement pst = con.prepareStatement("update maskeninfo set select_stmt=? where tid=?"); |
||||||
try { |
pst.setString(1, sql); |
||||||
String sql = StringUtils.readFile(new File(args[2])); |
pst.setInt(2, tid); |
||||||
|
int rows = pst.executeUpdate(); |
||||||
Statement stm = con.createStatement(); |
|
||||||
PreparedStatement pst = con |
|
||||||
.prepareStatement("update maskeninfo set select_stmt=? where tid=?"); |
if (rows == 0) throw new IllegalArgumentException("Wahrscheinlich gibt es keine Maske mit der tid " + tid); |
||||||
pst.setString(1, sql); |
System.out.println("update erfolgreich auf " + con.getMetaData().getURL() + " um " + DateUtils.getNowString()); |
||||||
pst.setInt(2, tid); |
stm.close(); |
||||||
int rows=pst.executeUpdate(); |
con.close(); |
||||||
|
} catch (Exception e) { |
||||||
|
System.out.println("ERROR:" + e); |
||||||
if (rows==0) throw new IllegalArgumentException("Wahrscheinlich gibt es keine Maske mit der tid "+tid); |
|
||||||
System.out.println("update erfolgreich auf "+con.getMetaData().getURL() +" um "+DateUtils.getNowString()); |
} |
||||||
stm.close(); |
} |
||||||
con.close(); |
} |
||||||
} catch (Exception e) { |
|
||||||
System.out.println("ERROR:"+e); |
//Created on 12.04.2005 at 11:14:26
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//Created on 12.04.2005 at 11:14:26
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,550 @@ |
|||||||
|
package de.superx.bin; |
||||||
|
|
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.Container; |
||||||
|
import java.awt.FlowLayout; |
||||||
|
import java.awt.Font; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.awt.event.ActionListener; |
||||||
|
import java.awt.event.ItemEvent; |
||||||
|
import java.awt.event.ItemListener; |
||||||
|
import java.awt.event.WindowAdapter; |
||||||
|
import java.awt.event.WindowEvent; |
||||||
|
import java.io.BufferedReader; |
||||||
|
import java.io.FileInputStream; |
||||||
|
import java.io.FileOutputStream; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
import java.io.OutputStream; |
||||||
|
import java.sql.Connection; |
||||||
|
import java.sql.DatabaseMetaData; |
||||||
|
import java.sql.DriverManager; |
||||||
|
import java.sql.ResultSet; |
||||||
|
import java.sql.Statement; |
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.Properties; |
||||||
|
|
||||||
|
import javax.swing.JButton; |
||||||
|
import javax.swing.JComboBox; |
||||||
|
import javax.swing.JFrame; |
||||||
|
import javax.swing.JLabel; |
||||||
|
import javax.swing.JOptionPane; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import javax.swing.JPasswordField; |
||||||
|
import javax.swing.JTextField; |
||||||
|
|
||||||
|
import de.memtext.util.CryptUtils; |
||||||
|
import de.memtext.util.GetOpts; |
||||||
|
import de.memtext.util.GetOpts.Options; |
||||||
|
import de.memtext.widgets.LabeledComboBox; |
||||||
|
import de.memtext.widgets.LabeledTextField; |
||||||
|
import de.memtext.widgets.RadioButtonGroup; |
||||||
|
import de.memtext.widgets.VerticalBox; |
||||||
|
import de.memtext.widgets.WarningMessage; |
||||||
|
import de.superx.util.ConnectionDialogCommon; |
||||||
|
import de.superx.util.SqlStringUtils; |
||||||
|
|
||||||
|
public class PropAdminOld extends JFrame implements ActionListener, ItemListener { |
||||||
|
static Container cp; |
||||||
|
|
||||||
|
static LinkedList logLevels = new LinkedList(); |
||||||
|
|
||||||
|
static JTextField tAdminPasswd, tdriver, turl, tadminUser, tRestrictedUser, tRestrictedPassword; |
||||||
|
|
||||||
|
static LabeledTextField ltfMaskCache; |
||||||
|
|
||||||
|
static LabeledTextField ltfUserCache; |
||||||
|
|
||||||
|
static JComboBox tname; |
||||||
|
|
||||||
|
static LabeledComboBox sqlLogLevel, xmlLogLevel; |
||||||
|
|
||||||
|
static LabeledTextField maxActive; |
||||||
|
|
||||||
|
static LabeledTextField minIdle; |
||||||
|
|
||||||
|
static LabeledTextField maxIdle; |
||||||
|
|
||||||
|
static RadioButtonGroup rbEntwicklungsmodus = new RadioButtonGroup(); |
||||||
|
|
||||||
|
static private String defaultDBDriver = "com.informix.jdbc.IfxDriver"; |
||||||
|
|
||||||
|
static private String defaultConnection = "jdbc:informix-sqli://<<hostname>>:<<Portnr>>:informixserver=<<informixserver>>;database=superx"; |
||||||
|
|
||||||
|
static private String defaultUser = "superx"; |
||||||
|
|
||||||
|
private static String dbpropfile = "db.properties"; |
||||||
|
|
||||||
|
static private String connTypes[][]; |
||||||
|
|
||||||
|
private static boolean isGuiWanted = true; |
||||||
|
|
||||||
|
static Properties props = new Properties(); |
||||||
|
|
||||||
|
static byte key[] = { (byte) 255, (byte) 221, (byte) 127, (byte) 109, (byte) 129 }; |
||||||
|
|
||||||
|
static int keyLength = key.length; |
||||||
|
|
||||||
|
private static String usage = "-------------------------------------\nGebrauch: java de.superx.bin.PropAdmin -dbproperties:<<Pfad zu den db-Properties>>(optional) \n---------------------------------------------------"; |
||||||
|
|
||||||
|
// private static String newAdminPassword;
|
||||||
|
|
||||||
|
public PropAdminOld() { |
||||||
|
super("DB-Properties Admin @version@"); |
||||||
|
ltfMaskCache = new LabeledTextField("Masken, die im Cache sein sollen", "select tid from maskeninfo where 1=0", 50); |
||||||
|
ltfUserCache = new LabeledTextField("User, die im Cache sein sollen", "select tid from userinfo where 1=0", 50); |
||||||
|
maxActive = new LabeledTextField("maxActive", 3); |
||||||
|
minIdle = new LabeledTextField("minIdle", 3); |
||||||
|
maxIdle = new LabeledTextField("maxIdle", 3); |
||||||
|
|
||||||
|
sqlLogLevel = new LabeledComboBox("Log Level SQL", logLevels); |
||||||
|
xmlLogLevel = new LabeledComboBox("Log Level XML", logLevels); |
||||||
|
sqlLogLevel.setSelectedIndex(1); |
||||||
|
xmlLogLevel.setSelectedIndex(1); |
||||||
|
rbEntwicklungsmodus.add(new JLabel("Entwicklungsmodus ")); |
||||||
|
rbEntwicklungsmodus.add("an"); |
||||||
|
rbEntwicklungsmodus.add("aus"); |
||||||
|
rbEntwicklungsmodus.setSelection("an"); |
||||||
|
JButton btnTestAdmin = new JButton("Verbindung testen"); |
||||||
|
btnTestAdmin.addActionListener(this); |
||||||
|
|
||||||
|
cp = this.getContentPane(); |
||||||
|
cp.setLayout(new BorderLayout()); |
||||||
|
JPanel titel = new JPanel(); |
||||||
|
JLabel ltitel = new JLabel("DB-Properties Admin für " + dbpropfile); |
||||||
|
ltitel.setFont(new Font("Courier", Font.BOLD, 14)); |
||||||
|
titel.add(ltitel); |
||||||
|
cp.add(titel, "North"); |
||||||
|
VerticalBox center = new VerticalBox(); |
||||||
|
JPanel p0 = new JPanel(new FlowLayout(FlowLayout.LEFT)); |
||||||
|
|
||||||
|
tname = new JComboBox(); |
||||||
|
|
||||||
|
connTypes = ConnectionDialogCommon.getTypes(); |
||||||
|
|
||||||
|
for (int i = 0; i < connTypes.length; i++) { |
||||||
|
tname.addItem(connTypes[i][0]); |
||||||
|
} |
||||||
|
// controls.add(types);
|
||||||
|
|
||||||
|
JLabel lname = new JLabel(" Driver :"); |
||||||
|
lname.setFont(new Font("Courier", Font.BOLD, 12)); |
||||||
|
// tname=new JTextField(30);
|
||||||
|
JLabel c_name = new JLabel("(mögliche Datenbanksysteme für SuperX)"); |
||||||
|
p0.add(lname); |
||||||
|
p0.add(tname); |
||||||
|
p0.add(c_name); |
||||||
|
center.add(p0); |
||||||
|
// JPanel center=new JPanel(new GridLayout(0,1));
|
||||||
|
JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT)); |
||||||
|
JLabel ldriver = new JLabel(" Driver Class:"); |
||||||
|
ldriver.setFont(new Font("Courier", Font.BOLD, 12)); |
||||||
|
tdriver = new JTextField(30); |
||||||
|
JLabel c_driver = new JLabel("(muss im CLASSPATH stehen!)"); |
||||||
|
p1.add(ldriver); |
||||||
|
p1.add(tdriver); |
||||||
|
p1.add(c_driver); |
||||||
|
center.add(p1); |
||||||
|
|
||||||
|
JPanel p1b = new JPanel(new FlowLayout(FlowLayout.LEFT)); |
||||||
|
JLabel lurl = new JLabel(" Connection URL:"); |
||||||
|
lurl.setFont(new Font("Courier", Font.BOLD, 12)); |
||||||
|
turl = new JTextField(50); |
||||||
|
p1b.add(lurl); |
||||||
|
p1b.add(turl); |
||||||
|
center.add(p1b); |
||||||
|
|
||||||
|
JPanel p3 = new JPanel(new FlowLayout(FlowLayout.LEFT)); |
||||||
|
JLabel luser = new JLabel(" Username:"); |
||||||
|
luser.setFont(new Font("Courier", Font.BOLD, 12)); |
||||||
|
tadminUser = new JTextField(10); |
||||||
|
JLabel lpasswd = new JLabel(" Password:"); |
||||||
|
lpasswd.setFont(new Font("Courier", Font.BOLD, 12)); |
||||||
|
tAdminPasswd = new JPasswordField(10); |
||||||
|
p3.add(luser); |
||||||
|
p3.add(tadminUser); |
||||||
|
p3.add(lpasswd); |
||||||
|
p3.add(tAdminPasswd); |
||||||
|
p3.add(btnTestAdmin); |
||||||
|
center.add(p3); |
||||||
|
JPanel p3b = new JPanel(new FlowLayout(FlowLayout.LEFT)); |
||||||
|
JLabel lbl33 = new JLabel(" Eingeschränkter User:"); |
||||||
|
lbl33.setFont(new Font("Courier", Font.BOLD, 12)); |
||||||
|
p3b.add(lbl33); |
||||||
|
|
||||||
|
tRestrictedUser = new JTextField(10); |
||||||
|
p3b.add(tRestrictedUser); |
||||||
|
tRestrictedPassword = new JPasswordField(10); |
||||||
|
p3b.add(new JLabel("Passwort")); |
||||||
|
p3b.add(tRestrictedPassword); |
||||||
|
JButton btnTest2 = new JButton("Verb.testen"); |
||||||
|
btnTest2.addActionListener(this); |
||||||
|
JButton btnSelectRights = new JButton("select-Rechte auf alle Tabellen"); |
||||||
|
btnSelectRights.addActionListener(this); |
||||||
|
|
||||||
|
p3b.add(btnTest2); |
||||||
|
p3b.add(btnSelectRights); |
||||||
|
center.add(p3b); |
||||||
|
center.add(sqlLogLevel); |
||||||
|
center.add(xmlLogLevel); |
||||||
|
center.addWithLeftAlignment(rbEntwicklungsmodus); |
||||||
|
center.addWithLeftAlignment(new JLabel("<html>(Im Entwicklungsmodus werden alle SQL-Befehle von Abfragen einzeln an die Datenbank geschickt.<br>Das dauert etwas länger, ermöglicht aber bessere Fehlermeldungen.)<br>")); |
||||||
|
|
||||||
|
center.add(ltfMaskCache); |
||||||
|
center.add(ltfUserCache); |
||||||
|
|
||||||
|
JPanel p4 = new JPanel(); |
||||||
|
p4.add(new JLabel("<html>Der Apache ConnectionPool verwaltet die Anzahl benötigter Verbindungen dynamisch.<br>min/max idle gibt an wieviele Connections ständig bereit gehalten werden sollen.<br>maxActive gibt an wieviele Connections maximal gleichzeitig aktiv sein sollen.")); |
||||||
|
center.add(p4); |
||||||
|
JPanel p5 = new JPanel(); |
||||||
|
p5.add(minIdle); |
||||||
|
p5.add(maxIdle); |
||||||
|
p5.add(maxActive); |
||||||
|
center.add(p5); |
||||||
|
cp.add(center, "Center"); |
||||||
|
JButton OK = new JButton("Speichern"); |
||||||
|
OK.addActionListener(this); |
||||||
|
JPanel unten = new JPanel(); |
||||||
|
|
||||||
|
unten.add(OK); |
||||||
|
cp.add(unten, "South"); |
||||||
|
addWindowListener(new WindowAdapter() { |
||||||
|
@Override |
||||||
|
public void windowClosing(WindowEvent e) { |
||||||
|
System.exit(0); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
tname.addItemListener(this); |
||||||
|
|
||||||
|
this.pack(); |
||||||
|
} |
||||||
|
|
||||||
|
private static void properties_einlesen() throws IOException { |
||||||
|
if (!isGuiWanted) System.out.println("Lese ein: " + dbpropfile); |
||||||
|
props = new Properties(); |
||||||
|
FileInputStream is = new FileInputStream(dbpropfile); |
||||||
|
|
||||||
|
if (is != null) { |
||||||
|
props.load(is); |
||||||
|
is.close(); |
||||||
|
} else { |
||||||
|
if (isGuiWanted) JOptionPane.showMessageDialog(null, "Kann Properties nicht einlesen.", "DB-Prop Admin", JOptionPane.INFORMATION_MESSAGE); |
||||||
|
System.out.println("kann properties nicht einlesen"); |
||||||
|
} |
||||||
|
// System.out.println(CryptUtils.decryptSimple(props.getProperty(
|
||||||
|
// "connectionPassword")));
|
||||||
|
} |
||||||
|
|
||||||
|
private static void initFormFromProps() { |
||||||
|
String tdriverclass = props.getProperty("driverName"); |
||||||
|
tdriver.setText(tdriverclass); |
||||||
|
|
||||||
|
// if(props.getProperty( "connectionURL" ).equals(""))
|
||||||
|
// {
|
||||||
|
// Default-Url:
|
||||||
|
for (int i = 0; i < connTypes.length; i++) { |
||||||
|
if (tdriverclass.equals(connTypes[i][1])) { |
||||||
|
tname.setSelectedIndex(i); |
||||||
|
} |
||||||
|
} |
||||||
|
if (props.getProperty("connectionURL") != null) turl.setText(props.getProperty("connectionURL")); |
||||||
|
// }
|
||||||
|
tadminUser.setText(props.getProperty("connectionName")); |
||||||
|
tRestrictedUser.setText(props.getProperty("restrictedConnectionName")); |
||||||
|
|
||||||
|
if (props.getProperty("logLevelSQL") != null) sqlLogLevel.setSelectedItem(props.getProperty("logLevelSQL")); |
||||||
|
if (props.getProperty("logLevelXML") != null) xmlLogLevel.setSelectedItem(props.getProperty("logLevelXML")); |
||||||
|
if (props.getProperty("maskCache") != null) ltfMaskCache.setValue(props.getProperty("maskCache")); |
||||||
|
if (props.getProperty("userCache") != null) ltfUserCache.setValue(props.getProperty("userCache")); |
||||||
|
if (props.getProperty("minIdle") != null) |
||||||
|
minIdle.setValue(props.getProperty("minIdle")); |
||||||
|
else |
||||||
|
minIdle.setValue("5"); |
||||||
|
if (props.getProperty("maxIdle") != null) maxIdle.setValue(props.getProperty("maxIdle")); |
||||||
|
if (props.getProperty("maxActive") != null) maxActive.setValue(props.getProperty("maxActive")); |
||||||
|
if (props.getProperty("developmentMode") == null || props.getProperty("developmentMode").equals("true")) |
||||||
|
rbEntwicklungsmodus.setSelection("an"); |
||||||
|
else |
||||||
|
rbEntwicklungsmodus.setSelection("aus"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent event) { |
||||||
|
String cmd = event.getActionCommand(); |
||||||
|
if (cmd.equals("Speichern")) |
||||||
|
|
||||||
|
{ |
||||||
|
try { |
||||||
|
formValuesToProps(); |
||||||
|
saveProps(); |
||||||
|
System.exit(0); |
||||||
|
} catch (Exception e) { |
||||||
|
System.out.println("Es ist ein Fehler aufgetreten."); |
||||||
|
e.printStackTrace(); |
||||||
|
WarningMessage.show(null, "Fehler: " + e, "SuperX"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
if (cmd.equals("Verbindung testen")) { |
||||||
|
try { |
||||||
|
formValuesToProps(); |
||||||
|
boolean isOk = testConnection(props.getProperty("connectionName"), tAdminPasswd.getText()); |
||||||
|
|
||||||
|
} catch (Exception e) { |
||||||
|
WarningMessage.show(null, "Fehler:" + e, "PropAdmin"); |
||||||
|
} |
||||||
|
} |
||||||
|
if (cmd.equals("Verb.testen")) { |
||||||
|
try { |
||||||
|
formValuesToProps(); |
||||||
|
testConnection(props.getProperty("restrictedConnectionName"), tRestrictedPassword.getText()); |
||||||
|
|
||||||
|
} catch (Exception e) { |
||||||
|
WarningMessage.show(null, "Fehler:" + e, "PropAdmin"); |
||||||
|
} |
||||||
|
} |
||||||
|
if (cmd.equals("select-Rechte auf alle Tabellen")) { |
||||||
|
try { |
||||||
|
if (tRestrictedUser.getText() == null || tRestrictedUser.getText().trim().equals("")) |
||||||
|
throw new IllegalArgumentException("Eingeschränkter user muss angegeben sein"); |
||||||
|
if (tadminUser.getText() == null || tadminUser.getText().trim().equals("")) throw new IllegalArgumentException("User muss angegeben sein"); |
||||||
|
if (tAdminPasswd.getText() == null || tAdminPasswd.getText().trim().equals("")) throw new IllegalArgumentException("Userpassword muss angegeben sein"); |
||||||
|
// int result=JOptionPane.showConfirmDialog(this,
|
||||||
|
// "Wollen Sie dem eingeschränktem User select-Rechte auf alle Tabellen geben?"
|
||||||
|
// ,"PropAdmin",JOptionPane.YES_NO_OPTION);
|
||||||
|
// if (result==JOptionPane.YES_OPTION)
|
||||||
|
grantSelectToRestrictedUser(); |
||||||
|
|
||||||
|
} catch (Exception e) { |
||||||
|
WarningMessage.show(null, "Fehler:" + e, "PropAdmin"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private void grantSelectToRestrictedUser() throws Exception { |
||||||
|
Class.forName(props.getProperty("driverName")); |
||||||
|
|
||||||
|
Connection conn = DriverManager.getConnection(props.getProperty("connectionURL"), tadminUser.getText(), tAdminPasswd.getText()); |
||||||
|
Statement stm = conn.createStatement(); |
||||||
|
ResultSet rs = null; |
||||||
|
if (props.getProperty("driverName").indexOf("postgres") > -1) |
||||||
|
rs = conn.getMetaData().getTables(null, null, null, null); |
||||||
|
else |
||||||
|
rs = conn.getMetaData().getTables("superx", "superx", null, null); |
||||||
|
while (rs.next()) { |
||||||
|
System.out.println(rs.getObject(3).toString()); |
||||||
|
if (rs.getString(4) != null && (rs.getString(4).equals("TABLE") || rs.getString(4).equals("VIEW"))) |
||||||
|
stm.execute("grant select on " + rs.getObject(3).toString() + " to " + tRestrictedUser.getText() + ";"); |
||||||
|
} |
||||||
|
rs.close(); |
||||||
|
stm.close(); |
||||||
|
conn.close(); |
||||||
|
} |
||||||
|
|
||||||
|
private static boolean testConnection(String username, String password) { |
||||||
|
boolean result = false; |
||||||
|
try { |
||||||
|
Class.forName(props.getProperty("driverName")); |
||||||
|
if (props.getProperty("driverName").indexOf("postgres") > -1) { |
||||||
|
props.put("charSet", SqlStringUtils.getEncoding().equals("xUTF-8") ? "UTF-8" : "Latin-1"); |
||||||
|
props.put("DateStyle", "German, DMY"); |
||||||
|
} else // Informix
|
||||||
|
{ |
||||||
|
props.put("GL_DATETIME", "%d.%m.%Y %T"); |
||||||
|
props.put("CLIENT_LOCALE", SqlStringUtils.getEncoding().equals("xUTF-8") ? "UTF-8" : "de_de.8859-1"); |
||||||
|
} |
||||||
|
Connection conn = DriverManager.getConnection(props.getProperty("connectionURL"), username, password); |
||||||
|
DatabaseMetaData dbmd = conn.getMetaData(); |
||||||
|
|
||||||
|
/* |
||||||
|
* am 19.1.2006 auskommentiert, weil propadmin auch für DBen ausser |
||||||
|
* superx genutzt wird. dq Statement stm=conn.createStatement(); if |
||||||
|
* (props.getProperty("driverName").indexOf("postgres")>-1) |
||||||
|
* |
||||||
|
* stm.executeQuery("select date('1.1.2005');"); else |
||||||
|
* stm.executeQuery("select 'xx' from xdummy"); |
||||||
|
*/ |
||||||
|
String msg = "Verbindung mit Datenbank " + conn.getCatalog() + " (" + dbmd.getDatabaseProductName() + " " + dbmd.getDatabaseProductVersion() + ") als " + username |
||||||
|
+ " erfolgreich aufgebaut"; |
||||||
|
if (isGuiWanted) |
||||||
|
JOptionPane.showMessageDialog(null, msg, "DB-Prop Admin", JOptionPane.INFORMATION_MESSAGE); |
||||||
|
else |
||||||
|
System.out.println(msg); |
||||||
|
// stm.close();
|
||||||
|
conn.close(); |
||||||
|
result = true; |
||||||
|
} catch (Exception e) { |
||||||
|
String msg = "Ein Fehler ist aufgetreten.\n" + e.toString(); |
||||||
|
if (props.getProperty("driverName").indexOf("postgres") > -1 && e.toString().indexOf("Date Style") > -1) { |
||||||
|
msg += "\nPrüfen Sie,ob Date Style auf dem Server auf German, DMY steht."; |
||||||
|
} |
||||||
|
if (isGuiWanted) |
||||||
|
JOptionPane.showMessageDialog(null, msg, "DB-Prop Admin", JOptionPane.WARNING_MESSAGE); |
||||||
|
else |
||||||
|
System.out.println("Fehler: " + e.toString()); |
||||||
|
|
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
private static void formValuesToProps() throws Exception { |
||||||
|
|
||||||
|
String driver = tdriver.getText(); |
||||||
|
String name = tadminUser.getText(); |
||||||
|
String passwd = tAdminPasswd.getText(); |
||||||
|
String url = turl.getText(); |
||||||
|
|
||||||
|
if (driver == null || name == null || passwd == null || url == null || driver.equals("") || name.equals("") || url.equals("")) { |
||||||
|
if (isGuiWanted) JOptionPane.showMessageDialog(null, "Bitte alle Felder ausfüllen!", "DB-Prop Admin", JOptionPane.INFORMATION_MESSAGE); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
props.setProperty("connectionPassword", "sx_des" + CryptUtils.encryptStringDES(tAdminPasswd.getText())); |
||||||
|
props.setProperty("connectionName", name); |
||||||
|
props.setProperty("restrictedConnectionName", tRestrictedUser.getText()); |
||||||
|
if (tRestrictedPassword.getText() != null && tRestrictedPassword.getText().length() > 1) |
||||||
|
props.setProperty("restrictedConnectionPassword", "sx_des" + CryptUtils.encryptStringDES(tRestrictedPassword.getText())); |
||||||
|
|
||||||
|
props.setProperty("connectionURL", url); |
||||||
|
props.setProperty("driverName", driver); |
||||||
|
props.setProperty("minIdle", (String) minIdle.getValue()); |
||||||
|
props.setProperty("maxIdle", (String) maxIdle.getValue()); |
||||||
|
props.setProperty("maxActive", (String) maxActive.getValue()); |
||||||
|
props.setProperty("maskCache", (String) ltfMaskCache.getValue()); |
||||||
|
props.setProperty("userCache", (String) ltfUserCache.getValue()); |
||||||
|
props.setProperty("logLevelSQL", sqlLogLevel.getSelectedItem().toString()); |
||||||
|
props.setProperty("logLevelXML", xmlLogLevel.getSelectedItem().toString()); |
||||||
|
props.setProperty("developmentMode", rbEntwicklungsmodus.getSelectedName().equals("an") ? "true" : "false"); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private static void saveProps() { |
||||||
|
try { |
||||||
|
props.remove("charSet"); |
||||||
|
props.remove("DateStyle"); |
||||||
|
|
||||||
|
props.remove("GL_DATETIME"); |
||||||
|
props.remove("CLIENT_LOCALE"); |
||||||
|
OutputStream os = new FileOutputStream(dbpropfile); |
||||||
|
props.store(os, "SuperX DB.properties"); |
||||||
|
os.close(); |
||||||
|
System.out.println("Änderung gespeichert in " + dbpropfile); |
||||||
|
|
||||||
|
} catch (IOException e) { |
||||||
|
String fehler = "Konnte db.properties-Datei nicht speichern:" + e.toString(); |
||||||
|
if (isGuiWanted) JOptionPane.showMessageDialog(null, fehler, "DB-Prop Admin", JOptionPane.WARNING_MESSAGE); |
||||||
|
System.out.println(e.toString()); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String args[]) { |
||||||
|
logLevels.add("SEVERE"); |
||||||
|
logLevels.add("WARNING"); |
||||||
|
logLevels.add("INFO"); |
||||||
|
logLevels.add("FINE"); |
||||||
|
logLevels.add("FINER"); |
||||||
|
logLevels.add("FINEST"); |
||||||
|
System.out.println("Umgebungsvariable LANG: " + System.getProperty("file.encoding")); |
||||||
|
GetOpts.setOpts(args); |
||||||
|
PropAdminOld propAdmin = null; |
||||||
|
if (GetOpts.isPresent(Options.opt_dbprops)) dbpropfile = GetOpts.getValue(Options.opt_dbprops); |
||||||
|
|
||||||
|
if (GetOpts.isPresent(Options.opt_noguiVar0) || GetOpts.isPresent(Options.opt_noguiVar1) || GetOpts.isPresent(Options.opt_noguiVar2)) { |
||||||
|
isGuiWanted = false; |
||||||
|
} else { |
||||||
|
try { |
||||||
|
// wenn keine graphische Umgebung verfügbar ist
|
||||||
|
// tritt ein Fehler auf.
|
||||||
|
JFrame f = new JFrame(); |
||||||
|
|
||||||
|
} catch (Throwable e) { |
||||||
|
System.out.println("Keine graphische Umgebung verfuegbar - starte Shell-Modus"); |
||||||
|
isGuiWanted = false; |
||||||
|
} |
||||||
|
if (isGuiWanted) propAdmin = new PropAdminOld(); |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
properties_einlesen(); |
||||||
|
if (isGuiWanted) { |
||||||
|
initFormFromProps(); |
||||||
|
} |
||||||
|
} catch (IOException e) { |
||||||
|
String fehler = "Konnte db.properties-Datei nicht finden.\nEs wird eine neue in \n" + dbpropfile + " \nangelegt."; |
||||||
|
if (isGuiWanted) { |
||||||
|
JOptionPane.showMessageDialog(null, fehler, "DB-Prop Admin", JOptionPane.INFORMATION_MESSAGE); |
||||||
|
System.out.println(fehler); |
||||||
|
tdriver.setText(defaultDBDriver); |
||||||
|
tadminUser.setText(defaultUser); |
||||||
|
turl.setText(defaultConnection); |
||||||
|
|
||||||
|
} else { |
||||||
|
System.out.println("Sie koennen nur bestehende db.properties Dateien bearbeiten."); |
||||||
|
System.out.println("Geben Sie den Parameter -dbproperties:/home/superx/../db.properties an"); |
||||||
|
System.out.println(e); |
||||||
|
System.exit(1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (isGuiWanted) { |
||||||
|
propAdmin.show(); |
||||||
|
} else { |
||||||
|
noGuiEdit(); |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void noGuiEdit() { |
||||||
|
try { |
||||||
|
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); |
||||||
|
|
||||||
|
System.out.println("Die meisten Paramter koennen Sie mit dem vi bearbeiten."); |
||||||
|
System.out.print("Passwort für uneingeschränkten User (erscheint auf Bildschirm!): "); |
||||||
|
|
||||||
|
String newAdminPassword = br.readLine(); |
||||||
|
System.out.println(); |
||||||
|
// System.out.println("you entered: " + pass);
|
||||||
|
|
||||||
|
if (testConnection(props.getProperty("connectionName"), newAdminPassword)) { |
||||||
|
System.out.print("Einen Moment - Verschlüsselung läuft ..."); |
||||||
|
props.setProperty("connectionPassword", "sx_des" + CryptUtils.encryptStringDES(newAdminPassword)); |
||||||
|
System.out.println(" OK"); |
||||||
|
saveProps(); |
||||||
|
} |
||||||
|
if (props.getProperty("restrictedConnectionName") != null) { |
||||||
|
System.out.print("Passwort für eingeschraenkten User (erscheint auf Bildschirm!): "); |
||||||
|
|
||||||
|
String newPassword = br.readLine(); |
||||||
|
|
||||||
|
System.out.println(); |
||||||
|
|
||||||
|
if (testConnection(props.getProperty("restrictedConnectionName"), newPassword)) { |
||||||
|
System.out.print("Einen Moment - Verschlüsselung läuft ..."); |
||||||
|
props.setProperty("restrictedConnectionPassword", "sx_des" + CryptUtils.encryptStringDES(newPassword)); |
||||||
|
System.out.println(" OK"); |
||||||
|
saveProps(); |
||||||
|
} |
||||||
|
} |
||||||
|
System.exit(0); |
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void itemStateChanged(ItemEvent e) { |
||||||
|
|
||||||
|
String s = (String) e.getItem(); |
||||||
|
|
||||||
|
for (int i = 0; i < connTypes.length; i++) { |
||||||
|
if (s.equals(connTypes[i][0])) { |
||||||
|
tdriver.setText(connTypes[i][1]); |
||||||
|
// if(turl.getText().indexOf( ">>") < 0)
|
||||||
|
turl.setText(connTypes[i][2]); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -1,119 +1,113 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
|
|
||||||
import java.sql.Connection; |
import java.sql.Connection; |
||||||
import java.sql.PreparedStatement; |
import java.sql.PreparedStatement; |
||||||
import java.sql.ResultSet; |
import java.sql.ResultSet; |
||||||
import java.sql.Statement; |
import java.sql.Statement; |
||||||
import java.util.Hashtable; |
import java.util.Hashtable; |
||||||
|
|
||||||
import de.memtext.util.DSAHandler; |
import de.memtext.util.DSAHandler; |
||||||
import de.memtext.util.GetOpts; |
import de.memtext.util.GetOpts; |
||||||
|
import de.memtext.util.GetOpts.Options; |
||||||
public class PublicPrivateKeyManager { |
|
||||||
|
public class PublicPrivateKeyManager { |
||||||
public static void main(String[] args) { |
|
||||||
GetOpts.setOpts(args); |
public static void main(String[] args) { |
||||||
String isdrin = GetOpts |
GetOpts.setOpts(args); |
||||||
.isAllRequiredOptionsPresent("-dbproperties,-function"); |
String isdrin = GetOpts.isAllRequiredOptionsPresent(new Options[] {Options.opt_dbprops,Options.opt_function}); |
||||||
if (isdrin != null) { |
if (isdrin != null) { |
||||||
System.err.println("Folgende Optionen fehlen: " + isdrin); |
System.err.println("Folgende Optionen fehlen: " + isdrin); |
||||||
System.exit(1); |
System.exit(1); |
||||||
} |
} |
||||||
|
|
||||||
SxConnection sxcon = new SxConnection(); |
SxConnection sxcon = new SxConnection(); |
||||||
sxcon.setPropfile(GetOpts.getValue("-dbproperties")); |
sxcon.setPropfile(GetOpts.getValue(Options.opt_dbprops)); |
||||||
|
|
||||||
String function = GetOpts.getValue("-function"); |
String function = GetOpts.getValue(Options.opt_function); |
||||||
try { |
try { |
||||||
if (function.equals("install")) |
if (function.equals("install")) { |
||||||
{ install(sxcon); |
install(sxcon); |
||||||
check(sxcon); |
check(sxcon); |
||||||
} |
} |
||||||
if (function.equals("delete")) |
if (function.equals("delete")) { |
||||||
{ |
delete(sxcon); |
||||||
delete(sxcon); |
System.out.println("public/private key entfernt"); |
||||||
System.out.println("public/private key entfernt"); |
} |
||||||
} |
if (function.equals("check")) { |
||||||
if (function.equals("check")) |
System.out.println("Suche keys ..."); |
||||||
{ |
check(sxcon); |
||||||
System.out.println("Suche keys ..."); |
} |
||||||
check(sxcon); |
} catch (Exception e) { |
||||||
} |
e.printStackTrace(); |
||||||
} catch (Exception e) { |
} |
||||||
e.printStackTrace(); |
} |
||||||
} |
|
||||||
} |
private static void check(SxConnection sxcon) throws Exception { |
||||||
|
Connection con = sxcon.getConnection(); |
||||||
private static void check(SxConnection sxcon) throws Exception |
Statement st = con.createStatement(); |
||||||
{ |
ResultSet rs = st.executeQuery("select count(*) from sx_repository where id='privatekey'"); |
||||||
Connection con = sxcon.getConnection(); |
int countprivate = 0; |
||||||
Statement st=con.createStatement(); |
while (rs.next()) |
||||||
ResultSet rs=st.executeQuery("select count(*) from sx_repository where id='privatekey'"); |
countprivate = rs.getInt(1); |
||||||
int countprivate=0; |
rs.close(); |
||||||
while (rs.next()) |
rs = st.executeQuery("select count(*) from sx_repository where id='publickey'"); |
||||||
countprivate=rs.getInt(1); |
int countpublic = 0; |
||||||
rs.close(); |
while (rs.next()) |
||||||
rs=st.executeQuery("select count(*) from sx_repository where id='publickey'"); |
countpublic = rs.getInt(1); |
||||||
int countpublic=0; |
rs.close(); |
||||||
while (rs.next()) |
st.close(); |
||||||
countpublic=rs.getInt(1); |
con.close(); |
||||||
rs.close(); |
if (countprivate == 0) System.out.println("private key nicht installiert"); |
||||||
st.close(); |
if (countprivate == 1) System.out.println("private key installiert"); |
||||||
con.close(); |
if (countprivate > 1) { |
||||||
if (countprivate==0) System.out.println("private key nicht installiert"); |
System.out.println("mehr als ein private key gefunden - alle keys werden gelöscht"); |
||||||
if (countprivate==1) System.out.println("private key installiert"); |
delete(sxcon); |
||||||
if (countprivate>1) |
} |
||||||
{ |
if (countpublic == 0) System.out.println("public key nicht installiert"); |
||||||
System.out.println("mehr als ein private key gefunden - alle keys werden gelöscht"); |
if (countpublic == 1) System.out.println("public key installiert"); |
||||||
delete(sxcon); |
if (countpublic > 1) { |
||||||
} |
System.out.println("mehr als ein public key gefunden - alle keys werden gelöscht"); |
||||||
if (countpublic==0) System.out.println("public key nicht installiert"); |
delete(sxcon); |
||||||
if (countpublic==1) System.out.println("public key installiert"); |
} |
||||||
if (countpublic>1) |
|
||||||
{ |
|
||||||
System.out.println("mehr als ein public key gefunden - alle keys werden gelöscht"); |
} |
||||||
delete(sxcon); |
|
||||||
} |
private static void delete(SxConnection sxcon) throws Exception { |
||||||
|
Connection con = sxcon.getConnection(); |
||||||
|
Statement st = con.createStatement(); |
||||||
} |
st.executeUpdate("delete from sx_repository where id in ('privatekey','publickey')"); |
||||||
private static void delete(SxConnection sxcon) throws Exception { |
st.close(); |
||||||
Connection con = sxcon.getConnection(); |
con.close(); |
||||||
Statement st = con.createStatement(); |
} |
||||||
st |
|
||||||
.executeUpdate("delete from sx_repository where id in ('privatekey','publickey')"); |
private static void install(SxConnection sxcon) throws Exception { |
||||||
st.close(); |
delete(sxcon); |
||||||
con.close(); |
Connection con = sxcon.getConnection(); |
||||||
} |
Statement st = con.createStatement(); |
||||||
|
ResultSet rs = st.executeQuery("select max(tid) from sx_repository"); |
||||||
private static void install(SxConnection sxcon) throws Exception { |
int tid = 0; |
||||||
delete(sxcon); |
while (rs.next()) |
||||||
Connection con = sxcon.getConnection(); |
tid = rs.getInt(1); |
||||||
Statement st=con.createStatement(); |
rs.close(); |
||||||
ResultSet rs=st.executeQuery("select max(tid) from sx_repository"); |
Hashtable table = DSAHandler.generateKeyPair(); |
||||||
int tid=0; |
//PreparedStatement pst = con .prepareStatement("insert into testmb (tid,id,content,active) (?,?,2)");
|
||||||
while (rs.next()) |
//
|
||||||
tid=rs.getInt(1); |
|
||||||
rs.close(); |
PreparedStatement pst = con.prepareStatement("insert into sx_repository (tid,id,content,aktiv) values (?,?,?,2)"); |
||||||
Hashtable table = DSAHandler.generateKeyPair(); |
pst.setInt(1, ++tid); |
||||||
//PreparedStatement pst = con .prepareStatement("insert into testmb (tid,id,content,active) (?,?,2)");
|
pst.setString(2, "privatekey"); |
||||||
//
|
pst.setString(3, table.get("privatekey").toString()); |
||||||
|
//System.out.println(pst.get);
|
||||||
PreparedStatement pst = con |
pst.execute(); |
||||||
.prepareStatement("insert into sx_repository (tid,id,content,aktiv) values (?,?,?,2)"); |
pst.setInt(1, ++tid); |
||||||
pst.setInt(1, ++tid); |
pst.setString(2, "publickey"); |
||||||
pst.setString(2, "privatekey"); |
pst.setString(3, table.get("publickey").toString()); |
||||||
pst.setString(3, table.get("privatekey").toString()); |
pst.execute(); |
||||||
//System.out.println(pst.get);
|
pst.close(); |
||||||
pst.execute(); |
con.close(); |
||||||
pst.setInt(1, ++tid); |
|
||||||
pst.setString(2, "publickey"); |
} |
||||||
pst.setString(3, table.get("publickey").toString()); |
} |
||||||
pst.execute(); |
|
||||||
pst.close(); |
//Created on 21.10.2006 at 10:03:41
|
||||||
con.close(); |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//Created on 21.10.2006 at 10:03:41
|
|
||||||
|
|||||||
@ -1,132 +1,116 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
|
|
||||||
import java.io.File; |
import java.io.File; |
||||||
import java.sql.Connection; |
import java.sql.Connection; |
||||||
import java.sql.DriverManager; |
import java.sql.DriverManager; |
||||||
import java.sql.ResultSet; |
import java.sql.ResultSet; |
||||||
import java.sql.Statement; |
import java.sql.Statement; |
||||||
import java.util.Properties; |
import java.util.Properties; |
||||||
|
|
||||||
import de.memtext.util.GetOpts; |
import de.memtext.util.GetOpts; |
||||||
import de.superx.util.PropsReader; |
import de.memtext.util.GetOpts.Options; |
||||||
|
import de.superx.util.PropsReader; |
||||||
public class RestrictedConnectionManager { |
|
||||||
|
public class RestrictedConnectionManager { |
||||||
public static void main(String[] args) { |
|
||||||
GetOpts.setOpts(args); |
public static void main(String[] args) { |
||||||
String isdrin = GetOpts |
GetOpts.setOpts(args); |
||||||
.isAllRequiredOptionsPresent("-dbproperties,-kern_tabellen_freischalten"); |
String isdrin = GetOpts.isAllRequiredOptionsPresent(new Options[] {Options.opt_dbprops,Options.opt_kernTabellenFreischalten}); |
||||||
if (isdrin != null) { |
if (isdrin != null) { |
||||||
System.err.println("Folgende Optionen fehlen: " + isdrin); |
System.err.println("Folgende Optionen fehlen: " + isdrin); |
||||||
System.exit(1); |
System.exit(1); |
||||||
} |
} |
||||||
|
|
||||||
String kerninsert = GetOpts.getValue("-kern_tabellen_freischalten"); |
String kerninsert = GetOpts.getValue(Options.opt_kernTabellenFreischalten); |
||||||
if (!kerninsert.equals("true") && !kerninsert.equals("false")) |
if (!kerninsert.equals("true") && !kerninsert.equals("false")) throw new IllegalArgumentException("-kern_tabellen_freischalten:true/false"); |
||||||
throw new IllegalArgumentException( |
|
||||||
"-kern_tabellen_freischalten:true/false"); |
String dbpropfile = GetOpts.getValue(Options.opt_dbprops); |
||||||
|
try { |
||||||
String dbpropfile = GetOpts.getValue("-dbproperties"); |
Properties props = PropsReader.prepareProps(new File(dbpropfile)); |
||||||
try { |
String restrictedUser = props.getProperty("restrictedConnectionName"); |
||||||
Properties props = PropsReader.prepareProps(new File(dbpropfile)); |
if (restrictedUser == null || restrictedUser.trim().equals("")) { |
||||||
String restrictedUser = props |
System.out.println("RestrictedRightsManager: Keine Aktion nötig, da kein eingeschränkter User gefunden in " + dbpropfile); |
||||||
.getProperty("restrictedConnectionName"); |
} else { |
||||||
if (restrictedUser == null || restrictedUser.trim().equals("")) { |
Class.forName(props.getProperty("driverName")); |
||||||
System.out |
|
||||||
.println("RestrictedRightsManager: Keine Aktion nötig, da kein eingeschränkter User gefunden in " |
Connection conn = DriverManager.getConnection(props.getProperty("connectionURL"), props.getProperty("connectionName"), |
||||||
+ dbpropfile); |
PropsReader.check(props.getProperty("connectionPassword"))); |
||||||
} else { |
Statement stm = conn.createStatement(); |
||||||
Class.forName(props.getProperty("driverName")); |
StringBuffer grant = new StringBuffer("grant update on userinfo to " + restrictedUser + ";grant insert,update on protokoll to " + restrictedUser |
||||||
|
+ ";grant insert,update,delete,select on user_pw to " + restrictedUser + ";"); |
||||||
Connection conn = DriverManager.getConnection(props |
if (props.getProperty("driverName").indexOf("postgres") > -1) |
||||||
.getProperty("connectionURL"), props |
grant.append(";grant all on protokoll_protokoll_id_seq to " + restrictedUser + ";" + "grant all on sx_captions_tid_seq to " + restrictedUser + ";"); |
||||||
.getProperty("connectionName"), PropsReader.check(props |
|
||||||
.getProperty("connectionPassword"))); |
if (kerninsert.equals("true")) { |
||||||
Statement stm = conn.createStatement(); |
freischalten(grant, restrictedUser, "protokoll"); |
||||||
StringBuffer grant = new StringBuffer( |
|
||||||
"grant update on userinfo to "+restrictedUser+";grant insert,update on protokoll to " + restrictedUser + |
|
||||||
";grant insert,update,delete,select on user_pw to "+restrictedUser+";") ; |
|
||||||
if (props.getProperty("driverName").indexOf("postgres")>-1) |
|
||||||
grant.append(";grant all on protokoll_protokoll_id_seq to "+restrictedUser+";"+ |
|
||||||
"grant all on sx_captions_tid_seq to "+restrictedUser+";"); |
freischalten(grant, restrictedUser, "user_pw"); |
||||||
|
|
||||||
if (kerninsert.equals("true")) { |
freischalten(grant, restrictedUser, "group_field_pref"); |
||||||
freischalten(grant, restrictedUser, "protokoll"); |
freischalten(grant, restrictedUser, "sx_captions"); |
||||||
|
freischalten(grant, restrictedUser, "sx_stylesheets"); |
||||||
|
freischalten(grant, restrictedUser, "sx_mask_style"); |
||||||
|
freischalten(grant, restrictedUser, "userinfo"); |
||||||
|
freischalten(grant, restrictedUser, "groupinfo"); |
||||||
|
freischalten(grant, restrictedUser, "user_institution"); |
||||||
freischalten(grant, restrictedUser, "user_pw"); |
freischalten(grant, restrictedUser, "user_sachgeb_bez"); |
||||||
|
freischalten(grant, restrictedUser, "user_masken_bez"); |
||||||
freischalten(grant, restrictedUser, "group_field_pref"); |
freischalten(grant, restrictedUser, "group_sachgeb_bez"); |
||||||
freischalten(grant, restrictedUser, "sx_captions"); |
freischalten(grant, restrictedUser, "group_masken_bez"); |
||||||
freischalten(grant, restrictedUser, "sx_stylesheets"); |
freischalten(grant, restrictedUser, "user_group_bez"); |
||||||
freischalten(grant, restrictedUser, "sx_mask_style"); |
freischalten(grant, restrictedUser, "user_sichten"); |
||||||
freischalten(grant, restrictedUser, "userinfo"); |
freischalten(grant, restrictedUser, "user_sichtarten"); |
||||||
freischalten(grant, restrictedUser, "groupinfo"); |
freischalten(grant, restrictedUser, "group_sichten"); |
||||||
freischalten(grant, restrictedUser, "user_institution"); |
freischalten(grant, restrictedUser, "group_sichtarten"); |
||||||
freischalten(grant, restrictedUser, "user_sachgeb_bez"); |
freischalten(grant, restrictedUser, "felderinfo"); |
||||||
freischalten(grant, restrictedUser, "user_masken_bez"); |
freischalten(grant, restrictedUser, "maskeninfo"); |
||||||
freischalten(grant, restrictedUser, "group_sachgeb_bez"); |
freischalten(grant, restrictedUser, "konstanten"); |
||||||
freischalten(grant, restrictedUser, "group_masken_bez"); |
freischalten(grant, restrictedUser, "maske_system_bez"); |
||||||
freischalten(grant, restrictedUser, "user_group_bez"); |
freischalten(grant, restrictedUser, "masken_felder_bez"); |
||||||
freischalten(grant, restrictedUser, "user_sichten"); |
freischalten(grant, restrictedUser, "sachgeb_maske_bez"); |
||||||
freischalten(grant, restrictedUser, "user_sichtarten"); |
freischalten(grant, restrictedUser, "organigramm"); |
||||||
freischalten(grant, restrictedUser, "group_sichten"); |
freischalten(grant, restrictedUser, "themenbaum"); |
||||||
freischalten(grant, restrictedUser, "group_sichtarten"); |
freischalten(grant, restrictedUser, "sx_downloads"); |
||||||
freischalten(grant, restrictedUser, "felderinfo"); |
freischalten(grant, restrictedUser, "download_group_bez"); |
||||||
freischalten(grant, restrictedUser, "maskeninfo"); |
freischalten(grant, restrictedUser, "download_keyw_bez"); |
||||||
freischalten(grant, restrictedUser, "konstanten"); |
freischalten(grant, restrictedUser, "download_user_bez"); |
||||||
freischalten(grant, restrictedUser, "maske_system_bez"); |
freischalten(grant, restrictedUser, "group_hinweis"); |
||||||
freischalten(grant, restrictedUser, "masken_felder_bez"); |
freischalten(grant, restrictedUser, "user_hinweis"); |
||||||
freischalten(grant, restrictedUser, "sachgeb_maske_bez"); |
freischalten(grant, restrictedUser, "user_einstellungen"); |
||||||
freischalten(grant, restrictedUser, "organigramm"); |
freischalten(grant, restrictedUser, "user_dialog"); |
||||||
freischalten(grant, restrictedUser, "themenbaum"); |
} |
||||||
freischalten(grant, restrictedUser, "sx_downloads"); |
stm.execute(grant.toString()); |
||||||
freischalten(grant, restrictedUser, "download_group_bez"); |
String upd = null; |
||||||
freischalten(grant, restrictedUser, "download_keyw_bez"); |
|
||||||
freischalten(grant, restrictedUser, "download_user_bez"); |
ResultSet rs = null; |
||||||
freischalten(grant, restrictedUser, "group_hinweis"); |
if (props.getProperty("driverName").indexOf("postgres") > -1) |
||||||
freischalten(grant, restrictedUser, "user_hinweis"); |
rs = conn.getMetaData().getTables(null, null, null, null); |
||||||
freischalten(grant, restrictedUser, "user_einstellungen"); |
else |
||||||
freischalten(grant, restrictedUser, "user_dialog"); |
rs = conn.getMetaData().getTables("superx", "superx", null, null); |
||||||
} |
|
||||||
stm.execute(grant.toString()); |
while (rs.next()) { |
||||||
String upd = null; |
upd = "grant select on " + rs.getObject(3).toString() + " to " + restrictedUser + ";"; |
||||||
|
//System.out.println(upd);
|
||||||
ResultSet rs = null; |
if (rs.getString(4) != null && (rs.getString(4).equals("TABLE") || rs.getString(4).equals("VIEW"))) stm.execute(upd); |
||||||
if (props.getProperty("driverName").indexOf("postgres") > -1) |
} |
||||||
rs = conn.getMetaData().getTables(null, null, null, null); |
rs.close(); |
||||||
else |
stm.close(); |
||||||
rs = conn.getMetaData().getTables("superx", "superx", null, |
conn.close(); |
||||||
null); |
System.out.println(" RestrictedRightsManager fertig"); |
||||||
|
} |
||||||
while (rs.next()) { |
} catch (Exception e) { |
||||||
upd = "grant select on " + rs.getObject(3).toString() |
System.out.println("Es ist ein Fehler aufgetreten:"); |
||||||
+ " to " + restrictedUser + ";"; |
e.printStackTrace(); |
||||||
//System.out.println(upd);
|
} |
||||||
if (rs.getString(4) != null |
} |
||||||
&& (rs.getString(4).equals("TABLE") || rs |
|
||||||
.getString(4).equals("VIEW"))) |
private static void freischalten(StringBuffer grant, String user, String table) { |
||||||
stm.execute(upd); |
grant.append("grant select,insert, update, delete on " + table + " to " + user + ";"); |
||||||
} |
} |
||||||
rs.close(); |
} |
||||||
stm.close(); |
|
||||||
conn.close(); |
//Created on 03.11.2006 at 15:44:10
|
||||||
System.out.println(" RestrictedRightsManager fertig"); |
|
||||||
} |
|
||||||
} catch (Exception e) { |
|
||||||
System.out.println("Es ist ein Fehler aufgetreten:"); |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private static void freischalten(StringBuffer grant, String user, |
|
||||||
String table) { |
|
||||||
grant.append("grant select,insert, update, delete on " + table + " to " + user |
|
||||||
+ ";"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//Created on 03.11.2006 at 15:44:10
|
|
||||||
|
|||||||
@ -1,123 +1,111 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
/* |
/* |
||||||
* |
* |
||||||
* Simple Transformation of an XML Source via xsl File |
* Simple Transformation of an XML Source via xsl File |
||||||
*/ |
*/ |
||||||
|
|
||||||
import java.io.File; |
import java.io.File; |
||||||
import java.io.FileInputStream; |
import java.io.FileInputStream; |
||||||
import java.io.FileNotFoundException; |
import java.io.FileNotFoundException; |
||||||
import java.io.IOException; |
import java.io.IOException; |
||||||
import java.util.logging.LogManager; |
import java.util.logging.LogManager; |
||||||
import java.util.logging.Logger; |
import java.util.logging.Logger; |
||||||
|
|
||||||
import javax.xml.transform.TransformerConfigurationException; |
import javax.xml.transform.TransformerConfigurationException; |
||||||
import javax.xml.transform.TransformerException; |
import javax.xml.transform.TransformerException; |
||||||
|
|
||||||
import de.memtext.util.GetOpts; |
import de.memtext.util.GetOpts; |
||||||
import de.memtext.util.TimeUtils; |
import de.memtext.util.GetOpts.Options; |
||||||
|
import de.memtext.util.TimeUtils; |
||||||
/** |
|
||||||
* Use the TraX interface to perform a transformation in the simplest manner possible |
/** |
||||||
* (3 statements). |
* Use the TraX interface to perform a transformation in the simplest manner possible |
||||||
*/ |
* (3 statements). |
||||||
public class SimpleTransform { |
*/ |
||||||
private static String usage = |
public class SimpleTransform { |
||||||
"-------------------------------------\nGebrauch: java de.superx.SimpleTransform -logger=<<Pfad zu logging.properties>> -IN=<<xml-Datei>> -XSL=<<xsl-Datei>> -method=<<xml |html|text>>(optional) -param=<<Parameter>>(optional) -OUT=<<Ausgabedatei>>(optional) \n---------------------------------------------------"; |
private static String usage = "-------------------------------------\nGebrauch: java de.superx.SimpleTransform -logger=<<Pfad zu logging.properties>> -IN=<<xml-Datei>> -XSL=<<xsl-Datei>> -method=<<xml |html|text>>(optional) -param=<<Parameter>>(optional) -OUT=<<Ausgabedatei>>(optional) \n---------------------------------------------------"; |
||||||
static Logger logger = |
|
||||||
(Logger) Logger.getLogger(SimpleTransform.class.toString()); |
static Logger logger = (Logger) Logger.getLogger(SimpleTransform.class.toString()); |
||||||
|
|
||||||
private static String _out = ""; |
private static String _out = ""; |
||||||
public static void transform(String args[]) |
|
||||||
throws |
public static void transform(String args[]) |
||||||
TransformerException, |
throws TransformerException, TransformerConfigurationException, FileNotFoundException, IOException, ClassNotFoundException, FileNotFoundException, IOException { |
||||||
TransformerConfigurationException, |
|
||||||
FileNotFoundException, |
String _xml = ""; |
||||||
IOException, |
String _xsl = ""; |
||||||
ClassNotFoundException, |
|
||||||
FileNotFoundException, |
String method = "text"; |
||||||
IOException { |
String _params = ""; |
||||||
|
String logfile = ""; |
||||||
String _xml = ""; |
GetOpts.setOpts(args); |
||||||
String _xsl = ""; |
String isdrin = GetOpts.isAllRequiredOptionsPresent(new Options[] {Options.opt_logger,Options.opt_in,Options.opt_xsl}); |
||||||
|
if (isdrin != null) { |
||||||
String method = "text"; |
System.err.println("Folgende Optionen fehlen: " + isdrin); |
||||||
String _params = ""; |
System.err.println(usage); |
||||||
String logfile = ""; |
System.exit(1); |
||||||
GetOpts.setOpts(args); |
} |
||||||
String isdrin = GetOpts.isAllRequiredOptionsPresent("-logger,-IN,-XSL"); |
|
||||||
if (isdrin != null) { |
//GetOpts myOpts=new GetOpts();
|
||||||
System.err.println("Folgende Optionen fehlen: " + isdrin); |
if (GetOpts.isPresent(Options.opt_logger)) logfile = GetOpts.getValue(Options.opt_logger); |
||||||
System.err.println(usage); |
if (GetOpts.isPresent(Options.opt_in)) _xml = GetOpts.getValue(Options.opt_in); |
||||||
System.exit(1); |
if (GetOpts.isPresent(Options.opt_xsl)) _xsl = GetOpts.getValue(Options.opt_xsl); |
||||||
} |
if (GetOpts.isPresent(Options.opt_out)) _out = GetOpts.getValue(Options.opt_out); |
||||||
|
if (GetOpts.isPresent(Options.opt_method)) method = GetOpts.getValue(Options.opt_method); |
||||||
//GetOpts myOpts=new GetOpts();
|
if (GetOpts.isPresent(Options.opt_params)) _params = GetOpts.getValue(Options.opt_params); |
||||||
if (GetOpts.isPresent("-logger")) |
|
||||||
logfile = GetOpts.getValue("-logger"); |
//logger.initRaw(dosql.class)
|
||||||
if (GetOpts.isPresent("-IN")) |
//PropertyConfigurator.configure(logfile);
|
||||||
_xml = GetOpts.getValue("-IN"); |
File f = new File(logfile); |
||||||
if (GetOpts.isPresent("-XSL")) |
if (!f.exists()) { |
||||||
_xsl = GetOpts.getValue("-XSL"); |
throw new IOException("Datei nicht gefunden: " + logfile); |
||||||
if (GetOpts.isPresent("-OUT")) |
} |
||||||
_out = GetOpts.getValue("-OUT"); |
FileInputStream ins = new FileInputStream(logfile); |
||||||
if (GetOpts.isPresent("-method")) |
LogManager MyLogManager = java.util.logging.LogManager.getLogManager(); |
||||||
method = GetOpts.getValue("-method"); |
MyLogManager.readConfiguration(ins); |
||||||
if (GetOpts.isPresent("-params")) |
//logfile = MyLogManager.getProperty(".level");
|
||||||
_params = GetOpts.getValue("-params"); |
logger.info("Using Loggging-Level " + MyLogManager.getProperty(".level")); |
||||||
|
|
||||||
//logger.initRaw(dosql.class)
|
SxTransformer myTransformer = null; |
||||||
//PropertyConfigurator.configure(logfile);
|
if (_out.equals("")) |
||||||
File f = new File(logfile); |
myTransformer = new SxTransformer(logger, System.out); |
||||||
if (!f.exists()) { |
else |
||||||
throw new IOException("Datei nicht gefunden: " + logfile); |
myTransformer = new SxTransformer(logger, _out); |
||||||
} |
myTransformer.quellstring = _xml; |
||||||
FileInputStream ins = new FileInputStream(logfile); |
myTransformer.stylesheet = _xsl; |
||||||
LogManager MyLogManager = java.util.logging.LogManager.getLogManager(); |
myTransformer.setParams(_params); |
||||||
MyLogManager.readConfiguration(ins); |
try { |
||||||
//logfile = MyLogManager.getProperty(".level");
|
myTransformer.transformFile(method); |
||||||
logger.info("Using Loggging-Level " + MyLogManager.getProperty(".level")); |
} catch (Exception e) { |
||||||
|
// TODO Auto-generated catch block
|
||||||
SxTransformer myTransformer = null; |
e.printStackTrace(); |
||||||
if (_out.equals("")) |
} |
||||||
myTransformer = new SxTransformer(logger, System.out); |
} |
||||||
else |
|
||||||
myTransformer = new SxTransformer(logger, _out); |
public static void main(String args[]) { |
||||||
myTransformer.quellstring = _xml; |
try { |
||||||
myTransformer.stylesheet = _xsl; |
if (args.length < 2) { |
||||||
myTransformer.setParams(_params); |
System.err.println("Mindestens drei Parameter (Pfad zu den logger.properties, Pfad zur xml-Datei,Pfad zur xsl-Datei) erfoderlich"); |
||||||
try { |
System.err.println(usage); |
||||||
myTransformer.transformFile(method); |
System.exit(1); |
||||||
} catch (Exception e) { |
} |
||||||
// TODO Auto-generated catch block
|
TimeUtils t = new TimeUtils(); |
||||||
e.printStackTrace(); |
t.start(); |
||||||
} |
transform(args); |
||||||
} |
t.print(" done"); |
||||||
public static void main(String args[]) { |
String msg = "XML-Transformation erfolgreich "; |
||||||
try { |
if (_out != null && !_out.equals("")) msg += _out + " erzeugt"; |
||||||
if (args.length < 2) { |
System.out.println(msg); |
||||||
System.err.println( |
} catch (Exception ex) { |
||||||
"Mindestens drei Parameter (Pfad zu den logger.properties, Pfad zur xml-Datei,Pfad zur xsl-Datei) erfoderlich"); |
System.err.println("Es ist ein Fehler aufgetreten, " + _out + " konnte nicht erstellt werden\n" + ex.toString()); |
||||||
System.err.println(usage); |
File f = new File(_out); |
||||||
System.exit(1); |
if (f.exists()) { |
||||||
} |
f.delete(); |
||||||
TimeUtils t=new TimeUtils(); t.start(); |
} |
||||||
transform(args); |
System.exit(1); |
||||||
t.print(" done"); |
} |
||||||
String msg = "XML-Transformation erfolgreich "; |
} |
||||||
if (_out != null && !_out.equals("")) |
} |
||||||
msg += _out + " erzeugt"; |
|
||||||
System.out.println(msg); |
|
||||||
} catch (Exception ex) { |
|
||||||
System.err.println("Es ist ein Fehler aufgetreten, "+_out+" konnte nicht erstellt werden\n"+ex.toString()); |
|
||||||
File f = new File(_out); |
|
||||||
if (f.exists()) { |
|
||||||
f.delete(); |
|
||||||
} |
|
||||||
System.exit(1); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,66 +1,64 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
|
|
||||||
import java.sql.Connection; |
import java.sql.Connection; |
||||||
import java.sql.PreparedStatement; |
import java.sql.PreparedStatement; |
||||||
import java.sql.ResultSet; |
import java.sql.ResultSet; |
||||||
import java.sql.SQLException; |
import java.sql.SQLException; |
||||||
import java.sql.Statement; |
import java.sql.Statement; |
||||||
|
|
||||||
import de.memtext.db.ConnectionCreator; |
import de.memtext.db.ConnectionCreator; |
||||||
|
|
||||||
public class SpecialUpdater { |
public class SpecialUpdater { |
||||||
public static String url="jdbc:informix-sqli://jupiter:50000:informixserver=superx_host;database=superx"; |
public static String url = "jdbc:informix-sqli://jupiter:50000:informixserver=superx_host;database=superx"; |
||||||
public static String passwd="anfang12"; |
|
||||||
SpecialUpdater() |
public static String passwd = "anfang12"; |
||||||
{ |
|
||||||
|
SpecialUpdater() { |
||||||
} |
|
||||||
public void run() throws SQLException |
} |
||||||
{ |
|
||||||
ConnectionCreator.loadClass("com.informix.jdbc.IfxDriver"); |
public void run() throws SQLException { |
||||||
Connection con=ConnectionCreator.getConnection(url,"superx",passwd); |
ConnectionCreator.loadClass("com.informix.jdbc.IfxDriver"); |
||||||
Statement stm=con.createStatement(); |
Connection con = ConnectionCreator.getConnection(url, "superx", passwd); |
||||||
ResultSet rs=stm.executeQuery("select tid,relation from felderinfo where art=12"); |
Statement stm = con.createStatement(); |
||||||
int tid; |
ResultSet rs = stm.executeQuery("select tid,relation from felderinfo where art=12"); |
||||||
String relation,relationCorr; |
int tid; |
||||||
PreparedStatement pst=con.prepareStatement("update felderinfo set relation=? where tid=?"); |
String relation, relationCorr; |
||||||
while (rs.next()) { |
PreparedStatement pst = con.prepareStatement("update felderinfo set relation=? where tid=?"); |
||||||
tid=rs.getInt("tid"); |
while (rs.next()) { |
||||||
relation=rs.getString("relation"); |
tid = rs.getInt("tid"); |
||||||
if (relation.indexOf("tid")>-1&&relation.indexOf("sichten")>-1) |
relation = rs.getString("relation"); |
||||||
{ |
if (relation.indexOf("tid") > -1 && relation.indexOf("sichten") > -1) { |
||||||
System.out.println("replace for "+tid+" "); |
System.out.println("replace for " + tid + " "); |
||||||
System.out.println(" "+relation); |
System.out.println(" " + relation); |
||||||
relationCorr=relation.replaceAll(" tid "," id "); |
relationCorr = relation.replaceAll(" tid ", " id "); |
||||||
System.out.println(" "+relationCorr); |
System.out.println(" " + relationCorr); |
||||||
|
|
||||||
pst.setString(1,relationCorr); |
pst.setString(1, relationCorr); |
||||||
pst.setInt(2,tid); |
pst.setInt(2, tid); |
||||||
pst.execute(); |
pst.execute(); |
||||||
} |
} |
||||||
|
|
||||||
} |
} |
||||||
rs.close(); |
rs.close(); |
||||||
stm.close(); |
stm.close(); |
||||||
con.close(); |
con.close(); |
||||||
} |
} |
||||||
public static void main(String[] args) { |
|
||||||
if (args.length==0) |
public static void main(String[] args) { |
||||||
{ |
if (args.length == 0) { |
||||||
System.out.println(" informix driver must be in classpath"); |
System.out.println(" informix driver must be in classpath"); |
||||||
System.out.println(" url [passwd]"); |
System.out.println(" url [passwd]"); |
||||||
|
|
||||||
} |
} |
||||||
if (args.length>0) |
if (args.length > 0) url = args[0]; |
||||||
url=args[0]; |
if (args.length > 1) passwd = args[1]; |
||||||
if (args.length>1) |
try { |
||||||
passwd=args[1]; |
new SpecialUpdater().run(); |
||||||
try { |
} catch (SQLException e) { |
||||||
new SpecialUpdater().run(); |
e.printStackTrace(); |
||||||
} catch (SQLException e) { |
} |
||||||
e.printStackTrace(); |
} |
||||||
} |
} |
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//Created on 17.02.2005 at 15:55:28
|
//Created on 17.02.2005 at 15:55:28
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,79 +1,77 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
|
|
||||||
import java.io.File; |
import java.io.File; |
||||||
import java.io.IOException; |
import java.io.IOException; |
||||||
import java.net.MalformedURLException; |
import java.net.MalformedURLException; |
||||||
|
|
||||||
import org.xml.sax.SAXException; |
import org.apache.commons.io.FileUtils; |
||||||
|
import org.xml.sax.SAXException; |
||||||
import com.meterware.httpunit.GetMethodWebRequest; |
|
||||||
import com.meterware.httpunit.WebConversation; |
import com.meterware.httpunit.GetMethodWebRequest; |
||||||
import com.meterware.httpunit.WebRequest; |
import com.meterware.httpunit.WebConversation; |
||||||
import com.meterware.httpunit.WebResponse; |
import com.meterware.httpunit.WebRequest; |
||||||
import com.meterware.httpunit.WebTable; |
import com.meterware.httpunit.WebResponse; |
||||||
|
import com.meterware.httpunit.WebTable; |
||||||
import de.memtext.util.StringUtils; |
|
||||||
|
import de.memtext.util.StringUtils; |
||||||
public class SxTestXmlCreator { |
|
||||||
public static void main(String args[]) { |
public class SxTestXmlCreator { |
||||||
|
public static void main(String args[]) { |
||||||
if (args.length != 1) { |
|
||||||
System.out.println("usage SxTestXmlCreator filename (which contains url or sql)"); |
if (args.length != 1) { |
||||||
System.exit(-1); |
System.out.println("usage SxTestXmlCreator filename (which contains url or sql)"); |
||||||
} |
System.exit(-1); |
||||||
try { |
} |
||||||
File f=new File(args[0]); |
try { |
||||||
createTestXml(f); |
File f = new File(args[0]); |
||||||
} catch (Exception e) { |
createTestXml(f); |
||||||
System.out.println(e); |
} catch (Exception e) { |
||||||
} |
System.out.println(e); |
||||||
} |
} |
||||||
|
} |
||||||
private static void createTestXml(File f) throws MalformedURLException, |
|
||||||
IOException, SAXException { |
private static void createTestXml(File f) throws MalformedURLException, IOException, SAXException { |
||||||
String input=StringUtils.readFile(f); |
String input = StringUtils.readFile(f); |
||||||
|
|
||||||
//if (input.startsWith("http"))
|
//if (input.startsWith("http"))
|
||||||
|
|
||||||
String url=input; |
String url = input; |
||||||
WebConversation wc = new WebConversation(); |
WebConversation wc = new WebConversation(); |
||||||
WebRequest req = new GetMethodWebRequest(url); |
WebRequest req = new GetMethodWebRequest(url); |
||||||
WebResponse resp = wc.getResponse(req); |
WebResponse resp = wc.getResponse(req); |
||||||
|
|
||||||
if (resp.getTables().length == 0) { |
if (resp.getTables().length == 0) { |
||||||
System.out.println("Keine Tabelle geliefert\n" + resp.getText()); |
System.out.println("Keine Tabelle geliefert\n" + resp.getText()); |
||||||
System.exit(1); |
System.exit(1); |
||||||
} |
} |
||||||
|
|
||||||
WebTable table = resp.getTables()[1]; |
WebTable table = resp.getTables()[1]; |
||||||
String params=url.substring(url.indexOf("?")+1); |
String params = url.substring(url.indexOf("?") + 1); |
||||||
params=params.trim(); |
params = params.trim(); |
||||||
if (params.charAt(params.length()-1)=='\n') params=params.substring(0,params.length()-2); |
if (params.charAt(params.length() - 1) == '\n') params = params.substring(0, params.length() - 2); |
||||||
StringBuffer erg = new StringBuffer( |
StringBuffer erg = new StringBuffer("<webtest name=\"\">\n <params><![CDATA[" + params + "]]></params>\n"); |
||||||
"<webtest name=\"\">\n <params><![CDATA[" + params + "]]></params>\n"); |
for (int col = 0; col < table.getColumnCount(); col++) { |
||||||
for (int col = 0; col < table.getColumnCount(); col++) { |
for (int row = 0; row < table.getRowCount(); row++) { |
||||||
for (int row = 0; row < table.getRowCount(); row++) { |
String val = table.getTableCell(row, col).getText(); |
||||||
String val = table.getTableCell(row, col).getText(); |
//wenn \n vorkommt test auskommentieren
|
||||||
//wenn \n vorkommt test auskommentieren
|
if (val.indexOf("\n") > -1) erg.append("<!-- "); |
||||||
if (val.indexOf("\n")> -1) erg.append("<!-- "); |
erg.append("<valuetest row=\"" + (row + 1) + "\" col=\"" + (col + 1) + "\" val=\"" + val + "\"/>\n"); |
||||||
erg.append("<valuetest row=\"" + (row + 1) + "\" col=\"" |
if (val.indexOf("\n") > -1) erg.append(" -->"); |
||||||
+ (col + 1) + "\" val=\"" + val + "\"/>\n"); |
} |
||||||
if (val.indexOf("\n")> -1) erg.append(" -->"); |
} |
||||||
} |
|
||||||
} |
erg.append("</webtest>\n"); |
||||||
|
|
||||||
erg.append("</webtest>\n"); |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FileUtils.writeStringToFile(new File("temp.xml"), erg.toString()); |
||||||
|
System.out.println("XML ist in temp.xml"); |
||||||
StringUtils.write(new File("temp.xml"),erg.toString()); |
} |
||||||
System.out.println("XML ist in temp.xml"); |
|
||||||
} |
} |
||||||
|
|
||||||
} |
//Created on 27.04.2006 at 14:47:18
|
||||||
|
|
||||||
//Created on 27.04.2006 at 14:47:18
|
|
||||||
|
|||||||
@ -1,284 +1,261 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
/* |
/* |
||||||
* Copyright 1999-2004 The Apache Software Foundation. |
* Copyright 1999-2004 The Apache Software Foundation. |
||||||
* |
* |
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
* you may not use this file except in compliance with the License. |
* you may not use this file except in compliance with the License. |
||||||
* You may obtain a copy of the License at |
* You may obtain a copy of the License at |
||||||
* |
* |
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* |
* |
||||||
* Unless required by applicable law or agreed to in writing, software |
* Unless required by applicable law or agreed to in writing, software |
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
* See the License for the specific language governing permissions and |
* See the License for the specific language governing permissions and |
||||||
* limitations under the License. |
* limitations under the License. |
||||||
*/ |
*/ |
||||||
/* |
|
||||||
* $Id: Validate.java,v 1.5 2004/02/17 19:11:45 minchau Exp $ |
/* |
||||||
* |
* $Id: Validate.java,v 1.5 2004/02/17 19:11:45 minchau Exp $ |
||||||
* Erweitert für SuperX von Daniel Quathamer |
* |
||||||
* 16.11.2006 |
* Erweitert für SuperX von Daniel Quathamer |
||||||
*/ |
* 16.11.2006 |
||||||
|
*/ |
||||||
import java.io.File; |
|
||||||
import java.io.FileInputStream; |
import java.io.File; |
||||||
import java.io.FileNotFoundException; |
import java.io.FileInputStream; |
||||||
import java.io.FilenameFilter; |
import java.io.FileNotFoundException; |
||||||
import java.io.IOException; |
import java.io.FilenameFilter; |
||||||
|
import java.io.IOException; |
||||||
import javax.xml.parsers.ParserConfigurationException; |
|
||||||
import javax.xml.parsers.SAXParser; |
import javax.xml.parsers.ParserConfigurationException; |
||||||
import javax.xml.parsers.SAXParserFactory; |
import javax.xml.parsers.SAXParser; |
||||||
|
import javax.xml.parsers.SAXParserFactory; |
||||||
import org.xml.sax.InputSource; |
|
||||||
import org.xml.sax.SAXException; |
import org.xml.sax.InputSource; |
||||||
import org.xml.sax.SAXParseException; |
import org.xml.sax.SAXException; |
||||||
import org.xml.sax.XMLReader; |
import org.xml.sax.SAXParseException; |
||||||
import org.xml.sax.ext.LexicalHandler; |
import org.xml.sax.XMLReader; |
||||||
import org.xml.sax.helpers.DefaultHandler; |
import org.xml.sax.ext.LexicalHandler; |
||||||
|
import org.xml.sax.helpers.DefaultHandler; |
||||||
/* Use JAXP SAXParser to parse 1 .xml file or all the .xml files in a directory. |
|
||||||
* Takes 1 or 2 command-line arguments: |
/* Use JAXP SAXParser to parse 1 .xml file or all the .xml files in a directory. |
||||||
* Argument 1 (required) is a file name or directory name. |
* Takes 1 or 2 command-line arguments: |
||||||
* Argument 2 (optional) is a log file name. If ommitted, messages are written to screen. |
* Argument 1 (required) is a file name or directory name. |
||||||
*/ |
* Argument 2 (optional) is a log file name. If ommitted, messages are written to screen. |
||||||
public class SxValidate |
*/ |
||||||
{ |
public class SxValidate { |
||||||
static int numXMLFiles = 0; |
static int numXMLFiles = 0; |
||||||
static int numValidFiles = 0; |
|
||||||
static int numInvalidFiles = 0; |
static int numValidFiles = 0; |
||||||
static int numFilesMissingDoctype = 0; |
|
||||||
static int numMalformedFiles = 0; |
static int numInvalidFiles = 0; |
||||||
static boolean useSchema = false; |
|
||||||
static StringBuffer buff = new StringBuffer(); |
static int numFilesMissingDoctype = 0; |
||||||
|
|
||||||
public static void main(String[] args) |
static int numMalformedFiles = 0; |
||||||
throws FileNotFoundException, IOException, ParserConfigurationException, SAXException |
|
||||||
{ |
static boolean useSchema = false; |
||||||
if (args.length == 0 || args.length > 2) |
|
||||||
{ |
static StringBuffer buff = new StringBuffer(); |
||||||
System.out.println("\nGeben Sie 'sx_validate.x -help' für Information über SxValidate"); |
|
||||||
System.exit(1); |
public static void main(String[] args) throws FileNotFoundException, IOException, ParserConfigurationException, SAXException { |
||||||
} |
if (args.length == 0 || args.length > 2) { |
||||||
if (args[0].toLowerCase().equals("-help")) |
System.out.println("\nGeben Sie 'sx_validate.x -help' für Information über SxValidate"); |
||||||
{ |
return; |
||||||
String sep = "\n====================================================\n"; |
} |
||||||
String a = "sx_validate <Datei oder Pfad> [SCHEMA] \nValidate nutzt Xerces um einen einzelnen XML-File zu validieren bzw. die xml Files in dem Verzeichnis das Sie spezifizieren. Der Parser validiert jedes Dokument (Konformität zum DOCTYPE oder XMLSchema).\n"; |
if (args[0].toLowerCase().equals("-help")) { |
||||||
String b = "Jede xml Datei sollte eine DOCTYPE declaration oder einen XMLSchema-Verweis enthalten.\n\n"; |
String sep = "\n====================================================\n"; |
||||||
String c = "SxValidate nimmt 1 oder 2 Argumente:\n"; |
String a = "sx_validate <Datei oder Pfad> [SCHEMA] \nValidate nutzt Xerces um einen einzelnen XML-File zu validieren bzw. die xml Files in dem Verzeichnis das Sie spezifizieren. Der Parser validiert jedes Dokument (Konformität zum DOCTYPE oder XMLSchema).\n"; |
||||||
String d = " Argument 1 spezifiziert das Verzeichnis oder die Datei.\n"; |
String b = "Jede xml Datei sollte eine DOCTYPE declaration oder einen XMLSchema-Verweis enthalten.\n\n"; |
||||||
String e = " Argument 2 (einfach 'SCHEMA') spezifiziert, ob nach XML-Schema validiert werden soll.\n"; |
String c = "SxValidate nimmt 1 oder 2 Argumente:\n"; |
||||||
System.out.println(sep+a+b+c+d+e+sep); |
String d = " Argument 1 spezifiziert das Verzeichnis oder die Datei.\n"; |
||||||
return; |
String e = " Argument 2 (einfach 'SCHEMA') spezifiziert, ob nach XML-Schema validiert werden soll.\n"; |
||||||
} |
System.out.println(sep + a + b + c + d + e + sep); |
||||||
try |
return; |
||||||
{ |
} |
||||||
SxValidate v = new SxValidate(); |
try { |
||||||
v.validate(args); |
SxValidate v = new SxValidate(); |
||||||
System.exit(0); |
v.validate(args); |
||||||
} |
} catch (Exception e) { |
||||||
catch (Exception e) |
e.printStackTrace(); |
||||||
{ |
} |
||||||
e.printStackTrace(); |
} |
||||||
System.exit(1); |
|
||||||
} |
void validate(String[] args) throws FileNotFoundException, IOException, ParserConfigurationException, SAXException { |
||||||
} |
File dir = new File(args[0]); |
||||||
|
|
||||||
void validate(String[] args) |
// User may include a 2nd argument for the validation method
|
||||||
throws Exception |
|
||||||
{ |
useSchema = false; |
||||||
File dir = new File(args[0]); |
if (args.length == 2 && args[1].equalsIgnoreCase("SCHEMA")) useSchema = true; |
||||||
|
|
||||||
// User may include a 2nd argument for the validation method
|
if (dir.isFile()) // Just checking one file.
|
||||||
|
{ |
||||||
useSchema = false; |
parse(null, args[0], useSchema); |
||||||
if(args.length == 2 && args[1].equalsIgnoreCase("SCHEMA")) |
} else if (dir.isDirectory()) // Checking the contents of a directory.
|
||||||
useSchema=true; |
{ |
||||||
|
// Only interested in .xml files.
|
||||||
if (dir.isFile()) // Just checking one file.
|
XMLFileFilter filter = new XMLFileFilter(); |
||||||
{ |
String[] files = dir.list(filter); |
||||||
parse(null,args[0],useSchema); |
for (int i = 0; i < files.length; i++) { |
||||||
} |
parse(dir.toString(), files[i], useSchema); // All the work is done here.
|
||||||
else if (dir.isDirectory()) // Checking the contents of a directory.
|
|
||||||
{ |
System.out.print(buff.toString()); |
||||||
// Only interested in .xml files.
|
buff = new StringBuffer(); |
||||||
XMLFileFilter filter = new XMLFileFilter(); |
|
||||||
String [] files = dir.list(filter); |
} |
||||||
for (int i = 0; i <files.length; i++) |
} else // Command-line argument is no good!
|
||||||
{ |
{ |
||||||
parse(dir.toString(),files[i],useSchema); // All the work is done here.
|
System.out.println(args[0] + " not found!"); |
||||||
|
return; |
||||||
System.out.print(buff.toString()); |
} |
||||||
buff = new StringBuffer(); |
// Provide user with a summary.
|
||||||
|
buff.append("================SUMMARY=============================\n"); |
||||||
} |
if (numXMLFiles > 1) buff.append("Parsed " + numXMLFiles + " .xml files in " + args[0] + ".\n"); |
||||||
} |
if (numValidFiles > 1) |
||||||
else // Command-line argument is no good!
|
buff.append(numValidFiles + " files are valid.\n"); |
||||||
{ |
else if (numValidFiles == 1) buff.append(numValidFiles + " file is valid.\n"); |
||||||
System.out.println(args[0] + " not found!"); |
if (numInvalidFiles > 1) |
||||||
System.exit(1); |
buff.append(numInvalidFiles + " files are not valid.\n"); |
||||||
} |
else if (numInvalidFiles == 1) buff.append(numInvalidFiles + " file is not valid.\n"); |
||||||
// Provide user with a summary.
|
if (numMalformedFiles > 1) |
||||||
buff.append("================SUMMARY=============================\n"); |
buff.append(numMalformedFiles + " files are not well-formed.\n"); |
||||||
if (numXMLFiles > 1) |
else if (numMalformedFiles == 1) buff.append(numMalformedFiles + " file is not well-formed.\n"); |
||||||
buff.append("Parsed " + numXMLFiles + " .xml files in " + args[0] + ".\n"); |
if (numFilesMissingDoctype > 1) |
||||||
if (numValidFiles > 1) |
buff.append(numFilesMissingDoctype + " files do not contain a DOCTYPE declaration.\n"); |
||||||
buff.append( numValidFiles + " files are valid.\n"); |
else if (numFilesMissingDoctype == 1) buff.append(numFilesMissingDoctype + " file does not contain a DOCTYPE declaration.\n"); |
||||||
else if (numValidFiles == 1) |
|
||||||
buff.append( numValidFiles + " file is valid.\n"); |
System.out.print(buff.toString()); |
||||||
if (numInvalidFiles > 1) |
|
||||||
buff.append(numInvalidFiles + " files are not valid.\n"); |
} |
||||||
else if (numInvalidFiles == 1) |
|
||||||
buff.append( numInvalidFiles + " file is not valid.\n"); |
// Parse each XML file.
|
||||||
if (numMalformedFiles > 1) |
void parse(String dir, String filename, boolean useSchema) throws FileNotFoundException, IOException, ParserConfigurationException, SAXException { |
||||||
buff.append(numMalformedFiles + " files are not well-formed.\n"); |
try { |
||||||
else if (numMalformedFiles == 1) |
File f = new File(dir, filename); |
||||||
buff.append( numMalformedFiles + " file is not well-formed.\n"); |
StringBuffer errorBuff = new StringBuffer(); |
||||||
if (numFilesMissingDoctype > 1) |
InputSource input = new InputSource(new FileInputStream(f)); |
||||||
buff.append(numFilesMissingDoctype + " files do not contain a DOCTYPE declaration.\n"); |
// Set systemID so parser can find the dtd with a relative URL in the source document.
|
||||||
else if (numFilesMissingDoctype == 1) |
input.setSystemId(f.toString()); |
||||||
buff.append(numFilesMissingDoctype + " file does not contain a DOCTYPE declaration.\n"); |
|
||||||
|
SAXParserFactory spfact = SAXParserFactory.newInstance(); |
||||||
System.out.print(buff.toString()); |
|
||||||
|
spfact.setValidating(true); |
||||||
} |
spfact.setNamespaceAware(true); |
||||||
|
|
||||||
// Parse each XML file.
|
SAXParser parser = spfact.newSAXParser(); |
||||||
void parse(String dir, String filename,boolean useSchema) |
XMLReader reader = parser.getXMLReader(); |
||||||
throws Exception |
|
||||||
{ |
//Instantiate inner-class error and lexical handler.
|
||||||
try |
Handler handler = new Handler(filename, errorBuff); |
||||||
{ |
reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler); |
||||||
File f = new File(dir, filename); |
if (useSchema) { |
||||||
StringBuffer errorBuff = new StringBuffer(); |
parser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema"); |
||||||
InputSource input = new InputSource(new FileInputStream(f)); |
buff.append("Nutze XML-Schema Validierung\n"); |
||||||
// Set systemID so parser can find the dtd with a relative URL in the source document.
|
} |
||||||
input.setSystemId(f.toString()); |
parser.parse(input, handler); |
||||||
|
if (handler.containsDTD && !handler.errorOrWarning) // valid
|
||||||
SAXParserFactory spfact = SAXParserFactory.newInstance(); |
{ |
||||||
|
buff.append("VALID " + filename + "\n"); |
||||||
spfact.setValidating(true); |
numValidFiles++; |
||||||
spfact.setNamespaceAware(true); |
} else if (handler.containsDTD) // not valid
|
||||||
|
{ |
||||||
SAXParser parser = spfact.newSAXParser(); |
buff.append("NOT VALID " + filename + "\n"); |
||||||
XMLReader reader = parser.getXMLReader(); |
buff.append(errorBuff.toString()); |
||||||
|
numInvalidFiles++; |
||||||
//Instantiate inner-class error and lexical handler.
|
} else // no DOCTYPE to use for validation
|
||||||
Handler handler = new Handler(filename, errorBuff); |
{ |
||||||
reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler); |
if (handler.errorOrWarning) { |
||||||
if(useSchema) |
buff.append("Datei " + filename + " wurde validiert:\n" + errorBuff.toString()); |
||||||
{ |
numInvalidFiles++; |
||||||
parser.setProperty( |
} else { |
||||||
"http://java.sun.com/xml/jaxp/properties/schemaLanguage", |
buff.append("Datei " + filename + " wurde validiert:\n" + errorBuff.toString()); |
||||||
"http://www.w3.org/2001/XMLSchema"); |
numValidFiles++; |
||||||
buff.append("Nutze XML-Schema Validierung\n"); |
|
||||||
} |
} |
||||||
parser.parse(input, handler); |
|
||||||
if (handler.containsDTD && !handler.errorOrWarning) // valid
|
} |
||||||
{ |
} catch (Exception e) // Serious problem!
|
||||||
buff.append("VALID " + filename +"\n"); |
{ |
||||||
numValidFiles++; |
buff.append("NOT WELL-FORMED " + filename + ". " + e.getMessage() + "\n"); |
||||||
} |
numMalformedFiles++; |
||||||
else if (handler.containsDTD) // not valid
|
} finally { |
||||||
{ |
numXMLFiles++; |
||||||
buff.append ("NOT VALID " + filename + "\n"); |
} |
||||||
buff.append(errorBuff.toString()); |
} |
||||||
numInvalidFiles++; |
// Inner classes
|
||||||
} |
|
||||||
else // no DOCTYPE to use for validation
|
// Only interested in parsing .xml files.
|
||||||
{ |
class XMLFileFilter implements FilenameFilter { |
||||||
if(handler.errorOrWarning) |
@Override |
||||||
{ |
public boolean accept(File dir, String fileName) { |
||||||
buff.append("Datei " + filename +" wurde validiert:\n"+errorBuff.toString()); |
return fileName.toLowerCase().endsWith(".xml") && new File(dir.toString(), fileName).isFile(); |
||||||
numInvalidFiles++; |
} |
||||||
} |
} |
||||||
else |
|
||||||
{ |
// Catch any errors or warnings, and verify presence of doctype statement.
|
||||||
buff.append("Datei " + filename +" wurde validiert:\n"+errorBuff.toString()); |
class Handler extends DefaultHandler implements LexicalHandler { |
||||||
numValidFiles++; |
boolean errorOrWarning; |
||||||
|
|
||||||
} |
boolean containsDTD; |
||||||
|
|
||||||
} |
String sourceFile; |
||||||
} |
|
||||||
catch (Exception e) // Serious problem!
|
StringBuffer errorBuff; |
||||||
{ |
|
||||||
buff.append("NOT WELL-FORMED " + filename + ". " + e.getMessage() + "\n"); |
Handler(String sourceFile, StringBuffer errorBuff) { |
||||||
numMalformedFiles++; |
super(); |
||||||
throw new Exception(e); |
this.sourceFile = sourceFile; |
||||||
} |
this.errorBuff = errorBuff; |
||||||
finally |
errorOrWarning = false; |
||||||
{ |
containsDTD = false; |
||||||
numXMLFiles++; |
} |
||||||
} |
|
||||||
} |
@Override |
||||||
// Inner classes
|
public void error(SAXParseException exc) { |
||||||
|
errorBuff.append(sourceFile + " Error: " + exc.getMessage() + "\n"); |
||||||
// Only interested in parsing .xml files.
|
errorOrWarning = true; |
||||||
class XMLFileFilter implements FilenameFilter |
} |
||||||
{ |
|
||||||
public boolean accept(File dir, String fileName) |
@Override |
||||||
{ |
public void warning(SAXParseException exc) { |
||||||
return fileName.toLowerCase().endsWith(".xml") && new File(dir.toString(),fileName).isFile(); |
errorBuff.append(sourceFile + " Warning:" + exc.getMessage() + "\n"); |
||||||
} |
errorOrWarning = true; |
||||||
} |
} |
||||||
|
|
||||||
// Catch any errors or warnings, and verify presence of doctype statement.
|
// LexicalHandler methods; all no-op except startDTD().
|
||||||
class Handler extends DefaultHandler implements LexicalHandler |
|
||||||
{ |
// Set containsDTD to true when startDTD event occurs.
|
||||||
boolean errorOrWarning; |
@Override |
||||||
boolean containsDTD; |
public void startDTD(String name, String publicId, String systemId) throws SAXException { |
||||||
String sourceFile; |
containsDTD = true; |
||||||
StringBuffer errorBuff; |
} |
||||||
|
|
||||||
Handler(String sourceFile, StringBuffer errorBuff) |
@Override |
||||||
{ |
public void endDTD() throws SAXException { |
||||||
super(); |
} |
||||||
this.sourceFile = sourceFile; |
|
||||||
this.errorBuff = errorBuff; |
@Override |
||||||
errorOrWarning = false; |
public void startEntity(String name) throws SAXException { |
||||||
containsDTD = false; |
} |
||||||
} |
|
||||||
|
@Override |
||||||
public void error(SAXParseException exc) |
public void endEntity(String name) throws SAXException { |
||||||
{ |
} |
||||||
errorBuff.append(sourceFile + " Error: " + exc.getMessage()+ "\n"); |
|
||||||
errorOrWarning = true; |
@Override |
||||||
} |
public void startCDATA() throws SAXException { |
||||||
public void warning(SAXParseException exc) |
} |
||||||
{ |
|
||||||
errorBuff.append(sourceFile + " Warning:" + exc.getMessage()+ "\n"); |
@Override |
||||||
errorOrWarning = true; |
public void endCDATA() throws SAXException { |
||||||
} |
} |
||||||
|
|
||||||
// LexicalHandler methods; all no-op except startDTD().
|
@Override |
||||||
|
public void comment(char ch[], int start, int length) throws SAXException { |
||||||
// Set containsDTD to true when startDTD event occurs.
|
} |
||||||
public void startDTD (String name, String publicId, String systemId) |
} |
||||||
throws SAXException |
} |
||||||
{ |
|
||||||
containsDTD = true; |
|
||||||
} |
|
||||||
|
|
||||||
public void endDTD () throws SAXException |
|
||||||
{} |
|
||||||
|
|
||||||
public void startEntity (String name) throws SAXException |
|
||||||
{} |
|
||||||
|
|
||||||
public void endEntity (String name) throws SAXException |
|
||||||
{} |
|
||||||
|
|
||||||
public void startCDATA () throws SAXException |
|
||||||
{} |
|
||||||
|
|
||||||
public void endCDATA () throws SAXException |
|
||||||
{} |
|
||||||
|
|
||||||
public void comment (char ch[], int start, int length) throws SAXException |
|
||||||
{} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,242 +1,214 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
|
|
||||||
import java.io.File; |
import java.io.File; |
||||||
import java.io.IOException; |
import java.io.IOException; |
||||||
import java.sql.Connection; |
import java.sql.Connection; |
||||||
import java.sql.ResultSet; |
import java.sql.ResultSet; |
||||||
import java.sql.SQLException; |
import java.sql.SQLException; |
||||||
import java.sql.Statement; |
import java.sql.Statement; |
||||||
import java.util.Date; |
import java.util.Date; |
||||||
import java.util.Iterator; |
import java.util.Iterator; |
||||||
import java.util.LinkedList; |
import java.util.LinkedList; |
||||||
import java.util.List; |
import java.util.List; |
||||||
import java.util.Vector; |
import java.util.Vector; |
||||||
|
|
||||||
import org.w3c.dom.Document; |
import org.apache.commons.io.FileUtils; |
||||||
import org.w3c.dom.Node; |
import org.w3c.dom.Document; |
||||||
import org.w3c.dom.NodeList; |
import org.w3c.dom.Node; |
||||||
import org.xml.sax.SAXException; |
import org.w3c.dom.NodeList; |
||||||
|
import org.xml.sax.SAXException; |
||||||
import com.meterware.httpunit.GetMethodWebRequest; |
|
||||||
import com.meterware.httpunit.WebConversation; |
import com.meterware.httpunit.GetMethodWebRequest; |
||||||
import com.meterware.httpunit.WebRequest; |
import com.meterware.httpunit.WebConversation; |
||||||
import com.meterware.httpunit.WebResponse; |
import com.meterware.httpunit.WebRequest; |
||||||
import com.meterware.httpunit.WebTable; |
import com.meterware.httpunit.WebResponse; |
||||||
|
import com.meterware.httpunit.WebTable; |
||||||
import de.memtext.db.ConnectionCreator; |
|
||||||
import de.memtext.util.EqualsUtil; |
import de.memtext.db.ConnectionCreator; |
||||||
import de.memtext.util.StringUtils; |
import de.memtext.util.EqualsUtil; |
||||||
import de.memtext.util.XMLUtils; |
import de.memtext.util.XMLUtils; |
||||||
|
|
||||||
public class SxXmlTester { |
public class SxXmlTester { |
||||||
Document document; |
Document document; |
||||||
List webserverlist = new LinkedList(); |
|
||||||
List dbserverConnections = new LinkedList(); |
List webserverlist = new LinkedList(); |
||||||
StringBuffer errors = new StringBuffer(); |
|
||||||
|
List dbserverConnections = new LinkedList(); |
||||||
private void readdbServers() throws IOException, SQLException, ClassNotFoundException { |
|
||||||
NodeList nl = document.getElementsByTagName("dbserver"); |
StringBuffer errors = new StringBuffer(); |
||||||
|
|
||||||
for (int i = 0; i < nl.getLength(); i++) { |
private void readdbServers() throws IOException, SQLException, ClassNotFoundException { |
||||||
Node serverNode = (Node) nl.item(i); |
NodeList nl = document.getElementsByTagName("dbserver"); |
||||||
Connection con=ConnectionCreator.getConnectionCryptPassword(XMLUtils.getAttribValue(serverNode, "db_properties"), |
|
||||||
"driverName", "connectionURL", "connectionName", |
for (int i = 0; i < nl.getLength(); i++) { |
||||||
"connectionPassword"); |
Node serverNode = (Node) nl.item(i); |
||||||
System.out.println("Found 1 db.properties node"); |
Connection con = ConnectionCreator.getConnectionCryptPassword(XMLUtils.getAttribValue(serverNode, "db_properties"), "driverName", "connectionURL", "connectionName", |
||||||
dbserverConnections.add(con); |
"connectionPassword"); |
||||||
} |
System.out.println("Found 1 db.properties node"); |
||||||
} |
dbserverConnections.add(con); |
||||||
|
} |
||||||
private void readWebServers() { |
} |
||||||
NodeList nl = document.getElementsByTagName("webserver"); |
|
||||||
|
private void readWebServers() { |
||||||
for (int i = 0; i < nl.getLength(); i++) { |
NodeList nl = document.getElementsByTagName("webserver"); |
||||||
Node serverNode = (Node) nl.item(i); |
|
||||||
webserverlist.add(XMLUtils.getAttribValue(serverNode, "url")); |
for (int i = 0; i < nl.getLength(); i++) { |
||||||
System.out.println("Found 1 webserver node"); |
Node serverNode = (Node) nl.item(i); |
||||||
} |
webserverlist.add(XMLUtils.getAttribValue(serverNode, "url")); |
||||||
} |
System.out.println("Found 1 webserver node"); |
||||||
|
} |
||||||
private void runDbTests() throws IOException, SQLException, ClassNotFoundException |
} |
||||||
{ |
|
||||||
readdbServers(); |
private void runDbTests() throws IOException, SQLException, ClassNotFoundException { |
||||||
NodeList nl = document.getElementsByTagName("dbtest"); |
readdbServers(); |
||||||
for (int i = 0; i < nl.getLength(); i++) { |
NodeList nl = document.getElementsByTagName("dbtest"); |
||||||
Node testNode = (Node) nl.item(i); |
for (int i = 0; i < nl.getLength(); i++) { |
||||||
|
Node testNode = (Node) nl.item(i); |
||||||
String name = XMLUtils.getAttribValue(testNode, "name"); |
|
||||||
System.out.println("Db-Testnr "+(i+1)+" :"+name); |
String name = XMLUtils.getAttribValue(testNode, "name"); |
||||||
String sql = XMLUtils.getAttribValue(testNode, "sql"); |
System.out.println("Db-Testnr " + (i + 1) + " :" + name); |
||||||
for (Iterator it = dbserverConnections.iterator(); it.hasNext();) { |
String sql = XMLUtils.getAttribValue(testNode, "sql"); |
||||||
Connection con= (Connection) it.next(); |
for (Iterator it = dbserverConnections.iterator(); it.hasNext();) { |
||||||
Statement stm=con.createStatement(); |
Connection con = (Connection) it.next(); |
||||||
ResultSet rs=stm.executeQuery(sql); |
Statement stm = con.createStatement(); |
||||||
Vector result=new Vector(); |
ResultSet rs = stm.executeQuery(sql); |
||||||
int colcount=0; |
Vector result = new Vector(); |
||||||
while (rs.next()) |
int colcount = 0; |
||||||
{ |
while (rs.next()) { |
||||||
colcount=rs.getMetaData().getColumnCount(); |
colcount = rs.getMetaData().getColumnCount(); |
||||||
Vector row=new Vector(); |
Vector row = new Vector(); |
||||||
for (int col=1;col<=colcount;col++) |
for (int col = 1; col <= colcount; col++) { |
||||||
{ |
row.add(rs.getObject(col)); |
||||||
row.add(rs.getObject(col)); |
} |
||||||
} |
result.add(row); |
||||||
result.add(row); |
} |
||||||
} |
|
||||||
|
|
||||||
|
for (Iterator it2 = XMLUtils.getChildNodeIterator(testNode); it2.hasNext();) { |
||||||
for (Iterator it2 = XMLUtils.getChildNodeIterator(testNode); it2 |
Node childNode = (Node) it2.next(); |
||||||
.hasNext();) { |
if (childNode.getNodeName().equals("valuetest")) { |
||||||
Node childNode = (Node) it2.next(); |
String rowStr = XMLUtils.getAttribValue(childNode, "row"); |
||||||
if (childNode.getNodeName().equals("valuetest")) { |
int row = Integer.parseInt(rowStr); |
||||||
String rowStr = XMLUtils.getAttribValue(childNode, |
String colStr = XMLUtils.getAttribValue(childNode, "col"); |
||||||
"row"); |
int col = Integer.parseInt(colStr); |
||||||
int row = Integer.parseInt(rowStr); |
String val = XMLUtils.getAttribValue(childNode, "val"); |
||||||
String colStr = XMLUtils.getAttribValue(childNode, |
|
||||||
"col"); |
if (col > colcount) { |
||||||
int col = Integer.parseInt(colStr); |
errors.append("Test " + name + " Versuch Spalte " + col + " zu lesen, Tabelle hat nur " + colcount + " Spalten\n"); |
||||||
String val = XMLUtils.getAttribValue(childNode, "val"); |
continue; |
||||||
|
} |
||||||
if (col>colcount) |
if (row > result.size()) { |
||||||
{ |
errors.append("Test " + name + " Versuch Zeile " + row + " zu lesen, ResultSet hat nur " + result.size() + " Zeilen\n"); |
||||||
errors.append("Test " + name |
continue; |
||||||
+ " Versuch Spalte "+col+" zu lesen, Tabelle hat nur " + colcount+" Spalten\n" ); |
} |
||||||
continue; |
Vector arow = (Vector) result.get(row - 1); |
||||||
} |
String gefunden = arow.get(col - 1).toString(); |
||||||
if (row>result.size()) |
|
||||||
{ |
if (!EqualsUtil.areEqual(val, gefunden)) { |
||||||
errors.append("Test " + name |
|
||||||
+ " Versuch Zeile "+row+" zu lesen, ResultSet hat nur " + result.size()+" Zeilen\n" ); |
errors.append("Test " + name + " Falscher Wert Zeile " + row + " Spalte " + col + " erwartet:" + val + " gefunden:" + gefunden + "\n(sql:" + sql |
||||||
continue; |
+ "\n\n"); |
||||||
} |
} |
||||||
Vector arow=(Vector)result.get(row-1); |
} |
||||||
String gefunden = arow.get(col - 1).toString() |
} |
||||||
; |
|
||||||
|
} |
||||||
if (!EqualsUtil.areEqual(val, gefunden)) { |
} |
||||||
|
} |
||||||
errors.append("Test " + name |
|
||||||
+ " Falscher Wert Zeile " + row |
public void go(String args[]) throws SAXException, IOException, SQLException, ClassNotFoundException { |
||||||
+ " Spalte " + col + " erwartet:" + val |
document = XMLUtils.buildDocument(new File(args[0])); |
||||||
+ " gefunden:" + gefunden + "\n(sql:"+sql+"\n\n"); |
runDbTests(); |
||||||
} |
runWebtests(); |
||||||
} |
if (errors.length() > 0) { |
||||||
} |
System.out.println("Es sind Fehler aufgetaucht siehe output-errors.txt"); |
||||||
|
FileUtils.writeStringToFile(new File("output-errors.txt"), new Date() + "\n" + errors.toString()); |
||||||
} |
|
||||||
} |
} else { |
||||||
} |
System.out.println("Keine Fehler aufgefallen"); |
||||||
public void go(String args[]) throws SAXException, IOException, SQLException, ClassNotFoundException { |
} |
||||||
XMLUtils.getExceptionHandler().setWithGui(false); |
} |
||||||
document = XMLUtils.buildDocument(new File(args[0])); |
|
||||||
runDbTests(); |
|
||||||
runWebtests(); |
private void runWebtests() throws SAXException, IOException { |
||||||
if (errors.length()>0) |
readWebServers(); |
||||||
{ |
|
||||||
System.out.println("Es sind Fehler aufgetaucht siehe output-errors.txt"); |
NodeList nl = document.getElementsByTagName("webtest"); |
||||||
StringUtils.write(new File("output-errors.txt"),new Date()+"\n"+errors.toString()); |
WebConversation wc = new WebConversation(); |
||||||
|
for (int i = 0; i < nl.getLength(); i++) { |
||||||
} |
Node testNode = (Node) nl.item(i); |
||||||
else |
|
||||||
{ |
String name = XMLUtils.getAttribValue(testNode, "name"); |
||||||
System.out.println("Keine Fehler aufgefallen"); |
System.out.println("Webserver-Testnr " + (i + 1) + " :" + name); |
||||||
} |
String params = XMLUtils.getChildNodeValue(testNode, "params"); |
||||||
} |
for (Iterator it = webserverlist.iterator(); it.hasNext();) { |
||||||
|
String serverUrl = (String) it.next(); |
||||||
|
serverUrl += params; |
||||||
private void runWebtests() throws SAXException, IOException { |
|
||||||
readWebServers(); |
WebRequest req = new GetMethodWebRequest(serverUrl); |
||||||
|
WebResponse resp; |
||||||
NodeList nl = document.getElementsByTagName("webtest"); |
try { |
||||||
WebConversation wc = new WebConversation(); |
resp = wc.getResponse(req); |
||||||
for (int i = 0; i < nl.getLength(); i++) { |
} catch (IOException e) { |
||||||
Node testNode = (Node) nl.item(i); |
System.err.println("Aufruf fehlgeschlagen von " + serverUrl); |
||||||
|
throw e; |
||||||
String name = XMLUtils.getAttribValue(testNode, "name"); |
} |
||||||
System.out.println("Webserver-Testnr "+(i+1)+" :"+name); |
FileUtils.writeStringToFile(new File("output_" + name + ".htm"), resp.getText()); |
||||||
String params = XMLUtils.getChildNodeValue(testNode, "params"); |
if (resp.getTables().length < 2) { |
||||||
for (Iterator it = webserverlist.iterator(); it.hasNext();) { |
errors.append("Test " + name + " Keine Ergebnistabelle geliefert\n "); |
||||||
String serverUrl = (String) it.next(); |
continue; |
||||||
serverUrl += params; |
|
||||||
|
} |
||||||
WebRequest req = new GetMethodWebRequest(serverUrl); |
for (Iterator it2 = XMLUtils.getChildNodeIterator(testNode); it2.hasNext();) { |
||||||
WebResponse resp; |
Node childNode = (Node) it2.next(); |
||||||
try { |
if (childNode.getNodeName().equals("valuetest")) { |
||||||
resp = wc.getResponse(req); |
String rowStr = XMLUtils.getAttribValue(childNode, "row"); |
||||||
} catch (IOException e) { |
int row = Integer.parseInt(rowStr); |
||||||
System.err.println("Aufruf fehlgeschlagen von "+serverUrl); |
String colStr = XMLUtils.getAttribValue(childNode, "col"); |
||||||
throw e; |
int col = Integer.parseInt(colStr); |
||||||
} |
String val = XMLUtils.getAttribValue(childNode, "val"); |
||||||
StringUtils.write(new File("output_" + name |
WebTable table = resp.getTables()[1]; |
||||||
+ ".htm"), resp.getText()); |
if (col > table.getColumnCount()) { |
||||||
if (resp.getTables().length <2) { |
FileUtils.writeStringToFile(new File("output_" + name + ".htm"), resp.getText()); |
||||||
errors.append("Test " + name |
errors.append("Test " + name + " Versuch Spalte " + col + " zu lesen, Tabelle hat nur " + table.getColumnCount() + " Spalten\n"); |
||||||
+ " Keine Ergebnistabelle geliefert\n "); |
continue; |
||||||
continue; |
} |
||||||
|
if (row > table.getRowCount()) { |
||||||
} |
FileUtils.writeStringToFile(new File("output_" + name + ".htm"), resp.getText()); |
||||||
for (Iterator it2 = XMLUtils.getChildNodeIterator(testNode); it2 |
errors.append("Test " + name + " Versuch Zeile " + row + " zu lesen, Tabelle hat nur " + table.getRowCount() + " Zeilen\n"); |
||||||
.hasNext();) { |
continue; |
||||||
Node childNode = (Node) it2.next(); |
} |
||||||
if (childNode.getNodeName().equals("valuetest")) { |
|
||||||
String rowStr = XMLUtils.getAttribValue(childNode, |
String gefunden = table.getTableCell(row - 1, col - 1).getText(); |
||||||
"row"); |
|
||||||
int row = Integer.parseInt(rowStr); |
if (!EqualsUtil.areEqual(val, gefunden)) { |
||||||
String colStr = XMLUtils.getAttribValue(childNode, |
|
||||||
"col"); |
errors.append("Test " + name + " Falscher Wert Zeile " + row + " Spalte " + col + " erwartet:" + val + " gefunden:" + gefunden + "\n(url:" + serverUrl |
||||||
int col = Integer.parseInt(colStr); |
+ "\n\n"); |
||||||
String val = XMLUtils.getAttribValue(childNode, "val"); |
} |
||||||
WebTable table = resp.getTables()[1]; |
} |
||||||
if (col>table.getColumnCount()) |
} |
||||||
{ |
|
||||||
StringUtils.write(new File("output_" + name |
} |
||||||
+ ".htm"), resp.getText()); |
} |
||||||
errors.append("Test " + name |
} |
||||||
+ " Versuch Spalte "+col+" zu lesen, Tabelle hat nur " + table.getColumnCount()+" Spalten\n" ); |
|
||||||
continue; |
public static void main(String[] args) { |
||||||
} |
|
||||||
if (row>table.getRowCount()) |
System.out.println(""); |
||||||
{ |
if (args.length != 1) { |
||||||
StringUtils.write(new File("output_" + name |
System.err.println("usage SxXmlTester test.xml"); |
||||||
+ ".htm"), resp.getText()); |
System.exit(-1); |
||||||
errors.append("Test " + name |
} |
||||||
+ " Versuch Zeile "+row+" zu lesen, Tabelle hat nur " + table.getRowCount()+" Zeilen\n" ); |
try { |
||||||
continue; |
new SxXmlTester().go(args); |
||||||
} |
} catch (Exception e) { |
||||||
|
System.out.println(e); |
||||||
String gefunden = table.getTableCell(row - 1, col - 1) |
e.printStackTrace(); |
||||||
.getText(); |
|
||||||
|
} |
||||||
if (!EqualsUtil.areEqual(val, gefunden)) { |
} |
||||||
|
// junit.textui.TestRunner.run(AutoTest.class);
|
||||||
errors.append("Test " + name |
} |
||||||
+ " Falscher Wert Zeile " + row |
|
||||||
+ " Spalte " + col + " erwartet:" + val |
//Created on 27.04.2006 at 10:25:34
|
||||||
+ " gefunden:" + gefunden + "\n(url:"+serverUrl+"\n\n"); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static void main(String[] args) { |
|
||||||
|
|
||||||
System.out.println(""); |
|
||||||
if (args.length != 1) { |
|
||||||
System.err.println("usage SxXmlTester test.xml"); |
|
||||||
System.exit(-1); |
|
||||||
} |
|
||||||
try { |
|
||||||
new SxXmlTester().go(args); |
|
||||||
} catch (Exception e) { |
|
||||||
System.out.println(e); |
|
||||||
e.printStackTrace(); |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
// junit.textui.TestRunner.run(AutoTest.class);
|
|
||||||
} |
|
||||||
|
|
||||||
//Created on 27.04.2006 at 10:25:34
|
|
||||||
|
|||||||
@ -1,85 +1,86 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
import de.superx.common.FileToTableUploader; |
import de.superx.common.FileToTableUploader; |
||||||
import de.memtext.util.GetOpts; |
import de.memtext.util.GetOpts; |
||||||
|
import de.memtext.util.GetOpts.Options; |
||||||
/* |
|
||||||
* @author Daniel Quathamer Projektgruppe SuperX |
/* |
||||||
* upload_records.java |
* @author Daniel Quathamer Projektgruppe SuperX |
||||||
* Dieses Javaprogramm lädt Inhalte einer Datei in eine Tabelle hoch") |
* upload_records.java |
||||||
* DQ 5.1.2006 Upload vom XML-Dateien möglich |
* Dieses Javaprogramm lädt Inhalte einer Datei in eine Tabelle hoch") |
||||||
* |
* DQ 5.1.2006 Upload vom XML-Dateien möglich |
||||||
*/ |
* |
||||||
|
*/ |
||||||
public class UploadRecords { |
|
||||||
private static String usage = |
public class UploadRecords { |
||||||
"-------------------------------------\n" |
private static String usage = |
||||||
+ "Gebrauch: java de.superx.bin.UploadRecords \n-dbproperties:<Pfad zu db.properties> \n" |
"-------------------------------------\n" |
||||||
+ "-table:<Tabellenname> \n-unl:<Dateipfad Quelldatei>(optional, default ist Tabellenname.unl) \n-delim:<delimiter>(optional, default ist ^) \n-header:<true|false>(optional, mit Feldüberschriften, default ist false)\n" |
+ "Gebrauch: java de.superx.bin.UploadRecords \n-dbproperties:<Pfad zu db.properties> \n" |
||||||
+ "-mode:<stop|exclude-row>(optional, default is stop) #Bei Fehlerhaften Daten kann das Hochladen gestoppt werden, oder der Datensatz wird übersprungen" |
+ "-table:<Tabellenname> \n-unl:<Dateipfad Quelldatei>(optional, default ist Tabellenname.unl) \n-delim:<delimiter>(optional, default ist ^) \n-header:<true|false>(optional, mit Feldüberschriften, default ist false)\n" |
||||||
+ "\n-inserts:<false|simple|batch>(optional, default is false) #Bei -inserts:simple und batch werden Die Rohdaten in Insert-sql-Statements übersetzt (nur für Debugging-Zwecke, sehr langsam. Der Modus exclude-field ist darüberhinaus nicht anwendbar)" |
+ "-mode:<stop|exclude-row>(optional, default is stop) #Bei Fehlerhaften Daten kann das Hochladen gestoppt werden, oder der Datensatz wird übersprungen" |
||||||
+ "\n-encoding:<utf8,ISO-8859-1, default ist System.file.encoding>" |
+ "\n-inserts:<false|simple|batch>(optional, default is false) #Bei -inserts:simple und batch werden Die Rohdaten in Insert-sql-Statements übersetzt (nur für Debugging-Zwecke, sehr langsam. Der Modus exclude-field ist darüberhinaus nicht anwendbar)" |
||||||
+ "\n---------------------------------------------------"; |
+ "\n-encoding:<utf8,ISO-8859-1, default ist System.file.encoding>" |
||||||
|
+ "\n---------------------------------------------------"; |
||||||
public static void main(String args[]) { |
|
||||||
try { |
public static void main(String args[]) { |
||||||
GetOpts.setOpts(args); |
try { |
||||||
String isdrin = |
GetOpts.setOpts(args); |
||||||
GetOpts.isAllRequiredOptionsPresent("-dbproperties,-table,-unl"); |
String isdrin = |
||||||
if (isdrin != null) { |
GetOpts.isAllRequiredOptionsPresent(new Options[] {Options.opt_dbprops,Options.opt_table,Options.opt_unl}); |
||||||
System.err.println("Folgende Optionen fehlen: " + isdrin); |
if (isdrin != null) { |
||||||
System.err.println(usage); |
System.err.println("Folgende Optionen fehlen: " + isdrin); |
||||||
System.exit(1); |
System.err.println(usage); |
||||||
} |
System.exit(1); |
||||||
FileToTableUploader myUploader=new FileToTableUploader(); |
} |
||||||
//GetOpts myOpts=new GetOpts();
|
FileToTableUploader myUploader=new FileToTableUploader(); |
||||||
if (GetOpts.isPresent("-dbproperties")) |
//GetOpts myOpts=new GetOpts();
|
||||||
myUploader.setDbpropfile(GetOpts.getValue("-dbproperties")); |
if (GetOpts.isPresent(Options.opt_dbprops)) |
||||||
if (GetOpts.isPresent("-informat")) |
myUploader.setDbpropfile(GetOpts.getValue(Options.opt_dbprops)); |
||||||
myUploader.setInFormat(GetOpts.getValue("-informat")); |
if (GetOpts.isPresent(Options.opt_inFormat)) |
||||||
if (GetOpts.isPresent("-table")) |
myUploader.setInFormat(GetOpts.getValue(Options.opt_inFormat)); |
||||||
myUploader.setTargetTable( GetOpts.getValue("-table")); |
if (GetOpts.isPresent(Options.opt_table)) |
||||||
|
myUploader.setTargetTable( GetOpts.getValue(Options.opt_table)); |
||||||
if (GetOpts.isPresent("-unl")) |
|
||||||
myUploader.setSrcFile(GetOpts.getValue("-unl")); |
if (GetOpts.isPresent(Options.opt_unl)) |
||||||
else |
myUploader.setSrcFile(GetOpts.getValue(Options.opt_unl)); |
||||||
myUploader.setSrcFile(myUploader.getTargetTable() + ".unl"); |
else |
||||||
if (GetOpts.isPresent("-header")) |
myUploader.setSrcFile(myUploader.getTargetTable() + ".unl"); |
||||||
myUploader.setHeader(GetOpts.getValue("-header").equalsIgnoreCase("true")?true:false); |
if (GetOpts.isPresent(Options.opt_header)) |
||||||
if (GetOpts.isPresent("-delim")) |
myUploader.setHeader(GetOpts.getValue(Options.opt_header).equalsIgnoreCase("true")?true:false); |
||||||
myUploader.setDelim(GetOpts.getValue("-delim")); |
if (GetOpts.isPresent(Options.opt_delim)) |
||||||
if (GetOpts.isPresent("-encoding")) |
myUploader.setDelim(GetOpts.getValue(Options.opt_delim)); |
||||||
{ |
if (GetOpts.isPresent(Options.opt_encoding)) |
||||||
String encodingParam=GetOpts.getValue("-encoding"); |
{ |
||||||
|
String encodingParam=GetOpts.getValue(Options.opt_encoding); |
||||||
if(encodingParam != null && !encodingParam.equals("") ) |
|
||||||
myUploader.setEncoding(encodingParam); |
if(encodingParam != null && !encodingParam.equals("") ) |
||||||
} |
myUploader.setEncoding(encodingParam); |
||||||
else |
} |
||||||
myUploader.setEncoding(System.getProperty("file.encoding")); |
else |
||||||
if (GetOpts.isPresent("-mode")) { |
myUploader.setEncoding(System.getProperty("file.encoding")); |
||||||
myUploader.setMode(GetOpts.getValue("-mode").toLowerCase()); |
if (GetOpts.isPresent(Options.opt_mode)) { |
||||||
|
myUploader.setMode(GetOpts.getValue(Options.opt_mode).toLowerCase()); |
||||||
} |
|
||||||
if (GetOpts.isPresent("-inserts")) |
} |
||||||
myUploader.setInserts(GetOpts.getValue("-inserts")); |
if (GetOpts.isPresent(Options.opt_inserts)) |
||||||
long jetzt = new java.util.Date().getTime() ; |
myUploader.setInserts(GetOpts.getValue(Options.opt_inserts)); |
||||||
myUploader.setUploadConnection(myUploader.getConnection(null,myUploader.getDbpropfile())); |
long jetzt = new java.util.Date().getTime() ; |
||||||
String protokoll=myUploader.uploadFile(); |
myUploader.setUploadConnection(myUploader.getConnection(null,myUploader.getDbpropfile())); |
||||||
long erstrecht = new java.util.Date().getTime() ; |
String protokoll=myUploader.uploadFile(); |
||||||
System.out.println(myUploader.numberOfRows+" lines loaded"); |
long erstrecht = new java.util.Date().getTime() ; |
||||||
System.out.println("File "+myUploader.getSrcFile() +" uploaded"); |
System.out.println(myUploader.numberOfRows+" lines loaded"); |
||||||
if(protokoll.equals("")) |
System.out.println("File "+myUploader.getSrcFile() +" uploaded"); |
||||||
protokoll= " in "+(erstrecht-jetzt)/1000 +" Sec."; |
if(protokoll.equals("")) |
||||||
System.out.println(protokoll); |
protokoll= " in "+(erstrecht-jetzt)/1000 +" Sec."; |
||||||
|
System.out.println(protokoll); |
||||||
} catch (Exception ex) { |
|
||||||
System.err.println("Upload fehlgeschlagen: " + ex); |
} catch (Exception ex) { |
||||||
System.exit(1); |
System.err.println("Upload fehlgeschlagen: " + ex); |
||||||
} |
System.exit(1); |
||||||
} |
} |
||||||
} |
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,97 +1,110 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
|
|
||||||
import java.io.BufferedReader; |
import java.io.BufferedWriter; |
||||||
import java.io.ByteArrayInputStream; |
import java.io.ByteArrayOutputStream; |
||||||
import java.io.File; |
import java.io.File; |
||||||
import java.io.FileReader; |
import java.io.FileWriter; |
||||||
import java.io.IOException; |
import java.util.logging.Logger; |
||||||
import java.io.StringWriter; |
|
||||||
import java.nio.charset.Charset; |
|
||||||
|
|
||||||
import javax.xml.soap.MessageFactory; |
|
||||||
import javax.xml.soap.MimeHeaders; |
|
||||||
import javax.xml.soap.SOAPConnection; |
import javax.xml.soap.SOAPConnection; |
||||||
import javax.xml.soap.SOAPConnectionFactory; |
import javax.xml.soap.SOAPConnectionFactory; |
||||||
import javax.xml.soap.SOAPException; |
|
||||||
import javax.xml.soap.SOAPMessage; |
import javax.xml.soap.SOAPMessage; |
||||||
import javax.xml.transform.OutputKeys; |
|
||||||
import javax.xml.transform.Transformer; |
import de.memtext.util.LogUtils; |
||||||
import javax.xml.transform.TransformerFactory; |
|
||||||
import javax.xml.transform.dom.DOMSource; |
|
||||||
import javax.xml.transform.stream.StreamResult; |
|
||||||
|
|
||||||
public class WebserviceChecker extends AbstractWebserviceClient { |
public class WebserviceChecker extends AbstractWebserviceClient { |
||||||
public static String[] args; |
public static String[] args; |
||||||
public void run() |
private static final Logger log = Logger.getLogger("wc"); |
||||||
{ |
|
||||||
|
public void run() { |
||||||
|
String testparam = ""; |
||||||
|
if (args.length > 3) |
||||||
|
testparam = args[3]; |
||||||
|
if (testparam.equals("multipletests")) |
||||||
|
multipletests(); |
||||||
|
else { |
||||||
|
singlerun(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void singlerun() { |
||||||
|
SOAPMessage soapResponse = null; |
||||||
try { |
try { |
||||||
// Create SOAP Connection
|
// Create SOAP Connection
|
||||||
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory |
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance(); |
||||||
.newInstance(); |
SOAPConnection soapConnection = soapConnectionFactory.createConnection(); |
||||||
SOAPConnection soapConnection = soapConnectionFactory |
|
||||||
.createConnection(); |
|
||||||
|
|
||||||
// Send SOAP Message to SOAP Server
|
// Send SOAP Message to SOAP Server
|
||||||
String url = readFile(new File(args[1])); |
StringBuffer url = readFile(new File(args[1])); |
||||||
|
|
||||||
SOAPMessage sr = getSoapMessageFromString(readFile(new File(args[0]))); |
SOAPMessage sr = getSoapMessageFromString(readFile(new File(args[0])).toString()); |
||||||
sr.getMimeHeaders().addHeader("SOAPAction", |
|
||||||
"http://sap.com/xi/WebService/soap1.1"); |
|
||||||
|
|
||||||
SOAPMessage soapResponse = soapConnection.call(sr, url); |
addAuthentification(sr); |
||||||
|
sr.getMimeHeaders().addHeader("SOAPAction", "http://sap.com/xi/WebService/soap1.1"); |
||||||
|
soapResponse = soapConnection.call(sr, adaptURL(url.toString())); |
||||||
|
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
||||||
Transformer transformer = TransformerFactory.newInstance() |
soapResponse.writeTo(out); |
||||||
.newTransformer(); |
String strMsg = new String(out.toByteArray()); |
||||||
// optional indenting
|
|
||||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); |
|
||||||
transformer.setOutputProperty( |
|
||||||
"{http://xml.apache.org/xslt}indent-amount", "2"); |
|
||||||
|
|
||||||
transformer.transform(new DOMSource(soapResponse.getSOAPPart()), |
/** |
||||||
new StreamResult(new File(args[2]))); |
* old code problem with namespace when using OpenJDK 15 Transformer transformer |
||||||
|
* = TransformerFactory.newInstance() .newTransformer(); |
||||||
|
* |
||||||
|
* // optional indenting transformer.setOutputProperty(OutputKeys.INDENT,
|
||||||
|
* "yes"); transformer.setOutputProperty( |
||||||
|
* "{http://xml.apache.org/xslt}indent-amount", "2"); //new
|
||||||
|
* DOMSource(soapResponse.getSOAPPart(). |
||||||
|
* |
||||||
|
* transformer.transform(new DOMSource(soapResponse.getSOAPPart()), new |
||||||
|
* StreamResult(new File(args[2]))); |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
BufferedWriter writer = new BufferedWriter(new FileWriter(args[2])); |
||||||
|
writer.write(format(strMsg)); |
||||||
|
|
||||||
|
writer.close(); |
||||||
soapConnection.close(); |
soapConnection.close(); |
||||||
} catch (Exception e) { |
} catch (Exception e) { |
||||||
|
System.out.println("Es ist ein Fehler aufgetreten: " + e); |
||||||
|
try { |
||||||
|
System.out.println(soapResponse.getSOAPPart().getChildNodes().item(0)); |
||||||
|
} catch (Exception e1) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void multipletests() { |
||||||
|
System.out.println("Versuche ggfs. mehrfach aufzurufen"); |
||||||
|
try { |
||||||
|
LogUtils.initRawFileDateTime("wc", "WebserviceClient.log", 100000, 1, true, false); |
||||||
|
StringBuffer url = readFile(new File(args[1])); |
||||||
|
File f = createSoapFile(readFile(new File(args[0])).toString(), adaptURL(url.toString())); |
||||||
|
System.out.println("Outfile: " + f); |
||||||
|
} catch (Exception e) { |
||||||
|
|
||||||
e.printStackTrace(); |
e.printStackTrace(); |
||||||
} |
} |
||||||
|
|
||||||
} |
} |
||||||
public static void main(String a[]) |
|
||||||
{ |
public static void main(String a[]) { |
||||||
args=a; |
args = a; |
||||||
if (args.length != 3) { |
if (args.length < 3 || args.length > 4) { |
||||||
System.out |
System.out |
||||||
.println("Usage path/to/envelope.xml path/to/urlfile /path/to/ouputfile.xml"); |
.println("Usage path/to/envelope.xml path/to/urlfile /path/to/ouputfile.xml optional:multipleruns"); |
||||||
System.exit(-1); |
System.exit(-1); |
||||||
} |
} |
||||||
WebserviceChecker wc=new WebserviceChecker(); |
WebserviceChecker wc = new WebserviceChecker(); |
||||||
wc.run(); |
wc.run(); |
||||||
|
|
||||||
} |
} |
||||||
|
|
||||||
|
|
||||||
private static SOAPMessage getSoapMessageFromString(String xml) |
|
||||||
throws SOAPException, IOException { |
|
||||||
MessageFactory factory = MessageFactory.newInstance(); |
|
||||||
SOAPMessage message = factory |
|
||||||
.createMessage( |
|
||||||
new MimeHeaders(), |
|
||||||
new ByteArrayInputStream(xml.getBytes(Charset |
|
||||||
.forName("UTF-8")))); |
|
||||||
return message; |
|
||||||
} |
|
||||||
private static String readFile(File f) throws IOException { |
|
||||||
FileReader fr = new FileReader(f); |
|
||||||
BufferedReader bfr = new BufferedReader(fr); |
|
||||||
String line; |
|
||||||
StringBuffer result = new StringBuffer(); |
|
||||||
while ((line = bfr.readLine()) != null) { |
|
||||||
result.append(line + "\n"); |
|
||||||
|
|
||||||
} |
|
||||||
bfr.close(); |
|
||||||
fr.close(); |
|
||||||
return result.toString(); |
|
||||||
} |
|
||||||
} |
} |
||||||
|
|||||||
@ -1,409 +1,394 @@ |
|||||||
package de.superx.bin; |
package de.superx.bin; |
||||||
|
|
||||||
import java.io.BufferedWriter; |
import java.io.BufferedWriter; |
||||||
import java.io.ByteArrayInputStream; |
|
||||||
import java.io.File; |
import java.io.File; |
||||||
import java.io.FileInputStream; |
import java.io.FileInputStream; |
||||||
import java.io.IOException; |
import java.io.IOException; |
||||||
import java.io.InputStream; |
import java.io.InputStream; |
||||||
import java.io.PrintWriter; |
import java.io.PrintWriter; |
||||||
import java.io.StringWriter; |
|
||||||
import java.net.Authenticator; |
|
||||||
import java.net.PasswordAuthentication; |
|
||||||
import java.net.Authenticator.RequestorType; |
|
||||||
import java.nio.charset.Charset; |
|
||||||
import java.util.Calendar; |
import java.util.Calendar; |
||||||
import java.util.GregorianCalendar; |
|
||||||
import java.util.logging.Level; |
import java.util.logging.Level; |
||||||
import java.util.logging.Logger; |
|
||||||
|
|
||||||
import javax.xml.soap.MessageFactory; |
|
||||||
import javax.xml.soap.MimeHeaders; |
|
||||||
import javax.xml.soap.SOAPConnection; |
|
||||||
import javax.xml.soap.SOAPConnectionFactory; |
|
||||||
import javax.xml.soap.SOAPException; |
|
||||||
import javax.xml.soap.SOAPMessage; |
|
||||||
import javax.xml.stream.XMLInputFactory; |
import javax.xml.stream.XMLInputFactory; |
||||||
import javax.xml.stream.XMLStreamConstants; |
import javax.xml.stream.XMLStreamConstants; |
||||||
import javax.xml.stream.XMLStreamException; |
import javax.xml.stream.XMLStreamException; |
||||||
import javax.xml.stream.XMLStreamReader; |
import javax.xml.stream.XMLStreamReader; |
||||||
import javax.xml.transform.OutputKeys; |
|
||||||
import javax.xml.transform.Transformer; |
|
||||||
import javax.xml.transform.TransformerConfigurationException; |
|
||||||
import javax.xml.transform.TransformerException; |
|
||||||
import javax.xml.transform.TransformerFactory; |
|
||||||
import javax.xml.transform.TransformerFactoryConfigurationError; |
|
||||||
import javax.xml.transform.dom.DOMSource; |
|
||||||
import javax.xml.transform.stream.StreamResult; |
|
||||||
|
|
||||||
import org.w3c.dom.Document; |
import org.w3c.dom.Document; |
||||||
import org.w3c.dom.Node; |
import org.w3c.dom.Node; |
||||||
|
import org.xml.sax.SAXException; |
||||||
|
|
||||||
import de.memtext.util.DateUtils; |
import de.memtext.util.DateUtils; |
||||||
import de.memtext.util.GetOpts; |
import de.memtext.util.GetOpts; |
||||||
|
import de.memtext.util.GetOpts.Options; |
||||||
import de.memtext.util.LogUtils; |
import de.memtext.util.LogUtils; |
||||||
import de.memtext.util.StringUtils; |
import de.memtext.util.StringUtils; |
||||||
import de.memtext.util.XMLUtils; |
import de.memtext.util.XMLUtils; |
||||||
|
|
||||||
public class WebserviceClientBewegungsdaten extends AbstractWebserviceClient { |
public class WebserviceClientBewegungsdaten extends AbstractWebserviceClient { |
||||||
|
|
||||||
private Document configDocument; |
private Document configDocument; |
||||||
private XMLInputFactory factory = XMLInputFactory.newInstance(); |
private XMLInputFactory factory = XMLInputFactory.newInstance(); |
||||||
|
private String hsnr; |
||||||
private String hsnr; |
private String xmlConfig, datentyp; |
||||||
|
private String url; |
||||||
private String xmlConfig, datentyp; |
private String soap; |
||||||
private String url; |
|
||||||
|
private String outfilename; |
||||||
private String soap; |
private boolean columnNamesWritten = false, columnNamesHdWritten = false; |
||||||
|
private File tmpFile, outFile, outFileHd; |
||||||
private String outfilename; |
private String jahr; |
||||||
private boolean columnNamesWritten = false, columnNamesHdWritten = false; |
private PrintWriter fw, fwhd; |
||||||
private File tmpFile, outFile, outFileHd; |
private BufferedWriter bfw, bfwhd; |
||||||
private String jahr; |
|
||||||
private PrintWriter fw, fwhd; |
private Calendar cal = Calendar.getInstance(); |
||||||
private BufferedWriter bfw, bfwhd; |
|
||||||
private static final Logger log = Logger.getLogger("wc"); |
public static void main(String args[]) { |
||||||
|
System.out |
||||||
public static void main(String args[]) { |
.println("SuperX-WebserviceClientBewegungsdaten Version 1.4 (2.2.2023)"); |
||||||
System.out |
WebserviceClientBewegungsdaten tc = new WebserviceClientBewegungsdaten(); |
||||||
.println("SuperX-WebserviceClientBewegungsdaten Version 0.9.3"); |
tc.run(args); |
||||||
WebserviceClientBewegungsdaten tc = new WebserviceClientBewegungsdaten(); |
} |
||||||
tc.run(args); |
|
||||||
|
|
||||||
} |
/** |
||||||
|
* @deprecated |
||||||
public WebserviceClientBewegungsdaten() { |
* @return |
||||||
|
*/ |
||||||
} |
private boolean isWorkaroundNeeded() { |
||||||
|
return hsnr.contentEquals("3001")&&jahr.contentEquals("2021") && datentyp.equals("fmifiit"); |
||||||
public void run(String args[]) { |
} |
||||||
try { |
public WebserviceClientBewegungsdaten() { |
||||||
|
} |
||||||
XMLUtils.getExceptionHandler().setWithGui(false); |
|
||||||
XMLUtils.getExceptionHandler().setExitWanted(true); |
public void run(String args[]) { |
||||||
// LogUtils.initRaw(log);
|
try { |
||||||
LogUtils.initRawFileDateTime("wc", "WebserviceClient.log", 100000, |
initLogging(); |
||||||
1, true, false); |
GetOpts.setOpts(args); |
||||||
|
String isdrin = GetOpts.isAllRequiredOptionsPresent(new Options[] {Options.opt_xmlconfig, |
||||||
log.setLevel(Level.FINEST); |
Options.opt_hsnr, |
||||||
log.getHandlers()[0].setLevel(Level.FINEST); |
Options.opt_jahr, |
||||||
GetOpts.setOpts(args); |
Options.opt_out, |
||||||
String isdrin = GetOpts |
Options.opt_datentyp}); |
||||||
.isAllRequiredOptionsPresent("-xmlconfig,-hsnr,-jahr,-out,-datentyp"); |
if (isdrin != null) { |
||||||
if (isdrin != null) { |
System.err.println("Folgende Optionen fehlen: " + isdrin); |
||||||
System.err.println("Folgende Optionen fehlen: " + isdrin); |
// System.err.println(usage);
|
||||||
// System.err.println(usage);
|
System.exit(1); |
||||||
System.exit(1); |
} |
||||||
} |
readConfig(); |
||||||
readConfig(); |
|
||||||
|
perform(); |
||||||
perform(); |
|
||||||
|
String msg = " fertig: " + DateUtils.getTodayString() + " " |
||||||
String msg = " fertig: " + DateUtils.getTodayString() + " " |
+ DateUtils.getNowString(); |
||||||
+ DateUtils.getNowString(); |
logger.info(msg); |
||||||
log.info(msg); |
System.out.println(msg); |
||||||
System.out.println(msg); |
} catch (Exception e) { |
||||||
} catch (Exception e) { |
logger.severe(e.getMessage()); |
||||||
log.severe(e.getMessage()); |
System.out.println("Error " + e.getMessage()); |
||||||
System.out.println("Error " + e.getMessage()); |
e.printStackTrace(); |
||||||
e.printStackTrace(); |
LogUtils.close("wc"); |
||||||
LogUtils.close("wc"); |
System.exit(1); |
||||||
System.exit(1); |
} finally { |
||||||
} finally { |
LogUtils.close("wc"); |
||||||
LogUtils.close("wc"); |
|
||||||
|
} |
||||||
} |
} |
||||||
} |
|
||||||
|
private void perform() throws Exception { |
||||||
private void perform() throws Exception { |
|
||||||
|
Node n = XMLUtils.getFirstNode(configDocument, datentyp + "detailurl"); |
||||||
Node n = XMLUtils.getFirstNode(configDocument, datentyp + "detailurl"); |
url = XMLUtils.getTheValue(n); |
||||||
url = XMLUtils.getTheValue(n); |
url = adaptURL(url); |
||||||
url = adaptURL(url); |
logger.fine("URL:" + url); |
||||||
n = XMLUtils.getFirstNode(configDocument, datentyp + "detailsoap"); |
System.out.println("URL:" + url); |
||||||
soap = XMLUtils.getTheValue(n); |
n = XMLUtils.getFirstNode(configDocument, datentyp + "detailsoap"); |
||||||
soap = soap.replace("XXHSNRXX", hsnr); |
soap = XMLUtils.getTheValue(n); |
||||||
soap = soap.replace("XXJAHRXX", jahr); |
soap = soap.replace("XXHSNRXX", hsnr); |
||||||
System.out.println(datentyp + "\n12x " + soap); |
soap = soap.replace("XXJAHRXX", jahr); |
||||||
//n = XMLUtils.getFirstNode(configDocument, datentyp + "detailreplacenode");
|
System.out.println(datentyp + "\nVorlage " + soap); |
||||||
|
//n = XMLUtils.getFirstNode(configDocument, datentyp + "detailreplacenode");
|
||||||
initOutFile(); |
|
||||||
|
initOutFile(); |
||||||
//Laut Herrn Schweitzer (SAP) keine Daten für Vorjahr und Folgejahr abrufen
|
//Laut Herrn Schweitzer (SAP) keine Daten für Vorjahr und Folgejahr abrufen
|
||||||
// monat 0 ist Vorjahr, Monat 13 ist Folgejahr
|
//sagt aber, dass dann Buchungen im Folgejahr fehlen, daher wieder aktiviert
|
||||||
for (int monat = 1; monat <= 12; monat++) { |
//Ticket https://hiszilla.his.de/hiszilla/show_bug.cgi?id=169286
|
||||||
|
//Nach Besprechung/Test mit Herren Kowalke/Weil (BitBw) nicht korrekt, Vor- und Folgejahr müssen abgerufen werden (5/2020)
|
||||||
String monatssoap = getMonatsoap(monat); |
//nicht ein Geschäftsjahr betreffende Buchungen später per delete entfernt
|
||||||
log.fine(datentyp + "\nSOAP Aufruf:\n" + monatssoap); |
//https://hiszilla.his.de/hiszilla/show_bug.cgi?id=237395
|
||||||
String msg = "starte Aufruf " + (monat ); |
// 11/2021 #237395 statt vorjahr und folgejahr längerer Zeitraum
|
||||||
|
int vorjahr = Integer.parseInt(jahr) - 1; |
||||||
System.out.print(msg); |
|
||||||
tmpFile = createSoapFile(monatssoap, url); |
runAbruf("1970-01-01", vorjahr + "-01-01"); |
||||||
msg =" - empfangen "; |
runAbruf(vorjahr + "-01-02", vorjahr + "-01-31"); |
||||||
if (!isDeleteTmpXmlFileWanted) |
runAbruf(vorjahr + "-02-01", vorjahr + "-03-01"); |
||||||
msg += " (" + tmpFile+")"; |
runAbruf(vorjahr + "-03-02", vorjahr + "-03-31"); |
||||||
msg+=" "+DateUtils.getNowString(); |
runAbruf(vorjahr + "-04-01", vorjahr + "-04-30"); |
||||||
System.out.println(msg); |
runAbruf(vorjahr + "-05-01", vorjahr + "-05-31"); |
||||||
|
runAbruf(vorjahr + "-06-01", vorjahr + "-06-30"); |
||||||
String nodeName = "EX_" + datentyp.toUpperCase(); |
runAbruf(vorjahr + "-07-01", vorjahr + "-07-31"); |
||||||
|
runAbruf(vorjahr + "-08-01", vorjahr + "-08-31"); |
||||||
if (isReplyOk()) { |
runAbruf(vorjahr + "-09-01", vorjahr + "-09-30"); |
||||||
String columnNames = getColumnNames(nodeName).toString(); |
runAbruf(vorjahr + "-10-01", vorjahr + "-10-31"); |
||||||
if (!columnNamesWritten && !columnNames.equals("")) { |
runAbruf(vorjahr + "-11-01", vorjahr + "-11-30"); |
||||||
bfw.write(columnNames); |
runAbruf(vorjahr + "-12-01", vorjahr + "-12-31"); |
||||||
columnNamesWritten = true; |
//jetzt jeden Tag einzeln
|
||||||
} |
int jahrint = Integer.parseInt(jahr); |
||||||
String data = getData(nodeName).toString(); |
cal.set(jahrint, 0, 1); |
||||||
if (!data.equals("")) |
while (cal.get(1) == jahrint) { |
||||||
bfw.write(data); |
String datum = getDateString(); |
||||||
bfw.flush(); |
runAbruf(datum, datum); |
||||||
|
cal.add(6, 1); |
||||||
// Header
|
} |
||||||
if (datentyp.equals("fmifiit")) { |
//jetzt Folgejahre
|
||||||
columnNames = getColumnNames("EX_FMIFIHD").toString(); |
int folgejahr = Integer.parseInt(jahr) + 1; |
||||||
if (!columnNamesHdWritten && !columnNames.equals("")) { |
runAbruf(folgejahr + "-01-01", folgejahr + "-01-31"); |
||||||
bfwhd.write(columnNames); |
runAbruf(folgejahr + "-02-01", folgejahr + "-03-01"); |
||||||
columnNamesHdWritten = true; |
runAbruf(folgejahr + "-03-02", folgejahr + "-03-31"); |
||||||
} |
runAbruf(folgejahr + "-04-01", folgejahr + "-04-30"); |
||||||
data = getData("EX_FMIFIHD").toString(); |
runAbruf(folgejahr + "-05-01", folgejahr + "-05-31"); |
||||||
if (!data.equals("")) |
runAbruf(folgejahr + "-06-01", folgejahr + "-06-30"); |
||||||
bfwhd.write(data); |
runAbruf(folgejahr + "-07-01", folgejahr + "-07-31"); |
||||||
bfwhd.flush(); |
runAbruf(folgejahr + "-08-01", folgejahr + "-08-31"); |
||||||
} |
runAbruf(folgejahr + "-09-01", folgejahr + "-09-30"); |
||||||
if (isDeleteTmpXmlFileWanted) |
runAbruf(folgejahr + "-10-01", folgejahr + "-10-31"); |
||||||
tmpFile.delete(); |
runAbruf(folgejahr + "-11-01", folgejahr + "-11-30"); |
||||||
|
runAbruf(folgejahr + "-12-01", folgejahr + "-12-31"); |
||||||
} else { |
int folgejahr2 = Integer.parseInt(jahr) + 2; |
||||||
msg = "Error: Aufruf von Webservice für Bewegungsdaten " |
runAbruf(folgejahr2 + "-01-01", "2100-12-31"); |
||||||
+ datentyp + " (" + xmlConfig + ") fehlgeschlagen"; |
|
||||||
System.out.println(msg); |
closeFile(); |
||||||
System.out.println(StringUtils.readFile(tmpFile)); |
} |
||||||
log.severe(msg); |
|
||||||
LogUtils.close("wc"); |
|
||||||
System.exit(-1); |
private String getDateString() { |
||||||
} |
int month = cal.get(2) + 1; |
||||||
|
String monthstr = "" + month + ""; |
||||||
} |
if (month < 10) { |
||||||
closeFile(); |
monthstr = "0" + month; |
||||||
} |
} |
||||||
|
int day = cal.get(5); |
||||||
private String getMonatsoap(int monat) { |
String daystring = "" + day + ""; |
||||||
String tempsoap = soap; |
if (day < 10) { |
||||||
if (monat == 0) { |
daystring = "0" + day; |
||||||
int vorjahr = Integer.parseInt(jahr); |
} |
||||||
vorjahr--; |
String result = "" + cal.get(1) + "-" + monthstr + "-" + daystring; |
||||||
tempsoap = tempsoap.replaceAll("XXSTARTXX", vorjahr + "-01-01"); |
return result; |
||||||
tempsoap = tempsoap.replaceAll("XXENDEXX", vorjahr + "-12-31"); |
} |
||||||
} |
|
||||||
|
|
||||||
if (monat >= 1 && monat <= 12) { |
protected void runAbruf(String datevon, String datebis) throws Exception, XMLStreamException, IOException { |
||||||
int jahrint = Integer.parseInt(jahr); |
String soap = getSoap(datevon, datebis); |
||||||
GregorianCalendar cal = new GregorianCalendar(jahrint,monat-1, 1); |
logger.fine(datentyp + "\nSOAP Aufruf:\n" + soap); |
||||||
String monatstr; |
String msg = "starte Aufruf fuer " + datevon + " bis " + datebis; |
||||||
if (monat < 10) |
|
||||||
monatstr = "0" + monat; |
System.out.println(msg); |
||||||
else |
|
||||||
monatstr = monat + ""; |
tmpFile = createSoapFile(soap, url); |
||||||
tempsoap = tempsoap.replaceAll("XXSTARTXX", jahr + "-" + monatstr |
msg = " - empfangen "; |
||||||
+ "-01"); |
if (!isDeleteTmpXmlFileWanted) |
||||||
int maxDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH); |
msg += " (" + tmpFile + ")"; |
||||||
// System.out.println(maxDay);
|
msg += " " + DateUtils.getNowString(); |
||||||
tempsoap = tempsoap.replaceAll("XXENDEXX", jahr + "-" + monatstr |
System.out.println(msg); |
||||||
+ "-" + maxDay); |
|
||||||
} |
String nodeName = "EX_" + datentyp.toUpperCase(); |
||||||
|
|
||||||
if (monat == 13) { |
if (isReplyOk(tmpFile)) { |
||||||
int folgejahr = Integer.parseInt(jahr); |
String columnNames = getColumnNames(nodeName).toString(); |
||||||
folgejahr++; |
if (!columnNamesWritten && !columnNames.equals("")) { |
||||||
tempsoap = tempsoap.replaceAll("XXSTARTXX", folgejahr + "-01-01"); |
bfw.write(columnNames); |
||||||
tempsoap = tempsoap.replaceAll("XXENDEXX", folgejahr + "-12-31"); |
columnNamesWritten = true; |
||||||
} |
} |
||||||
return tempsoap; |
String data = getData(nodeName).toString(); |
||||||
} |
if (!data.equals("")) |
||||||
|
bfw.write(data); |
||||||
private void readConfig() { |
bfw.flush(); |
||||||
|
|
||||||
xmlConfig = GetOpts.getValue("-xmlconfig"); |
// Header
|
||||||
outfilename = GetOpts.getValue("-out"); |
if (datentyp.equals("fmifiit")) { |
||||||
|
columnNames = getColumnNames("EX_FMIFIHD").toString(); |
||||||
hsnr = GetOpts.getValue("-hsnr"); |
if (!columnNamesHdWritten && !columnNames.equals("")) { |
||||||
jahr = GetOpts.getValue("-jahr"); |
bfwhd.write(columnNames); |
||||||
datentyp = GetOpts.getValue("-datentyp"); |
columnNamesHdWritten = true; |
||||||
System.out.println("\n" + DateUtils.getTodayString() + " " |
} |
||||||
+ DateUtils.getNowString() + "\nHochschulnummer " + hsnr); |
data = getData("EX_FMIFIHD").toString(); |
||||||
log.info("\nHochschulnummer " + hsnr); |
if (!data.equals("")) |
||||||
if (GetOpts.isPresent("-nodelete")) |
bfwhd.write(data); |
||||||
isDeleteTmpXmlFileWanted = false; |
bfwhd.flush(); |
||||||
log.log(Level.INFO, "Geschaeftsjahr " + jahr); |
} |
||||||
System.out.println("Geschaeftsjahr " + jahr); |
if (isDeleteTmpXmlFileWanted) |
||||||
|
tmpFile.delete(); |
||||||
log.log(Level.INFO, "Verarbeite " + xmlConfig); |
|
||||||
System.out.println("Verarbeite " + xmlConfig); |
} else { |
||||||
configDocument = XMLUtils.buildDocument(new File(xmlConfig)); |
msg = "Error: Aufruf von Webservice für Bewegungsdaten " + datentyp + " (" + xmlConfig |
||||||
|
+ ") fehlgeschlagen"; |
||||||
} |
System.out.println(msg); |
||||||
|
System.out.println(StringUtils.readFile(tmpFile)); |
||||||
private void initOutFile() throws Exception { |
logger.severe(msg); |
||||||
outFile = new File(outfilename); |
LogUtils.close("wc"); |
||||||
if (outFile.exists()) |
System.exit(-1); |
||||||
outFile.delete(); |
} |
||||||
// FileWriter fw = new FileWriter(f);
|
} |
||||||
fw = new PrintWriter(outFile); |
|
||||||
// FileOutputStream fos = new FileOutputStream(f, false);
|
private String getSoap(String datevon, String datebis) { |
||||||
// BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(fos));
|
String tempsoap = soap; |
||||||
|
tempsoap = tempsoap.replaceAll("XXSTARTXX", datevon); |
||||||
bfw = new BufferedWriter(fw); |
tempsoap = tempsoap.replaceAll("XXENDEXX", datebis); |
||||||
|
return tempsoap; |
||||||
if (datentyp.equals("fmifiit")) { |
|
||||||
|
} |
||||||
String hdfilename = StringUtils.replace(outfilename, ".", "hd."); |
|
||||||
outFileHd = new File(hdfilename); |
private void readConfig() throws IOException, SAXException { |
||||||
String msg = "Erzeuge zusaetzliche Header_Datei " + hdfilename; |
|
||||||
log.log(Level.INFO, msg); |
xmlConfig = GetOpts.getValue(Options.opt_xmlconfig); |
||||||
System.out.println(msg); |
outfilename = GetOpts.getValue(Options.opt_out); |
||||||
fwhd = new PrintWriter(outFileHd); |
|
||||||
bfwhd = new BufferedWriter(fwhd); |
hsnr = GetOpts.getValue(Options.opt_hsnr); |
||||||
} |
jahr = GetOpts.getValue(Options.opt_jahr); |
||||||
|
datentyp = GetOpts.getValue(Options.opt_datentyp); |
||||||
} |
System.out.println("\n" + DateUtils.getTodayString() + " " |
||||||
|
+ DateUtils.getNowString() + "\nHochschulnummer " + hsnr); |
||||||
private void closeFile() throws Exception { |
logger.info("\nHochschulnummer " + hsnr); |
||||||
|
if (GetOpts.isPresent(Options.opt_noDelete)) |
||||||
bfw.close(); |
isDeleteTmpXmlFileWanted = false; |
||||||
fw.close(); |
logger.log(Level.INFO, "Geschaeftsjahr " + jahr); |
||||||
|
System.out.println("Geschaeftsjahr " + jahr); |
||||||
if (datentyp.equals("fmifiit")) { |
|
||||||
bfwhd.close(); |
logger.log(Level.INFO, "Verarbeite " + xmlConfig); |
||||||
fwhd.close(); |
System.out.println("Verarbeite " + xmlConfig); |
||||||
} |
configDocument = XMLUtils.buildDocument(new File(xmlConfig)); |
||||||
|
|
||||||
if (isDeleteTmpXmlFileWanted) |
} |
||||||
if (tmpFile.exists()) tmpFile.delete(); |
|
||||||
} |
private void initOutFile() throws Exception { |
||||||
|
outFile = new File(outfilename); |
||||||
private boolean isReplyOk() throws XMLStreamException, IOException { |
if (outFile.exists()) |
||||||
InputStream in = new FileInputStream(tmpFile); |
outFile.delete(); |
||||||
XMLStreamReader parser = factory.createXMLStreamReader(in); |
// FileWriter fw = new FileWriter(f);
|
||||||
boolean checkReturn = false; |
fw = new PrintWriter(outFile); |
||||||
String result = ""; |
// FileOutputStream fos = new FileOutputStream(f, false);
|
||||||
while (parser.hasNext()) { |
// BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(fos));
|
||||||
switch (parser.getEventType()) { |
|
||||||
case XMLStreamConstants.START_ELEMENT: |
bfw = new BufferedWriter(fw); |
||||||
if (parser.getLocalName().equals("RETURN")) { |
|
||||||
checkReturn = true; |
if (datentyp.equals("fmifiit")) { |
||||||
|
|
||||||
} |
String hdfilename = StringUtils.replace(outfilename, ".", "hd."); |
||||||
break; |
outFileHd = new File(hdfilename); |
||||||
|
String msg = "Erzeuge zusaetzliche Header_Datei " + hdfilename; |
||||||
case XMLStreamConstants.CHARACTERS: |
logger.log(Level.INFO, msg); |
||||||
if (checkReturn && !parser.isWhiteSpace()) { |
System.out.println(msg); |
||||||
result = parser.getText(); |
fwhd = new PrintWriter(outFileHd); |
||||||
checkReturn = false; |
bfwhd = new BufferedWriter(fwhd); |
||||||
} |
} |
||||||
break; |
|
||||||
case XMLStreamConstants.END_DOCUMENT: |
} |
||||||
|
|
||||||
parser.close(); |
private void closeFile() throws Exception { |
||||||
break; |
|
||||||
|
bfw.close(); |
||||||
} |
fw.close(); |
||||||
|
|
||||||
parser.next(); |
if (datentyp.equals("fmifiit")) { |
||||||
|
bfwhd.close(); |
||||||
} |
fwhd.close(); |
||||||
in.close(); |
} |
||||||
return result.equals("I"); |
|
||||||
} |
if (isDeleteTmpXmlFileWanted) |
||||||
|
if (tmpFile.exists()) tmpFile.delete(); |
||||||
private StringBuilder getData(String topnode) throws XMLStreamException, |
} |
||||||
IOException { |
|
||||||
InputStream in = new FileInputStream(tmpFile); |
|
||||||
XMLStreamReader parser = factory.createXMLStreamReader(in); |
|
||||||
final String datumspattern = "(\\d\\d\\d\\d)-(\\d\\d)-(\\d\\d)"; |
private StringBuilder getData(String topnode) throws XMLStreamException, |
||||||
|
IOException { |
||||||
StringBuilder result = new StringBuilder(); |
InputStream in = new FileInputStream(tmpFile); |
||||||
boolean getData = false; |
XMLStreamReader parser = factory.createXMLStreamReader(in); |
||||||
while (parser.hasNext()) { |
|
||||||
|
|
||||||
switch (parser.getEventType()) { |
StringBuilder result = new StringBuilder(); |
||||||
case XMLStreamConstants.START_ELEMENT: |
boolean getData = false; |
||||||
String name = parser.getLocalName(); |
while (parser.hasNext()) { |
||||||
if (name.equals(topnode)) |
|
||||||
getData = true; |
switch (parser.getEventType()) { |
||||||
// Spaltennamen zu Debugzwecken anzeigen
|
case XMLStreamConstants.START_ELEMENT: |
||||||
// else if (getData && !name.equals("item"))
|
String name = parser.getLocalName(); |
||||||
// result.append(prefix + "_" + parser.getLocalName());
|
if (name.equals(topnode)) |
||||||
break; |
getData = true; |
||||||
case XMLStreamConstants.CHARACTERS: |
// Spaltennamen zu Debugzwecken anzeigen
|
||||||
if (getData && !parser.isWhiteSpace()) { |
// else if (getData && !name.equals("item"))
|
||||||
String data = parser.getText(); |
// result.append(prefix + "_" + parser.getLocalName());
|
||||||
|
break; |
||||||
if (data.matches(datumspattern)) |
case XMLStreamConstants.CHARACTERS: |
||||||
data = data.replaceAll(datumspattern, "$3.$2.$1"); |
if (getData && !parser.isWhiteSpace()) { |
||||||
else |
String data = parser.getText(); |
||||||
data = purge(data); |
if (data.matches(DATUMSPATTERN)) |
||||||
|
data = adaptDatePattern(data); |
||||||
result.append(data); |
else |
||||||
} |
data = purge(data, true); |
||||||
break; |
|
||||||
case XMLStreamConstants.END_ELEMENT: |
result.append(data); |
||||||
if (parser.getLocalName().equals(topnode)) |
} |
||||||
getData = false; |
break; |
||||||
else if (getData && parser.getLocalName().equals("item")) |
case XMLStreamConstants.END_ELEMENT: |
||||||
result.append("\n"); |
if (parser.getLocalName().equals(topnode)) |
||||||
else if (getData) { |
getData = false; |
||||||
result.append("^"); |
else if (getData && parser.getLocalName().equals("item")) |
||||||
} |
result.append("\n"); |
||||||
break; |
else if (getData) { |
||||||
|
result.append("^"); |
||||||
case XMLStreamConstants.END_DOCUMENT: |
} |
||||||
parser.close(); |
break; |
||||||
break; |
|
||||||
} |
case XMLStreamConstants.END_DOCUMENT: |
||||||
parser.next(); |
parser.close(); |
||||||
} |
break; |
||||||
in.close(); |
} |
||||||
// abschließendes ^ entfernen
|
parser.next(); |
||||||
//if (result.length() > 0) result.setLength(result.length() - 1);
|
} |
||||||
return result; |
in.close(); |
||||||
|
// abschließendes ^ entfernen
|
||||||
} |
//if (result.length() > 0) result.setLength(result.length() - 1);
|
||||||
|
return result; |
||||||
private String getColumnNames(String topnode) |
|
||||||
throws XMLStreamException, IOException { |
} |
||||||
InputStream in = new FileInputStream(tmpFile); |
|
||||||
XMLStreamReader parser = factory.createXMLStreamReader(in); |
private String getColumnNames(String topnode) |
||||||
|
throws XMLStreamException, IOException { |
||||||
String prefix = topnode.replaceAll("EX_", ""); |
InputStream in = new FileInputStream(tmpFile); |
||||||
StringBuilder result = new StringBuilder(); |
XMLStreamReader parser = factory.createXMLStreamReader(in); |
||||||
boolean getNames = false; |
|
||||||
while (parser.hasNext()) { |
String prefix = topnode.replaceAll("EX_", ""); |
||||||
|
StringBuilder result = new StringBuilder(); |
||||||
switch (parser.getEventType()) { |
boolean getNames = false; |
||||||
case XMLStreamConstants.START_ELEMENT: |
while (parser.hasNext()) { |
||||||
String name = parser.getLocalName(); |
|
||||||
if (parser.getLocalName().equals(topnode)) |
switch (parser.getEventType()) { |
||||||
getNames = true; |
case XMLStreamConstants.START_ELEMENT: |
||||||
else if (getNames && !name.equals("item")) |
String name = parser.getLocalName(); |
||||||
result.append(prefix + "_" + parser.getLocalName() + "^"); |
if (parser.getLocalName().equals(topnode)) |
||||||
break; |
getNames = true; |
||||||
case XMLStreamConstants.END_ELEMENT: |
else if (getNames && !name.equals("item")) |
||||||
if (parser.getLocalName().equals(topnode)||parser.getLocalName().equals("item")) |
result.append(prefix + "_" + parser.getLocalName() + "^"); |
||||||
getNames = false; |
break; |
||||||
break; |
case XMLStreamConstants.END_ELEMENT: |
||||||
|
if (parser.getLocalName().equals(topnode)||parser.getLocalName().equals("item")) |
||||||
case XMLStreamConstants.END_DOCUMENT: |
getNames = false; |
||||||
parser.close(); |
break; |
||||||
break; |
|
||||||
} |
case XMLStreamConstants.END_DOCUMENT: |
||||||
parser.next(); |
parser.close(); |
||||||
} |
break; |
||||||
in.close(); |
} |
||||||
// abschließendes ^ entfernen
|
parser.next(); |
||||||
if (result.length() > 0) |
} |
||||||
result.setLength(result.length() - 1); |
in.close(); |
||||||
if (result.length() > 0) |
// abschließendes ^ entfernen
|
||||||
result.append("\n"); |
if (result.length() > 0) |
||||||
return result.toString().toLowerCase(); |
result.setLength(result.length() - 1); |
||||||
} |
if (result.length() > 0) |
||||||
} |
result.append("\n"); |
||||||
|
return result.toString().toLowerCase(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue