added visuallization again

This commit is contained in:
Jochen Stärk
2020-08-20 17:33:28 +02:00
parent db4c86315a
commit 9414f86d6f
9 changed files with 7558 additions and 9 deletions

View File

@@ -25,6 +25,7 @@
switch
- change from ZUGFeRDExporter to IZUGFeRDExporter
- javadoc export
- have visualizer
### 2.0 still todo
- release notes
@@ -36,6 +37,10 @@ switch
- be able to disable "source pdf set to timeout"
- automated tests zuv/verapdf validate created library test files
- unify loggers
- *visualizer to work with Extended profile
- *visualizer tests
- *validator not to log to stdout
- *validator not to XR error on ZF files (only notices)
- xmp errors may not show correctly in log
- switch for no log and no notices
- merge readmes and history.md

View File

@@ -24,10 +24,7 @@ import org.mustangproject.ZUGFeRD.*;
import org.mustangproject.validator.Validator;
import org.mustangproject.validator.ZUGFeRDValidator;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -39,6 +36,8 @@ import java.nio.file.Paths;
import org.slf4j.LoggerFactory;
import javax.xml.transform.TransformerException;
public class Main {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(Validator.class.getCanonicalName()); // log output
@@ -47,7 +46,7 @@ public class Main {
}
private static String getUsage() {
return "Usage: --action metrics|combine|extract|a3only|validate [-d,--directory] [-l,--listfromstdin] [-i,--ignore fileextension, PDF/A errors] | [-h,--help] \r\n"
return "Usage: --action metrics|combine|extract|a3only|validate|visualize [-d,--directory] [-l,--listfromstdin] [-i,--ignore fileextension, PDF/A errors] | [-h,--help] \r\n"
+ "* merics\n" + " -d, --directory count ZUGFeRD files in directory to be scanned\n"
+ " If it is a directory, it will recurse.\n"
+ " -l, --listfromstdin count ZUGFeRD files from a list of linefeed separated files on runtime.\n"
@@ -84,6 +83,7 @@ public class Main {
+ " [--no-notices]: refrain from reporting notices\n"
+ " Additional parameters (optional - user will be prompted if not defined)\n"
+ " -d, --directory to check recursively\n"
+ " visualize convert XML to HTML \n"
;
}
@@ -299,6 +299,9 @@ public class Main {
} else if ((action!=null)&&(action.equals("a3only"))) {
performConvert(sourceName, outName);
optionsRecognized=true;
} else if ((action!=null)&&(action.equals("visualize"))) {
performVisualization(sourceName, outName);
optionsRecognized=true;
} else if ((action!=null)&&(action.equals("validate"))) {
optionsRecognized=performValidate(sourceName, noNotices!=null&&noNotices);
} else if ((action!=null)&&(action.equals("validateExpectValid"))) {
@@ -430,7 +433,7 @@ public class Main {
}
if (xmlName == null) {
xmlName = getFilenameFromUser("ZUGFeRD XML", "ZUGFeRD-invoice.xml", "xml", true, false);
xmlName = getFilenameFromUser("ZUGFeRD XML", "factur-x.xml", "xml", true, false);
} else {
System.out.println("ZUGFeRD XML set to " + xmlName);
}
@@ -583,6 +586,91 @@ public class Main {
System.out.println(sr.getSummaryLine());
}
private static void performVisualization(String sourceName, String outName) {
// Get params from user if not already defined
if (sourceName == null) {
sourceName = getFilenameFromUser("ZUGFeRD XML source", "factur-x.xml", "xml", true, false);
} else {
System.out.println("ZUGFeRD XML source set to " + sourceName);
}
if (outName == null) {
outName = getFilenameFromUser("ZUGFeRD 2.0 XML target", "factur-x.html", "html", false, true);
} else {
System.out.println("ZUGFeRD 1.0 XML source set to " + outName);
}
// Verify params
try {
ensureFileExists(sourceName);
ensureFileNotExists(outName);
// stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer();
String xml = null;
try {
xml = zvi.visualize(sourceName);
Files.write(Paths.get(outName), xml.getBytes());
} catch (FileNotFoundException e) {
LOGGER.error(e.getMessage(), e);
} catch (UnsupportedEncodingException e) {
LOGGER.error(e.getMessage(), e);
} catch (TransformerException e) {
LOGGER.error(e.getMessage(), e);
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
System.out.println("Written to " + outName);
try {
ExportResource("/xrechnung-viewer.css");
ExportResource("/xrechnung-viewer.js");
System.out.println("xrechnung-viewer.css and xrechnung-viewer.js written as well (to local working dir)");
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
/**
* Export a resource embedded into a Jar file to the local file path.
*
* @param resourceName ie.: "/SmartLibrary.dll"
* @return The path to the exported resource
* @throws Exception
*/
static public String ExportResource(String resourceName) throws Exception {
InputStream stream = null;
OutputStream resStreamOut = null;
String jarFolder;
try {
stream = Main.class.getResourceAsStream(resourceName);//note that each / is a directory down in the "jar tree" been the jar the root of the tree
if(stream == null) {
throw new Exception("Cannot get resource \"" + resourceName + "\" from Jar file.");
}
int readBytes;
byte[] buffer = new byte[4096];
jarFolder = System.getProperty("user.dir");
resStreamOut = new FileOutputStream(jarFolder + resourceName);
while ((readBytes = stream.read(buffer)) > 0) {
resStreamOut.write(buffer, 0, readBytes);
}
} catch (Exception ex) {
throw ex;
} finally {
stream.close();
resStreamOut.close();
}
return jarFolder + resourceName;
}
private static void ensureFileExists(String fileName) throws IOException {
if (!fileExists(fileName)) {
throw new IOException(String.format("File %s does not exists", fileName));

View File

@@ -496,7 +496,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
xml = xml + " <ram:SpecifiedTradeSettlementHeaderMonetarySummation>\n"
+ " <ram:LineTotalAmount>" + currencyFormat(getTotal()) + "</ram:LineTotalAmount>\n" //$NON-NLS-2$
// currencyID=\"EUR\"
+ " <ram:ChargeTotalAmount>0.00</ram:ChargeTotalAmount>\n" currencyID=\"EUR\"
+ " <ram:ChargeTotalAmount>0.00</ram:ChargeTotalAmount>\n"
+ " <ram:AllowanceTotalAmount>0.00</ram:AllowanceTotalAmount>\n" //
// currencyID=\"EUR\"
// + " <ChargeTotalAmount currencyID=\"EUR\">5.80</ChargeTotalAmount>\n"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,917 @@
/* Grundformatierung ********************************************/
*,
*:after,
*:before
{
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.clear:after
{
content: ".";
clear: both;
display: block;
visibility: hidden;
height: 0;
}
html,
body
{
height: 100%;
min-width: 320px;
margin: 0;
padding: 0;
color: #000;
font-size: 14px;
}
body
{
overflow-y: scroll;
background-color: rgba(4, 101, 161, 0.08);
}
h4
{
color: inherit;
font-size: inherit;
margin-bottom: 0.5rem;
}
/* Grundaufbau *************************************************/
.menue
{
position: relative;
z-index: 2000;
background-color: #000;
margin-bottom: 30px;
}
.innen
{
max-width: 1080px;
margin: 0 auto;
padding: 0 2%;
}
/* Formatierungen *************************************************/
.color2
{
color: rgba(0, 0, 0, 0.6);
}
.schwarz
{
color: #555 !important;
}
.normal
{
font-weight: normal;
}
.bold
{
font-weight: bold;
}
.abstandUnten
{
margin-bottom: 5px;
}
.abstandUntenKlein
{
margin-bottom: 10px;
}
.noPaddingTop
{
padding-top: 0 !important;
}
.ausrichtungRechts
{
text-align: right;
}
/* Menü ********************************************************/
button
{
position: relative;
font-family: serif;
padding-top: 15px;
padding-left: 0;
padding-right: 0;
margin-right: 2%;
}
.btnAktiv
{
font-size: 22px;
color: #ffb619;
height: 50px;
outline: none;
border: none;
background: none;
}
.btnAktiv:after
{
content: "";
display: block;
position: absolute;
top: 50px;
left: 50%;
z-index: 10;
font-size: 0;
line-height: 0;
height: 0;
padding: 0;
margin: 0;
transform: translateX(-50%);
border: 15px solid #000;
border-right-color: transparent;
border-bottom-color: transparent;
border-left-color: transparent;
}
.btnInaktiv,
.tab
{
font-size: 22px;
color: #fff;
height: 50px;
z-index: 0;
outline: none;
border: none;
background: none;
transition: color 0.3s ease;
}
.btnInaktiv:hover,
.tab:hover
{
color: #ffb619;
cursor: pointer;
}
.divHide
{
display: none;
}
/* Content *********************************************************************/
.inhalt
{
font-family: sans-serif;
margin-bottom: 30px;
}
.haftungausschluss
{
color: #000;
text-align: center;
padding: 7px;
margin-bottom: 30px;
width: 100%;
border: 1px solid #ffb619;
background-color: #fff;
}
.box
{
position: relative;
display: table-cell;
padding: 0;
border: 1px solid rgba(4, 101, 161, 0.2);
background-color: #fff;
}
.subBox
{
border-top: none;
width: 50%;
}
.subBox:last-child
{
border-left: none;
}
.first > .boxzeile > .subBox
{
border-top: 1px solid rgba(4, 101, 161, 0.2) !important;
}
.boxtitel
{
display: inline-block;
background-color: #0465A1;
padding: 7px 10px;
color: #fff;
font-weight: bold;
}
.boxBorderTop
{
border-top: none;
}
.boxBorderLeft
{
border-left: none;
}
.boxtitelSub
{
color: #000;
background-color: rgba(4, 101, 161, 0.1);
border-right: 1px solid rgba(4, 101, 161, 0.2);
border-bottom: 1px solid rgba(4, 101, 161, 0.2);
}
.boxinhalt
{
padding: 15px 20px;
}
.boxtabelle
{
display: table;
width: 100%;
}
.borderSpacing
{
border-spacing: 0 5px;
}
.boxabstandtop
{
margin-top: 30px;
}
.boxzeile
{
display: table-row;
}
.boxzeile .box:last-child
{
margin-bottom: 0;
}
.boxdaten
{
display: table-cell;
padding: 5px 0;
vertical-align: middle;
height: 38px;
/*
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
-webkit-hyphens: auto;
-moz-hyphens: auto;
hyphens: auto;
*/
}
.boxdaten.wert
{
padding: 5px 10px;
}
.boxcell
{
display: table-cell;
}
.boxdatenBlock
{
display: block;
padding: 3px 0;
/*
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
-webkit-hyphens: auto;
-moz-hyphens: auto;
hyphens: auto;
*/
}
.noBreak
{
-ms-word-break: keep-all;
word-break: keep-all;
word-break: keep-all;
-webkit-hyphens: none;
-moz-hyphens: none;
hyphens: none;
}
.boxabstand
{
display: table-cell;
width: 30px;
}
.legende
{
color: rgba(0, 0, 0, 0.6);
width: 170px;
font-size: 13px;
line-height: 16px;
padding-right: 5px;
}
.wert
{
background-color: rgba(4, 101, 161, 0.03);
}
.boxtabelleEinspaltig
{
width: 49%;
}
.boxtabelleZweispaltig,
.boxtabelleDreispaltig
{
width: 100%;
}
.box5050
{
width: 50%;
}
.boxEinspaltig
{
width: 100%;
}
.boxZweispaltig
{
width: 48.5%;
}
.boxSpalte1 {
width: 50%;
}
.boxSpalte2 {
width: 50%;
padding-left: 20px;
}
.paddingLeft {
padding-left: 0.1em;
}
.noPadding {
padding-top: 0 !important;
padding-bottom: 0 !important;
}
.rechnungsZeile
{
display: table-row;
}
.rechnungsZeile .boxdaten
{
height: auto;
}
.rechnungSp1
{
width: 65%;
font-size: 16px;
}
.rechnungSp2
{
width: 10%;
}
.rechnungSp3
{
width: 25%;
font-size: 16px;
text-align: right;
}
.detailSp1,
.detailSp2
{
width: 50%;
}
.detailSp2
{
text-align: right;
}
.line1Bottom
{
border-bottom: 1px solid #000;
}
.line1BottomLight
{
padding-bottom: 5px;
border-bottom: 1px solid #f0f0f0;
margin-bottom: 5px;
}
.line2Bottom
{
border-bottom: 2px solid #000;
}
.paddingTop
{
padding-top: 10px;
}
.paddingBottom
{
padding-bottom: 10px;
}
.grund
{
font-size: 16px;
display: block;
width: 100%;
padding: 0 20px 15px 20px;
}
.grundDetail
{
display: block;
width: 100%;
padding: 0 20px 15px 20px;
}
/* Übersichtformatierungen */
#uebersichtLastschrift.box,
#uebersichtUeberweisung.box
{
border-top: none;
}
#uebersichtUeberweisung.box
{
border-left: none;
}
/* Formatierungen Detailseite */
.detailsSpalte1,
.detailsSpalte2
{
width: 30%;
float: left;
font-size: 90%;
line-height: 115%;
margin-right: 5%;
}
.detailsSpalte3
{
width: 30%;
float: left;
font-size: 90%;
line-height: 115%;
}
.detailsSpalte1 .legende,
.detailsSpalte2 .legende,
.detailsSpalte3 .legende
{
width: 145px;
}
.titelPosition
{
font-size: 17px;
font-weight: bold;
}
/* Laufzettelformatierungen */
#laufzettelHistorie .boxtabelle:not(:nth-child(2))
{
border-top: 1px solid rgba(4, 101, 161, 0.2);
padding-top: 10px;
margin-top: 10px;
}
/* 1023px und kleiner ************************************************/
@media screen and (max-width : 1023px) {
.box
{
display: block;
width: 100%;
margin-bottom: 20px;
}
.boxabstandtop
{
margin-top: 15px;
}
.subBox:first-child
{
margin-bottom: 0 !important;
}
.subBox:last-child
{
border-left: 1px solid rgba(4, 101, 161, 0.2);
}
.first > .boxzeile > .subBox
{
border-top: none !important;
}
.first > .boxzeile > .subBox:first-child
{
border-top: 1px solid rgba(4, 101, 161, 0.2) !important;
}
.first > .boxzeile
{
margin-bottom: 0;
}
#uebersichtUeberweisung.box
{
border-left: 1px solid rgba(4, 101, 161, 0.2);
}
#uebersichtLastschrift.box
{
margin-bottom: 0;
}
.boxzeile
{
display: block;
margin-bottom: 5px;
}
.boxzeile:after
{
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
#details > .boxtabelle > .boxzeile
{
margin-bottom: 0px;
}
.boxcell
{
display: block;
}
.boxcell:last-child
{
margin-top: 20px;
}
.boxZweispaltig
{
width: 100%;
}
.legende
{
display: block;
float: left;
width: 170px;
padding: 5px 0;
height: auto;
}
.wert
{
display: block;
float: left;
width: calc(100% - 170px);
padding: 11px 10px !important;
line-height: 1.3;
min-height: 38px;
height: auto;
}
.boxdaten .legende
{
height: auto;
}
.rechnungsZeile .boxdaten
{
padding: 5px 0;
}
.boxabstand
{
display: none;
}
.boxtabelleEinspaltig {
width: 100%;
}
.boxSpalte1 {
display: block;
width: auto;
}
.boxSpalte2 {
display: block;
width: auto;
padding-left: 0px;
margin-top: 1.2rem;
}
.detailsSpalte1,
.detailsSpalte2,
.detailsSpalte3
{
width: 100%;
float: none;
padding-right: 0px;
}
.detailsSpalte2,
.detailsSpalte3
{
margin-top: 15px;
}
.detailsSpalte2,
.detailsSpalte3
{
margin-top: 10px;
}
.tableNumberAlignRight
{
display: block;
width: 130px;
text-align: right;
}
}
/* 800px und kleiner ************************************************/
@media screen and (max-width : 800px) {
button
{
padding-top: 10px;
}
.btnAktiv,
.btnInaktiv,
.tab
{
font-size: 20px;
height: 40px;
}
.btnAktiv:after
{
top: 40px;
}
.rechnungSp1
{
width: 55%;
font-size: 15px;
}
.rechnungSp2
{
width: 10%;
}
.rechnungSp3
{
width: 35%;
text-align: right;
font-size: 15px;
}
.grund
{
font-size: 15px;
}
}
/* 450px und kleiner ************************************************/
@media screen and (max-width : 450px)
{
html,
body
{
font-size: 12px;
}
.menue
{
margin-bottom: 20px;
}
button
{
padding-top: 5px;
}
.btnAktiv,
.btnInaktiv,
.tab
{
font-size: 17px;
height: 35px;
}
.btnAktiv:after
{
top: 35px;
}
.legende
{
font-size: 12px;
width: 100%;
}
.wert
{
font-size: 12px;
line-height: 1.3;
width: 100%;
margin-bottom: 10px
}
.boxzeile
{
margin-bottom: 0px
}
.boxdaten
{
height: auto;
}
.haftungausschluss
{
margin-bottom: 20px;
}
.boxinhalt
{
margin-top: 0px;
}
.boxabstandtop
{
margin-top: 20px;
}
.boxtitel
{
padding: 7px 8px;
}
.box
{
margin-bottom: 10px;
padding: 0;
}
.boxabstandtop
{
margin-top: 10px;
}
.boxdaten,
.boxdatenBlock
{
padding: 2px 0;
}
.rechnungSp1
{
width: 50%;
font-size: inherit;
}
.rechnungSp2
{
width: 15%;
}
.rechnungSp3
{
width: 35%;
font-size: inherit;
text-align: right;
}
.grund
{
font-size: inherit;
}
.titelPosition
{
font-size: 15px;
}
.abstandUnten
{
margin-bottom: 5px;
}
.detailsSpalte1,
.detailsSpalte2,
.detailsSpalte3
{
font-size: inherit;
line-height: inherit;
}
}
/* 380px und kleiner ************************************************/
@media screen and (max-width : 380px) {
html,
body
{
font-size: 11px;
line-height: 100%;
}
.btnAktiv,
.btnInaktiv,
.tab
{
font-size: 15px;
}
.boxdaten
.boxdatenBlock
{
padding: 2px 0;
}
.boxinhalt
{
margin-top: 0px;
}
.boxtitel
{
padding: 5px 7px;
}
}

View File

@@ -0,0 +1,145 @@
/* Tab-Container aufbauen **************************************************/
var a = new Array("uebersicht", "details", "zusaetze", "anlagen", "laufzettel");
var b = new Array("menueUebersicht", "menueDetails", "menueZusaetze", "menueAnlagen", "menueLaufzettel");
function show(e) {
var i = 0;
var j = 1;
for (var t = 0; t < b.length; t++) {
if (b[t] === e.id) {
i = t;
if (i > 0) {
j = 0;
} else {
j = i + 1;
}
break;
}
}
e.setAttribute("class", "btnAktiv");
for (var k = 0; k < b.length; k++) {
if (k === i && (document.getElementById(a[k]) != null)) {
document.getElementById(a[k]).style.display = "block";
if (i === j)
j = i + 1;
} else {
if (document.getElementById(a[k]) != null) {
document.getElementById(a[j]).style.display = "none";
document.getElementById(b[j]).setAttribute("class", "btnInaktiv");
j += 1;
}
}
}
}
window.onload = function () {
document.getElementById(b[0]).setAttribute("class", "btnAktiv");
}
/* Eingebettete Binaerdaten runterladen ************************************/
function base64_to_binary (data) {
var chars = atob(data);
var bytes = new Array(chars.length);
for (var i = 0; i < chars.length; i++) {
bytes[i] = chars.charCodeAt(i);
}
return new Uint8Array(bytes);
}
function downloadData (element_id) {
var data_element = document.getElementById(element_id);
var mimetype = data_element.getAttribute('mimeType');
var filename = data_element.getAttribute('filename');
var text = data_element.innerHTML;
var binary = base64_to_binary(text);
var blob = new Blob([binary], {
type: mimetype, size: binary.length
});
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
// IE
window.navigator.msSaveOrOpenBlob(blob, filename);
} else {
// Non-IE
var url = window.URL.createObjectURL(blob);
window.open(url);
}
}
/* Polyfill IE atob/btoa ************************************/
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], function () {
factory(root);
});
} else factory(root);
// node.js has always supported base64 conversions, while browsers that support
// web workers support base64 too, but you may never know.
})(typeof exports !== "undefined" ? exports: this, function (root) {
if (root.atob) {
// Some browsers' implementation of atob doesn't support whitespaces
// in the encoded string (notably, IE). This wraps the native atob
// in a function that strips the whitespaces.
// The original function can be retrieved in atob.original
try {
root.atob(" ");
}
catch (e) {
root.atob = (function (atob) {
var func = function (string) {
return atob(String(string).replace(/[\t\n\f\r ]+/g, ""));
};
func.original = atob;
return func;
})(root.atob);
}
return;
}
// base64 character set, plus padding character (=)
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
// Regular expression to check formal correctness of base64 encoded strings
b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
root.btoa = function (string) {
string = String(string);
var bitmap, a, b, c,
result = "", i = 0,
rest = string.length % 3; // To determine the final padding
for (; i < string.length;) {
if ((a = string.charCodeAt(i++)) > 255 || (b = string.charCodeAt(i++)) > 255 || (c = string.charCodeAt(i++)) > 255)
throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");
bitmap = (a << 16) | (b << 8) | c;
result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) + b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63);
}
// If there's need of padding, replace the last 'A's with equal signs
return rest ? result.slice(0, rest - 3) + "===".substring(rest): result;
};
root.atob = function (string) {
// atob can work with strings with whitespaces, even inside the encoded part,
// but only \t, \n, \f, \r and ' ', which can be stripped.
string = String(string).replace(/[\t\n\f\r ]+/g, "");
if (! b64re.test(string))
throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");
// Adding the padding if missing, for semplicity
string += "==".slice(2 - (string.length & 3));
var bitmap, result = "", r1, r2, i = 0;
for (; i < string.length;) {
bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12 | (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++)));
result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255): r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255): String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255);
}
return result;
};
});

View File

@@ -44,7 +44,7 @@ public class UXTest extends TestCase {
public void testShortExport() {
// the writing part
/*
try (InputStream SOURCE_PDF = this.getClass()
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505PDFA3.pdf"))
{
@@ -113,6 +113,6 @@ public class UXTest extends TestCase {
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
}
}