From a538db4eb944003cdd0233ca1f8f8fb5bcc86ef3 Mon Sep 17 00:00:00 2001 From: user Date: Thu, 25 May 2023 09:49:27 +0300 Subject: [PATCH 1/7] 3_5_HW2_xslt --- .../masterjava/xml/util/XsltProcessor.java | 4 ++ src/main/resources/groups.xsl | 37 +++++++++++++++++++ .../java/ru/javaops/masterjava/MainXml.java | 16 ++++++++ 3 files changed, 57 insertions(+) create mode 100644 src/main/resources/groups.xsl diff --git a/src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java b/src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java index 019eeed..083febb 100644 --- a/src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java +++ b/src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java @@ -40,4 +40,8 @@ public void transform(Reader sourceReader, Writer result) throws TransformerExce public static String getXsltHeader(String xslt) { return "\n"; } + + public void setParameter(String name, String value) { + xformer.setParameter(name, value); + } } diff --git a/src/main/resources/groups.xsl b/src/main/resources/groups.xsl new file mode 100644 index 0000000..c5ade36 --- /dev/null +++ b/src/main/resources/groups.xsl @@ -0,0 +1,37 @@ + + + + + + + + + + <xsl:value-of select="$projectName"/> groups + + + +

+ groups +

+ + + + + + + + + + + +
GroupType
+ + + +
+ + +
+
\ No newline at end of file diff --git a/src/test/java/ru/javaops/masterjava/MainXml.java b/src/test/java/ru/javaops/masterjava/MainXml.java index bcd5894..8f57825 100644 --- a/src/test/java/ru/javaops/masterjava/MainXml.java +++ b/src/test/java/ru/javaops/masterjava/MainXml.java @@ -11,6 +11,7 @@ import ru.javaops.masterjava.xml.util.JaxbParser; import ru.javaops.masterjava.xml.util.Schemas; import ru.javaops.masterjava.xml.util.StaxStreamProcessor; +import ru.javaops.masterjava.xml.util.XsltProcessor; import javax.xml.stream.events.XMLEvent; import java.io.InputStream; @@ -49,6 +50,12 @@ public static void main(String[] args) throws Exception { System.out.println(); users = processByStax(projectName, payloadUrl); users.forEach(System.out::println); + + System.out.println(); + html = transform(projectName, payloadUrl); + try (Writer writer = Files.newBufferedWriter(Paths.get("out/groups.html"))) { + writer.write(html); + } } private static Set parseByJaxb(String projectName, URL payloadUrl) throws Exception { @@ -121,4 +128,13 @@ private static String toHtml(Set users, String projectName) { body().with(h1(projectName + " users"), table) ).render(); } + + private static String transform(String projectName, URL payloadUrl) throws Exception { + URL xsl = Resources.getResource("groups.xsl"); + try (InputStream xmlStream = payloadUrl.openStream(); InputStream xslStream = xsl.openStream()) { + XsltProcessor processor = new XsltProcessor(xslStream); + processor.setParameter("projectName", projectName); + return processor.transform(xmlStream); + } + } } From cdb54e1f6280104c577883d9f70b2c288c5994f6 Mon Sep 17 00:00:00 2001 From: user Date: Wed, 7 Jun 2023 16:51:00 +0300 Subject: [PATCH 2/7] 3_6_multimodule.patch --- common/pom.xml | 21 +++++++++ parent/pom.xml | 69 ++++++++++++++++++++++++++++ pom.xml | 120 +++++-------------------------------------------- upload/pom.xml | 39 ++++++++++++++++ 4 files changed, 140 insertions(+), 109 deletions(-) create mode 100644 common/pom.xml create mode 100644 parent/pom.xml create mode 100644 upload/pom.xml diff --git a/common/pom.xml b/common/pom.xml new file mode 100644 index 0000000..33d3da8 --- /dev/null +++ b/common/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + + + ru.javaops + parent + ../parent/pom.xml + 1.0-SNAPSHOT + + + common + 1.0-SNAPSHOT + jar + Common + + + + \ No newline at end of file diff --git a/parent/pom.xml b/parent/pom.xml new file mode 100644 index 0000000..d7b056d --- /dev/null +++ b/parent/pom.xml @@ -0,0 +1,69 @@ + + + 4.0.0 + + ru.javaops + parent + pom + 1.0-SNAPSHOT + Parent + + + 1.8 + UTF-8 + UTF-8 + + + + install + + + org.apache.maven.plugins + maven-compiler-plugin + 3.7.0 + + ${java.version} + ${java.version} + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.20.1 + + -Dfile.encoding=UTF-8 + + + + + + + + com.google.guava + guava + 23.3-jre + + + one.util + streamex + RELEASE + + + + + junit + junit + 4.12 + test + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8809434..0085819 100644 --- a/pom.xml +++ b/pom.xml @@ -4,119 +4,21 @@ ru.javaops masterjava - jar + pom 1.0-SNAPSHOT Master Java https://github.com/JavaOPs/masterjava - - 1.8 - UTF-8 - UTF-8 - - - - masterjava - install - - - org.apache.maven.plugins - maven-compiler-plugin - 3.7.0 - - ${java.version} - ${java.version} - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.20.1 - - -Dfile.encoding=UTF-8 - - - - org.apache.maven.plugins - maven-shade-plugin - 3.1.0 - - - package - - shade - - - benchmarks - - - org.openjdk.jmh.Main - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - - - - org.openjdk.jmh - jmh-core - RELEASE - - - org.openjdk.jmh - jmh-generator-annprocess - RELEASE - provided - - - com.google.guava - guava - 21.0 - - - one.util - streamex - RELEASE - - - - com.j2html - j2html - RELEASE - - - - - junit - junit - 4.12 - test - - - - - - - - + + upload + common + + diff --git a/upload/pom.xml b/upload/pom.xml new file mode 100644 index 0000000..7cac01c --- /dev/null +++ b/upload/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + + ru.javaops + parent + ../parent/pom.xml + 1.0-SNAPSHOT + + + upload + 1.0-SNAPSHOT + war + Upload + + + + + org.apache.maven.plugins + maven-war-plugin + 3.2.0 + + false + + + + + + + + ru.javaops + common + ${project.version} + + + \ No newline at end of file From 797f01ba17cf9895e4e62970e3b7a84702bc7555 Mon Sep 17 00:00:00 2001 From: user Date: Wed, 7 Jun 2023 19:28:28 +0300 Subject: [PATCH 3/7] HW3 with no Optional --- mail-service/pom.xml | 31 ++ parent-web/pom.xml | 45 +++ pom.xml | 2 - .../javaops/masterjava/matrix/MainMatrix.java | 48 --- .../masterjava/matrix/MatrixBenchmark.java | 85 ----- .../javaops/masterjava/matrix/MatrixUtil.java | 157 --------- .../masterjava/service/MailService.java | 141 -------- .../masterjava/xml/schema/CityType.java | 94 ----- .../masterjava/xml/schema/FlagType.java | 54 --- .../masterjava/xml/schema/GroupType.java | 40 --- .../masterjava/xml/schema/ObjectFactory.java | 109 ------ .../masterjava/xml/schema/Payload.java | 328 ------------------ .../masterjava/xml/schema/Project.java | 216 ------------ .../javaops/masterjava/xml/schema/User.java | 180 ---------- .../masterjava/xml/util/JaxbMarshaller.java | 39 --- .../masterjava/xml/util/JaxbParser.java | 93 ----- .../masterjava/xml/util/JaxbUnmarshaller.java | 38 -- .../javaops/masterjava/xml/util/Schemas.java | 48 --- .../xml/util/StaxStreamProcessor.java | 79 ----- .../masterjava/xml/util/XPathProcessor.java | 58 ---- .../masterjava/xml/util/XsltProcessor.java | 47 --- src/main/resources/cities.xsl | 9 - src/main/resources/groups.xsl | 37 -- src/main/resources/payload.xsd | 97 ------ .../java/ru/javaops/masterjava/MainXml.java | 140 -------- .../masterjava/xml/util/JaxbParserTest.java | 40 --- .../xml/util/StaxStreamProcessorTest.java | 36 -- .../xml/util/XPathProcessorTest.java | 26 -- .../xml/util/XsltProcessorTest.java | 18 - src/test/resources/city.xml | 4 - src/test/resources/payload.xml | 31 -- test/pom.xml | 77 ++++ upload/pom.xml | 21 +- 33 files changed, 162 insertions(+), 2306 deletions(-) create mode 100644 mail-service/pom.xml create mode 100644 parent-web/pom.xml delete mode 100644 src/main/java/ru/javaops/masterjava/matrix/MainMatrix.java delete mode 100644 src/main/java/ru/javaops/masterjava/matrix/MatrixBenchmark.java delete mode 100644 src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java delete mode 100644 src/main/java/ru/javaops/masterjava/service/MailService.java delete mode 100644 src/main/java/ru/javaops/masterjava/xml/schema/CityType.java delete mode 100644 src/main/java/ru/javaops/masterjava/xml/schema/FlagType.java delete mode 100644 src/main/java/ru/javaops/masterjava/xml/schema/GroupType.java delete mode 100644 src/main/java/ru/javaops/masterjava/xml/schema/ObjectFactory.java delete mode 100644 src/main/java/ru/javaops/masterjava/xml/schema/Payload.java delete mode 100644 src/main/java/ru/javaops/masterjava/xml/schema/Project.java delete mode 100644 src/main/java/ru/javaops/masterjava/xml/schema/User.java delete mode 100644 src/main/java/ru/javaops/masterjava/xml/util/JaxbMarshaller.java delete mode 100644 src/main/java/ru/javaops/masterjava/xml/util/JaxbParser.java delete mode 100644 src/main/java/ru/javaops/masterjava/xml/util/JaxbUnmarshaller.java delete mode 100644 src/main/java/ru/javaops/masterjava/xml/util/Schemas.java delete mode 100644 src/main/java/ru/javaops/masterjava/xml/util/StaxStreamProcessor.java delete mode 100644 src/main/java/ru/javaops/masterjava/xml/util/XPathProcessor.java delete mode 100644 src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java delete mode 100644 src/main/resources/cities.xsl delete mode 100644 src/main/resources/groups.xsl delete mode 100644 src/main/resources/payload.xsd delete mode 100644 src/test/java/ru/javaops/masterjava/MainXml.java delete mode 100644 src/test/java/ru/javaops/masterjava/xml/util/JaxbParserTest.java delete mode 100644 src/test/java/ru/javaops/masterjava/xml/util/StaxStreamProcessorTest.java delete mode 100644 src/test/java/ru/javaops/masterjava/xml/util/XPathProcessorTest.java delete mode 100644 src/test/java/ru/javaops/masterjava/xml/util/XsltProcessorTest.java delete mode 100644 src/test/resources/city.xml delete mode 100644 src/test/resources/payload.xml create mode 100644 test/pom.xml diff --git a/mail-service/pom.xml b/mail-service/pom.xml new file mode 100644 index 0000000..8870a21 --- /dev/null +++ b/mail-service/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + + ru.javaops + parent-web + ../parent-web/pom.xml + 1.0-SNAPSHOT + + + mail-service + 1.0-SNAPSHOT + Mail-service + war + + + mail-service + + + + + ru.javaops + mail-api + 1.0-SNAPSHOT + + + + \ No newline at end of file diff --git a/parent-web/pom.xml b/parent-web/pom.xml new file mode 100644 index 0000000..3282378 --- /dev/null +++ b/parent-web/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + + ru.javaops + parent + ../parent/pom.xml + 1.0-SNAPSHOT + + + parent-web + pom + 1.0-SNAPSHOT + Parent Web + + + + + org.apache.maven.plugins + maven-war-plugin + 3.2.0 + + false + + + + + + + + ${project.groupId} + common + ${project.version} + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 0085819..5b1a0e6 100644 --- a/pom.xml +++ b/pom.xml @@ -14,11 +14,9 @@ upload common - diff --git a/src/main/java/ru/javaops/masterjava/matrix/MainMatrix.java b/src/main/java/ru/javaops/masterjava/matrix/MainMatrix.java deleted file mode 100644 index 1f13806..0000000 --- a/src/main/java/ru/javaops/masterjava/matrix/MainMatrix.java +++ /dev/null @@ -1,48 +0,0 @@ -package ru.javaops.masterjava.matrix; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -public class MainMatrix { - private static final int MATRIX_SIZE = 1000; - private static final int THREAD_NUMBER = 10; - - private final static ExecutorService executor = Executors.newFixedThreadPool(MainMatrix.THREAD_NUMBER); - - public static void main(String[] args) throws ExecutionException, InterruptedException { - final int[][] matrixA = MatrixUtil.create(MATRIX_SIZE); - final int[][] matrixB = MatrixUtil.create(MATRIX_SIZE); - - double singleThreadSum = 0.; - double concurrentThreadSum = 0.; - int count = 1; - while (count < 6) { - System.out.println("Pass " + count); - long start = System.currentTimeMillis(); - final int[][] matrixC = MatrixUtil.singleThreadMultiplyOpt(matrixA, matrixB); - double duration = (System.currentTimeMillis() - start) / 1000.; - out("Single thread time, sec: %.3f", duration); - singleThreadSum += duration; - - start = System.currentTimeMillis(); - final int[][] concurrentMatrixC = MatrixUtil.concurrentMultiplyStreams(matrixA, matrixB, Runtime.getRuntime().availableProcessors() - 1); - duration = (System.currentTimeMillis() - start) / 1000.; - out("Concurrent thread time, sec: %.3f", duration); - concurrentThreadSum += duration; - - if (!MatrixUtil.compare(matrixC, concurrentMatrixC)) { - System.err.println("Comparison failed"); - break; - } - count++; - } - executor.shutdown(); - out("\nAverage single thread time, sec: %.3f", singleThreadSum / 5.); - out("Average concurrent thread time, sec: %.3f", concurrentThreadSum / 5.); - } - - private static void out(String format, double ms) { - System.out.println(String.format(format, ms)); - } -} diff --git a/src/main/java/ru/javaops/masterjava/matrix/MatrixBenchmark.java b/src/main/java/ru/javaops/masterjava/matrix/MatrixBenchmark.java deleted file mode 100644 index 2df2fc6..0000000 --- a/src/main/java/ru/javaops/masterjava/matrix/MatrixBenchmark.java +++ /dev/null @@ -1,85 +0,0 @@ -package ru.javaops.masterjava.matrix; - -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; -import org.openjdk.jmh.runner.options.TimeValue; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -@Warmup(iterations = 10) -@Measurement(iterations = 10) -@BenchmarkMode({Mode.SingleShotTime}) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@State(Scope.Benchmark) -@Threads(1) -@Fork(10) -@Timeout(time = 5, timeUnit = TimeUnit.MINUTES) -public class MatrixBenchmark { - - // Matrix size - private static final int MATRIX_SIZE = 1000; - - @Param({"3", "4", "10"}) - private int threadNumber; - - private static int[][] matrixA; - private static int[][] matrixB; - - @Setup - public void setUp() { - matrixA = MatrixUtil.create(MATRIX_SIZE); - matrixB = MatrixUtil.create(MATRIX_SIZE); - } - - private ExecutorService executor; - - public static void main(String[] args) throws RunnerException { - Options options = new OptionsBuilder() - .include(MatrixBenchmark.class.getSimpleName()) - .threads(1) - .forks(10) - .timeout(TimeValue.minutes(5)) - .build(); - new Runner(options).run(); - } - - // @Benchmark - public int[][] singleThreadMultiplyOpt() throws Exception { - return MatrixUtil.singleThreadMultiplyOpt(matrixA, matrixB); - } - - // @Benchmark - public int[][] singleThreadMultiplyOpt2() throws Exception { - return MatrixUtil.singleThreadMultiplyOpt(matrixA, matrixB); - } - - @Benchmark - public int[][] concurrentMultiplyStreams() throws Exception { - return MatrixUtil.concurrentMultiplyStreams(matrixA, matrixB, threadNumber); - } - - // @Benchmark - public int[][] concurrentMultiply() throws Exception { - return MatrixUtil.concurrentMultiply(matrixA, matrixB, executor); - } - - @Benchmark - public int[][] concurrentMultiply2() throws Exception { - return MatrixUtil.concurrentMultiply2(matrixA, matrixB, executor); - } - - @Setup - public void setup() { - executor = Executors.newFixedThreadPool(threadNumber); - } - - @TearDown - public void tearDown() { - executor.shutdown(); - } -} \ No newline at end of file diff --git a/src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java b/src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java deleted file mode 100644 index d00a67a..0000000 --- a/src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java +++ /dev/null @@ -1,157 +0,0 @@ -package ru.javaops.masterjava.matrix; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.concurrent.*; -import java.util.stream.IntStream; - -public class MatrixUtil { - - public static int[][] concurrentMultiplyStreams(int[][] matrixA, int[][] matrixB, int threadNumber) - throws InterruptedException, ExecutionException { - - final int matrixSize = matrixA.length; - final int[][] matrixC = new int[matrixSize][matrixSize]; - - new ForkJoinPool(threadNumber).submit( - () -> IntStream.range(0, matrixSize) - .parallel() - .forEach(row -> { - final int[] rowA = matrixA[row]; - final int[] rowC = matrixC[row]; - - for (int idx = 0; idx < matrixSize; idx++) { - final int elA = rowA[idx]; - final int[] rowB = matrixB[idx]; - for (int col = 0; col < matrixSize; col++) { - rowC[col] += elA * rowB[col]; - } - } - })).get(); - - return matrixC; - } - - public static int[][] concurrentMultiply(int[][] matrixA, int[][] matrixB, ExecutorService executor) throws InterruptedException, ExecutionException { - final int matrixSize = matrixA.length; - final int[][] matrixC = new int[matrixSize][]; - - final int[][] matrixBT = new int[matrixSize][matrixSize]; - for (int i = 0; i < matrixSize; i++) { - for (int j = 0; j < matrixSize; j++) { - matrixBT[i][j] = matrixB[j][i]; - } - } - - List> tasks = new ArrayList<>(matrixSize); - for (int j = 0; j < matrixSize; j++) { - final int row = j; - tasks.add(() -> { - final int[] rowC = new int[matrixSize]; - for (int col = 0; col < matrixSize; col++) { - final int[] rowA = matrixA[row]; - final int[] columnB = matrixBT[col]; - int sum = 0; - for (int k = 0; k < matrixSize; k++) { - sum += rowA[k] * columnB[k]; - } - rowC[col] = sum; - } - matrixC[row] = rowC; - return null; - }); - } - executor.invokeAll(tasks); - return matrixC; - } - - public static int[][] concurrentMultiply2(int[][] matrixA, int[][] matrixB, ExecutorService executor) throws InterruptedException { - final int matrixSize = matrixA.length; - final int[][] matrixC = new int[matrixSize][matrixSize]; - final CountDownLatch latch = new CountDownLatch(matrixSize); - - for (int row = 0; row < matrixSize; row++) { - final int[] rowA = matrixA[row]; - final int[] rowC = matrixC[row]; - - executor.submit(() -> { - for (int idx = 0; idx < matrixSize; idx++) { - final int elA = rowA[idx]; - final int[] rowB = matrixB[idx]; - for (int col = 0; col < matrixSize; col++) { - rowC[col] += elA * rowB[col]; - } - } - latch.countDown(); - }); - } - latch.await(); - return matrixC; - } - - public static int[][] singleThreadMultiplyOpt(int[][] matrixA, int[][] matrixB) { - final int matrixSize = matrixA.length; - final int[][] matrixC = new int[matrixSize][matrixSize]; - - for (int col = 0; col < matrixSize; col++) { - final int[] columnB = new int[matrixSize]; - for (int k = 0; k < matrixSize; k++) { - columnB[k] = matrixB[k][col]; - } - - for (int row = 0; row < matrixSize; row++) { - int sum = 0; - final int[] rowA = matrixA[row]; - for (int k = 0; k < matrixSize; k++) { - sum += rowA[k] * columnB[k]; - } - matrixC[row][col] = sum; - } - } - return matrixC; - } - - public static int[][] singleThreadMultiplyOpt2(int[][] matrixA, int[][] matrixB) { - final int matrixSize = matrixA.length; - final int[][] matrixC = new int[matrixSize][matrixSize]; - - for (int row = 0; row < matrixSize; row++) { - final int[] rowA = matrixA[row]; - final int[] rowC = matrixC[row]; - - for (int idx = 0; idx < matrixSize; idx++) { - final int elA = rowA[idx]; - final int[] rowB = matrixB[idx]; - for (int col = 0; col < matrixSize; col++) { - rowC[col] += elA * rowB[col]; - } - } - } - return matrixC; - } - - public static int[][] create(int size) { - int[][] matrix = new int[size][size]; - Random rn = new Random(); - - for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { - matrix[i][j] = rn.nextInt(10); - } - } - return matrix; - } - - public static boolean compare(int[][] matrixA, int[][] matrixB) { - final int matrixSize = matrixA.length; - for (int i = 0; i < matrixSize; i++) { - for (int j = 0; j < matrixSize; j++) { - if (matrixA[i][j] != matrixB[i][j]) { - return false; - } - } - } - return true; - } -} \ No newline at end of file diff --git a/src/main/java/ru/javaops/masterjava/service/MailService.java b/src/main/java/ru/javaops/masterjava/service/MailService.java deleted file mode 100644 index cef46e5..0000000 --- a/src/main/java/ru/javaops/masterjava/service/MailService.java +++ /dev/null @@ -1,141 +0,0 @@ -package ru.javaops.masterjava.service; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.*; -import java.util.stream.Collectors; - -public class MailService { - private static final String OK = "OK"; - - private static final String INTERRUPTED_BY_FAULTS_NUMBER = "+++ Interrupted by faults number"; - private static final String INTERRUPTED_BY_TIMEOUT = "+++ Interrupted by timeout"; - private static final String INTERRUPTED_EXCEPTION = "+++ InterruptedException"; - - private final ExecutorService mailExecutor = Executors.newFixedThreadPool(8); - - public GroupResult sendToList(final String template, final Set emails) throws Exception { - final CompletionService completionService = new ExecutorCompletionService<>(mailExecutor); - - List> futures = emails.stream() - .map(email -> completionService.submit(() -> sendToUser(template, email))) - .collect(Collectors.toList()); - - return new Callable() { - private int success = 0; - private List failed = new ArrayList<>(); - - @Override - public GroupResult call() { - while (!futures.isEmpty()) { - try { - Future future = completionService.poll(10, TimeUnit.SECONDS); - if (future == null) { - return cancelWithFail(INTERRUPTED_BY_TIMEOUT); - } - futures.remove(future); - MailResult mailResult = future.get(); - if (mailResult.isOk()) { - success++; - } else { - failed.add(mailResult); - if (failed.size() >= 5) { - return cancelWithFail(INTERRUPTED_BY_FAULTS_NUMBER); - } - } - } catch (ExecutionException e) { - return cancelWithFail(e.getCause().toString()); - } catch (InterruptedException e) { - return cancelWithFail(INTERRUPTED_EXCEPTION); - } - } -/* - for (Future future : futures) { - MailResult mailResult; - try { - mailResult = future.get(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - return cancelWithFail(INTERRUPTED_EXCEPTION); - } catch (ExecutionException e) { - return cancelWithFail(e.getCause().toString()); - } catch (TimeoutException e) { - return cancelWithFail(INTERRUPTED_BY_TIMEOUT); - } - if (mailResult.isOk()) { - success++; - } else { - failed.add(mailResult); - if (failed.size() >= 5) { - return cancelWithFail(INTERRUPTED_BY_FAULTS_NUMBER); - } - } - } -*/ - return new GroupResult(success, failed, null); - } - - private GroupResult cancelWithFail(String cause) { - futures.forEach(f -> f.cancel(true)); - return new GroupResult(success, failed, cause); - } - }.call(); - } - - // dummy realization - public MailResult sendToUser(String template, String email) throws Exception { - try { - Thread.sleep(500); //delay - } catch (InterruptedException e) { - // log cancel; - return null; - } - return Math.random() < 0.7 ? MailResult.ok(email) : MailResult.error(email, "Error"); - } - - public static class MailResult { - private final String email; - private final String result; - - private static MailResult ok(String email) { - return new MailResult(email, OK); - } - - private static MailResult error(String email, String error) { - return new MailResult(email, error); - } - - public boolean isOk() { - return OK.equals(result); - } - - private MailResult(String email, String cause) { - this.email = email; - this.result = cause; - } - - @Override - public String toString() { - return '(' + email + ',' + result + ')'; - } - } - - public static class GroupResult { - private final int success; // number of successfully sent email - private final List failed; // failed emails with causes - private final String failedCause; // global fail cause - - public GroupResult(int success, List failed, String failedCause) { - this.success = success; - this.failed = failed; - this.failedCause = failedCause; - } - - @Override - public String toString() { - return "Success: " + success + '\n' + - "Failed: " + failed.toString() + '\n' + - (failedCause == null ? "" : "Failed cause" + failedCause); - } - } -} \ No newline at end of file diff --git a/src/main/java/ru/javaops/masterjava/xml/schema/CityType.java b/src/main/java/ru/javaops/masterjava/xml/schema/CityType.java deleted file mode 100644 index 029e352..0000000 --- a/src/main/java/ru/javaops/masterjava/xml/schema/CityType.java +++ /dev/null @@ -1,94 +0,0 @@ - -package ru.javaops.masterjava.xml.schema; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlID; -import javax.xml.bind.annotation.XmlSchemaType; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.XmlValue; -import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; - - -/** - *

