package org.activityinfo.legacy.client.remote.cache; /* * #%L * ActivityInfo Server * %% * Copyright (C) 2009 - 2013 UNICEF * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.inject.Inject; import org.activityinfo.legacy.client.CommandCache; import org.activityinfo.legacy.client.DispatchEventSource; import org.activityinfo.legacy.client.DispatchListener; import org.activityinfo.legacy.shared.command.*; import org.activityinfo.legacy.shared.command.result.CommandResult; import org.activityinfo.legacy.shared.model.ActivityFormDTO; import org.activityinfo.legacy.shared.model.SchemaDTO; import org.activityinfo.model.legacy.CuidAdapter; import java.util.Map; import java.util.Set; /** * Caches the user's schema in-memory for the duration of the session. * <p/> * TODO: we need to peridiodically check the server for updates. Do we do this * here or in a separate class? * * @author Alex Bertram */ public class SchemaCache implements DispatchListener { private SchemaDTO schema = null; private Set<String> schemaEntityTypes = Sets.newHashSet(); private Map<Integer, ActivityFormDTO> activityMap = Maps.newHashMap(); @Inject public SchemaCache(DispatchEventSource source) { source.registerProxy(GetSchema.class, new SchemaProxy()); source.registerListener(GetSchema.class, this); source.registerListener(UpdateEntity.class, this); source.registerListener(CreateEntity.class, this); source.registerListener(AddPartner.class, this); source.registerListener(RemovePartner.class, this); source.registerListener(RequestChange.class, this); source.registerListener(BatchCommand.class, this); source.registerListener(CloneDatabase.class, this); source.registerListener(UpdateFormClass.class, this); source.registerListener(Delete.class, this); schemaEntityTypes.add("UserDatabase"); schemaEntityTypes.add("Activity"); schemaEntityTypes.add("Indicator"); schemaEntityTypes.add("AttributeGroup"); schemaEntityTypes.add("AttributeDimension"); schemaEntityTypes.add("Attribute"); schemaEntityTypes.add("Partner"); schemaEntityTypes.add("Project"); schemaEntityTypes.add("LockedPeriod"); } @Override public void beforeDispatched(Command command) { if (command instanceof UpdateEntity || command instanceof CreateEntity || command instanceof Delete) { clearCache(); } else if (command instanceof CloneDatabase) { clearCache(); } else if (command instanceof AddPartner || command instanceof RemovePartner) { clearCache(); } else if (command instanceof RequestChange && isSchemaEntity(((RequestChange) command).getEntityType())) { clearCache(); } else if (command instanceof UpdateFormClass) { String formClassId = ((UpdateFormClass) command).getFormClassId(); activityMap.remove(CuidAdapter.getLegacyIdFromCuid(formClassId)); } else if (command instanceof BatchCommand) { for (Command element : ((BatchCommand) command).getCommands()) { beforeDispatched(element); } } } private void clearCache() { schema = null; activityMap.clear(); } private boolean isSchemaEntity(String entityName) { return schemaEntityTypes.contains(entityName); } @Override public void onSuccess(Command command, CommandResult result) { if (command instanceof GetSchema) { cache((SchemaDTO) result); } else if (command instanceof GetActivityForm) { ActivityFormDTO activity = (ActivityFormDTO) result; activityMap.put(activity.getId(), activity); } else if (schema != null) { if (command instanceof AddPartner) { clearCache(); } } } /** * Caches the schema in-memory following a successful GetSchema call. * Subclasses can override this to provide a more permanent cache. * * @param schema The schema to cache */ protected void cache(SchemaDTO schema) { this.schema = schema; } @Override public void onFailure(Command command, Throwable caught) { } private class SchemaProxy implements CommandCache<GetSchema> { @Override public CacheResult maybeExecute(GetSchema command) { if (schema == null) { return CacheResult.couldNotExecute(); } else { return new CacheResult<>(schema); } } @Override public void clear() { clearCache(); } } }