View Javadoc

1   /*
2    * #%L
3    * Native ARchive plugin for Maven
4    * %%
5    * Copyright (C) 2002 - 2014 NAR Maven Plugin developers.
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * 
11   * http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package com.github.maven_nar.cpptasks.apple;
21  
22  import java.io.File;
23  import java.io.FileOutputStream;
24  import java.io.IOException;
25  import java.util.Arrays;
26  import java.util.List;
27  import java.util.Map;
28  
29  import javax.xml.transform.TransformerConfigurationException;
30  import javax.xml.transform.TransformerFactory;
31  import javax.xml.transform.sax.SAXTransformerFactory;
32  import javax.xml.transform.sax.TransformerHandler;
33  import javax.xml.transform.stream.StreamResult;
34  
35  import org.xml.sax.ContentHandler;
36  import org.xml.sax.SAXException;
37  import org.xml.sax.helpers.AttributesImpl;
38  
39  /**
40   * Static class that provides methods to serialize
41   * a Map to a Cocoa XML Property List. Does not currently support
42   * date or data elements.
43   */
44  public final class PropertyListSerialization {
45    /**
46     * Serializes a property list into a Cocoa XML Property List document.
47     * 
48     * @param propertyList
49     *          property list.
50     * @param file
51     *          destination.
52     * @param comments
53     *          comments to insert into document.
54     * @throws SAXException
55     *           if exception during serialization.
56     * @throws TransformerConfigurationException
57     *           if exception creating serializer.
58     */
59    public static void serialize(final Map propertyList, final List comments, final File file)
60        throws IOException, SAXException, TransformerConfigurationException {
61      final SAXTransformerFactory sf = (SAXTransformerFactory) TransformerFactory.newInstance();
62      final TransformerHandler handler = sf.newTransformerHandler();
63  
64      final FileOutputStream os = new FileOutputStream(file);
65      final StreamResult result = new StreamResult(os);
66      handler.setResult(result);
67  
68      handler.startDocument();
69      for (final Object comment1 : comments) {
70        final char[] comment = String.valueOf(comment1).toCharArray();
71        handler.comment(comment, 0, comment.length);
72      }
73      final AttributesImpl attributes = new AttributesImpl();
74      handler.startElement(null, "plist", "plist", attributes);
75      serializeMap(propertyList, handler);
76      handler.endElement(null, "plist", "plist");
77  
78      handler.endDocument();
79    }
80  
81    /**
82     * Serialize a Boolean as a true or false element.
83     * 
84     * @param val
85     *          boolean to serialize.
86     * @param handler
87     *          destination of serialization events.
88     * @throws SAXException
89     *           if exception during serialization.
90     */
91    private static void serializeBoolean(final Boolean val, final ContentHandler handler) throws SAXException {
92      String tag = "false";
93      if (val.booleanValue()) {
94        tag = "true";
95      }
96      final AttributesImpl attributes = new AttributesImpl();
97      handler.startElement(null, tag, tag, attributes);
98      handler.endElement(null, tag, tag);
99    }
100 
101   /**
102    * Creates an element with the specified tag name and character content.
103    * 
104    * @param tag
105    *          tag name.
106    * @param content
107    *          character content.
108    * @param handler
109    *          destination of serialization events.
110    * @throws SAXException
111    *           if exception during serialization.
112    */
113   private static void serializeElement(final String tag, final String content, final ContentHandler handler)
114       throws SAXException {
115     final AttributesImpl attributes = new AttributesImpl();
116     handler.startElement(null, tag, tag, attributes);
117     handler.characters(content.toCharArray(), 0, content.length());
118     handler.endElement(null, tag, tag);
119   }
120 
121   /**
122    * Serialize a Number as an integer element.
123    * 
124    * @param integer
125    *          number to serialize.
126    * @param handler
127    *          destination of serialization events.
128    * @throws SAXException
129    *           if exception during serialization.
130    */
131   private static void serializeInteger(final Number integer, final ContentHandler handler) throws SAXException {
132     serializeElement("integer", String.valueOf(integer.longValue()), handler);
133   }
134 
135   /**
136    * Serialize a list as an array element.
137    * 
138    * @param list
139    *          list to serialize.
140    * @param handler
141    *          destination of serialization events.
142    * @throws SAXException
143    *           if exception during serialization.
144    */
145   private static void serializeList(final List list, final ContentHandler handler) throws SAXException {
146     final AttributesImpl attributes = new AttributesImpl();
147     handler.startElement(null, "array", "array", attributes);
148     for (final Object aList : list) {
149       serializeObject(aList, handler);
150     }
151     handler.endElement(null, "array", "array");
152   }
153 
154   /**
155    * Serialize a map as a dict element.
156    * 
157    * @param map
158    *          map to serialize.
159    * @param handler
160    *          destination of serialization events.
161    * @throws SAXException
162    *           if exception during serialization.
163    */
164   private static void serializeMap(final Map map, final ContentHandler handler) throws SAXException {
165     final AttributesImpl attributes = new AttributesImpl();
166     handler.startElement(null, "dict", "dict", attributes);
167 
168     if (map.size() > 0) {
169       //
170       // need to output with sorted keys to maintain
171       // reproducability
172       //
173       final Object[] keys = map.keySet().toArray();
174       Arrays.sort(keys);
175       for (final Object key2 : keys) {
176         final String key = String.valueOf(key2);
177         handler.startElement(null, "key", "key", attributes);
178         handler.characters(key.toCharArray(), 0, key.length());
179         handler.endElement(null, "key", "key");
180         serializeObject(map.get(key2), handler);
181       }
182     }
183     handler.endElement(null, "dict", "dict");
184   }
185 
186   /**
187    * Serialize an object using the best available element.
188    * 
189    * @param obj
190    *          object to serialize.
191    * @param handler
192    *          destination of serialization events.
193    * @throws SAXException
194    *           if exception during serialization.
195    */
196   private static void serializeObject(final Object obj, final ContentHandler handler) throws SAXException {
197     if (obj instanceof Map) {
198       serializeMap((Map) obj, handler);
199     } else if (obj instanceof List) {
200       serializeList((List) obj, handler);
201     } else if (obj instanceof Number) {
202       if (obj instanceof Double || obj instanceof Float) {
203         serializeReal((Number) obj, handler);
204       } else {
205         serializeInteger((Number) obj, handler);
206       }
207     } else if (obj instanceof Boolean) {
208       serializeBoolean((Boolean) obj, handler);
209     } else {
210       serializeString(String.valueOf(obj), handler);
211     }
212   }
213 
214   /**
215    * Serialize a Number as a real element.
216    * 
217    * @param real
218    *          number to serialize.
219    * @param handler
220    *          destination of serialization events.
221    * @throws SAXException
222    *           if exception during serialization.
223    */
224   private static void serializeReal(final Number real, final ContentHandler handler) throws SAXException {
225     serializeElement("real", String.valueOf(real.doubleValue()), handler);
226   }
227 
228   /**
229    * Serialize a string as a string element.
230    * 
231    * @param val
232    *          string to serialize.
233    * @param handler
234    *          destination of serialization events.
235    * @throws SAXException
236    *           if exception during serialization.
237    */
238   private static void serializeString(final String val, final ContentHandler handler) throws SAXException {
239     serializeElement("string", val, handler);
240   }
241 
242   /**
243    * Private constructor.
244    */
245   private PropertyListSerialization() {
246 
247   }
248 }