nyomtatványok kezelése Java-ban

Jasper Report Dev

Jasper Report Dev

Forráskód - Jasper Reports 6.2.2

Hogyan használjuk fel a Jasper Reports library kódját

2016. július 06. - lacimol

Az esetek többségében a Jasper Studio használata a vizuális felületen való kattintgatásban kimerül, de speciális esetekben szükség lehet a forráskód mélyebb ismeretére is. Ilyen eset lehet a listák kezelése kapcsán használandó JsonDataSource osztály kódja vagy a hibakezelés is.

A forráskódot a https://sourceforge.net/projects/jasperreports/files/jasperreports oldalról tölthetjük le, ha kiválasztjuk a szükséges verziót (pl: 6.2.2), majd a "jasperreports-x.x.x-project.zip" elemet választva. A letöltött fájl kicsomagolása után importálhatjuk az Eclipse-be Maven projektként.

A JsonDataSource kódjának részlete:

public class JsonDataSource extends JRAbstractTextDataSource implements JsonData {
... @Override public Object getFieldValue(JRField jrField) throws JRException { if (currentJsonNode == null) { return null; } String expression = jrField.getDescription(); if (expression == null || expression.length() == 0) { expression = jrField.getName(); if (expression == null || expression.length() == 0) { return null; } } Object value = null; Class<?> valueClass = jrField.getValueClass(); JsonNode selectedObject = getJsonData(currentJsonNode, expression); if (Object.class != valueClass) { boolean hasValue = selectedObject != null && !selectedObject.isMissingNode() && !selectedObject.isNull(); if (hasValue) { try { if (valueClass.equals(String.class)) { if (selectedObject.isArray()) { value = selectedObject.toString(); } else { value = selectedObject.asText(); } } else if (valueClass.equals(Boolean.class)) { value = selectedObject.booleanValue(); } else if (Number.class.isAssignableFrom(valueClass)) { value = convertStringValue(selectedObject.asText(), valueClass); } else if (Date.class.isAssignableFrom(valueClass)) { value = convertStringValue(selectedObject.asText(), valueClass); } else { throw new JRException(EXCEPTION_MESSAGE_KEY_CANNOT_CONVERT_FIELD_TYPE, new Object[] { jrField.getName(), valueClass.getName() }); } } catch (Exception e) { throw new JRException(EXCEPTION_MESSAGE_KEY_JSON_FIELD_VALUE_NOT_RETRIEVED, new Object[] { jrField.getName(), valueClass.getName() }, e); } } } else { value = selectedObject; } return value; }
... }

List helyett ArrayNode

A fenti kódban látszik, hogy a mező visszatérési értéke csak String, Number, Boolean vagy Date lehet. Ha egy lista elemeit szeretnénk visszakapni java.util.List típusként, akkor csalódnunk kell. Ebben az esetben csak java.lang.Object-ként kérhetjük el, de még így sem cast-olhatjuk List-re, hanem csak JsonNode lehet (selectedObject). Látható az is, hogy ha tömböt String-ként kérünk el, akkor azt ugyan visszakapjuk, de már csak String-ként dolgozhatunk vele (["", "", ""]). A tömb elemeinek számát például nem kérdezhetjük le így (csak csűrés-csavarással: replace + Arrays.asList).

Hogyan tudjuk meg egy adott lista elemeinek számát?

A megoldást a kódban továbbugrálva kaphatjuk meg: getJsonData - goDownPathWithAttribute - goDownPath:

protected JsonNode goDownPath(JsonNode rootNode, String simplePath) {
		if(rootNode != null && !rootNode.isMissingNode()) {
			JsonNode result = null;
			if (rootNode.isObject()) {
				result = rootNode.path(simplePath);
			} else if (rootNode.isArray()) {
				result = mapper.createArrayNode();
				for (JsonNode node: rootNode) {
					JsonNode deeperNode = node.path(simplePath);
					if (!deeperNode.isMissingNode()) {
						if (deeperNode.isArray()) {
							for(JsonNode arrayNode: deeperNode) {
								((ArrayNode)result).add(arrayNode);
							}
						} else {
							((ArrayNode)result).add(deeperNode);
						}
					} 
				}
			}
			return result;
		} 
		return rootNode;
	}

A createArrayNode() visszatérési értéke com.fasterxml.jackson.databind.node.ArrayNode, amelynek már van size() metódusa, így megkaphatjuk az adott lista elemeinek számát is.

Visszatérési érték bővítése List-tel

A fenti getFieldValue() metódust bővíthetjük a következő kódrészlettel:

    @Override
	public Object getFieldValue(JRField jrField) throws JRException {
		...		
		if (Object.class != valueClass) {
			boolean hasValue = selectedObject != null && !selectedObject.isMissingNode() && !selectedObject.isNull();
			if (hasValue) {
				try {
					if (valueClass.equals(String.class)) {
						...
					} else if (List.class.equals(valueClass)) {
						List<Object> result = new ArrayList<Object>();
						if (!selectedObject.isMissingNode() && selectedObject.isArray()) {
							value = this.convertToList(selectedObject, result);
						} else {
							value = result;
						}
						
					} ...
				} catch (Exception e) {
					...
				}
			}
		} ...
		
		return value;
	}

A listát összepakoló metódus szöveges elemként teszi be a listaelemeket, függetlenül azok típusától (a jelenlegi cél a lista elemszámának kiderítése). A listába ágyazott mélységi listák felderítését a rekurzivitás biztosítja.

private List<Object> convertToList(JsonNode selectedObject, List<Object> result) {
		for (JsonNode node : selectedObject) {
			if (!node.isMissingNode() && node.isArray()) {
				List<Object> innerResult = new ArrayList<Object>();
				result.add(innerResult);
				this.convertToList(node, innerResult);
			} else {
				// don't care about type
				result.add(node.asText());
			}
		}
		return result;
	}

A módosított kód használata

A maven install után a target mappában találjuk a "jasperreports-6.2.2.jar" fájlt. A Jasper Studio telepített mappájában keressünk rá a "jasperreports*.jar"-ra és a 6.2.2-es verziót tartalmazzó mappában írjuk felül a legenerált jar fájllal az ottani jart (a mappa helye a frissítésektől függ). Ez a fájl nálam a következő helyen található:

..\configuration\org.eclipse.osgi\506\0\.cp\lib\jasperreports-6.2.2-20160505.150232-15.jar

Az $F{issues} mező class property-jét Object-ről java.util.List-re állítjuk. Így, ha egy jármű bejegyzéseinek számára vagyunk kíváncsiak, akkor a korábban használt kifejezés helyett az $V{issueSize} változóban egy egyszerűbbet használhatunk (nem kell a MissingNode miatti feltétel és nem kell cast-olni sem):

//($F{issues} instanceof ArrayNode) ? ((ArrayNode)$F{issues}).size() : 0;
$F{issues}.size()

A bejegyzés trackback címe:

https://jasperreport.blog.hu/api/trackback/id/tr548810618

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása