1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.openehealth.ipf.commons.xml;
17
18 import lombok.Getter;
19 import lombok.Setter;
20 import org.openehealth.ipf.commons.core.modules.api.Transmogrifier;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import javax.xml.transform.*;
25 import java.util.Map;
26 import java.util.Map.Entry;
27 import java.util.concurrent.ConcurrentHashMap;
28 import java.util.concurrent.ConcurrentMap;
29
30
31
32
33
34
35
36
37
38
39
40
41 public class XsltTransmogrifier<T> extends AbstractCachingXmlProcessor<Templates> implements Transmogrifier<Source, T> {
42 private static final Logger LOG = LoggerFactory.getLogger(XsltTransmogrifier.class);
43
44 private static final ConcurrentMap<String, Loader<Templates>> XSLT_CACHE = new ConcurrentHashMap<>();
45
46 @Getter @Setter private Map<String, Object> staticParams;
47 private final TransformerFactory factory;
48 private final URIResolver resolver;
49 private final Class<T> outputFormat;
50
51 @SuppressWarnings("unchecked")
52 public XsltTransmogrifier() {
53 this((Class<T>) String.class, null, null);
54 }
55
56 public XsltTransmogrifier(Class<T> outputFormat) {
57 this(outputFormat, null, null);
58 }
59
60 public XsltTransmogrifier(Class<T> outputFormat, ClassLoader classLoader) {
61 this(outputFormat, classLoader, null);
62 }
63
64 public XsltTransmogrifier(Class<T> outputFormat, Map<String, Object> staticParams) {
65 this(outputFormat, null, staticParams);
66 }
67
68 public TransformerFactory getFactory() {
69 return factory;
70 }
71
72 @Override
73 protected ConcurrentMap<String, Loader<Templates>> getCache() {
74 return XSLT_CACHE;
75 }
76
77
78
79
80
81
82
83
84
85 public XsltTransmogrifier(
86 Class<T> outputFormat,
87 ClassLoader classLoader,
88 Map<String, Object> staticParams)
89 {
90 super(classLoader);
91 factory = TransformerFactory.newInstance();
92
93 resolver = new ClasspathUriResolver(factory.getURIResolver());
94 factory.setURIResolver(resolver);
95 this.outputFormat = outputFormat;
96 this.staticParams = staticParams;
97 }
98
99
100
101
102
103
104
105
106
107 @Override
108 public T zap(Source source, Object... params) {
109 ResultHolder<T> accessor = ResultHolderFactory.create(outputFormat);
110 if (accessor == null) throw new IllegalArgumentException("Format " + outputFormat.getClass() + " is not supported");
111 Result result = accessor.createResult();
112 doZap(source, result, params);
113 return accessor.getResult();
114 }
115
116 private void doZap(Source source, Result result, Object... params) {
117 if (params.length == 0) {
118 throw new IllegalArgumentException("Expected XSL location in first parameter");
119 }
120 try {
121 Templates template = resource(params);
122 Transformer transformer = template.newTransformer();
123 transformer.setURIResolver(resolver);
124 setXsltParameters(transformer, staticParams);
125 setXsltParameters(transformer, resourceParameters(params));
126 transformer.transform(source, result);
127 } catch (Exception e) {
128 throw new RuntimeException("XSLT processing failed", e);
129 }
130
131 }
132
133
134
135
136 protected void setXsltParameters(Transformer transformer, Map<String, Object> param) {
137 if (param == null) {
138 return;
139 }
140 for (Entry<String, Object> entry : param.entrySet()) {
141 LOG.debug("Add new parameter for transformer: {}", entry.getKey());
142 transformer.setParameter(entry.getKey(), entry.getValue());
143 }
144 }
145
146 @Override
147 protected Templates createResource(Object... params) {
148 try {
149 return factory.newTemplates(resourceContent(params));
150 } catch (TransformerConfigurationException e) {
151 throw new IllegalArgumentException("Could not initialize XSLT template", e);
152 }
153 }
154
155 }