1
17 package org.torweg.pulse.site.content;
18
19 import java.io.IOException;
20 import java.io.StringReader;
21 import java.util.HashSet;
22 import java.util.Set;
23
24 import javax.persistence.CascadeType;
25 import javax.persistence.Column;
26 import javax.persistence.FetchType;
27 import javax.persistence.Lob;
28 import javax.persistence.ManyToOne;
29 import javax.persistence.MappedSuperclass;
30 import javax.persistence.Transient;
31 import javax.xml.bind.annotation.XmlAccessOrder;
32 import javax.xml.bind.annotation.XmlAccessType;
33 import javax.xml.bind.annotation.XmlAccessorOrder;
34 import javax.xml.bind.annotation.XmlAccessorType;
35 import javax.xml.bind.annotation.XmlAttribute;
36 import javax.xml.bind.annotation.XmlElement;
37 import javax.xml.bind.annotation.XmlRootElement;
38 import javax.xml.bind.annotation.XmlTransient;
39 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
40
41 import org.hibernate.LazyInitializationException;
42 import org.jdom.Element;
43 import org.jdom.JDOMException;
44 import org.jdom.input.SAXBuilder;
45 import org.torweg.pulse.accesscontrol.User;
46 import org.torweg.pulse.service.PulseException;
47 import org.torweg.pulse.service.request.ServiceRequest;
48 import org.torweg.pulse.site.content.util.ILinkCorrectableElement;
49 import org.torweg.pulse.util.xml.XMLConverter;
50 import org.torweg.pulse.util.xml.bind.ElementXmlAdapter;
51
52
59 @MappedSuperclass
60 @XmlRootElement(name = "abstract-basic-variant")
61 @XmlAccessorOrder(XmlAccessOrder.UNDEFINED)
62 @XmlAccessorType(XmlAccessType.FIELD)
63 public abstract class AbstractBasicVariant<T extends AbstractBasicVariant<T>>
64 extends Variant<T> {
65
66
69 private static final long serialVersionUID = 1697853927204347160L;
70
71
74 @ManyToOne(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST,
75 CascadeType.MERGE, CascadeType.REFRESH }, optional = false)
76 @XmlTransient
77 private Content content = null;
79
80
83 @Lob
84 @Column(length = 65535)
85 @XmlTransient
86 private String summary = "<body/>";
87
88
92 @Transient
93 private transient Element summaryElement = null;
95
96
101 @Override
102 public final Content getContent() {
103 return this.content;
104 }
105
106
112 @Override
113 public void setContent(final Content pContent) {
114 if (pContent == null) {
115 throw new IllegalArgumentException(
116 "The given Content must be not be null.");
117 } else if (!Content.class.isAssignableFrom(pContent.getClass())) {
118 throw new IllegalArgumentException("The runtime class "
119 + "of the given Content must be Content.");
120 }
121 this.content = (Content) pContent;
122 if (!getVariants().isEmpty() && getVariants() != null) {
123 for (AbstractBasicVariant<?> variant : getVariants()) {
124 variant.setContent(pContent);
125 }
126 }
127 }
128
129
134 @XmlElement(name = "content-id")
135 @SuppressWarnings("unused")
136 @Deprecated
137 private Long getContentIdJAXB() {
138 try {
139 return getContent().getId();
140 } catch (LazyInitializationException e) {
141 LOGGER.debug("ignored: {}", e.getLocalizedMessage());
142 return null;
143 }
144 }
145
146
151 @XmlAttribute(name = "bundle")
152 @SuppressWarnings("unused")
153 @Deprecated
154 private String getBundleJAXB() {
155 try {
156 return getContent().getBundle().getName();
157 } catch (LazyInitializationException e) {
158 LOGGER.debug("ignored: {}", e.getLocalizedMessage());
159 return null;
160 }
161 }
162
163
168 public final String getSummary() {
169 return this.summary;
170 }
171
172
179 public final void setSummary(final Element pSummaryElement) {
180 this.summary = XMLConverter.getRawString(pSummaryElement, true);
181 this.summaryElement = pSummaryElement;
182 }
183
184
191 public final Element getSummaryElement() {
192 if (getSummary() == null) {
193 return null;
194 }
195 if (this.summaryElement == null) {
196 try {
197 this.summaryElement = new SAXBuilder().build(
198 new StringReader(getSummary())).getRootElement();
199 } catch (JDOMException e) {
200 throw new PulseException("Error parsing XML for summary: "
201 + e.getLocalizedMessage(), e);
202 } catch (IOException e) {
203 throw new PulseException("Error reading XML for summary: "
204 + e.getLocalizedMessage(), e);
205 }
206 }
207 return (Element) this.summaryElement.clone();
208 }
209
210
215 @XmlElement(name = "summary-element")
216 @XmlJavaTypeAdapter(value = ElementXmlAdapter.class)
217 @SuppressWarnings("unused")
218 @Deprecated
219 private Element getSummaryElementJAXB() {
220 try {
221 return getSummaryElement();
222 } catch (LazyInitializationException e) {
223 LOGGER.debug("ignored: {}", e.getLocalizedMessage());
224 return null;
225 }
226 }
227
228
240 @Override
241 public StringBuilder getFullTextValue() {
242 return new StringBuilder(getName()).append(' ').append(
243 XMLConverter.getHTMLText(getSummaryElement()));
244 }
245
246
253 public Element deserializeToJDOM() {
254 return deserializeToJDOM(null);
255 }
256
257
267 public Element deserializeToJDOM(final ServiceRequest pServiceRequest) {
268 Element element = new Element("Variant").setAttribute("class",
269 getClass().getCanonicalName());
270 if (getId() != null) {
271 element.setAttribute("id", getId().toString());
272 }
273 if (getContent() != null) {
274 element.setAttribute("bundle", getContent().getBundle().getName());
275 element.addContent(new Element("content-id").setText(getContent()
276 .getId().toString()));
277 }
278 if (getName() != null) {
279 element.addContent(new Element("name").setText(getName()));
280 }
281 addAttachments(pServiceRequest, element);
282 if (getSummary() != null) {
283 element.addContent(new Element("summary")
284 .addContent((Element) getSummaryElement().clone()));
285 }
286 if (getParentVariant() != null) {
287 element.addContent(new Element("parent-variant-id")
288 .setText(getParentVariant().getId().toString()));
289 }
290 Element variants = new Element("variants");
291 try {
292 for (T variant : getVariants()) {
293 variants.addContent(variant.deserializeToJDOM());
294 }
295 } catch (LazyInitializationException e) {
296 LOGGER.debug("ignored: {}", e.getLocalizedMessage());
297 }
298 element.addContent(variants);
299 return element;
300 }
301
302
306 public Set<ILinkCorrectableElement> getLinkCorrectables() {
307 Set<ILinkCorrectableElement> correctables = new HashSet<ILinkCorrectableElement>();
308 correctables.add(new SummaryCorrectable(this));
309 return correctables;
310 }
311
312
321 private void addAttachments(final ServiceRequest pServiceRequest,
322 final Element pElement) {
323
324 User user = null;
325 if (pServiceRequest != null) {
326 user = pServiceRequest.getUser();
327 }
328 Element element = new Element("attachments");
329 try {
330 for (Attachment attachment : getAttachments()) {
331 Element attElem = attachment.deserializeToJDOM();
332 attElem.setAttribute("canRead", Boolean.toString(attachment
333 .getVirtualFile().canRead(user)));
334 attElem.setAttribute("canWrite", Boolean.toString(attachment
335 .getVirtualFile().canWrite(user)));
336 element.addContent(attElem);
337 }
338 } catch (LazyInitializationException e) {
339 LOGGER.trace("adding attachments: {}", e.getMessage());
340 } finally {
341 pElement.addContent(element);
342 }
343 }
344
345
351 private static final class SummaryCorrectable implements
352 ILinkCorrectableElement {
353
354
357 private final AbstractBasicVariant<?> variant;
358
359
366 public SummaryCorrectable(final AbstractBasicVariant<?> v) {
367 super();
368 this.variant = v;
369 }
370
371
375 public Element getElement() {
376 return this.variant.getSummaryElement();
377 }
378
379
384 public void setElement(final Element e) {
385 this.variant.setSummary(e);
386 }
387
388 }
389
390 }
391