All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.marid.spring.xml.AbstractData Maven / Gradle / Ivy

/*
 * Copyright (c) 2016 Dmitry Ovchinnikov
 * Marid, the free data acquisition and visualization software
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see .
 */

package org.marid.spring.xml;

import javafx.beans.property.Property;
import javafx.beans.value.WritableValue;
import javafx.collections.ObservableList;
import javafx.collections.ObservableMap;

import javax.xml.bind.annotation.XmlTransient;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.Map.Entry;

import static java.lang.reflect.Modifier.isStatic;
import static java.lang.reflect.Modifier.isTransient;
import static java.util.stream.Collectors.toCollection;
import static java.util.stream.Collectors.toMap;

/**
 * @author Dmitry Ovchinnikov
 */
@XmlTransient
public abstract class AbstractData> implements Externalizable, Cloneable {

    @SuppressWarnings({"CloneDoesntCallSuperClone", "unchecked"})
    @Override
    public T clone() {
        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try (final ObjectOutputStream oos = new ObjectOutputStream(bos)) {
            oos.writeObject(this);
        } catch (IOException x) {
            throw new IllegalStateException(x);
        }
        try (final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()))) {
            return (T) ois.readObject();
        } catch (IOException | ClassNotFoundException x) {
            throw new IllegalStateException(x);
        }
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        final TreeMap map = new TreeMap<>();
        for (final Field field : getClass().getFields()) {
            if (!isTransient(field.getModifiers()) && !isStatic(field.getModifiers())) {
                try {
                    map.put(field.getName(), toSerializable(field.get(this)));
                } catch (ReflectiveOperationException x) {
                    throw new IllegalStateException(x);
                }
            }
        }
        out.writeObject(map);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        final TreeMap map = (TreeMap) in.readObject();
        for (final Entry e : map.entrySet()) {
            try {
                final Field field = getClass().getField(e.getKey().toString());
                if (Property.class.isAssignableFrom(field.getType())) {
                    final Method setValue = WritableValue.class.getMethod("setValue", Object.class);
                    setValue.invoke(field.get(this), e.getValue());
                } else if (ObservableList.class.isAssignableFrom(field.getType())) {
                    final Method addAll = List.class.getMethod("addAll", Collection.class);
                    addAll.invoke(field.get(this), e.getValue());
                } else if (ObservableMap.class.isAssignableFrom(field.getType())) {
                    final Method putAll = Map.class.getMethod("putAll", Map.class);
                    putAll.invoke(field.get(this), e.getValue());
                }
            } catch (NoSuchFieldException x) {
                throw new InvalidClassException(x.getMessage());
            } catch (ReflectiveOperationException x) {
                throw new IllegalStateException(x);
            }
        }
    }

    private Serializable toSerializable(Object o) {
        if (o == null || o instanceof Serializable) {
            return (Serializable) o;
        } else if (o instanceof ObservableList) {
            final ObservableList list = (ObservableList) o;
            return list.stream().map(this::toSerializable).collect(toCollection(ArrayList::new));
        } else if (o instanceof ObservableMap) {
            final Map m = (ObservableMap) o;
            return m.entrySet().stream().collect(toMap(Entry::getKey,
                    e -> toSerializable(e.getValue()), (u, v) -> v, LinkedHashMap::new));
        } else if (o instanceof Property) {
            return toSerializable(((Property) o).getValue());
        } else {
            throw new IllegalArgumentException("Not serializable value " + o);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy