/** * This file is protected by Copyright. * Please refer to the COPYRIGHT file distributed with this source distribution. * * This file is part of REDHAWK IDE. * * All rights reserved. This program and the accompanying materials are made available under * the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html. * */ package gov.redhawk.sca.launch.internal; import gov.redhawk.model.sca.ScaAbstractProperty; import gov.redhawk.model.sca.ScaPackage; import gov.redhawk.model.sca.ScaPropertyContainer; import gov.redhawk.model.sca.ScaSimpleProperty; import gov.redhawk.model.sca.ScaSimpleSequenceProperty; import gov.redhawk.model.sca.ScaStructProperty; import gov.redhawk.model.sca.ScaStructSequenceProperty; import java.beans.Encoder; import java.beans.Expression; import java.beans.PersistenceDelegate; import java.beans.XMLDecoder; import java.beans.XMLEncoder; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Utility methods to load/save properties for a component to/from a string. Allows passing this information through * Eclipse launch configurations. The format is NOT portable - load and save must occur through this class. */ public class ScaPropertyUtil { private ScaPropertyUtil() { } /** * Loads a set of properties from a string of XML. * @param component A property container (component) * @param serializedValue The serialized string */ public static void load(final ScaPropertyContainer< ? , ? > component, final String serializedValue) { if (component != null && serializedValue != null) { final XMLDecoder decoder = new XMLDecoder(new ByteArrayInputStream(serializedValue.getBytes())); final Map< ? , ? > propMap = (Map< ? , ? >) decoder.readObject(); ScaPropertyUtil.restoreProperties(component, propMap); decoder.close(); } } /** * Saves a set of properties to a string of XML. Only properties with non-default values are saved. * @param component A property container (component) * @return The serialized string */ public static String save(final ScaPropertyContainer<?, ?> component) { if (component != null) { final Map< ? , ? > propMap = ScaPropertyUtil.storeProperties(component); if (propMap.isEmpty()) { return null; } ByteArrayOutputStream buffer = null; XMLEncoder encoder = null; buffer = new ByteArrayOutputStream(); encoder = new XMLEncoder(buffer); encoder.setPersistenceDelegate(BigInteger.class, new BigIntegerPersistenceDelegate()); encoder.writeObject(propMap); encoder.close(); try { buffer.close(); } catch (IOException e) { // PASS } return buffer.toString(); } else { return null; } } /** * Allows persisting {@link BigInteger}s with the java.beans system. */ private static class BigIntegerPersistenceDelegate extends PersistenceDelegate { public BigIntegerPersistenceDelegate() { } @Override protected Expression instantiate(Object oldInstance, Encoder out) { BigInteger bigInt = (BigInteger) oldInstance; return new Expression(bigInt, BigInteger.class, "new", new Object[] { bigInt.toString() }); } } private static Map< ? , ? > storeProperties(final ScaPropertyContainer< ?, ? > component) { final Map<Object, Object> propMap = new HashMap<Object, Object>(); for (final ScaAbstractProperty< ? > prop : component.getProperties()) { if (prop.isDefaultValue()) { continue; } Object value = ScaPropertyUtil.storeProperty(prop); propMap.put(prop.getId(), value); } return propMap; } private static Object storeProperty(final ScaAbstractProperty< ? > prop) { switch (prop.eClass().getClassifierID()) { case ScaPackage.SCA_SIMPLE_PROPERTY: return ((ScaSimpleProperty) prop).getValue(); case ScaPackage.SCA_SIMPLE_SEQUENCE_PROPERTY: return ((ScaSimpleSequenceProperty) prop).getValue(); case ScaPackage.SCA_STRUCT_PROPERTY: return ScaPropertyUtil.storeStruct((ScaStructProperty) prop); case ScaPackage.SCA_STRUCT_SEQUENCE_PROPERTY: return ScaPropertyUtil.storeStructSequence((ScaStructSequenceProperty) prop); default: throw new IllegalArgumentException("Unknown property type"); } } private static Map< ? , ? > storeStruct(final ScaStructProperty struct) { final HashMap<Object, Object> retVal = new HashMap<Object, Object>(); for (final ScaAbstractProperty< ? > prop : struct.getFields()) { if (prop.isDefaultValue()) { continue; } retVal.put(prop.getId(), ScaPropertyUtil.storeProperty(prop)); } return retVal; } private static List< ? > storeStructSequence(final ScaStructSequenceProperty prop) { final ArrayList<Object> retVal = new ArrayList<Object>(); for (final ScaStructProperty struct : prop.getStructs()) { retVal.add(ScaPropertyUtil.storeStruct(struct)); } return retVal; } private static void restoreProperties(final ScaPropertyContainer< ? , ? > component, final Map< ? , ? > propMap) { for (final ScaAbstractProperty< ? > prop : component.getProperties()) { if (!propMap.containsKey(prop.getId())) { continue; } final Object value = propMap.get(prop.getId()); ScaPropertyUtil.restoreProperty(prop, value); } } private static void restoreProperty(final ScaAbstractProperty< ? > prop, Object value) { switch (prop.eClass().getClassifierID()) { case ScaPackage.SCA_SIMPLE_PROPERTY: ((ScaSimpleProperty) prop).setValue(value); break; case ScaPackage.SCA_SIMPLE_SEQUENCE_PROPERTY: ((ScaSimpleSequenceProperty) prop).setValue((Object[]) value); break; case ScaPackage.SCA_STRUCT_PROPERTY: ScaPropertyUtil.restoreStruct((ScaStructProperty) prop, (Map< ? , ? >) value); break; case ScaPackage.SCA_STRUCT_SEQUENCE_PROPERTY: ScaPropertyUtil.restoreStructSequence((ScaStructSequenceProperty) prop, (List< ? >) value); break; default: throw new IllegalArgumentException("Unknown property type"); } } private static void restoreStructSequence(final ScaStructSequenceProperty prop, final List< ? > values) { if (values != null) { prop.getStructs().clear(); for (final Object obj : values) { final ScaStructProperty struct = prop.createScaStructProperty(); ScaPropertyUtil.restoreStruct(struct, (Map< ? , ? >) obj); prop.getStructs().add(struct); } } } private static void restoreStruct(final ScaStructProperty struct, final Map< ? , ? > propMap) { if (propMap != null) { for (final ScaAbstractProperty< ? > prop : struct.getFields()) { if (propMap.containsKey(prop.getId())) { final Object value = propMap.get(prop.getId()); ScaPropertyUtil.restoreProperty(prop, value); } } } } }