de.huxhorn.sulky.plist.impl.PropertyListWriter.java Source code

Java tutorial

Introduction

Here is the source code for de.huxhorn.sulky.plist.impl.PropertyListWriter.java

Source

/*
 * sulky-modules - several general-purpose modules.
 * Copyright (C) 2007-2011 Joern Huxhorn
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * Copyright 2007-2011 Joern Huxhorn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.huxhorn.sulky.plist.impl;

import de.huxhorn.sulky.plist.PropertyList;
import de.huxhorn.sulky.stax.GenericStreamWriter;
import de.huxhorn.sulky.stax.StaxUtilities;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class PropertyListWriter implements GenericStreamWriter<PropertyList>, PropertyListConstants {
    private final Logger logger = LoggerFactory.getLogger(PropertyListWriter.class);

    private SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);

    public void write(XMLStreamWriter writer, PropertyList object, boolean isRoot) throws XMLStreamException {
        if (isRoot) {
            writer.writeStartDocument("utf-8", "1.0");
            writer.writeCharacters("\n");
            writer.writeDTD(
                    "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">");
            writer.writeCharacters("\n");
        }
        StaxUtilities.writeStartElement(writer, null, null, PLIST_NODE);
        StaxUtilities.writeAttribute(writer, false, null, null, PLIST_VERSION_ATTRIBUTE, PLIST_VERSION);

        if (object != null) {
            writeValue(writer, object.getRoot());
        }

        writer.writeEndElement();
        if (isRoot) {
            writer.writeEndDocument();
        }
    }

    private void writeValue(XMLStreamWriter writer, Object value) throws XMLStreamException {
        if (value == null) {
            return;
        }
        if (value instanceof String) {
            StaxUtilities.writeSimpleTextNode(writer, null, null, STRING_NODE, (String) value);
            return;
        }
        if (value instanceof Boolean) {
            Boolean bool = (Boolean) value;
            if (bool) {
                StaxUtilities.writeEmptyElement(writer, null, null, TRUE_NODE);
            } else {
                StaxUtilities.writeEmptyElement(writer, null, null, FALSE_NODE);
            }
            return;
        }

        if (value instanceof Character) {
            StaxUtilities.writeSimpleTextNode(writer, null, null, STRING_NODE, value.toString());
            return;
        }

        if (value instanceof Byte || value instanceof Short || value instanceof Integer || value instanceof Long) {
            Number number = (Number) value;
            StaxUtilities.writeSimpleTextNode(writer, null, null, INTEGER_NODE, Long.toString(number.longValue()));
            return;
        }

        if (value instanceof Float || value instanceof Double) {
            Number number = (Number) value;
            StaxUtilities.writeSimpleTextNode(writer, null, null, REAL_NODE, Double.toString(number.doubleValue()));
            return;
        }

        if (value instanceof byte[]) {
            byte[] data = (byte[]) value;
            writeData(writer, data);
            return;
        }

        if (value instanceof Date) {
            Date date = (Date) value;
            writeDate(writer, date);
            return;
        }

        if (value instanceof Map) {
            Map map = (Map) value;
            writeDict(writer, map);
            return;
        }

        if (value instanceof Collection) {
            Collection collection = (Collection) value;
            writeArray(writer, collection);
            return;
        }

        Class valueClass = value.getClass();
        if (valueClass.isArray()) {
            List<?> list;
            // we handled byte[] already
            if (value instanceof short[]) {
                short[] array = (short[]) value;
                ArrayList<Short> arrayList = new ArrayList<Short>(array.length);
                for (short v : array) {
                    arrayList.add(v);
                }
                list = arrayList;
            } else if (valueClass == int[].class) {
                int[] array = (int[]) value;
                ArrayList<Integer> arrayList = new ArrayList<Integer>(array.length);
                for (int v : array) {
                    arrayList.add(v);
                }
                list = arrayList;
            } else if (valueClass == long[].class) {
                long[] array = (long[]) value;
                ArrayList<Long> arrayList = new ArrayList<Long>(array.length);
                for (long v : array) {
                    arrayList.add(v);
                }
                list = arrayList;
            } else if (valueClass == float[].class) {
                float[] array = (float[]) value;
                ArrayList<Float> arrayList = new ArrayList<Float>(array.length);
                for (float v : array) {
                    arrayList.add(v);
                }
                list = arrayList;
            } else if (valueClass == double[].class) {
                double[] array = (double[]) value;
                ArrayList<Double> arrayList = new ArrayList<Double>(array.length);
                for (double v : array) {
                    arrayList.add(v);
                }
                list = arrayList;
            } else if (valueClass == boolean[].class) {
                boolean[] array = (boolean[]) value;
                ArrayList<Boolean> arrayList = new ArrayList<Boolean>(array.length);
                for (boolean v : array) {
                    arrayList.add(v);
                }
                list = arrayList;
            } else if (valueClass == char[].class) {
                char[] array = (char[]) value;
                String s = new String(array);
                StaxUtilities.writeSimpleTextNode(writer, null, null, STRING_NODE, s);
                return;
            } else {
                list = Arrays.asList((Object[]) value);
                // special handling of container Object[]
            }
            writeArray(writer, list);
            return;
        }

        if (logger.isDebugEnabled())
            logger.debug("No suitable conversion found for {}. Will save it as string.", valueClass.getName());
        StaxUtilities.writeSimpleTextNode(writer, null, null, STRING_NODE, value.toString());
    }

    private void writeArray(XMLStreamWriter writer, Collection collection) throws XMLStreamException {
        StaxUtilities.writeStartElement(writer, null, null, ARRAY_NODE);

        for (Object o : collection) {
            writeValue(writer, o);
        }

        writer.writeEndElement();
    }

    private void writeDict(XMLStreamWriter writer, Map<?, ?> map) throws XMLStreamException {
        StaxUtilities.writeStartElement(writer, null, null, DICT_NODE);

        for (Map.Entry current : map.entrySet()) {
            Object key = current.getKey();
            if (key != null) {
                StaxUtilities.writeSimpleTextNode(writer, null, null, KEY_NODE, key.toString());

                writeValue(writer, current.getValue());
            }
        }

        writer.writeEndElement();
    }

    private void writeDate(XMLStreamWriter writer, Date date) throws XMLStreamException {
        StaxUtilities.writeSimpleTextNode(writer, null, null, DATE_NODE, format.format(date));
    }

    private void writeData(XMLStreamWriter writer, byte[] data) throws XMLStreamException {
        StaxUtilities.writeSimpleTextNode(writer, null, null, DATA_NODE, Base64.encodeBase64URLSafeString(data));
    }
}