Java class for cityType complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="cityType">
- *   <simpleContent>
- *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
- *       <attribute name="id" use="required" type="{http://www.w3.org/2001/XMLSchema}ID" />
- *     </extension>
- *   </simpleContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "cityType", namespace = "http://javaops.ru", propOrder = { - "value" -}) -public class CityType { - - @XmlValue - protected String value; - @XmlAttribute(name = "id", required = true) - @XmlJavaTypeAdapter(CollapsedStringAdapter.class) - @XmlID - @XmlSchemaType(name = "ID") - protected String id; - - /** - * Gets the value of the value property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getValue() { - return value; - } - - /** - * Sets the value of the value property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setValue(String value) { - this.value = value; - } - - /** - * Gets the value of the id property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getId() { - return id; - } - - /** - * Sets the value of the id property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setId(String value) { - this.id = value; - } - -} diff --git a/src/main/java/ru/javaops/masterjava/xml/schema/FlagType.java b/src/main/java/ru/javaops/masterjava/xml/schema/FlagType.java deleted file mode 100644 index eda39fa..0000000 --- a/src/main/java/ru/javaops/masterjava/xml/schema/FlagType.java +++ /dev/null @@ -1,54 +0,0 @@ - -package ru.javaops.masterjava.xml.schema; - -import javax.xml.bind.annotation.XmlEnum; -import javax.xml.bind.annotation.XmlEnumValue; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for flagType. - * - *

The following schema fragment specifies the expected content contained within this class. - *

- *

- * <simpleType name="flagType">
- *   <restriction base="{http://www.w3.org/2001/XMLSchema}string">
- *     <enumeration value="active"/>
- *     <enumeration value="deleted"/>
- *     <enumeration value="superuser"/>
- *   </restriction>
- * </simpleType>
- * 
- * - */ -@XmlType(name = "flagType", namespace = "http://javaops.ru") -@XmlEnum -public enum FlagType { - - @XmlEnumValue("active") - ACTIVE("active"), - @XmlEnumValue("deleted") - DELETED("deleted"), - @XmlEnumValue("superuser") - SUPERUSER("superuser"); - private final String value; - - FlagType(String v) { - value = v; - } - - public String value() { - return value; - } - - public static FlagType fromValue(String v) { - for (FlagType c: FlagType.values()) { - if (c.value.equals(v)) { - return c; - } - } - throw new IllegalArgumentException(v); - } - -} diff --git a/src/main/java/ru/javaops/masterjava/xml/schema/GroupType.java b/src/main/java/ru/javaops/masterjava/xml/schema/GroupType.java deleted file mode 100644 index d504164..0000000 --- a/src/main/java/ru/javaops/masterjava/xml/schema/GroupType.java +++ /dev/null @@ -1,40 +0,0 @@ - -package ru.javaops.masterjava.xml.schema; - -import javax.xml.bind.annotation.XmlEnum; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for groupType. - * - *

The following schema fragment specifies the expected content contained within this class. - *

- *

- * <simpleType name="groupType">
- *   <restriction base="{http://www.w3.org/2001/XMLSchema}string">
- *     <enumeration value="REGISTERING"/>
- *     <enumeration value="CURRENT"/>
- *     <enumeration value="FINISHED"/>
- *   </restriction>
- * </simpleType>
- * 
- * - */ -@XmlType(name = "groupType", namespace = "http://javaops.ru") -@XmlEnum -public enum GroupType { - - REGISTERING, - CURRENT, - FINISHED; - - public String value() { - return name(); - } - - public static GroupType fromValue(String v) { - return valueOf(v); - } - -} diff --git a/src/main/java/ru/javaops/masterjava/xml/schema/ObjectFactory.java b/src/main/java/ru/javaops/masterjava/xml/schema/ObjectFactory.java deleted file mode 100644 index bfb3932..0000000 --- a/src/main/java/ru/javaops/masterjava/xml/schema/ObjectFactory.java +++ /dev/null @@ -1,109 +0,0 @@ - -package ru.javaops.masterjava.xml.schema; - -import javax.xml.bind.JAXBElement; -import javax.xml.bind.annotation.XmlElementDecl; -import javax.xml.bind.annotation.XmlRegistry; -import javax.xml.namespace.QName; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the ru.javaops.masterjava.xml.schema package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - private final static QName _City_QNAME = new QName("http://javaops.ru", "City"); - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: ru.javaops.masterjava.xml.schema - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link Project } - * - */ - public Project createProject() { - return new Project(); - } - - /** - * Create an instance of {@link Payload } - * - */ - public Payload createPayload() { - return new Payload(); - } - - /** - * Create an instance of {@link Project.Group } - * - */ - public Project.Group createProjectGroup() { - return new Project.Group(); - } - - /** - * Create an instance of {@link User } - * - */ - public User createUser() { - return new User(); - } - - /** - * Create an instance of {@link Payload.Projects } - * - */ - public Payload.Projects createPayloadProjects() { - return new Payload.Projects(); - } - - /** - * Create an instance of {@link Payload.Cities } - * - */ - public Payload.Cities createPayloadCities() { - return new Payload.Cities(); - } - - /** - * Create an instance of {@link Payload.Users } - * - */ - public Payload.Users createPayloadUsers() { - return new Payload.Users(); - } - - /** - * Create an instance of {@link CityType } - * - */ - public CityType createCityType() { - return new CityType(); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CityType }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://javaops.ru", name = "City") - public JAXBElement createCity(CityType value) { - return new JAXBElement(_City_QNAME, CityType.class, null, value); - } - -} diff --git a/src/main/java/ru/javaops/masterjava/xml/schema/Payload.java b/src/main/java/ru/javaops/masterjava/xml/schema/Payload.java deleted file mode 100644 index 9d4cc30..0000000 --- a/src/main/java/ru/javaops/masterjava/xml/schema/Payload.java +++ /dev/null @@ -1,328 +0,0 @@ - -package ru.javaops.masterjava.xml.schema; - -import javax.xml.bind.annotation.*; -import java.util.ArrayList; -import java.util.List; - - -/** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType>
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="Projects">
- *           <complexType>
- *             <complexContent>
- *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *                 <sequence maxOccurs="unbounded">
- *                   <element ref="{http://javaops.ru}Project"/>
- *                 </sequence>
- *               </restriction>
- *             </complexContent>
- *           </complexType>
- *         </element>
- *         <element name="Cities">
- *           <complexType>
- *             <complexContent>
- *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *                 <sequence maxOccurs="unbounded">
- *                   <element ref="{http://javaops.ru}City"/>
- *                 </sequence>
- *               </restriction>
- *             </complexContent>
- *           </complexType>
- *         </element>
- *         <element name="Users">
- *           <complexType>
- *             <complexContent>
- *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *                 <sequence maxOccurs="unbounded" minOccurs="0">
- *                   <element ref="{http://javaops.ru}User"/>
- *                 </sequence>
- *               </restriction>
- *             </complexContent>
- *           </complexType>
- *         </element>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "", propOrder = { - "projects", - "cities", - "users" -}) -@XmlRootElement(name = "Payload", namespace = "http://javaops.ru") -public class Payload { - - @XmlElement(name = "Projects", namespace = "http://javaops.ru", required = true) - protected Payload.Projects projects; - @XmlElement(name = "Cities", namespace = "http://javaops.ru", required = true) - protected Payload.Cities cities; - @XmlElement(name = "Users", namespace = "http://javaops.ru", required = true) - protected Payload.Users users; - - /** - * Gets the value of the projects property. - * - * @return - * possible object is - * {@link Payload.Projects } - * - */ - public Payload.Projects getProjects() { - return projects; - } - - /** - * Sets the value of the projects property. - * - * @param value - * allowed object is - * {@link Payload.Projects } - * - */ - public void setProjects(Payload.Projects value) { - this.projects = value; - } - - /** - * Gets the value of the cities property. - * - * @return - * possible object is - * {@link Payload.Cities } - * - */ - public Payload.Cities getCities() { - return cities; - } - - /** - * Sets the value of the cities property. - * - * @param value - * allowed object is - * {@link Payload.Cities } - * - */ - public void setCities(Payload.Cities value) { - this.cities = value; - } - - /** - * Gets the value of the users property. - * - * @return - * possible object is - * {@link Payload.Users } - * - */ - public Payload.Users getUsers() { - return users; - } - - /** - * Sets the value of the users property. - * - * @param value - * allowed object is - * {@link Payload.Users } - * - */ - public void setUsers(Payload.Users value) { - this.users = value; - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-     * <complexType>
-     *   <complexContent>
-     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-     *       <sequence maxOccurs="unbounded">
-     *         <element ref="{http://javaops.ru}City"/>
-     *       </sequence>
-     *     </restriction>
-     *   </complexContent>
-     * </complexType>
-     * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = { - "city" - }) - public static class Cities { - - @XmlElement(name = "City", namespace = "http://javaops.ru", required = true) - protected List city; - - /** - * Gets the value of the city property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the city property. - * - *

- * For example, to add a new item, do as follows: - *

-         *    getCity().add(newItem);
-         * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link CityType } - * - * - */ - public List getCity() { - if (city == null) { - city = new ArrayList(); - } - return this.city; - } - - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-     * <complexType>
-     *   <complexContent>
-     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-     *       <sequence maxOccurs="unbounded">
-     *         <element ref="{http://javaops.ru}Project"/>
-     *       </sequence>
-     *     </restriction>
-     *   </complexContent>
-     * </complexType>
-     * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = { - "project" - }) - public static class Projects { - - @XmlElement(name = "Project", namespace = "http://javaops.ru", required = true) - protected List project; - - /** - * Gets the value of the project property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the project property. - * - *

- * For example, to add a new item, do as follows: - *

-         *    getProject().add(newItem);
-         * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link Project } - * - * - */ - public List getProject() { - if (project == null) { - project = new ArrayList(); - } - return this.project; - } - - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-     * <complexType>
-     *   <complexContent>
-     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-     *       <sequence maxOccurs="unbounded" minOccurs="0">
-     *         <element ref="{http://javaops.ru}User"/>
-     *       </sequence>
-     *     </restriction>
-     *   </complexContent>
-     * </complexType>
-     * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = { - "user" - }) - public static class Users { - - @XmlElement(name = "User", namespace = "http://javaops.ru") - protected List user; - - /** - * Gets the value of the user property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the user property. - * - *

- * For example, to add a new item, do as follows: - *

-         *    getUser().add(newItem);
-         * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link User } - * - * - */ - public List getUser() { - if (user == null) { - user = new ArrayList(); - } - return this.user; - } - - } - -} diff --git a/src/main/java/ru/javaops/masterjava/xml/schema/Project.java b/src/main/java/ru/javaops/masterjava/xml/schema/Project.java deleted file mode 100644 index 180a997..0000000 --- a/src/main/java/ru/javaops/masterjava/xml/schema/Project.java +++ /dev/null @@ -1,216 +0,0 @@ - -package ru.javaops.masterjava.xml.schema; - -import javax.xml.bind.annotation.*; -import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; -import java.util.ArrayList; -import java.util.List; - - -/** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType>
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="description" type="{http://www.w3.org/2001/XMLSchema}string"/>
- *         <sequence maxOccurs="unbounded">
- *           <element name="Group">
- *             <complexType>
- *               <complexContent>
- *                 <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *                   <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}ID" />
- *                   <attribute name="type" use="required" type="{http://javaops.ru}groupType" />
- *                 </restriction>
- *               </complexContent>
- *             </complexType>
- *           </element>
- *         </sequence>
- *       </sequence>
- *       <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "", propOrder = { - "description", - "group" -}) -@XmlRootElement(name = "Project", namespace = "http://javaops.ru") -public class Project { - - @XmlElement(namespace = "http://javaops.ru", required = true) - protected String description; - @XmlElement(name = "Group", namespace = "http://javaops.ru", required = true) - protected List group; - @XmlAttribute(name = "name", required = true) - protected String name; - - /** - * Gets the value of the description property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getDescription() { - return description; - } - - /** - * Sets the value of the description property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setDescription(String value) { - this.description = value; - } - - /** - * Gets the value of the group property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the group property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getGroup().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link Project.Group } - * - * - */ - public List getGroup() { - if (group == null) { - group = new ArrayList(); - } - return this.group; - } - - /** - * Gets the value of the name property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getName() { - return name; - } - - /** - * Sets the value of the name property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setName(String value) { - this.name = value; - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-     * <complexType>
-     *   <complexContent>
-     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-     *       <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}ID" />
-     *       <attribute name="type" use="required" type="{http://javaops.ru}groupType" />
-     *     </restriction>
-     *   </complexContent>
-     * </complexType>
-     * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "") - public static class Group { - - @XmlAttribute(name = "name", required = true) - @XmlJavaTypeAdapter(CollapsedStringAdapter.class) - @XmlID - @XmlSchemaType(name = "ID") - protected String name; - @XmlAttribute(name = "type", required = true) - protected GroupType type; - - /** - * Gets the value of the name property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getName() { - return name; - } - - /** - * Sets the value of the name property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setName(String value) { - this.name = value; - } - - /** - * Gets the value of the type property. - * - * @return - * possible object is - * {@link GroupType } - * - */ - public GroupType getType() { - return type; - } - - /** - * Sets the value of the type property. - * - * @param value - * allowed object is - * {@link GroupType } - * - */ - public void setType(GroupType value) { - this.type = value; - } - - } - -} diff --git a/src/main/java/ru/javaops/masterjava/xml/schema/User.java b/src/main/java/ru/javaops/masterjava/xml/schema/User.java deleted file mode 100644 index b2cc1c4..0000000 --- a/src/main/java/ru/javaops/masterjava/xml/schema/User.java +++ /dev/null @@ -1,180 +0,0 @@ - -package ru.javaops.masterjava.xml.schema; - -import javax.xml.bind.annotation.*; -import java.util.ArrayList; -import java.util.List; - - -/** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType>
- *   <simpleContent>
- *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
- *       <attribute name="email" type="{http://javaops.ru}emailAddressType" />
- *       <attribute name="flag" use="required" type="{http://javaops.ru}flagType" />
- *       <attribute name="city" use="required" type="{http://www.w3.org/2001/XMLSchema}IDREF" />
- *       <attribute name="groupRefs" type="{http://www.w3.org/2001/XMLSchema}IDREFS" />
- *     </extension>
- *   </simpleContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "", propOrder = { - "value" -}) -@XmlRootElement(name = "User", namespace = "http://javaops.ru") -public class User { - - @XmlValue - protected String value; - @XmlAttribute(name = "email") - protected String email; - @XmlAttribute(name = "flag", required = true) - protected FlagType flag; - @XmlAttribute(name = "city", required = true) - @XmlIDREF - @XmlSchemaType(name = "IDREF") - protected Object city; - @XmlAttribute(name = "groupRefs") - @XmlIDREF - @XmlSchemaType(name = "IDREFS") - protected List groupRefs; - - /** - * Gets the value of the value property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getValue() { - return value; - } - - /** - * Sets the value of the value property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setValue(String value) { - this.value = value; - } - - /** - * Gets the value of the email property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getEmail() { - return email; - } - - /** - * Sets the value of the email property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setEmail(String value) { - this.email = value; - } - - /** - * Gets the value of the flag property. - * - * @return - * possible object is - * {@link FlagType } - * - */ - public FlagType getFlag() { - return flag; - } - - /** - * Sets the value of the flag property. - * - * @param value - * allowed object is - * {@link FlagType } - * - */ - public void setFlag(FlagType value) { - this.flag = value; - } - - /** - * Gets the value of the city property. - * - * @return - * possible object is - * {@link Object } - * - */ - public Object getCity() { - return city; - } - - /** - * Sets the value of the city property. - * - * @param value - * allowed object is - * {@link Object } - * - */ - public void setCity(Object value) { - this.city = value; - } - - /** - * Gets the value of the groupRefs property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the groupRefs property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getGroupRefs().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link Object } - * - * - */ - public List getGroupRefs() { - if (groupRefs == null) { - groupRefs = new ArrayList(); - } - return this.groupRefs; - } - - @Override - public String toString() { - return value + '(' + email + ')'; - } -} diff --git a/src/main/java/ru/javaops/masterjava/xml/util/JaxbMarshaller.java b/src/main/java/ru/javaops/masterjava/xml/util/JaxbMarshaller.java deleted file mode 100644 index d600680..0000000 --- a/src/main/java/ru/javaops/masterjava/xml/util/JaxbMarshaller.java +++ /dev/null @@ -1,39 +0,0 @@ -package ru.javaops.masterjava.xml.util; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.bind.PropertyException; -import javax.xml.validation.Schema; -import java.io.StringWriter; -import java.io.Writer; - -public class JaxbMarshaller { - private Marshaller marshaller; - - public JaxbMarshaller(JAXBContext ctx) throws JAXBException { - marshaller = ctx.createMarshaller(); - marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); - marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); - marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true); - } - - public void setProperty(String prop, Object value) throws PropertyException { - marshaller.setProperty(prop, value); - } - - public synchronized void setSchema(Schema schema) { - marshaller.setSchema(schema); - } - - public String marshal(Object instance) throws JAXBException { - StringWriter sw = new StringWriter(); - marshal(instance, sw); - return sw.toString(); - } - - public synchronized void marshal(Object instance, Writer writer) throws JAXBException { - marshaller.marshal(instance, writer); - } - -} diff --git a/src/main/java/ru/javaops/masterjava/xml/util/JaxbParser.java b/src/main/java/ru/javaops/masterjava/xml/util/JaxbParser.java deleted file mode 100644 index 563d53b..0000000 --- a/src/main/java/ru/javaops/masterjava/xml/util/JaxbParser.java +++ /dev/null @@ -1,93 +0,0 @@ -package ru.javaops.masterjava.xml.util; - -import org.xml.sax.SAXException; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.PropertyException; -import javax.xml.stream.XMLStreamReader; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import java.io.*; - - -/** - * Marshalling/Unmarshalling JAXB helper - * XML Facade - */ -public class JaxbParser { - - protected JaxbMarshaller jaxbMarshaller; - protected JaxbUnmarshaller jaxbUnmarshaller; - protected Schema schema; - - public JaxbParser(Class... classesToBeBound) { - try { - init(JAXBContext.newInstance(classesToBeBound)); - } catch (JAXBException e) { - throw new IllegalArgumentException(e); - } - } - - // http://stackoverflow.com/questions/30643802/what-is-jaxbcontext-newinstancestring-contextpath - public JaxbParser(String context) { - try { - init(JAXBContext.newInstance(context)); - } catch (JAXBException e) { - throw new IllegalArgumentException(e); - } - } - - private void init(JAXBContext ctx) throws JAXBException { - jaxbMarshaller = new JaxbMarshaller(ctx); - jaxbUnmarshaller = new JaxbUnmarshaller(ctx); - } - - // Unmarshaller - public T unmarshal(InputStream is) throws JAXBException { - return (T) jaxbUnmarshaller.unmarshal(is); - } - - public T unmarshal(Reader reader) throws JAXBException { - return (T) jaxbUnmarshaller.unmarshal(reader); - } - - public T unmarshal(String str) throws JAXBException { - return (T) jaxbUnmarshaller.unmarshal(str); - } - - public T unmarshal(XMLStreamReader reader, Class elementClass) throws JAXBException { - return jaxbUnmarshaller.unmarshal(reader, elementClass); - } - - // Marshaller - public void setMarshallerProperty(String prop, Object value) { - try { - jaxbMarshaller.setProperty(prop, value); - } catch (PropertyException e) { - throw new IllegalArgumentException(e); - } - } - - public String marshal(Object instance) throws JAXBException { - return jaxbMarshaller.marshal(instance); - } - - public void marshal(Object instance, Writer writer) throws JAXBException { - jaxbMarshaller.marshal(instance, writer); - } - - public void setSchema(Schema schema) { - this.schema = schema; - jaxbUnmarshaller.setSchema(schema); - jaxbMarshaller.setSchema(schema); - } - - public void validate(String str) throws IOException, SAXException { - validate(new StringReader(str)); - } - - public void validate(Reader reader) throws IOException, SAXException { - schema.newValidator().validate(new StreamSource(reader)); - } -} diff --git a/src/main/java/ru/javaops/masterjava/xml/util/JaxbUnmarshaller.java b/src/main/java/ru/javaops/masterjava/xml/util/JaxbUnmarshaller.java deleted file mode 100644 index 1de89d8..0000000 --- a/src/main/java/ru/javaops/masterjava/xml/util/JaxbUnmarshaller.java +++ /dev/null @@ -1,38 +0,0 @@ -package ru.javaops.masterjava.xml.util; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.stream.XMLStreamReader; -import javax.xml.validation.Schema; -import java.io.InputStream; -import java.io.Reader; -import java.io.StringReader; - -public class JaxbUnmarshaller { - private Unmarshaller unmarshaller; - - public JaxbUnmarshaller(JAXBContext ctx) throws JAXBException { - unmarshaller = ctx.createUnmarshaller(); - } - - public synchronized void setSchema(Schema schema) { - unmarshaller.setSchema(schema); - } - - public synchronized Object unmarshal(InputStream is) throws JAXBException { - return unmarshaller.unmarshal(is); - } - - public synchronized Object unmarshal(Reader reader) throws JAXBException { - return unmarshaller.unmarshal(reader); - } - - public Object unmarshal(String str) throws JAXBException { - return unmarshal(new StringReader(str)); - } - - public synchronized T unmarshal(XMLStreamReader reader, Class elementClass) throws JAXBException { - return unmarshaller.unmarshal(reader, elementClass).getValue(); - } -} \ No newline at end of file diff --git a/src/main/java/ru/javaops/masterjava/xml/util/Schemas.java b/src/main/java/ru/javaops/masterjava/xml/util/Schemas.java deleted file mode 100644 index 42f41df..0000000 --- a/src/main/java/ru/javaops/masterjava/xml/util/Schemas.java +++ /dev/null @@ -1,48 +0,0 @@ -package ru.javaops.masterjava.xml.util; - -import com.google.common.io.Resources; -import org.xml.sax.SAXException; - -import javax.xml.XMLConstants; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; -import java.io.File; -import java.io.StringReader; -import java.net.URL; - - -public class Schemas { - - // SchemaFactory is not thread-safe - private static final SchemaFactory SCHEMA_FACTORY = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - - public static synchronized Schema ofString(String xsd) { - try { - return SCHEMA_FACTORY.newSchema(new StreamSource(new StringReader(xsd))); - } catch (SAXException e) { - throw new IllegalArgumentException(e); - } - } - - public static synchronized Schema ofClasspath(String resource) { - // http://digitalsanctum.com/2012/11/30/how-to-read-file-contents-in-java-the-easy-way-with-guava/ - return ofURL(Resources.getResource(resource)); - } - - public static synchronized Schema ofURL(URL url) { - try { - return SCHEMA_FACTORY.newSchema(url); - } catch (SAXException e) { - throw new IllegalArgumentException(e); - } - } - - public static synchronized Schema ofFile(File file) { - try { - return SCHEMA_FACTORY.newSchema(file); - } catch (SAXException e) { - throw new IllegalArgumentException(e); - } - } -} diff --git a/src/main/java/ru/javaops/masterjava/xml/util/StaxStreamProcessor.java b/src/main/java/ru/javaops/masterjava/xml/util/StaxStreamProcessor.java deleted file mode 100644 index 5878118..0000000 --- a/src/main/java/ru/javaops/masterjava/xml/util/StaxStreamProcessor.java +++ /dev/null @@ -1,79 +0,0 @@ -package ru.javaops.masterjava.xml.util; - -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; -import javax.xml.stream.events.XMLEvent; -import java.io.InputStream; - -public class StaxStreamProcessor implements AutoCloseable { - private static final XMLInputFactory FACTORY = XMLInputFactory.newInstance(); - - private final XMLStreamReader reader; - - public StaxStreamProcessor(InputStream is) throws XMLStreamException { - reader = FACTORY.createXMLStreamReader(is); - } - - public boolean startElement(String element, String parent) throws XMLStreamException { - while (reader.hasNext()) { - int event = reader.next(); - if (parent != null && isElementEnd(event, parent)) { - return false; - } - if (isElementStart(event, element)) { - return true; - } - } - return false; - } - - private boolean isElementStart(int event, String el) { - return event == XMLEvent.START_ELEMENT && el.equals(reader.getLocalName()); - } - - private boolean isElementEnd(int event, String el) { - return event == XMLEvent.END_ELEMENT && el.equals(reader.getLocalName()); - } - - public XMLStreamReader getReader() { - return reader; - } - - public String getAttribute(String name) throws XMLStreamException { - return reader.getAttributeValue(null, name); - } - - public boolean doUntil(int stopEvent, String value) throws XMLStreamException { - while (reader.hasNext()) { - int event = reader.next(); - if (event == stopEvent && value.equals(getValue(event))) { - return true; - } - } - return false; - } - - public String getValue(int event) throws XMLStreamException { - return (event == XMLEvent.CHARACTERS) ? reader.getText() : reader.getLocalName(); - } - - public String getElementValue(String element) throws XMLStreamException { - return doUntil(XMLEvent.START_ELEMENT, element) ? reader.getElementText() : null; - } - - public String getText() throws XMLStreamException { - return reader.getElementText(); - } - - @Override - public void close() { - if (reader != null) { - try { - reader.close(); - } catch (XMLStreamException e) { - // empty - } - } - } -} diff --git a/src/main/java/ru/javaops/masterjava/xml/util/XPathProcessor.java b/src/main/java/ru/javaops/masterjava/xml/util/XPathProcessor.java deleted file mode 100644 index 63baae5..0000000 --- a/src/main/java/ru/javaops/masterjava/xml/util/XPathProcessor.java +++ /dev/null @@ -1,58 +0,0 @@ -package ru.javaops.masterjava.xml.util; - -import org.w3c.dom.Document; -import org.xml.sax.SAXException; - -import javax.xml.namespace.QName; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathExpression; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathFactory; -import java.io.IOException; -import java.io.InputStream; - -public class XPathProcessor { - private static final DocumentBuilderFactory DOCUMENT_FACTORY = DocumentBuilderFactory.newInstance(); - private static final DocumentBuilder DOCUMENT_BUILDER; - - private static final XPathFactory XPATH_FACTORY = XPathFactory.newInstance(); - private static final XPath XPATH = XPATH_FACTORY.newXPath(); - - static { - DOCUMENT_FACTORY.setNamespaceAware(true); - try { - DOCUMENT_BUILDER = DOCUMENT_FACTORY.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - throw new IllegalStateException(e); - } - } - - private final Document doc; - - public XPathProcessor(InputStream is) { - try { - doc = DOCUMENT_BUILDER.parse(is); - } catch (SAXException | IOException e) { - throw new IllegalArgumentException(e); - } - } - - public static synchronized XPathExpression getExpression(String exp) { - try { - return XPATH.compile(exp); - } catch (XPathExpressionException e) { - throw new IllegalArgumentException(e); - } - } - - public T evaluate(XPathExpression expression, QName type) { - try { - return (T) expression.evaluate(doc, type); - } catch (XPathExpressionException e) { - throw new IllegalArgumentException(e); - } - } -} diff --git a/src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java b/src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java deleted file mode 100644 index 083febb..0000000 --- a/src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.javaops.masterjava.xml.util; - -import javax.xml.transform.*; -import javax.xml.transform.stream.StreamResult; -import javax.xml.transform.stream.StreamSource; -import java.io.*; -import java.nio.charset.StandardCharsets; - -public class XsltProcessor { - private static TransformerFactory FACTORY = TransformerFactory.newInstance(); - private final Transformer xformer; - - public XsltProcessor(InputStream xslInputStream) { - this(new BufferedReader(new InputStreamReader(xslInputStream, StandardCharsets.UTF_8))); - } - - public XsltProcessor(Reader xslReader) { - try { - Templates template = FACTORY.newTemplates(new StreamSource(xslReader)); - xformer = template.newTransformer(); - } catch (TransformerConfigurationException e) { - throw new IllegalStateException("XSLT transformer creation failed: " + e.toString(), e); - } - } - - public String transform(InputStream xmlInputStream) throws TransformerException { - StringWriter out = new StringWriter(); - transform(xmlInputStream, out); - return out.getBuffer().toString(); - } - - public void transform(InputStream xmlInputStream, Writer result) throws TransformerException { - transform(new BufferedReader(new InputStreamReader(xmlInputStream, StandardCharsets.UTF_8)), result); - } - - public void transform(Reader sourceReader, Writer result) throws TransformerException { - xformer.transform(new StreamSource(sourceReader), new StreamResult(result)); - } - - public static String getXsltHeader(String xslt) { - return "\n"; - } - - public void setParameter(String name, String value) { - xformer.setParameter(name, value); - } -} diff --git a/src/main/resources/cities.xsl b/src/main/resources/cities.xsl deleted file mode 100644 index 1c50912..0000000 --- a/src/main/resources/cities.xsl +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/groups.xsl b/src/main/resources/groups.xsl deleted file mode 100644 index c5ade36..0000000 --- a/src/main/resources/groups.xsl +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - <xsl:value-of select="$projectName"/> groups - - - -

- groups -

- - - - - - - - - - - -
GroupType
- - - -
- - -
-
\ No newline at end of file diff --git a/src/main/resources/payload.xsd b/src/main/resources/payload.xsd deleted file mode 100644 index 3d545ec..0000000 --- a/src/main/resources/payload.xsd +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/test/java/ru/javaops/masterjava/MainXml.java b/src/test/java/ru/javaops/masterjava/MainXml.java deleted file mode 100644 index 8f57825..0000000 --- a/src/test/java/ru/javaops/masterjava/MainXml.java +++ /dev/null @@ -1,140 +0,0 @@ -package ru.javaops.masterjava; - -import com.google.common.base.Splitter; -import com.google.common.io.Resources; -import j2html.tags.ContainerTag; -import one.util.streamex.StreamEx; -import ru.javaops.masterjava.xml.schema.ObjectFactory; -import ru.javaops.masterjava.xml.schema.Payload; -import ru.javaops.masterjava.xml.schema.Project; -import ru.javaops.masterjava.xml.schema.User; -import ru.javaops.masterjava.xml.util.JaxbParser; -import ru.javaops.masterjava.xml.util.Schemas; -import ru.javaops.masterjava.xml.util.StaxStreamProcessor; -import ru.javaops.masterjava.xml.util.XsltProcessor; - -import javax.xml.stream.events.XMLEvent; -import java.io.InputStream; -import java.io.Writer; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.*; -import java.util.stream.Collectors; - -import static com.google.common.base.Strings.nullToEmpty; -import static j2html.TagCreator.*; - -public class MainXml { - - private static final Comparator USER_COMPARATOR = Comparator.comparing(User::getValue).thenComparing(User::getEmail); - - public static void main(String[] args) throws Exception { - if (args.length != 1) { - System.out.println("Required argument: projectName"); - System.exit(1); - } - String projectName = args[0]; - URL payloadUrl = Resources.getResource("payload.xml"); - - Set users = parseByJaxb(projectName, payloadUrl); - users.forEach(System.out::println); - - System.out.println(); - String html = toHtml(users, projectName); - System.out.println(html); - try (Writer writer = Files.newBufferedWriter(Paths.get("out/users.html"))) { - writer.write(html); - } - - System.out.println(); - users = processByStax(projectName, payloadUrl); - users.forEach(System.out::println); - - System.out.println(); - html = transform(projectName, payloadUrl); - try (Writer writer = Files.newBufferedWriter(Paths.get("out/groups.html"))) { - writer.write(html); - } - } - - private static Set parseByJaxb(String projectName, URL payloadUrl) throws Exception { - JaxbParser parser = new JaxbParser(ObjectFactory.class); - parser.setSchema(Schemas.ofClasspath("payload.xsd")); - Payload payload; - try (InputStream is = payloadUrl.openStream()) { - payload = parser.unmarshal(is); - } - - Project project = StreamEx.of(payload.getProjects().getProject()) - .filter(p -> p.getName().equals(projectName)) - .findAny() - .orElseThrow(() -> new IllegalArgumentException("Invalid project name '" + projectName + '\'')); - - final Set groups = new HashSet<>(project.getGroup()); // identity compare - return StreamEx.of(payload.getUsers().getUser()) - .filter(u -> !Collections.disjoint(groups, u.getGroupRefs())) - .collect( - Collectors.toCollection(() -> new TreeSet<>(USER_COMPARATOR)) - ); - } - - private static Set processByStax(String projectName, URL payloadUrl) throws Exception { - - try (InputStream is = payloadUrl.openStream()) { - StaxStreamProcessor processor = new StaxStreamProcessor(is); - final Set groupNames = new HashSet<>(); - - // Projects loop - projects: - while (processor.startElement("Project", "Projects")) { - if (projectName.equals(processor.getAttribute("name"))) { - while (processor.startElement("Group", "Project")) { - groupNames.add(processor.getAttribute("name")); - } - break; - } - } - if (groupNames.isEmpty()) { - throw new IllegalArgumentException("Invalid " + projectName + " or no groups"); - } - - // Users loop - Set users = new TreeSet<>(USER_COMPARATOR); - - JaxbParser parser = new JaxbParser(User.class); - while (processor.doUntil(XMLEvent.START_ELEMENT, "User")) { - String groupRefs = processor.getAttribute("groupRefs"); - if (!Collections.disjoint(groupNames, Splitter.on(' ').splitToList(nullToEmpty(groupRefs)))) { - User user = parser.unmarshal(processor.getReader(), User.class); - users.add(user); - } - } - return users; - } - } - - private static String toHtml(Set users, String projectName) { - final ContainerTag table = table().with( - tr().with(th("FullName"), th("email"))) - .attr("border", "1") - .attr("cellpadding", "8") - .attr("cellspacing", "0"); - - users.forEach(u -> table.with(tr().with(td(u.getValue()), td(u.getEmail())))); - - return html().with( - head().with(title(projectName + " users")), - body().with(h1(projectName + " users"), table) - ).render(); - } - - private static String transform(String projectName, URL payloadUrl) throws Exception { - URL xsl = Resources.getResource("groups.xsl"); - try (InputStream xmlStream = payloadUrl.openStream(); InputStream xslStream = xsl.openStream()) { - XsltProcessor processor = new XsltProcessor(xslStream); - processor.setParameter("projectName", projectName); - return processor.transform(xmlStream); - } - } -} diff --git a/src/test/java/ru/javaops/masterjava/xml/util/JaxbParserTest.java b/src/test/java/ru/javaops/masterjava/xml/util/JaxbParserTest.java deleted file mode 100644 index 6232654..0000000 --- a/src/test/java/ru/javaops/masterjava/xml/util/JaxbParserTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package ru.javaops.masterjava.xml.util; - -import com.google.common.io.Resources; -import org.junit.Test; -import ru.javaops.masterjava.xml.schema.CityType; -import ru.javaops.masterjava.xml.schema.ObjectFactory; -import ru.javaops.masterjava.xml.schema.Payload; - -import javax.xml.bind.JAXBElement; -import javax.xml.namespace.QName; - -public class JaxbParserTest { - private static final JaxbParser JAXB_PARSER = new JaxbParser(ObjectFactory.class); - - static { - JAXB_PARSER.setSchema(Schemas.ofClasspath("payload.xsd")); - } - - @Test - public void testPayload() throws Exception { -// JaxbParserTest.class.getResourceAsStream("/city.xml") - Payload payload = JAXB_PARSER.unmarshal( - Resources.getResource("payload.xml").openStream()); - String strPayload = JAXB_PARSER.marshal(payload); - JAXB_PARSER.validate(strPayload); - System.out.println(strPayload); - } - - @Test - public void testCity() throws Exception { - JAXBElement cityElement = JAXB_PARSER.unmarshal( - Resources.getResource("city.xml").openStream()); - CityType city = cityElement.getValue(); - JAXBElement cityElement2 = - new JAXBElement<>(new QName("http://javaops.ru", "City"), CityType.class, city); - String strCity = JAXB_PARSER.marshal(cityElement2); - JAXB_PARSER.validate(strCity); - System.out.println(strCity); - } -} \ No newline at end of file diff --git a/src/test/java/ru/javaops/masterjava/xml/util/StaxStreamProcessorTest.java b/src/test/java/ru/javaops/masterjava/xml/util/StaxStreamProcessorTest.java deleted file mode 100644 index fd55963..0000000 --- a/src/test/java/ru/javaops/masterjava/xml/util/StaxStreamProcessorTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package ru.javaops.masterjava.xml.util; - -import com.google.common.io.Resources; -import org.junit.Test; - -import javax.xml.stream.XMLStreamReader; -import javax.xml.stream.events.XMLEvent; - -public class StaxStreamProcessorTest { - @Test - public void readCities() throws Exception { - try (StaxStreamProcessor processor = - new StaxStreamProcessor(Resources.getResource("payload.xml").openStream())) { - XMLStreamReader reader = processor.getReader(); - while (reader.hasNext()) { - int event = reader.next(); - if (event == XMLEvent.START_ELEMENT) { - if ("City".equals(reader.getLocalName())) { - System.out.println(reader.getElementText()); - } - } - } - } - } - - @Test - public void readCities2() throws Exception { - try (StaxStreamProcessor processor = - new StaxStreamProcessor(Resources.getResource("payload.xml").openStream())) { - String city; - while ((city = processor.getElementValue("City")) != null) { - System.out.println(city); - } - } - } -} \ No newline at end of file diff --git a/src/test/java/ru/javaops/masterjava/xml/util/XPathProcessorTest.java b/src/test/java/ru/javaops/masterjava/xml/util/XPathProcessorTest.java deleted file mode 100644 index 199f676..0000000 --- a/src/test/java/ru/javaops/masterjava/xml/util/XPathProcessorTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.javaops.masterjava.xml.util; - -import com.google.common.io.Resources; -import org.junit.Test; -import org.w3c.dom.NodeList; - -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpression; -import java.io.InputStream; -import java.util.stream.IntStream; - -public class XPathProcessorTest { - @Test - public void getCities() throws Exception { - try (InputStream is = - Resources.getResource("payload.xml").openStream()) { - XPathProcessor processor = new XPathProcessor(is); - XPathExpression expression = - XPathProcessor.getExpression("/*[name()='Payload']/*[name()='Cities']/*[name()='City']/text()"); - NodeList nodes = processor.evaluate(expression, XPathConstants.NODESET); - IntStream.range(0, nodes.getLength()).forEach( - i -> System.out.println(nodes.item(i).getNodeValue()) - ); - } - } -} \ No newline at end of file diff --git a/src/test/java/ru/javaops/masterjava/xml/util/XsltProcessorTest.java b/src/test/java/ru/javaops/masterjava/xml/util/XsltProcessorTest.java deleted file mode 100644 index d7f42a6..0000000 --- a/src/test/java/ru/javaops/masterjava/xml/util/XsltProcessorTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package ru.javaops.masterjava.xml.util; - -import com.google.common.io.Resources; -import org.junit.Test; - -import java.io.InputStream; - -public class XsltProcessorTest { - @Test - public void transform() throws Exception { - try (InputStream xslInputStream = Resources.getResource("cities.xsl").openStream(); - InputStream xmlInputStream = Resources.getResource("payload.xml").openStream()) { - - XsltProcessor processor = new XsltProcessor(xslInputStream); - System.out.println(processor.transform(xmlInputStream)); - } - } -} diff --git a/src/test/resources/city.xml b/src/test/resources/city.xml deleted file mode 100644 index 8b0abcf..0000000 --- a/src/test/resources/city.xml +++ /dev/null @@ -1,4 +0,0 @@ -Санкт-Петербург - \ No newline at end of file diff --git a/src/test/resources/payload.xml b/src/test/resources/payload.xml deleted file mode 100644 index fadf8c6..0000000 --- a/src/test/resources/payload.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - Topjava - - - - - - Masterjava - - - - - Санкт-Петербург - Москва - Киев - Минск - - - Full Name - Admin - Deleted - User1 - User2 - User3 - - \ No newline at end of file diff --git a/test/pom.xml b/test/pom.xml new file mode 100644 index 0000000..805d56d --- /dev/null +++ b/test/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + + ru.javaops + parent + ../parent/pom.xml + 1.0-SNAPSHOT + + + test + 1.0-SNAPSHOT + Test + jar + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.2 + + + package + + shade + + + benchmarks + + + org.openjdk.jmh.Main + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + + + + + + + + org.openjdk.jmh + jmh-core + 1.19 + + + org.openjdk.jmh + jmh-generator-annprocess + 1.19 + provided + + + \ No newline at end of file diff --git a/upload/pom.xml b/upload/pom.xml index 7cac01c..2ed2d46 100644 --- a/upload/pom.xml +++ b/upload/pom.xml @@ -6,8 +6,8 @@ ru.javaops - parent - ../parent/pom.xml + parent-web + ../parent-web/pom.xml 1.0-SNAPSHOT @@ -17,16 +17,7 @@ Upload - - - org.apache.maven.plugins - maven-war-plugin - 3.2.0 - - false - - - + upload @@ -35,5 +26,11 @@ common ${project.version} + + + com.j2html + j2html + 1.6.0 + \ No newline at end of file From 346fe616014b1a64c6d10f0950018b04551f5848 Mon Sep 17 00:00:00 2001 From: user Date: Wed, 7 Jun 2023 19:33:47 +0300 Subject: [PATCH 4/7] HW3 with no Optional --- mail-api/pom.xml | 27 ++ .../javaops/masterjava/matrix/MainMatrix.java | 48 +++ .../masterjava/matrix/MatrixBenchmark.java | 85 +++++ .../javaops/masterjava/matrix/MatrixUtil.java | 157 +++++++++ .../masterjava/xml/schema/CityType.java | 94 +++++ .../masterjava/xml/schema/FlagType.java | 54 +++ .../masterjava/xml/schema/GroupType.java | 40 +++ .../masterjava/xml/schema/ObjectFactory.java | 109 ++++++ .../masterjava/xml/schema/Payload.java | 328 ++++++++++++++++++ .../masterjava/xml/schema/Project.java | 216 ++++++++++++ .../javaops/masterjava/xml/schema/User.java | 180 ++++++++++ .../masterjava/xml/util/JaxbMarshaller.java | 39 +++ .../masterjava/xml/util/JaxbParser.java | 93 +++++ .../masterjava/xml/util/JaxbUnmarshaller.java | 38 ++ .../javaops/masterjava/xml/util/Schemas.java | 48 +++ .../xml/util/StaxStreamProcessor.java | 79 +++++ .../masterjava/xml/util/XPathProcessor.java | 58 ++++ .../masterjava/xml/util/XsltProcessor.java | 47 +++ upload/src/main/resources/cities.xsl | 9 + upload/src/main/resources/groups.xsl | 37 ++ upload/src/main/resources/payload.xsd | 97 ++++++ .../java/ru/javaops/masterjava/MainXml.java | 140 ++++++++ .../masterjava/xml/util/JaxbParserTest.java | 40 +++ .../xml/util/StaxStreamProcessorTest.java | 36 ++ .../xml/util/XPathProcessorTest.java | 26 ++ .../xml/util/XsltProcessorTest.java | 18 + upload/src/test/resources/city.xml | 4 + upload/src/test/resources/payload.xml | 31 ++ webapp/pom.xml | 31 ++ 29 files changed, 2209 insertions(+) create mode 100644 mail-api/pom.xml create mode 100644 test/src/main/java/ru/javaops/masterjava/matrix/MainMatrix.java create mode 100644 test/src/main/java/ru/javaops/masterjava/matrix/MatrixBenchmark.java create mode 100644 test/src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/xml/schema/CityType.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/xml/schema/FlagType.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/xml/schema/GroupType.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/xml/schema/ObjectFactory.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/xml/schema/Payload.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/xml/schema/Project.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/xml/schema/User.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbMarshaller.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbParser.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbUnmarshaller.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/xml/util/Schemas.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/xml/util/StaxStreamProcessor.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/xml/util/XPathProcessor.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java create mode 100644 upload/src/main/resources/cities.xsl create mode 100644 upload/src/main/resources/groups.xsl create mode 100644 upload/src/main/resources/payload.xsd create mode 100644 upload/src/test/java/ru/javaops/masterjava/MainXml.java create mode 100644 upload/src/test/java/ru/javaops/masterjava/xml/util/JaxbParserTest.java create mode 100644 upload/src/test/java/ru/javaops/masterjava/xml/util/StaxStreamProcessorTest.java create mode 100644 upload/src/test/java/ru/javaops/masterjava/xml/util/XPathProcessorTest.java create mode 100644 upload/src/test/java/ru/javaops/masterjava/xml/util/XsltProcessorTest.java create mode 100644 upload/src/test/resources/city.xml create mode 100644 upload/src/test/resources/payload.xml create mode 100644 webapp/pom.xml diff --git a/mail-api/pom.xml b/mail-api/pom.xml new file mode 100644 index 0000000..6f90fdd --- /dev/null +++ b/mail-api/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + + parent + ru.javaops + 1.0-SNAPSHOT + ../parent/pom.xml + + + mail-api + 1.0-SNAPSHOT + Mail-api + jar + + + + ru.javaops + common + 1.0-SNAPSHOT + + + + \ No newline at end of file diff --git a/test/src/main/java/ru/javaops/masterjava/matrix/MainMatrix.java b/test/src/main/java/ru/javaops/masterjava/matrix/MainMatrix.java new file mode 100644 index 0000000..1f13806 --- /dev/null +++ b/test/src/main/java/ru/javaops/masterjava/matrix/MainMatrix.java @@ -0,0 +1,48 @@ +package ru.javaops.masterjava.matrix; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class MainMatrix { + private static final int MATRIX_SIZE = 1000; + private static final int THREAD_NUMBER = 10; + + private final static ExecutorService executor = Executors.newFixedThreadPool(MainMatrix.THREAD_NUMBER); + + public static void main(String[] args) throws ExecutionException, InterruptedException { + final int[][] matrixA = MatrixUtil.create(MATRIX_SIZE); + final int[][] matrixB = MatrixUtil.create(MATRIX_SIZE); + + double singleThreadSum = 0.; + double concurrentThreadSum = 0.; + int count = 1; + while (count < 6) { + System.out.println("Pass " + count); + long start = System.currentTimeMillis(); + final int[][] matrixC = MatrixUtil.singleThreadMultiplyOpt(matrixA, matrixB); + double duration = (System.currentTimeMillis() - start) / 1000.; + out("Single thread time, sec: %.3f", duration); + singleThreadSum += duration; + + start = System.currentTimeMillis(); + final int[][] concurrentMatrixC = MatrixUtil.concurrentMultiplyStreams(matrixA, matrixB, Runtime.getRuntime().availableProcessors() - 1); + duration = (System.currentTimeMillis() - start) / 1000.; + out("Concurrent thread time, sec: %.3f", duration); + concurrentThreadSum += duration; + + if (!MatrixUtil.compare(matrixC, concurrentMatrixC)) { + System.err.println("Comparison failed"); + break; + } + count++; + } + executor.shutdown(); + out("\nAverage single thread time, sec: %.3f", singleThreadSum / 5.); + out("Average concurrent thread time, sec: %.3f", concurrentThreadSum / 5.); + } + + private static void out(String format, double ms) { + System.out.println(String.format(format, ms)); + } +} diff --git a/test/src/main/java/ru/javaops/masterjava/matrix/MatrixBenchmark.java b/test/src/main/java/ru/javaops/masterjava/matrix/MatrixBenchmark.java new file mode 100644 index 0000000..2df2fc6 --- /dev/null +++ b/test/src/main/java/ru/javaops/masterjava/matrix/MatrixBenchmark.java @@ -0,0 +1,85 @@ +package ru.javaops.masterjava.matrix; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; +import org.openjdk.jmh.runner.options.TimeValue; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +@Warmup(iterations = 10) +@Measurement(iterations = 10) +@BenchmarkMode({Mode.SingleShotTime}) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +@Threads(1) +@Fork(10) +@Timeout(time = 5, timeUnit = TimeUnit.MINUTES) +public class MatrixBenchmark { + + // Matrix size + private static final int MATRIX_SIZE = 1000; + + @Param({"3", "4", "10"}) + private int threadNumber; + + private static int[][] matrixA; + private static int[][] matrixB; + + @Setup + public void setUp() { + matrixA = MatrixUtil.create(MATRIX_SIZE); + matrixB = MatrixUtil.create(MATRIX_SIZE); + } + + private ExecutorService executor; + + public static void main(String[] args) throws RunnerException { + Options options = new OptionsBuilder() + .include(MatrixBenchmark.class.getSimpleName()) + .threads(1) + .forks(10) + .timeout(TimeValue.minutes(5)) + .build(); + new Runner(options).run(); + } + + // @Benchmark + public int[][] singleThreadMultiplyOpt() throws Exception { + return MatrixUtil.singleThreadMultiplyOpt(matrixA, matrixB); + } + + // @Benchmark + public int[][] singleThreadMultiplyOpt2() throws Exception { + return MatrixUtil.singleThreadMultiplyOpt(matrixA, matrixB); + } + + @Benchmark + public int[][] concurrentMultiplyStreams() throws Exception { + return MatrixUtil.concurrentMultiplyStreams(matrixA, matrixB, threadNumber); + } + + // @Benchmark + public int[][] concurrentMultiply() throws Exception { + return MatrixUtil.concurrentMultiply(matrixA, matrixB, executor); + } + + @Benchmark + public int[][] concurrentMultiply2() throws Exception { + return MatrixUtil.concurrentMultiply2(matrixA, matrixB, executor); + } + + @Setup + public void setup() { + executor = Executors.newFixedThreadPool(threadNumber); + } + + @TearDown + public void tearDown() { + executor.shutdown(); + } +} \ No newline at end of file diff --git a/test/src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java b/test/src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java new file mode 100644 index 0000000..d00a67a --- /dev/null +++ b/test/src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java @@ -0,0 +1,157 @@ +package ru.javaops.masterjava.matrix; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.*; +import java.util.stream.IntStream; + +public class MatrixUtil { + + public static int[][] concurrentMultiplyStreams(int[][] matrixA, int[][] matrixB, int threadNumber) + throws InterruptedException, ExecutionException { + + final int matrixSize = matrixA.length; + final int[][] matrixC = new int[matrixSize][matrixSize]; + + new ForkJoinPool(threadNumber).submit( + () -> IntStream.range(0, matrixSize) + .parallel() + .forEach(row -> { + final int[] rowA = matrixA[row]; + final int[] rowC = matrixC[row]; + + for (int idx = 0; idx < matrixSize; idx++) { + final int elA = rowA[idx]; + final int[] rowB = matrixB[idx]; + for (int col = 0; col < matrixSize; col++) { + rowC[col] += elA * rowB[col]; + } + } + })).get(); + + return matrixC; + } + + public static int[][] concurrentMultiply(int[][] matrixA, int[][] matrixB, ExecutorService executor) throws InterruptedException, ExecutionException { + final int matrixSize = matrixA.length; + final int[][] matrixC = new int[matrixSize][]; + + final int[][] matrixBT = new int[matrixSize][matrixSize]; + for (int i = 0; i < matrixSize; i++) { + for (int j = 0; j < matrixSize; j++) { + matrixBT[i][j] = matrixB[j][i]; + } + } + + List> tasks = new ArrayList<>(matrixSize); + for (int j = 0; j < matrixSize; j++) { + final int row = j; + tasks.add(() -> { + final int[] rowC = new int[matrixSize]; + for (int col = 0; col < matrixSize; col++) { + final int[] rowA = matrixA[row]; + final int[] columnB = matrixBT[col]; + int sum = 0; + for (int k = 0; k < matrixSize; k++) { + sum += rowA[k] * columnB[k]; + } + rowC[col] = sum; + } + matrixC[row] = rowC; + return null; + }); + } + executor.invokeAll(tasks); + return matrixC; + } + + public static int[][] concurrentMultiply2(int[][] matrixA, int[][] matrixB, ExecutorService executor) throws InterruptedException { + final int matrixSize = matrixA.length; + final int[][] matrixC = new int[matrixSize][matrixSize]; + final CountDownLatch latch = new CountDownLatch(matrixSize); + + for (int row = 0; row < matrixSize; row++) { + final int[] rowA = matrixA[row]; + final int[] rowC = matrixC[row]; + + executor.submit(() -> { + for (int idx = 0; idx < matrixSize; idx++) { + final int elA = rowA[idx]; + final int[] rowB = matrixB[idx]; + for (int col = 0; col < matrixSize; col++) { + rowC[col] += elA * rowB[col]; + } + } + latch.countDown(); + }); + } + latch.await(); + return matrixC; + } + + public static int[][] singleThreadMultiplyOpt(int[][] matrixA, int[][] matrixB) { + final int matrixSize = matrixA.length; + final int[][] matrixC = new int[matrixSize][matrixSize]; + + for (int col = 0; col < matrixSize; col++) { + final int[] columnB = new int[matrixSize]; + for (int k = 0; k < matrixSize; k++) { + columnB[k] = matrixB[k][col]; + } + + for (int row = 0; row < matrixSize; row++) { + int sum = 0; + final int[] rowA = matrixA[row]; + for (int k = 0; k < matrixSize; k++) { + sum += rowA[k] * columnB[k]; + } + matrixC[row][col] = sum; + } + } + return matrixC; + } + + public static int[][] singleThreadMultiplyOpt2(int[][] matrixA, int[][] matrixB) { + final int matrixSize = matrixA.length; + final int[][] matrixC = new int[matrixSize][matrixSize]; + + for (int row = 0; row < matrixSize; row++) { + final int[] rowA = matrixA[row]; + final int[] rowC = matrixC[row]; + + for (int idx = 0; idx < matrixSize; idx++) { + final int elA = rowA[idx]; + final int[] rowB = matrixB[idx]; + for (int col = 0; col < matrixSize; col++) { + rowC[col] += elA * rowB[col]; + } + } + } + return matrixC; + } + + public static int[][] create(int size) { + int[][] matrix = new int[size][size]; + Random rn = new Random(); + + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + matrix[i][j] = rn.nextInt(10); + } + } + return matrix; + } + + public static boolean compare(int[][] matrixA, int[][] matrixB) { + final int matrixSize = matrixA.length; + for (int i = 0; i < matrixSize; i++) { + for (int j = 0; j < matrixSize; j++) { + if (matrixA[i][j] != matrixB[i][j]) { + return false; + } + } + } + return true; + } +} \ No newline at end of file diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/schema/CityType.java b/upload/src/main/java/ru/javaops/masterjava/xml/schema/CityType.java new file mode 100644 index 0000000..029e352 --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/xml/schema/CityType.java @@ -0,0 +1,94 @@ + +package ru.javaops.masterjava.xml.schema; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlID; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + + +/** + *

Java class for cityType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="cityType">
+ *   <simpleContent>
+ *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ *       <attribute name="id" use="required" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ *     </extension>
+ *   </simpleContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "cityType", namespace = "http://javaops.ru", propOrder = { + "value" +}) +public class CityType { + + @XmlValue + protected String value; + @XmlAttribute(name = "id", required = true) + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + @XmlID + @XmlSchemaType(name = "ID") + protected String id; + + /** + * Gets the value of the value property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getValue() { + return value; + } + + /** + * Sets the value of the value property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setValue(String value) { + this.value = value; + } + + /** + * Gets the value of the id property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getId() { + return id; + } + + /** + * Sets the value of the id property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setId(String value) { + this.id = value; + } + +} diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/schema/FlagType.java b/upload/src/main/java/ru/javaops/masterjava/xml/schema/FlagType.java new file mode 100644 index 0000000..eda39fa --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/xml/schema/FlagType.java @@ -0,0 +1,54 @@ + +package ru.javaops.masterjava.xml.schema; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for flagType. + * + *

The following schema fragment specifies the expected content contained within this class. + *

+ *

+ * <simpleType name="flagType">
+ *   <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *     <enumeration value="active"/>
+ *     <enumeration value="deleted"/>
+ *     <enumeration value="superuser"/>
+ *   </restriction>
+ * </simpleType>
+ * 
+ * + */ +@XmlType(name = "flagType", namespace = "http://javaops.ru") +@XmlEnum +public enum FlagType { + + @XmlEnumValue("active") + ACTIVE("active"), + @XmlEnumValue("deleted") + DELETED("deleted"), + @XmlEnumValue("superuser") + SUPERUSER("superuser"); + private final String value; + + FlagType(String v) { + value = v; + } + + public String value() { + return value; + } + + public static FlagType fromValue(String v) { + for (FlagType c: FlagType.values()) { + if (c.value.equals(v)) { + return c; + } + } + throw new IllegalArgumentException(v); + } + +} diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/schema/GroupType.java b/upload/src/main/java/ru/javaops/masterjava/xml/schema/GroupType.java new file mode 100644 index 0000000..d504164 --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/xml/schema/GroupType.java @@ -0,0 +1,40 @@ + +package ru.javaops.masterjava.xml.schema; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for groupType. + * + *

The following schema fragment specifies the expected content contained within this class. + *

+ *

+ * <simpleType name="groupType">
+ *   <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *     <enumeration value="REGISTERING"/>
+ *     <enumeration value="CURRENT"/>
+ *     <enumeration value="FINISHED"/>
+ *   </restriction>
+ * </simpleType>
+ * 
+ * + */ +@XmlType(name = "groupType", namespace = "http://javaops.ru") +@XmlEnum +public enum GroupType { + + REGISTERING, + CURRENT, + FINISHED; + + public String value() { + return name(); + } + + public static GroupType fromValue(String v) { + return valueOf(v); + } + +} diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/schema/ObjectFactory.java b/upload/src/main/java/ru/javaops/masterjava/xml/schema/ObjectFactory.java new file mode 100644 index 0000000..bfb3932 --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/xml/schema/ObjectFactory.java @@ -0,0 +1,109 @@ + +package ru.javaops.masterjava.xml.schema; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlElementDecl; +import javax.xml.bind.annotation.XmlRegistry; +import javax.xml.namespace.QName; + + +/** + * This object contains factory methods for each + * Java content interface and Java element interface + * generated in the ru.javaops.masterjava.xml.schema package. + *

An ObjectFactory allows you to programatically + * construct new instances of the Java representation + * for XML content. The Java representation of XML + * content can consist of schema derived interfaces + * and classes representing the binding of schema + * type definitions, element declarations and model + * groups. Factory methods for each of these are + * provided in this class. + * + */ +@XmlRegistry +public class ObjectFactory { + + private final static QName _City_QNAME = new QName("http://javaops.ru", "City"); + + /** + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: ru.javaops.masterjava.xml.schema + * + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link Project } + * + */ + public Project createProject() { + return new Project(); + } + + /** + * Create an instance of {@link Payload } + * + */ + public Payload createPayload() { + return new Payload(); + } + + /** + * Create an instance of {@link Project.Group } + * + */ + public Project.Group createProjectGroup() { + return new Project.Group(); + } + + /** + * Create an instance of {@link User } + * + */ + public User createUser() { + return new User(); + } + + /** + * Create an instance of {@link Payload.Projects } + * + */ + public Payload.Projects createPayloadProjects() { + return new Payload.Projects(); + } + + /** + * Create an instance of {@link Payload.Cities } + * + */ + public Payload.Cities createPayloadCities() { + return new Payload.Cities(); + } + + /** + * Create an instance of {@link Payload.Users } + * + */ + public Payload.Users createPayloadUsers() { + return new Payload.Users(); + } + + /** + * Create an instance of {@link CityType } + * + */ + public CityType createCityType() { + return new CityType(); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CityType }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://javaops.ru", name = "City") + public JAXBElement createCity(CityType value) { + return new JAXBElement(_City_QNAME, CityType.class, null, value); + } + +} diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/schema/Payload.java b/upload/src/main/java/ru/javaops/masterjava/xml/schema/Payload.java new file mode 100644 index 0000000..9d4cc30 --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/xml/schema/Payload.java @@ -0,0 +1,328 @@ + +package ru.javaops.masterjava.xml.schema; + +import javax.xml.bind.annotation.*; +import java.util.ArrayList; +import java.util.List; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Projects">
+ *           <complexType>
+ *             <complexContent>
+ *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 <sequence maxOccurs="unbounded">
+ *                   <element ref="{http://javaops.ru}Project"/>
+ *                 </sequence>
+ *               </restriction>
+ *             </complexContent>
+ *           </complexType>
+ *         </element>
+ *         <element name="Cities">
+ *           <complexType>
+ *             <complexContent>
+ *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 <sequence maxOccurs="unbounded">
+ *                   <element ref="{http://javaops.ru}City"/>
+ *                 </sequence>
+ *               </restriction>
+ *             </complexContent>
+ *           </complexType>
+ *         </element>
+ *         <element name="Users">
+ *           <complexType>
+ *             <complexContent>
+ *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 <sequence maxOccurs="unbounded" minOccurs="0">
+ *                   <element ref="{http://javaops.ru}User"/>
+ *                 </sequence>
+ *               </restriction>
+ *             </complexContent>
+ *           </complexType>
+ *         </element>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "projects", + "cities", + "users" +}) +@XmlRootElement(name = "Payload", namespace = "http://javaops.ru") +public class Payload { + + @XmlElement(name = "Projects", namespace = "http://javaops.ru", required = true) + protected Payload.Projects projects; + @XmlElement(name = "Cities", namespace = "http://javaops.ru", required = true) + protected Payload.Cities cities; + @XmlElement(name = "Users", namespace = "http://javaops.ru", required = true) + protected Payload.Users users; + + /** + * Gets the value of the projects property. + * + * @return + * possible object is + * {@link Payload.Projects } + * + */ + public Payload.Projects getProjects() { + return projects; + } + + /** + * Sets the value of the projects property. + * + * @param value + * allowed object is + * {@link Payload.Projects } + * + */ + public void setProjects(Payload.Projects value) { + this.projects = value; + } + + /** + * Gets the value of the cities property. + * + * @return + * possible object is + * {@link Payload.Cities } + * + */ + public Payload.Cities getCities() { + return cities; + } + + /** + * Sets the value of the cities property. + * + * @param value + * allowed object is + * {@link Payload.Cities } + * + */ + public void setCities(Payload.Cities value) { + this.cities = value; + } + + /** + * Gets the value of the users property. + * + * @return + * possible object is + * {@link Payload.Users } + * + */ + public Payload.Users getUsers() { + return users; + } + + /** + * Sets the value of the users property. + * + * @param value + * allowed object is + * {@link Payload.Users } + * + */ + public void setUsers(Payload.Users value) { + this.users = value; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+     * <complexType>
+     *   <complexContent>
+     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       <sequence maxOccurs="unbounded">
+     *         <element ref="{http://javaops.ru}City"/>
+     *       </sequence>
+     *     </restriction>
+     *   </complexContent>
+     * </complexType>
+     * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "city" + }) + public static class Cities { + + @XmlElement(name = "City", namespace = "http://javaops.ru", required = true) + protected List city; + + /** + * Gets the value of the city property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the city property. + * + *

+ * For example, to add a new item, do as follows: + *

+         *    getCity().add(newItem);
+         * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link CityType } + * + * + */ + public List getCity() { + if (city == null) { + city = new ArrayList(); + } + return this.city; + } + + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+     * <complexType>
+     *   <complexContent>
+     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       <sequence maxOccurs="unbounded">
+     *         <element ref="{http://javaops.ru}Project"/>
+     *       </sequence>
+     *     </restriction>
+     *   </complexContent>
+     * </complexType>
+     * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "project" + }) + public static class Projects { + + @XmlElement(name = "Project", namespace = "http://javaops.ru", required = true) + protected List project; + + /** + * Gets the value of the project property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the project property. + * + *

+ * For example, to add a new item, do as follows: + *

+         *    getProject().add(newItem);
+         * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Project } + * + * + */ + public List getProject() { + if (project == null) { + project = new ArrayList(); + } + return this.project; + } + + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+     * <complexType>
+     *   <complexContent>
+     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       <sequence maxOccurs="unbounded" minOccurs="0">
+     *         <element ref="{http://javaops.ru}User"/>
+     *       </sequence>
+     *     </restriction>
+     *   </complexContent>
+     * </complexType>
+     * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "user" + }) + public static class Users { + + @XmlElement(name = "User", namespace = "http://javaops.ru") + protected List user; + + /** + * Gets the value of the user property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the user property. + * + *

+ * For example, to add a new item, do as follows: + *

+         *    getUser().add(newItem);
+         * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link User } + * + * + */ + public List getUser() { + if (user == null) { + user = new ArrayList(); + } + return this.user; + } + + } + +} diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/schema/Project.java b/upload/src/main/java/ru/javaops/masterjava/xml/schema/Project.java new file mode 100644 index 0000000..180a997 --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/xml/schema/Project.java @@ -0,0 +1,216 @@ + +package ru.javaops.masterjava.xml.schema; + +import javax.xml.bind.annotation.*; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import java.util.ArrayList; +import java.util.List; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="description" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <sequence maxOccurs="unbounded">
+ *           <element name="Group">
+ *             <complexType>
+ *               <complexContent>
+ *                 <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                   <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ *                   <attribute name="type" use="required" type="{http://javaops.ru}groupType" />
+ *                 </restriction>
+ *               </complexContent>
+ *             </complexType>
+ *           </element>
+ *         </sequence>
+ *       </sequence>
+ *       <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "description", + "group" +}) +@XmlRootElement(name = "Project", namespace = "http://javaops.ru") +public class Project { + + @XmlElement(namespace = "http://javaops.ru", required = true) + protected String description; + @XmlElement(name = "Group", namespace = "http://javaops.ru", required = true) + protected List group; + @XmlAttribute(name = "name", required = true) + protected String name; + + /** + * Gets the value of the description property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getDescription() { + return description; + } + + /** + * Sets the value of the description property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setDescription(String value) { + this.description = value; + } + + /** + * Gets the value of the group property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the group property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getGroup().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Project.Group } + * + * + */ + public List getGroup() { + if (group == null) { + group = new ArrayList(); + } + return this.group; + } + + /** + * Gets the value of the name property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+     * <complexType>
+     *   <complexContent>
+     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}ID" />
+     *       <attribute name="type" use="required" type="{http://javaops.ru}groupType" />
+     *     </restriction>
+     *   </complexContent>
+     * </complexType>
+     * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "") + public static class Group { + + @XmlAttribute(name = "name", required = true) + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + @XmlID + @XmlSchemaType(name = "ID") + protected String name; + @XmlAttribute(name = "type", required = true) + protected GroupType type; + + /** + * Gets the value of the name property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the type property. + * + * @return + * possible object is + * {@link GroupType } + * + */ + public GroupType getType() { + return type; + } + + /** + * Sets the value of the type property. + * + * @param value + * allowed object is + * {@link GroupType } + * + */ + public void setType(GroupType value) { + this.type = value; + } + + } + +} diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/schema/User.java b/upload/src/main/java/ru/javaops/masterjava/xml/schema/User.java new file mode 100644 index 0000000..b2cc1c4 --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/xml/schema/User.java @@ -0,0 +1,180 @@ + +package ru.javaops.masterjava.xml.schema; + +import javax.xml.bind.annotation.*; +import java.util.ArrayList; +import java.util.List; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <simpleContent>
+ *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ *       <attribute name="email" type="{http://javaops.ru}emailAddressType" />
+ *       <attribute name="flag" use="required" type="{http://javaops.ru}flagType" />
+ *       <attribute name="city" use="required" type="{http://www.w3.org/2001/XMLSchema}IDREF" />
+ *       <attribute name="groupRefs" type="{http://www.w3.org/2001/XMLSchema}IDREFS" />
+ *     </extension>
+ *   </simpleContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "value" +}) +@XmlRootElement(name = "User", namespace = "http://javaops.ru") +public class User { + + @XmlValue + protected String value; + @XmlAttribute(name = "email") + protected String email; + @XmlAttribute(name = "flag", required = true) + protected FlagType flag; + @XmlAttribute(name = "city", required = true) + @XmlIDREF + @XmlSchemaType(name = "IDREF") + protected Object city; + @XmlAttribute(name = "groupRefs") + @XmlIDREF + @XmlSchemaType(name = "IDREFS") + protected List groupRefs; + + /** + * Gets the value of the value property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getValue() { + return value; + } + + /** + * Sets the value of the value property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setValue(String value) { + this.value = value; + } + + /** + * Gets the value of the email property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getEmail() { + return email; + } + + /** + * Sets the value of the email property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setEmail(String value) { + this.email = value; + } + + /** + * Gets the value of the flag property. + * + * @return + * possible object is + * {@link FlagType } + * + */ + public FlagType getFlag() { + return flag; + } + + /** + * Sets the value of the flag property. + * + * @param value + * allowed object is + * {@link FlagType } + * + */ + public void setFlag(FlagType value) { + this.flag = value; + } + + /** + * Gets the value of the city property. + * + * @return + * possible object is + * {@link Object } + * + */ + public Object getCity() { + return city; + } + + /** + * Sets the value of the city property. + * + * @param value + * allowed object is + * {@link Object } + * + */ + public void setCity(Object value) { + this.city = value; + } + + /** + * Gets the value of the groupRefs property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the groupRefs property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getGroupRefs().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Object } + * + * + */ + public List getGroupRefs() { + if (groupRefs == null) { + groupRefs = new ArrayList(); + } + return this.groupRefs; + } + + @Override + public String toString() { + return value + '(' + email + ')'; + } +} diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbMarshaller.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbMarshaller.java new file mode 100644 index 0000000..d600680 --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbMarshaller.java @@ -0,0 +1,39 @@ +package ru.javaops.masterjava.xml.util; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.PropertyException; +import javax.xml.validation.Schema; +import java.io.StringWriter; +import java.io.Writer; + +public class JaxbMarshaller { + private Marshaller marshaller; + + public JaxbMarshaller(JAXBContext ctx) throws JAXBException { + marshaller = ctx.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); + marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true); + } + + public void setProperty(String prop, Object value) throws PropertyException { + marshaller.setProperty(prop, value); + } + + public synchronized void setSchema(Schema schema) { + marshaller.setSchema(schema); + } + + public String marshal(Object instance) throws JAXBException { + StringWriter sw = new StringWriter(); + marshal(instance, sw); + return sw.toString(); + } + + public synchronized void marshal(Object instance, Writer writer) throws JAXBException { + marshaller.marshal(instance, writer); + } + +} diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbParser.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbParser.java new file mode 100644 index 0000000..563d53b --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbParser.java @@ -0,0 +1,93 @@ +package ru.javaops.masterjava.xml.util; + +import org.xml.sax.SAXException; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.PropertyException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import java.io.*; + + +/** + * Marshalling/Unmarshalling JAXB helper + * XML Facade + */ +public class JaxbParser { + + protected JaxbMarshaller jaxbMarshaller; + protected JaxbUnmarshaller jaxbUnmarshaller; + protected Schema schema; + + public JaxbParser(Class... classesToBeBound) { + try { + init(JAXBContext.newInstance(classesToBeBound)); + } catch (JAXBException e) { + throw new IllegalArgumentException(e); + } + } + + // http://stackoverflow.com/questions/30643802/what-is-jaxbcontext-newinstancestring-contextpath + public JaxbParser(String context) { + try { + init(JAXBContext.newInstance(context)); + } catch (JAXBException e) { + throw new IllegalArgumentException(e); + } + } + + private void init(JAXBContext ctx) throws JAXBException { + jaxbMarshaller = new JaxbMarshaller(ctx); + jaxbUnmarshaller = new JaxbUnmarshaller(ctx); + } + + // Unmarshaller + public T unmarshal(InputStream is) throws JAXBException { + return (T) jaxbUnmarshaller.unmarshal(is); + } + + public T unmarshal(Reader reader) throws JAXBException { + return (T) jaxbUnmarshaller.unmarshal(reader); + } + + public T unmarshal(String str) throws JAXBException { + return (T) jaxbUnmarshaller.unmarshal(str); + } + + public T unmarshal(XMLStreamReader reader, Class elementClass) throws JAXBException { + return jaxbUnmarshaller.unmarshal(reader, elementClass); + } + + // Marshaller + public void setMarshallerProperty(String prop, Object value) { + try { + jaxbMarshaller.setProperty(prop, value); + } catch (PropertyException e) { + throw new IllegalArgumentException(e); + } + } + + public String marshal(Object instance) throws JAXBException { + return jaxbMarshaller.marshal(instance); + } + + public void marshal(Object instance, Writer writer) throws JAXBException { + jaxbMarshaller.marshal(instance, writer); + } + + public void setSchema(Schema schema) { + this.schema = schema; + jaxbUnmarshaller.setSchema(schema); + jaxbMarshaller.setSchema(schema); + } + + public void validate(String str) throws IOException, SAXException { + validate(new StringReader(str)); + } + + public void validate(Reader reader) throws IOException, SAXException { + schema.newValidator().validate(new StreamSource(reader)); + } +} diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbUnmarshaller.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbUnmarshaller.java new file mode 100644 index 0000000..1de89d8 --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbUnmarshaller.java @@ -0,0 +1,38 @@ +package ru.javaops.masterjava.xml.util; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.stream.XMLStreamReader; +import javax.xml.validation.Schema; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; + +public class JaxbUnmarshaller { + private Unmarshaller unmarshaller; + + public JaxbUnmarshaller(JAXBContext ctx) throws JAXBException { + unmarshaller = ctx.createUnmarshaller(); + } + + public synchronized void setSchema(Schema schema) { + unmarshaller.setSchema(schema); + } + + public synchronized Object unmarshal(InputStream is) throws JAXBException { + return unmarshaller.unmarshal(is); + } + + public synchronized Object unmarshal(Reader reader) throws JAXBException { + return unmarshaller.unmarshal(reader); + } + + public Object unmarshal(String str) throws JAXBException { + return unmarshal(new StringReader(str)); + } + + public synchronized T unmarshal(XMLStreamReader reader, Class elementClass) throws JAXBException { + return unmarshaller.unmarshal(reader, elementClass).getValue(); + } +} \ No newline at end of file diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/util/Schemas.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/Schemas.java new file mode 100644 index 0000000..42f41df --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/xml/util/Schemas.java @@ -0,0 +1,48 @@ +package ru.javaops.masterjava.xml.util; + +import com.google.common.io.Resources; +import org.xml.sax.SAXException; + +import javax.xml.XMLConstants; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import java.io.File; +import java.io.StringReader; +import java.net.URL; + + +public class Schemas { + + // SchemaFactory is not thread-safe + private static final SchemaFactory SCHEMA_FACTORY = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + + public static synchronized Schema ofString(String xsd) { + try { + return SCHEMA_FACTORY.newSchema(new StreamSource(new StringReader(xsd))); + } catch (SAXException e) { + throw new IllegalArgumentException(e); + } + } + + public static synchronized Schema ofClasspath(String resource) { + // http://digitalsanctum.com/2012/11/30/how-to-read-file-contents-in-java-the-easy-way-with-guava/ + return ofURL(Resources.getResource(resource)); + } + + public static synchronized Schema ofURL(URL url) { + try { + return SCHEMA_FACTORY.newSchema(url); + } catch (SAXException e) { + throw new IllegalArgumentException(e); + } + } + + public static synchronized Schema ofFile(File file) { + try { + return SCHEMA_FACTORY.newSchema(file); + } catch (SAXException e) { + throw new IllegalArgumentException(e); + } + } +} diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/util/StaxStreamProcessor.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/StaxStreamProcessor.java new file mode 100644 index 0000000..5878118 --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/xml/util/StaxStreamProcessor.java @@ -0,0 +1,79 @@ +package ru.javaops.masterjava.xml.util; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.events.XMLEvent; +import java.io.InputStream; + +public class StaxStreamProcessor implements AutoCloseable { + private static final XMLInputFactory FACTORY = XMLInputFactory.newInstance(); + + private final XMLStreamReader reader; + + public StaxStreamProcessor(InputStream is) throws XMLStreamException { + reader = FACTORY.createXMLStreamReader(is); + } + + public boolean startElement(String element, String parent) throws XMLStreamException { + while (reader.hasNext()) { + int event = reader.next(); + if (parent != null && isElementEnd(event, parent)) { + return false; + } + if (isElementStart(event, element)) { + return true; + } + } + return false; + } + + private boolean isElementStart(int event, String el) { + return event == XMLEvent.START_ELEMENT && el.equals(reader.getLocalName()); + } + + private boolean isElementEnd(int event, String el) { + return event == XMLEvent.END_ELEMENT && el.equals(reader.getLocalName()); + } + + public XMLStreamReader getReader() { + return reader; + } + + public String getAttribute(String name) throws XMLStreamException { + return reader.getAttributeValue(null, name); + } + + public boolean doUntil(int stopEvent, String value) throws XMLStreamException { + while (reader.hasNext()) { + int event = reader.next(); + if (event == stopEvent && value.equals(getValue(event))) { + return true; + } + } + return false; + } + + public String getValue(int event) throws XMLStreamException { + return (event == XMLEvent.CHARACTERS) ? reader.getText() : reader.getLocalName(); + } + + public String getElementValue(String element) throws XMLStreamException { + return doUntil(XMLEvent.START_ELEMENT, element) ? reader.getElementText() : null; + } + + public String getText() throws XMLStreamException { + return reader.getElementText(); + } + + @Override + public void close() { + if (reader != null) { + try { + reader.close(); + } catch (XMLStreamException e) { + // empty + } + } + } +} diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/util/XPathProcessor.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/XPathProcessor.java new file mode 100644 index 0000000..63baae5 --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/xml/util/XPathProcessor.java @@ -0,0 +1,58 @@ +package ru.javaops.masterjava.xml.util; + +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import java.io.IOException; +import java.io.InputStream; + +public class XPathProcessor { + private static final DocumentBuilderFactory DOCUMENT_FACTORY = DocumentBuilderFactory.newInstance(); + private static final DocumentBuilder DOCUMENT_BUILDER; + + private static final XPathFactory XPATH_FACTORY = XPathFactory.newInstance(); + private static final XPath XPATH = XPATH_FACTORY.newXPath(); + + static { + DOCUMENT_FACTORY.setNamespaceAware(true); + try { + DOCUMENT_BUILDER = DOCUMENT_FACTORY.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException(e); + } + } + + private final Document doc; + + public XPathProcessor(InputStream is) { + try { + doc = DOCUMENT_BUILDER.parse(is); + } catch (SAXException | IOException e) { + throw new IllegalArgumentException(e); + } + } + + public static synchronized XPathExpression getExpression(String exp) { + try { + return XPATH.compile(exp); + } catch (XPathExpressionException e) { + throw new IllegalArgumentException(e); + } + } + + public T evaluate(XPathExpression expression, QName type) { + try { + return (T) expression.evaluate(doc, type); + } catch (XPathExpressionException e) { + throw new IllegalArgumentException(e); + } + } +} diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java new file mode 100644 index 0000000..083febb --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java @@ -0,0 +1,47 @@ +package ru.javaops.masterjava.xml.util; + +import javax.xml.transform.*; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; +import java.io.*; +import java.nio.charset.StandardCharsets; + +public class XsltProcessor { + private static TransformerFactory FACTORY = TransformerFactory.newInstance(); + private final Transformer xformer; + + public XsltProcessor(InputStream xslInputStream) { + this(new BufferedReader(new InputStreamReader(xslInputStream, StandardCharsets.UTF_8))); + } + + public XsltProcessor(Reader xslReader) { + try { + Templates template = FACTORY.newTemplates(new StreamSource(xslReader)); + xformer = template.newTransformer(); + } catch (TransformerConfigurationException e) { + throw new IllegalStateException("XSLT transformer creation failed: " + e.toString(), e); + } + } + + public String transform(InputStream xmlInputStream) throws TransformerException { + StringWriter out = new StringWriter(); + transform(xmlInputStream, out); + return out.getBuffer().toString(); + } + + public void transform(InputStream xmlInputStream, Writer result) throws TransformerException { + transform(new BufferedReader(new InputStreamReader(xmlInputStream, StandardCharsets.UTF_8)), result); + } + + public void transform(Reader sourceReader, Writer result) throws TransformerException { + xformer.transform(new StreamSource(sourceReader), new StreamResult(result)); + } + + public static String getXsltHeader(String xslt) { + return "\n"; + } + + public void setParameter(String name, String value) { + xformer.setParameter(name, value); + } +} diff --git a/upload/src/main/resources/cities.xsl b/upload/src/main/resources/cities.xsl new file mode 100644 index 0000000..1c50912 --- /dev/null +++ b/upload/src/main/resources/cities.xsl @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/upload/src/main/resources/groups.xsl b/upload/src/main/resources/groups.xsl new file mode 100644 index 0000000..c5ade36 --- /dev/null +++ b/upload/src/main/resources/groups.xsl @@ -0,0 +1,37 @@ + + + + + + + + + + <xsl:value-of select="$projectName"/> groups + + + +

+ groups +

+ + + + + + + + + + + +
GroupType
+ + + +
+ + +
+
\ No newline at end of file diff --git a/upload/src/main/resources/payload.xsd b/upload/src/main/resources/payload.xsd new file mode 100644 index 0000000..3d545ec --- /dev/null +++ b/upload/src/main/resources/payload.xsd @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/upload/src/test/java/ru/javaops/masterjava/MainXml.java b/upload/src/test/java/ru/javaops/masterjava/MainXml.java new file mode 100644 index 0000000..8f57825 --- /dev/null +++ b/upload/src/test/java/ru/javaops/masterjava/MainXml.java @@ -0,0 +1,140 @@ +package ru.javaops.masterjava; + +import com.google.common.base.Splitter; +import com.google.common.io.Resources; +import j2html.tags.ContainerTag; +import one.util.streamex.StreamEx; +import ru.javaops.masterjava.xml.schema.ObjectFactory; +import ru.javaops.masterjava.xml.schema.Payload; +import ru.javaops.masterjava.xml.schema.Project; +import ru.javaops.masterjava.xml.schema.User; +import ru.javaops.masterjava.xml.util.JaxbParser; +import ru.javaops.masterjava.xml.util.Schemas; +import ru.javaops.masterjava.xml.util.StaxStreamProcessor; +import ru.javaops.masterjava.xml.util.XsltProcessor; + +import javax.xml.stream.events.XMLEvent; +import java.io.InputStream; +import java.io.Writer; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Collectors; + +import static com.google.common.base.Strings.nullToEmpty; +import static j2html.TagCreator.*; + +public class MainXml { + + private static final Comparator USER_COMPARATOR = Comparator.comparing(User::getValue).thenComparing(User::getEmail); + + public static void main(String[] args) throws Exception { + if (args.length != 1) { + System.out.println("Required argument: projectName"); + System.exit(1); + } + String projectName = args[0]; + URL payloadUrl = Resources.getResource("payload.xml"); + + Set users = parseByJaxb(projectName, payloadUrl); + users.forEach(System.out::println); + + System.out.println(); + String html = toHtml(users, projectName); + System.out.println(html); + try (Writer writer = Files.newBufferedWriter(Paths.get("out/users.html"))) { + writer.write(html); + } + + System.out.println(); + users = processByStax(projectName, payloadUrl); + users.forEach(System.out::println); + + System.out.println(); + html = transform(projectName, payloadUrl); + try (Writer writer = Files.newBufferedWriter(Paths.get("out/groups.html"))) { + writer.write(html); + } + } + + private static Set parseByJaxb(String projectName, URL payloadUrl) throws Exception { + JaxbParser parser = new JaxbParser(ObjectFactory.class); + parser.setSchema(Schemas.ofClasspath("payload.xsd")); + Payload payload; + try (InputStream is = payloadUrl.openStream()) { + payload = parser.unmarshal(is); + } + + Project project = StreamEx.of(payload.getProjects().getProject()) + .filter(p -> p.getName().equals(projectName)) + .findAny() + .orElseThrow(() -> new IllegalArgumentException("Invalid project name '" + projectName + '\'')); + + final Set groups = new HashSet<>(project.getGroup()); // identity compare + return StreamEx.of(payload.getUsers().getUser()) + .filter(u -> !Collections.disjoint(groups, u.getGroupRefs())) + .collect( + Collectors.toCollection(() -> new TreeSet<>(USER_COMPARATOR)) + ); + } + + private static Set processByStax(String projectName, URL payloadUrl) throws Exception { + + try (InputStream is = payloadUrl.openStream()) { + StaxStreamProcessor processor = new StaxStreamProcessor(is); + final Set groupNames = new HashSet<>(); + + // Projects loop + projects: + while (processor.startElement("Project", "Projects")) { + if (projectName.equals(processor.getAttribute("name"))) { + while (processor.startElement("Group", "Project")) { + groupNames.add(processor.getAttribute("name")); + } + break; + } + } + if (groupNames.isEmpty()) { + throw new IllegalArgumentException("Invalid " + projectName + " or no groups"); + } + + // Users loop + Set users = new TreeSet<>(USER_COMPARATOR); + + JaxbParser parser = new JaxbParser(User.class); + while (processor.doUntil(XMLEvent.START_ELEMENT, "User")) { + String groupRefs = processor.getAttribute("groupRefs"); + if (!Collections.disjoint(groupNames, Splitter.on(' ').splitToList(nullToEmpty(groupRefs)))) { + User user = parser.unmarshal(processor.getReader(), User.class); + users.add(user); + } + } + return users; + } + } + + private static String toHtml(Set users, String projectName) { + final ContainerTag table = table().with( + tr().with(th("FullName"), th("email"))) + .attr("border", "1") + .attr("cellpadding", "8") + .attr("cellspacing", "0"); + + users.forEach(u -> table.with(tr().with(td(u.getValue()), td(u.getEmail())))); + + return html().with( + head().with(title(projectName + " users")), + body().with(h1(projectName + " users"), table) + ).render(); + } + + private static String transform(String projectName, URL payloadUrl) throws Exception { + URL xsl = Resources.getResource("groups.xsl"); + try (InputStream xmlStream = payloadUrl.openStream(); InputStream xslStream = xsl.openStream()) { + XsltProcessor processor = new XsltProcessor(xslStream); + processor.setParameter("projectName", projectName); + return processor.transform(xmlStream); + } + } +} diff --git a/upload/src/test/java/ru/javaops/masterjava/xml/util/JaxbParserTest.java b/upload/src/test/java/ru/javaops/masterjava/xml/util/JaxbParserTest.java new file mode 100644 index 0000000..6232654 --- /dev/null +++ b/upload/src/test/java/ru/javaops/masterjava/xml/util/JaxbParserTest.java @@ -0,0 +1,40 @@ +package ru.javaops.masterjava.xml.util; + +import com.google.common.io.Resources; +import org.junit.Test; +import ru.javaops.masterjava.xml.schema.CityType; +import ru.javaops.masterjava.xml.schema.ObjectFactory; +import ru.javaops.masterjava.xml.schema.Payload; + +import javax.xml.bind.JAXBElement; +import javax.xml.namespace.QName; + +public class JaxbParserTest { + private static final JaxbParser JAXB_PARSER = new JaxbParser(ObjectFactory.class); + + static { + JAXB_PARSER.setSchema(Schemas.ofClasspath("payload.xsd")); + } + + @Test + public void testPayload() throws Exception { +// JaxbParserTest.class.getResourceAsStream("/city.xml") + Payload payload = JAXB_PARSER.unmarshal( + Resources.getResource("payload.xml").openStream()); + String strPayload = JAXB_PARSER.marshal(payload); + JAXB_PARSER.validate(strPayload); + System.out.println(strPayload); + } + + @Test + public void testCity() throws Exception { + JAXBElement cityElement = JAXB_PARSER.unmarshal( + Resources.getResource("city.xml").openStream()); + CityType city = cityElement.getValue(); + JAXBElement cityElement2 = + new JAXBElement<>(new QName("http://javaops.ru", "City"), CityType.class, city); + String strCity = JAXB_PARSER.marshal(cityElement2); + JAXB_PARSER.validate(strCity); + System.out.println(strCity); + } +} \ No newline at end of file diff --git a/upload/src/test/java/ru/javaops/masterjava/xml/util/StaxStreamProcessorTest.java b/upload/src/test/java/ru/javaops/masterjava/xml/util/StaxStreamProcessorTest.java new file mode 100644 index 0000000..fd55963 --- /dev/null +++ b/upload/src/test/java/ru/javaops/masterjava/xml/util/StaxStreamProcessorTest.java @@ -0,0 +1,36 @@ +package ru.javaops.masterjava.xml.util; + +import com.google.common.io.Resources; +import org.junit.Test; + +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.events.XMLEvent; + +public class StaxStreamProcessorTest { + @Test + public void readCities() throws Exception { + try (StaxStreamProcessor processor = + new StaxStreamProcessor(Resources.getResource("payload.xml").openStream())) { + XMLStreamReader reader = processor.getReader(); + while (reader.hasNext()) { + int event = reader.next(); + if (event == XMLEvent.START_ELEMENT) { + if ("City".equals(reader.getLocalName())) { + System.out.println(reader.getElementText()); + } + } + } + } + } + + @Test + public void readCities2() throws Exception { + try (StaxStreamProcessor processor = + new StaxStreamProcessor(Resources.getResource("payload.xml").openStream())) { + String city; + while ((city = processor.getElementValue("City")) != null) { + System.out.println(city); + } + } + } +} \ No newline at end of file diff --git a/upload/src/test/java/ru/javaops/masterjava/xml/util/XPathProcessorTest.java b/upload/src/test/java/ru/javaops/masterjava/xml/util/XPathProcessorTest.java new file mode 100644 index 0000000..199f676 --- /dev/null +++ b/upload/src/test/java/ru/javaops/masterjava/xml/util/XPathProcessorTest.java @@ -0,0 +1,26 @@ +package ru.javaops.masterjava.xml.util; + +import com.google.common.io.Resources; +import org.junit.Test; +import org.w3c.dom.NodeList; + +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import java.io.InputStream; +import java.util.stream.IntStream; + +public class XPathProcessorTest { + @Test + public void getCities() throws Exception { + try (InputStream is = + Resources.getResource("payload.xml").openStream()) { + XPathProcessor processor = new XPathProcessor(is); + XPathExpression expression = + XPathProcessor.getExpression("/*[name()='Payload']/*[name()='Cities']/*[name()='City']/text()"); + NodeList nodes = processor.evaluate(expression, XPathConstants.NODESET); + IntStream.range(0, nodes.getLength()).forEach( + i -> System.out.println(nodes.item(i).getNodeValue()) + ); + } + } +} \ No newline at end of file diff --git a/upload/src/test/java/ru/javaops/masterjava/xml/util/XsltProcessorTest.java b/upload/src/test/java/ru/javaops/masterjava/xml/util/XsltProcessorTest.java new file mode 100644 index 0000000..d7f42a6 --- /dev/null +++ b/upload/src/test/java/ru/javaops/masterjava/xml/util/XsltProcessorTest.java @@ -0,0 +1,18 @@ +package ru.javaops.masterjava.xml.util; + +import com.google.common.io.Resources; +import org.junit.Test; + +import java.io.InputStream; + +public class XsltProcessorTest { + @Test + public void transform() throws Exception { + try (InputStream xslInputStream = Resources.getResource("cities.xsl").openStream(); + InputStream xmlInputStream = Resources.getResource("payload.xml").openStream()) { + + XsltProcessor processor = new XsltProcessor(xslInputStream); + System.out.println(processor.transform(xmlInputStream)); + } + } +} diff --git a/upload/src/test/resources/city.xml b/upload/src/test/resources/city.xml new file mode 100644 index 0000000..8b0abcf --- /dev/null +++ b/upload/src/test/resources/city.xml @@ -0,0 +1,4 @@ +Санкт-Петербург + \ No newline at end of file diff --git a/upload/src/test/resources/payload.xml b/upload/src/test/resources/payload.xml new file mode 100644 index 0000000..fadf8c6 --- /dev/null +++ b/upload/src/test/resources/payload.xml @@ -0,0 +1,31 @@ + + + + + Topjava + + + + + + Masterjava + + + + + Санкт-Петербург + Москва + Киев + Минск + + + Full Name + Admin + Deleted + User1 + User2 + User3 + + \ No newline at end of file diff --git a/webapp/pom.xml b/webapp/pom.xml new file mode 100644 index 0000000..679a103 --- /dev/null +++ b/webapp/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + + ru.javaops + parent-web + ../parent-web/pom.xml + 1.0-SNAPSHOT + + + webapp + 1.0-SNAPSHOT + war + Webapp + + + webapp + + + + + ru.javaops + mail-api + ${project.version} + + + + \ No newline at end of file From 70982211729c766db2e4ed33e8fede5a0a6cde21 Mon Sep 17 00:00:00 2001 From: user Date: Mon, 12 Jun 2023 14:28:30 +0300 Subject: [PATCH 5/7] HW3 Optional: upload users by Stax --- parent-web/pom.xml | 5 ++ upload/pom.xml | 5 ++ .../ru/javaops/masterjava/UserProccessor.java | 24 ++++++ .../ru/javaops/masterjava/UserServlet.java | 77 +++++++++++++++++++ .../ru/javaops/masterjava/model/User.java | 63 +++++++++++++++ .../ru/javaops/masterjava/model/UserFlag.java | 7 ++ .../main/webapp/WEB-INF/templates/upload.html | 14 ++++ .../main/webapp/WEB-INF/templates/users.html | 28 +++++++ 8 files changed, 223 insertions(+) create mode 100644 upload/src/main/java/ru/javaops/masterjava/UserProccessor.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/UserServlet.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/model/User.java create mode 100644 upload/src/main/java/ru/javaops/masterjava/model/UserFlag.java create mode 100644 upload/src/main/webapp/WEB-INF/templates/upload.html create mode 100644 upload/src/main/webapp/WEB-INF/templates/users.html diff --git a/parent-web/pom.xml b/parent-web/pom.xml index 3282378..4d4d689 100644 --- a/parent-web/pom.xml +++ b/parent-web/pom.xml @@ -35,6 +35,11 @@ common ${project.version} + + javax.servlet + javax.servlet-api + 3.1.0 + diff --git a/upload/pom.xml b/upload/pom.xml index 2ed2d46..700ec04 100644 --- a/upload/pom.xml +++ b/upload/pom.xml @@ -32,5 +32,10 @@ j2html 1.6.0 + + org.thymeleaf + thymeleaf + 3.0.0.ALPHA03 + \ No newline at end of file diff --git a/upload/src/main/java/ru/javaops/masterjava/UserProccessor.java b/upload/src/main/java/ru/javaops/masterjava/UserProccessor.java new file mode 100644 index 0000000..9f8c246 --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/UserProccessor.java @@ -0,0 +1,24 @@ +package ru.javaops.masterjava; + +import org.thymeleaf.TemplateEngine; +import org.thymeleaf.context.WebContext; +import org.thymeleaf.templatemode.TemplateMode; +import org.thymeleaf.templateresolver.ServletContextTemplateResolver; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class UserProccessor { + private static final TemplateEngine templateEngine = new TemplateEngine(); + private static final ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(); + static { + resolver.setTemplateMode(TemplateMode.HTML); + resolver.setSuffix(".html"); + resolver.setPrefix("WEB-INF/templates/"); + templateEngine.setTemplateResolver(resolver); + } + + public static void process(HttpServletResponse response, String template, WebContext ctx) throws IOException { + templateEngine.process(template, ctx, response.getWriter()); + } +} diff --git a/upload/src/main/java/ru/javaops/masterjava/UserServlet.java b/upload/src/main/java/ru/javaops/masterjava/UserServlet.java new file mode 100644 index 0000000..7a1394e --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/UserServlet.java @@ -0,0 +1,77 @@ +package ru.javaops.masterjava; + +import org.thymeleaf.context.WebContext; +import ru.javaops.masterjava.model.User; +import ru.javaops.masterjava.model.UserFlag; +import ru.javaops.masterjava.xml.util.StaxStreamProcessor; + +import javax.servlet.ServletException; +import javax.servlet.annotation.MultipartConfig; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.events.XMLEvent; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +@WebServlet(urlPatterns = "/", loadOnStartup = 1) +@MultipartConfig +public class UserServlet extends HttpServlet { + private final static Logger LOGGER = + Logger.getLogger(UserServlet.class.getCanonicalName()); + private static final long serialVersionUID = 2L; + + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { + final WebContext ctx = new WebContext(request, response, request.getServletContext(), request.getLocale()); + UserProccessor.process(response, "upload", ctx); + } + + public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + final WebContext ctx = new WebContext(request, response, request.getServletContext(), request.getLocale()); +// Collection parts = request.getParts(); +// for (Part part : parts) { +// System.out.println("Part Name:" + part.getName()); +// System.out.println("Part: "+part); +// System.out.println("Header: "); +// for (String headerName : part.getHeaderNames()) { +// System.out.println(headerName + " -> " + part.getHeader(headerName)); +// } +// System.out.println("Part Size: " + part.getSize()+"\n----------------------------"); +// InputStream inputStream = part.getInputStream(); +// Reader reader = new InputStreamReader(inputStream); +// BufferedReader bufferedReader = new BufferedReader(reader); +// while(bufferedReader.ready()){ +// String s = bufferedReader.readLine(); +// System.out.println(s); +// } +// System.out.println("==============================================="); +// } + List users = new ArrayList(); + try (InputStream inputStream = request.getPart("file").getInputStream()) { + StaxStreamProcessor staxProcessor = new StaxStreamProcessor(inputStream); + while (staxProcessor.doUntil(XMLEvent.START_ELEMENT, "User")) { + XMLStreamReader reader = staxProcessor.getReader(); + String email = reader.getAttributeValue("", "email"); + String flag = reader.getAttributeValue("", "flag"); + String fullName = reader.getElementText(); + users.add(new User(fullName, email, UserFlag.valueOf(flag))); +// reader.close(); + } + staxProcessor.close(); + } catch (XMLStreamException e) { + LOGGER.log(Level.INFO, "No users: " + request.getPart("file").getSubmittedFileName()); + e.printStackTrace(); + } + ctx.setVariable("users", users); + ctx.setVariable("file", request.getPart("file").getSubmittedFileName()); + UserProccessor.process(response, "users", ctx); + } +} + \ No newline at end of file diff --git a/upload/src/main/java/ru/javaops/masterjava/model/User.java b/upload/src/main/java/ru/javaops/masterjava/model/User.java new file mode 100644 index 0000000..d7c3f8c --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/model/User.java @@ -0,0 +1,63 @@ +package ru.javaops.masterjava.model; + +import java.util.Objects; + +public class User { + private final Integer id; + private final String fullName; + private final String email; + private final UserFlag flag; + + public User(String fullName, String email, UserFlag flag) { + this(null, fullName, email, flag); + } + + public User(Integer id, String fullName, String email, UserFlag flag) { + this.id = id; + this.fullName = fullName; + this.email = email; + this.flag = flag; + } + + public Integer getId() { + return id; + } + + public String getFullName() { + return fullName; + } + + public String getEmail() { + return email; + } + + public UserFlag getFlag() { + return flag; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + User user = (User) o; + return Objects.equals(id, user.id) && + Objects.equals(fullName, user.fullName) && + Objects.equals(email, user.email) && + flag == user.flag; + } + + @Override + public int hashCode() { + return Objects.hash(id, fullName, email, flag); + } + + @Override + public String toString() { + return "User (" + + "id=" + id + + ", fullName='" + fullName + '\'' + + ", email='" + email + '\'' + + ", flag=" + flag + + ')'; + } +} diff --git a/upload/src/main/java/ru/javaops/masterjava/model/UserFlag.java b/upload/src/main/java/ru/javaops/masterjava/model/UserFlag.java new file mode 100644 index 0000000..341cc44 --- /dev/null +++ b/upload/src/main/java/ru/javaops/masterjava/model/UserFlag.java @@ -0,0 +1,7 @@ +package ru.javaops.masterjava.model; + +public enum UserFlag { + active, + deleted, + superuser; +} diff --git a/upload/src/main/webapp/WEB-INF/templates/upload.html b/upload/src/main/webapp/WEB-INF/templates/upload.html new file mode 100644 index 0000000..76f75c6 --- /dev/null +++ b/upload/src/main/webapp/WEB-INF/templates/upload.html @@ -0,0 +1,14 @@ + + File Upload + + + +
+
+ File to upload: +
+
+ +
+ + diff --git a/upload/src/main/webapp/WEB-INF/templates/users.html b/upload/src/main/webapp/WEB-INF/templates/users.html new file mode 100644 index 0000000..30029d4 --- /dev/null +++ b/upload/src/main/webapp/WEB-INF/templates/users.html @@ -0,0 +1,28 @@ + + + + Uploaded users from XML + + +

Upload XML

+

Uploaded users from XML file -

+ + + + + + + + + + + + + + + + + +
Full NameEmailFlag
+ + \ No newline at end of file From 876f763a807707cb462a4661fed54d3ddc3d013f Mon Sep 17 00:00:00 2001 From: user Date: Mon, 12 Jun 2023 18:19:38 +0300 Subject: [PATCH 6/7] HW3 Optional: upload users by Stax+Jaxb --- ...erProccessor.java => ThymeleafEngine.java} | 2 +- .../ru/javaops/masterjava/UserServlet.java | 51 +++++++++++++++---- .../main/webapp/WEB-INF/templates/users.html | 2 +- 3 files changed, 44 insertions(+), 11 deletions(-) rename upload/src/main/java/ru/javaops/masterjava/{UserProccessor.java => ThymeleafEngine.java} (96%) diff --git a/upload/src/main/java/ru/javaops/masterjava/UserProccessor.java b/upload/src/main/java/ru/javaops/masterjava/ThymeleafEngine.java similarity index 96% rename from upload/src/main/java/ru/javaops/masterjava/UserProccessor.java rename to upload/src/main/java/ru/javaops/masterjava/ThymeleafEngine.java index 9f8c246..9344e74 100644 --- a/upload/src/main/java/ru/javaops/masterjava/UserProccessor.java +++ b/upload/src/main/java/ru/javaops/masterjava/ThymeleafEngine.java @@ -8,7 +8,7 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; -public class UserProccessor { +public class ThymeleafEngine { private static final TemplateEngine templateEngine = new TemplateEngine(); private static final ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(); static { diff --git a/upload/src/main/java/ru/javaops/masterjava/UserServlet.java b/upload/src/main/java/ru/javaops/masterjava/UserServlet.java index 7a1394e..26e6c54 100644 --- a/upload/src/main/java/ru/javaops/masterjava/UserServlet.java +++ b/upload/src/main/java/ru/javaops/masterjava/UserServlet.java @@ -3,6 +3,8 @@ import org.thymeleaf.context.WebContext; import ru.javaops.masterjava.model.User; import ru.javaops.masterjava.model.UserFlag; +import ru.javaops.masterjava.xml.schema.ObjectFactory; +import ru.javaops.masterjava.xml.util.JaxbParser; import ru.javaops.masterjava.xml.util.StaxStreamProcessor; import javax.servlet.ServletException; @@ -11,6 +13,10 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.events.XMLEvent; @@ -30,10 +36,10 @@ public class UserServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { final WebContext ctx = new WebContext(request, response, request.getServletContext(), request.getLocale()); - UserProccessor.process(response, "upload", ctx); + ThymeleafEngine.process(response, "upload", ctx); } - public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { final WebContext ctx = new WebContext(request, response, request.getServletContext(), request.getLocale()); // Collection parts = request.getParts(); // for (Part part : parts) { @@ -53,9 +59,17 @@ public void doPost(HttpServletRequest request, HttpServletResponse response) thr // } // System.out.println("==============================================="); // } - List users = new ArrayList(); - try (InputStream inputStream = request.getPart("file").getInputStream()) { - StaxStreamProcessor staxProcessor = new StaxStreamProcessor(inputStream); +// List users = getUsersByStax(request); + List users = getUsersByStaxJaxb(request); + ctx.setVariable("users", users); + ctx.setVariable("file", request.getPart("file").getSubmittedFileName()); + ThymeleafEngine.process(response, "users", ctx); + } + + private List getUsersByStax(HttpServletRequest request) throws IOException, ServletException { + List users = new ArrayList<>(); + try (InputStream inputStream = request.getPart("file").getInputStream(); + StaxStreamProcessor staxProcessor = new StaxStreamProcessor(inputStream)) { while (staxProcessor.doUntil(XMLEvent.START_ELEMENT, "User")) { XMLStreamReader reader = staxProcessor.getReader(); String email = reader.getAttributeValue("", "email"); @@ -64,14 +78,33 @@ public void doPost(HttpServletRequest request, HttpServletResponse response) thr users.add(new User(fullName, email, UserFlag.valueOf(flag))); // reader.close(); } - staxProcessor.close(); } catch (XMLStreamException e) { LOGGER.log(Level.INFO, "No users: " + request.getPart("file").getSubmittedFileName()); e.printStackTrace(); } - ctx.setVariable("users", users); - ctx.setVariable("file", request.getPart("file").getSubmittedFileName()); - UserProccessor.process(response, "users", ctx); + return users; + } + + private List getUsersByStaxJaxb(HttpServletRequest request) throws IOException, ServletException { + JaxbParser jaxbParser = new JaxbParser(ObjectFactory.class); + List users = new ArrayList<>(); + try (InputStream inputStream = request.getPart("file").getInputStream(); + StaxStreamProcessor staxProcessor = new StaxStreamProcessor(inputStream)) { + while (staxProcessor.doUntil(XMLEvent.START_ELEMENT, "User")) { + XMLStreamReader reader = staxProcessor.getReader(); + JAXBContext jaxbContext = JAXBContext.newInstance("ru.javaops.masterjava.xml.schema"); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + JAXBElement xmlUser = unmarshaller.unmarshal(reader, ru.javaops.masterjava.xml.schema.User.class); + users.add(new User(xmlUser.getValue().getValue(), + xmlUser.getValue().getEmail(), + UserFlag.valueOf(xmlUser.getValue().getFlag().value()))); +// reader.close(); + } + } catch (XMLStreamException | JAXBException e) { + LOGGER.log(Level.INFO, "No users: " + request.getPart("file").getSubmittedFileName()); + e.printStackTrace(); + } + return users; } } \ No newline at end of file diff --git a/upload/src/main/webapp/WEB-INF/templates/users.html b/upload/src/main/webapp/WEB-INF/templates/users.html index 30029d4..350acef 100644 --- a/upload/src/main/webapp/WEB-INF/templates/users.html +++ b/upload/src/main/webapp/WEB-INF/templates/users.html @@ -5,7 +5,7 @@

Upload XML

-

Uploaded users from XML file -

+

Uploaded users from XML file -

From 8fc71ef76395620bb2db73a8737894f4359b3814 Mon Sep 17 00:00:00 2001 From: user Date: Wed, 14 Jun 2023 10:18:15 +0300 Subject: [PATCH 7/7] HW3 Optional: upload users by Stax+Jaxb with exception --- .../ru/javaops/masterjava/UserServlet.java | 26 ++++++++++++------- .../webapp/WEB-INF/templates/exception.html | 17 ++++++++++++ 2 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 upload/src/main/webapp/WEB-INF/templates/exception.html diff --git a/upload/src/main/java/ru/javaops/masterjava/UserServlet.java b/upload/src/main/java/ru/javaops/masterjava/UserServlet.java index 26e6c54..17b97e1 100644 --- a/upload/src/main/java/ru/javaops/masterjava/UserServlet.java +++ b/upload/src/main/java/ru/javaops/masterjava/UserServlet.java @@ -39,7 +39,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro ThymeleafEngine.process(response, "upload", ctx); } - public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { final WebContext ctx = new WebContext(request, response, request.getServletContext(), request.getLocale()); // Collection parts = request.getParts(); // for (Part part : parts) { @@ -60,10 +60,19 @@ public void doPost(HttpServletRequest request, HttpServletResponse response) thr // System.out.println("==============================================="); // } // List users = getUsersByStax(request); - List users = getUsersByStaxJaxb(request); - ctx.setVariable("users", users); - ctx.setVariable("file", request.getPart("file").getSubmittedFileName()); - ThymeleafEngine.process(response, "users", ctx); + List users = null; + try { + users = getUsersByStaxJaxb(request); + ctx.setVariable("users", users); + ctx.setVariable("file", request.getPart("file").getSubmittedFileName()); + ThymeleafEngine.process(response, "users", ctx); + } catch (ServletException | IOException | XMLStreamException | JAXBException e) { + ctx.setVariable("exception", e); + String fileName = request.getPart("file").getSubmittedFileName(); + ctx.setVariable("file", "".equals(fileName) ? "File is not selected" : fileName); + ThymeleafEngine.process(response, "exception", ctx); + e.printStackTrace(); + } } private List getUsersByStax(HttpServletRequest request) throws IOException, ServletException { @@ -79,13 +88,13 @@ private List getUsersByStax(HttpServletRequest request) throws IOException // reader.close(); } } catch (XMLStreamException e) { - LOGGER.log(Level.INFO, "No users: " + request.getPart("file").getSubmittedFileName()); + LOGGER.log(Level.INFO, "Error while reading file: " + request.getPart("file").getSubmittedFileName()); e.printStackTrace(); } return users; } - private List getUsersByStaxJaxb(HttpServletRequest request) throws IOException, ServletException { + private List getUsersByStaxJaxb(HttpServletRequest request) throws ServletException, IOException, XMLStreamException, JAXBException { JaxbParser jaxbParser = new JaxbParser(ObjectFactory.class); List users = new ArrayList<>(); try (InputStream inputStream = request.getPart("file").getInputStream(); @@ -100,9 +109,6 @@ private List getUsersByStaxJaxb(HttpServletRequest request) throws IOExcep UserFlag.valueOf(xmlUser.getValue().getFlag().value()))); // reader.close(); } - } catch (XMLStreamException | JAXBException e) { - LOGGER.log(Level.INFO, "No users: " + request.getPart("file").getSubmittedFileName()); - e.printStackTrace(); } return users; } diff --git a/upload/src/main/webapp/WEB-INF/templates/exception.html b/upload/src/main/webapp/WEB-INF/templates/exception.html new file mode 100644 index 0000000..c935c7a --- /dev/null +++ b/upload/src/main/webapp/WEB-INF/templates/exception.html @@ -0,0 +1,17 @@ + + + + Exception + + +
+

Application Exception:

+ +

exception.message

+

File : File is not selected

+
    +
  • +
+ + + \ No newline at end of file