View Javadoc
1   package ca.uhn.fhir.model.primitive;
2   
3   /*
4    * #%L
5    * HAPI FHIR - Core Library
6    * %%
7    * Copyright (C) 2014 University Health Network
8    * %%
9    * Licensed under the Apache License, Version 2.0 (the "License");
10   * you may not use this file except in compliance with the License.
11   * You may obtain a copy of the License at
12   * 
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   * 
15   * Unless required by applicable law or agreed to in writing, software
16   * distributed under the License is distributed on an "AS IS" BASIS,
17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   * See the License for the specific language governing permissions and
19   * limitations under the License.
20   * #L%
21   */
22  
23  import java.io.IOException;
24  import java.io.OutputStream;
25  import java.io.StringReader;
26  import java.io.StringWriter;
27  import java.io.UnsupportedEncodingException;
28  import java.io.Writer;
29  import java.util.ArrayList;
30  import java.util.List;
31  
32  import javax.xml.stream.FactoryConfigurationError;
33  import javax.xml.stream.XMLEventReader;
34  import javax.xml.stream.XMLEventWriter;
35  import javax.xml.stream.XMLStreamException;
36  import javax.xml.stream.events.XMLEvent;
37  
38  import org.apache.commons.lang3.StringEscapeUtils;
39  import org.codehaus.stax2.io.EscapingWriterFactory;
40  
41  import ca.uhn.fhir.context.ConfigurationException;
42  import ca.uhn.fhir.model.api.BasePrimitive;
43  import ca.uhn.fhir.model.api.annotation.DatatypeDef;
44  import ca.uhn.fhir.model.api.annotation.SimpleSetter;
45  import ca.uhn.fhir.parser.DataFormatException;
46  import ca.uhn.fhir.util.XmlUtil;
47  
48  @DatatypeDef(name = "xhtml")
49  public class XhtmlDt extends BasePrimitive<List<XMLEvent>> {
50  
51  	private List<XMLEvent> myValue;
52  
53  	/**
54  	 * Constructor
55  	 */
56  	public XhtmlDt() {
57  		// nothing
58  	}
59  
60  	/**
61  	 * Constructor which accepts a string code
62  	 * 
63  	 * @see #setValueAsString(String) for a description of how this value is applied
64  	 */
65  	@SimpleSetter()
66  	public XhtmlDt(@SimpleSetter.Parameter(name = "theTextDiv") String theTextDiv) {
67  		setValueAsString(theTextDiv);
68  	}
69  
70  	/**
71  	 * Accepts a textual DIV and parses it into XHTML events which are stored internally.
72  	 * <p>
73  	 * <b>Formatting note:</b> The text will be trimmed {@link String#trim()}. If the text does not start with an HTML tag (generally this would be a div tag), a div tag will be automatically placed
74  	 * surrounding the text.
75  	 * </p>
76  	 * <p>
77  	 * Also note that if the parsed text contains any entities (&foo;) which are not a part of the entities defined in core XML (e.g. &sect; which
78  	 * is valid in XHTML 1.0 but not in XML 1.0) they will be parsed and converted to their equivalent unicode character.
79  	 * </p>
80  	 */
81  	@Override
82  	public void setValueAsString(String theValue) throws DataFormatException {
83  		if (theValue == null) {
84  			myValue = null;
85  			return;
86  		}
87  
88  		String val = theValue.trim();
89  		if (!val.startsWith("<")) {
90  			val = "<div>" + val + "</div>";
91  		}
92  		if (val.startsWith("<?") && val.endsWith("?>")) {
93  			myValue = null;
94  			return;
95  		}
96  
97  		try {
98  			ArrayList<XMLEvent> value = new ArrayList<XMLEvent>();
99  			StringReader reader = new StringReader(val);
100 			XMLEventReader er = XmlUtil.createXmlReader(reader);
101 			boolean first = true;
102 			while (er.hasNext()) {
103 				XMLEvent next = er.nextEvent();
104 				if (first) {
105 					first = false;
106 					continue;
107 				}
108 				if (er.hasNext()) {
109 					// don't add the last event
110 					value.add(next);
111 				}
112 			}
113 			setValue(value);
114 
115 		} catch (XMLStreamException e) {
116 			throw new DataFormatException("String does not appear to be valid XML/XHTML (error is \"" + e.getMessage() + "\"): " + theValue, e);
117 		} catch (FactoryConfigurationError e) {
118 			throw new ConfigurationException(e);
119 		}
120 	}
121 
122 	@Override
123 	public String getValueAsString() throws DataFormatException {
124 		if (myValue == null) {
125 			return null;
126 		}
127 		try {
128 			StringWriter w = new StringWriter();
129 			XMLEventWriter ew = XmlUtil.createXmlWriter(w);
130 			for (XMLEvent next : myValue) {
131 				if (next.isCharacters()) {
132 					ew.add(next);
133 				} else {
134 					ew.add(next);
135 				}
136 			}
137 			ew.close();
138 			return w.toString();
139 		} catch (XMLStreamException e) {
140 			throw new DataFormatException("Problem with the contained XML events", e);
141 		} catch (FactoryConfigurationError e) {
142 			throw new ConfigurationException(e);
143 		}
144 	}
145 
146 	@Override
147 	public List<XMLEvent> getValue() {
148 		return myValue;
149 	}
150 
151 	@Override
152 	public void setValue(List<XMLEvent> theValue) throws DataFormatException {
153 		myValue = theValue;
154 	}
155 
156 	public boolean hasContent() {
157 		return myValue != null && myValue.size() > 0;
158 	}
159 
160 }