/*
* Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi)
*
* Licensed under the EUPL, Version 1.1 or – as soon they
* will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
*
* You may not use this work except in compliance with the Licence.
*
* You may obtain a copy of the Licence at:
*
* https://joinup.ec.europa.eu/community/eupl/og_page/eupl
*
* Unless required by applicable law or agreed to in
* writing, software distributed under the Licence is
* distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the Licence for the specific language governing
* permissions and limitations under the Licence.
*/
package no.difi.oxalis.test.datagenerator;
import java.io.*;
/**
* Generates PEPPOL BIS catalogue files of arbitrary size.
* <p>
* The purpose of this generator is to generate files varying in size in order to execute performance tests.
* <p>
* The number of catalogue items will determine the size of the resulting file. The resulting file might be slightly
* larger than requested as the size of the catalogue line item can not be changed.
* <p>
* The generated file will be generated in the temporary folder according to the JVM system porperties.
*
* @author steinar
* Date: 08.06.15
* Time: 21.06
*/
public class FileGenerator {
public static final long kB = 1000L;
public static final long MB = kB * 1000;
public static final long GB = MB * 1000;
static protected String xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
static protected String sbdhHeader = "<StandardBusinessDocument xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n" +
" xmlns=\"http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader\">\n" +
" <StandardBusinessDocumentHeader>\n" +
" <HeaderVersion>1.0</HeaderVersion>\n" +
" <Sender>\n" +
" <Identifier Authority=\"iso6523-actorid-upis\">0007:5567125082</Identifier>\n" +
" </Sender>\n" +
" <Receiver>\n" +
" <Identifier Authority=\"iso6523-actorid-upis\">0007:4455454480</Identifier>\n" +
" </Receiver>\n" +
" <DocumentIdentification>\n" +
" <Standard>urn:oasis:names:specification:ubl:schema:xsd:Catalogue-2</Standard>\n" +
" <TypeVersion>2.0</TypeVersion>\n" +
" <InstanceIdentifier>1070e7f0-3bae-11e3-aa6e-0800200c9a66</InstanceIdentifier>\n" +
" <Type>Catalogue</Type>\n" +
" <CreationDateAndTime>2013-02-19T05:10:10</CreationDateAndTime>\n" +
" </DocumentIdentification>\n" +
" <BusinessScope>\n" +
" <Scope>\n" +
" <Type>DOCUMENTID</Type>\n" +
" <InstanceIdentifier>urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0</InstanceIdentifier>\n" +
" </Scope>\n" +
" <Scope>\n" +
" <Type>PROCESSID</Type>\n" +
" <InstanceIdentifier>urn:www.cenbii.eu:profile:bii04:ver1.0</InstanceIdentifier>\n" +
" </Scope>\n" +
" </BusinessScope>\n" +
" </StandardBusinessDocumentHeader>\n";
static protected String header = xmlHeader + sbdhHeader +
"<Catalogue xmlns:sdt=\"urn:oasis:names:specification:ubl:schema:xsd:SpecializedDatatypes-2\" xmlns:cac=\"urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2\" xmlns:a=\"urn:oasis:names:specification:ubl:schema:xsd:Catalogue-2\" xmlns:udt=\"urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:cbc=\"urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2\" xmlns=\"urn:oasis:names:specification:ubl:schema:xsd:Catalogue-2\" xmlns:ccts=\"urn:oasis:names:specification:ubl:schema:xsd:CoreComponentParameters-2\" xsi:schemaLocation=\"urn:oasis:names:specification:ubl:schema:xsd:Catalogue-2 ../UBL%202.1%20schema/maindoc/UBL-Catalogue-2.1.xsd\">\n" +
"\t<cbc:UBLVersionID>2.1</cbc:UBLVersionID>\n" +
"\t<cbc:CustomizationID>urn:www.cenbii.eu:transaction:biitrns019:ver2.0:extended:urn:www.peppol.eu:bis:peppol1a:ver2.0:extended:urn:www.difi.no:ehf:katalog:ver1.0</cbc:CustomizationID>\n" +
"\t<cbc:ProfileID>urn:www.cenbii.eu:profile:bii01:ver2.0</cbc:ProfileID>\n" +
"\t<cbc:ID>1234</cbc:ID>\n" +
"\t<cbc:ActionCode listID=\"ACTIONCODE:PEPPOL\">Add</cbc:ActionCode>\n" +
"\t<cbc:IssueDate>2013-09-23</cbc:IssueDate>\n" +
"\t<cbc:VersionID>v1.0</cbc:VersionID>\n" +
"\t<cac:ValidityPeriod>\n" +
"\t\t<cbc:StartDate>2013-09-25</cbc:StartDate>\n" +
"\t\t<cbc:EndDate>2013-12-31</cbc:EndDate>\n" +
"\t</cac:ValidityPeriod>\n" +
"\t<cac:ReferencedContract>\n" +
"\t\t<cbc:ID>123123</cbc:ID>\n" +
"\t\t<cbc:ContractType>StandardContract</cbc:ContractType>\n" +
"\t</cac:ReferencedContract>\n" +
"\t<cac:ProviderParty>\n" +
"\t\t<cbc:EndpointID schemeID=\"NO:ORGNR\">1234567890</cbc:EndpointID>\n" +
"\t\t<cac:PartyIdentification>\n" +
"\t\t\t<cbc:ID schemeID=\"ZZZ\">Provider AS</cbc:ID>\n" +
"\t\t</cac:PartyIdentification>\n" +
"\t\t<cac:PartyName>\n" +
"\t\t\t<cbc:Name>Produsentnavn</cbc:Name>\n" +
"\t\t</cac:PartyName>\n" +
"\t</cac:ProviderParty>\n" +
"\t<cac:ReceiverParty>\n" +
"\t\t<cbc:EndpointID schemeID=\"NO:ORGNR\">123456789</cbc:EndpointID>\n" +
"\t\t<cac:PartyIdentification>\n" +
"\t\t\t<cbc:ID schemeID=\"ZZZ\">HBE 1018275</cbc:ID>\n" +
"\t\t</cac:PartyIdentification>\n" +
"\t\t<cac:PartyName>\n" +
"\t\t\t<cbc:Name>Helse Vest</cbc:Name>\n" +
"\t\t</cac:PartyName>\n" +
"\t</cac:ReceiverParty>\n" +
"\t<cac:SellerSupplierParty>\n" +
"\t\t<cac:Party>\n" +
"\t\t\t<cbc:EndpointID schemeID=\"NO:ORGNR\">987654321</cbc:EndpointID>\n" +
"\t\t\t<cac:PartyIdentification>\n" +
"\t\t\t\t<cbc:ID schemeID=\"NO:ORGNR\">984297793</cbc:ID>\n" +
"\t\t\t</cac:PartyIdentification>\n" +
"\t\t\t<cac:PartyName>\n" +
"\t\t\t\t<cbc:Name>Supplier</cbc:Name>\n" +
"\t\t\t</cac:PartyName>\n" +
"\t\t\t<cac:PostalAddress>\n" +
"\t\t\t\t<cbc:StreetName>Per Krohgs vei 1,Karihaugen</cbc:StreetName>\n" +
"\t\t\t\t<cbc:CityName>OSLO</cbc:CityName>\n" +
"\t\t\t\t<cbc:CountrySubentity>Norway</cbc:CountrySubentity>\n" +
"\t\t\t\t<cac:Country>\n" +
"\t\t\t\t\t<cbc:IdentificationCode listID=\"ISO3166-1\">NO</cbc:IdentificationCode>\n" +
"\t\t\t\t</cac:Country>\n" +
"\t\t\t</cac:PostalAddress>\n" +
"\t\t\t<cac:Contact>\n" +
"\t\t\t\t<cbc:Name>Ole Olsen</cbc:Name>\n" +
"\t\t\t\t<cbc:Telephone>+46123123123</cbc:Telephone>\n" +
"\t\t\t\t<cbc:ElectronicMail>test@ibxeurope.com</cbc:ElectronicMail>\n" +
"\t\t\t</cac:Contact>\n" +
"\t\t</cac:Party>\n" +
"\t</cac:SellerSupplierParty>\n" +
"\t<!-- Catalogue items starts here...-->\n";
static protected String catalogueLine = "\t<cac:CatalogueLine>\n" +
"\t\t<cbc:ID>200</cbc:ID>\n" +
"\t\t<cbc:ActionCode listID=\"ACTIONCODE:BII\">Add</cbc:ActionCode>\n" +
"\t\t<cbc:OrderableIndicator>true</cbc:OrderableIndicator>\n" +
"\t\t<cbc:OrderableUnit>EA</cbc:OrderableUnit>\n" +
"\t\t<cbc:ContentUnitQuantity unitCode=\"EA\" unitCodeListID=\"UNECERec20\">1</cbc:ContentUnitQuantity>\n" +
"\t\t<cbc:OrderQuantityIncrementNumeric>1</cbc:OrderQuantityIncrementNumeric>\n" +
"\t\t<cbc:MinimumOrderQuantity unitCode=\"EA\" unitCodeListID=\"UNECERec20\">1</cbc:MinimumOrderQuantity>\n" +
"\t\t<cbc:MaximumOrderQuantity unitCode=\"EA\" unitCodeListID=\"UNECERec20\">1</cbc:MaximumOrderQuantity>\n" +
"\t\t<cbc:PackLevelCode listID=\"GS17009:PEPPOL\">CU</cbc:PackLevelCode>\n" +
"\t\t<cac:LineValidityPeriod>\n" +
"\t\t\t<cbc:StartDate>2013-10-01</cbc:StartDate>\n" +
"\t\t\t<cbc:EndDate>2013-12-31</cbc:EndDate>\n" +
"\t\t</cac:LineValidityPeriod>\n" +
"\t\t<cac:RequiredItemLocationQuantity>\n" +
"\t\t\t<cbc:LeadTimeMeasure unitCode=\"DAY\">13</cbc:LeadTimeMeasure>\n" +
"\t\t\t<cac:Price>\n" +
"\t\t\t\t<cbc:PriceAmount currencyID=\"NOK\">504.5</cbc:PriceAmount>\n" +
"\t\t\t</cac:Price>\n" +
"\t\t</cac:RequiredItemLocationQuantity>\n" +
"\t\t<cac:Item>\n" +
"\t\t\t<cbc:Description/>\n" +
"\t\t\t<cbc:PackQuantity unitCode=\"EA\" unitCodeListID=\"UNECERec20\">1</cbc:PackQuantity>\n" +
"\t\t\t<cbc:Name>LÅSKASSE LK1362/28 R STOLPE25</cbc:Name>\n" +
"\t\t\t<cac:SellersItemIdentification>\n" +
"\t\t\t\t<cbc:ID>2451015</cbc:ID>\n" +
"\t\t\t</cac:SellersItemIdentification>\n" +
"\t\t\t<cac:ManufacturersItemIdentification>\n" +
"\t\t\t\t<cbc:ID>2451015</cbc:ID>\n" +
"\t\t\t</cac:ManufacturersItemIdentification>\n" +
"\t\t\t<cac:StandardItemIdentification>\n" +
"\t\t\t\t<cbc:ID schemeID=\"GTIN\">05704368876486</cbc:ID>\n" +
"\t\t\t</cac:StandardItemIdentification>\n" +
"\t\t\t<cac:CommodityClassification>\n" +
"\t\t\t\t<cbc:ItemClassificationCode listID=\"UNSPSC\">46171500</cbc:ItemClassificationCode>\n" +
"\t\t\t</cac:CommodityClassification>\n" +
"\t\t\t<cac:ClassifiedTaxCategory>\n" +
"\t\t\t\t<cbc:ID schemeID=\"UNCL5305\">S</cbc:ID>\n" +
"\t\t\t\t<cac:TaxScheme>\n" +
"\t\t\t\t\t<cbc:ID>VAT</cbc:ID>\n" +
"\t\t\t\t</cac:TaxScheme>\n" +
"\t\t\t</cac:ClassifiedTaxCategory>\n" +
"\t\t\t<cac:ManufacturerParty>\n" +
"\t\t\t\t<cac:PartyName>\n" +
"\t\t\t\t\t<cbc:Name>Manufacturer</cbc:Name>\n" +
"\t\t\t\t</cac:PartyName>\n" +
"\t\t\t</cac:ManufacturerParty>\n" +
"\t\t\t<cac:Dimension>\n" +
"\t\t\t\t<cbc:AttributeID schemeID=\"UNCL6313\">AAE</cbc:AttributeID>\n" +
"\t\t\t\t<cbc:Measure unitCode=\"KGM\">0.574</cbc:Measure>\n" +
"\t\t\t</cac:Dimension>\n" +
"\t\t</cac:Item>\n" +
"\t</cac:CatalogueLine>\n";
static String footer = "</Catalogue>\n" +
"</StandardBusinessDocument>\n";
/**
* Generates a file of the given size and return the File object referencing it.
*
* @param requestedSize the minimum size of the file to be generated, will be rounded up to the nearest integer count of catalogue
* items
* @return File object referencing the temporary file holding the data.
*/
public static File generate(long requestedSize) {
try {
File outputFile = File.createTempFile("PEPPOL-TEST-CATALOGUE", ".xml");
generate(outputFile, requestedSize);
return outputFile;
} catch (IOException e) {
throw new IllegalStateException("Unable to create the outputFile:" + e.getMessage(), e);
}
}
/**
* Generates an XML catalogue file
*
* @param outputFile a reference to the file into which the catalogue will be written
* @param requestedSize the minimum size of the file to be generated.
* @see #generate(long)
*/
public static void generate(File outputFile, long requestedSize) {
try (OutputStream outputStream = new FileOutputStream(outputFile);
Writer writer = new OutputStreamWriter(outputStream);
BufferedWriter bufferedWriter = new BufferedWriter(writer)) {
bufferedWriter.write(header); // Writes the header
// Calculates the number of catalogue items.
long numberOfItems = calculateNumberOfLines(requestedSize);
// Writes the catalogue items
for (int i = 0; i < numberOfItems; i++) {
bufferedWriter.write(catalogueLine);
}
// Finally, writes the footer in order to complete the XML file
bufferedWriter.write(footer);
} catch (FileNotFoundException e) {
throw new IllegalStateException("Unable to open " + outputFile + ", reason: " + e.getMessage(), e);
} catch (IOException e) {
throw new IllegalStateException("Unable to write data to " + outputFile + ", reason:" + e.getMessage(), e);
}
}
/**
* Calculates the number of catalogue items required to create a file of at least the size requested.
*
* @param requestedSize the size (in bytes) of the file to be generated
* @return number of lines needed
*/
static long calculateNumberOfLines(long requestedSize) {
long fixedLength = header.length() + footer.length();
long lineCount = (requestedSize - fixedLength) / catalogueLine.length();
long remainder = (requestedSize - fixedLength) % catalogueLine.length();
if (remainder > 0) {
lineCount++;
}
return lineCount;
}
}