/* * Copyright (C) 2011 Virginia Tech Department of Computer Science * * 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 sofia.app.internal; import sofia.app.Persistent; import sofia.app.Persistor; import android.app.Activity; import android.content.Context; import org.yaml.snakeyaml.Yaml; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; //------------------------------------------------------------------------- /** * <p> * <em>This class is not intended for public use.</em> * </p><p> * Handles the storing and reconstructing of persistent fields in a * {@link Screen}. * </p> * * @see Persistent * @see Persistor * * @author Tony Allevato */ public class PersistenceManager { //~ Instance/static fields ................................................ private static ThreadLocal<PersistenceManager> instance = new ThreadLocal<PersistenceManager>(); private Yaml yaml; //~ Constructors .......................................................... // ---------------------------------------------------------- private PersistenceManager() { yaml = new Yaml(new SofiaConstructor(), new SofiaRepresenter()); } //~ Methods ............................................................... // ---------------------------------------------------------- public static PersistenceManager getInstance() { if (instance.get() == null) { instance.set(new PersistenceManager()); } return instance.get(); } // ---------------------------------------------------------- @SuppressWarnings("unchecked") public void loadPersistentContext(Context activity) { String filename = activity.getClass().getCanonicalName() + ".yaml"; Map<String, Object> persistMap = new HashMap<String, Object>(); FileInputStream stream = null; try { stream = activity.openFileInput(filename); persistMap = (Map<String, Object>) yaml.load(stream); } catch (IOException e) { // Do nothing; will initialize objects fresh below. } finally { if (stream != null) { try { stream.close(); } catch (IOException e) { // Do nothing. } } } HashMap<Field, Persistent> persistFields = new HashMap<Field, Persistent>(); findPersistentFields(activity.getClass(), persistFields); for (Field field : persistFields.keySet()) { Persistent annotation = persistFields.get(field); Object value = persistMap.get(field.getName()); boolean valueSet = false; if (value != null) { try { field.set(activity, value); valueSet = true; } catch (Exception e) { // Do nothing. } } if (!valueSet && annotation.create()) { try { value = field.getType().newInstance(); field.set(activity, value); } catch (Exception e) { throw new IllegalStateException("Could not create a new " + "instance of " + field.getType().getCanonicalName(), e); } } } } // ---------------------------------------------------------- public void savePersistentContext(Context activity) { HashMap<String, Object> persistMap = new HashMap<String, Object>(); HashMap<Field, Persistent> persistFields = new HashMap<Field, Persistent>(); findPersistentFields(activity.getClass(), persistFields); for (Field field : persistFields.keySet()) { try { persistMap.put(field.getName(), field.get(activity)); } catch (Exception e) { // Do nothing. } } String filename = activity.getClass().getCanonicalName() + ".yaml"; if (persistMap.isEmpty()) { activity.deleteFile(filename); } else { OutputStreamWriter writer = null; try { FileOutputStream stream = activity.openFileOutput( filename, Activity.MODE_PRIVATE); writer = new OutputStreamWriter(stream); yaml.dump(persistMap, writer); } catch (IOException e) { // FIXME handle error somehow } finally { if (writer != null) { try { writer.close(); } catch (IOException e) { // Do nothing. } } } } } // ---------------------------------------------------------- private void findPersistentFields(Class<?> klass, Map<Field, Persistent> fields) { for (Field field : klass.getDeclaredFields()) { Persistent annotation = field.getAnnotation(Persistent.class); if (annotation != null) { field.setAccessible(true); fields.put(field, annotation); } } if (!klass.getSuperclass().equals(Object.class)) { findPersistentFields(klass.getSuperclass(), fields); } } // ---------------------------------------------------------- private static Class<?> getPersistor(Class<?> klass) { Persistor annotation = klass.getAnnotation(Persistor.class); Class<?> persistor = null; try { if (annotation != null) { persistor = annotation.value(); } else { persistor = Class.forName( klass.getCanonicalName() + "Persistor"); } } catch (Exception e) { // Do nothing. } return persistor; } // ---------------------------------------------------------- public static Method getRepresentMethod(Class<?> klass) { Method method = null; try { Class<?> persistor = getPersistor(klass); if (persistor != null) { // TODO replace with "best match" for parameter method = persistor.getMethod("represent", Object.class, Map.class); } return method; } catch (Exception e) { // Do nothing. } return method; } // ---------------------------------------------------------- public static Method getConstructMethod(Class<?> klass) { Method method = null; try { Class<?> persistor = getPersistor(klass); if (persistor != null) { method = persistor.getMethod("construct", Map.class); } return method; } catch (Exception e) { // Do nothing. } return method; } }