/*==========================================================================*\ | $Id: QueryAssistantManager.java,v 1.2 2010/10/15 00:43:17 stedwar2 Exp $ |*-------------------------------------------------------------------------*| | Copyright (C) 2006-2008 Virginia Tech | | This file is part of Web-CAT. | | Web-CAT 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. | | Web-CAT 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 Affero General Public License | along with Web-CAT; if not, see <http://www.gnu.org/licenses/>. \*==========================================================================*/ package org.webcat.core.objectquery; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSBundle; import com.webobjects.foundation.NSData; import com.webobjects.foundation.NSDictionary; import com.webobjects.foundation.NSMutableArray; import com.webobjects.foundation.NSMutableDictionary; import com.webobjects.foundation.NSPropertyListSerialization; import org.apache.log4j.Logger; import org.webcat.core.Application; import org.webcat.core.Subsystem; import org.webcat.core.SubsystemManager; //------------------------------------------------------------------------- /** * A singleton that manages the set of query assistants that are available, * and looks up those that are applicable based on the kind of entity a query * is for. The available query assistants are read from a plist file * stored in the subsystem's resources. * * @author aallowat * @version $Id: QueryAssistantManager.java,v 1.2 2010/10/15 00:43:17 stedwar2 Exp $ */ public class QueryAssistantManager { //~ Constructors .......................................................... // ---------------------------------------------------------- /** * Get the singleton instance of this class. * @return The single shared instance of this class */ public static QueryAssistantManager getInstance() { if (instance == null) { instance = new QueryAssistantManager(); } return instance; } // ---------------------------------------------------------- /** * The constructor is private, since this is a singleton class. */ private QueryAssistantManager() { assistants = new NSMutableDictionary<String, QueryAssistantDescriptor>(); entitiesToIds = new NSMutableDictionary<String, NSMutableArray<String>>(); SubsystemManager subsystemManager = Application.wcApplication().subsystemManager(); for (Subsystem subsystem : subsystemManager.subsystems()) { try { loadQueryAssistantsFromSubsystem(subsystem); } catch (IOException e) { log.warn("Error loading query assistant descriptors from " + "subsystem " + subsystem.name(), e); } } } // ---------------------------------------------------------- /** * Loads the query assistants in the specified bundle, if any. * * @param bundle the bundle representing the subsystem to load from */ private void loadQueryAssistantsFromSubsystem(Subsystem subsystem) throws IOException { File file = new File(subsystem.myResourcesDir(), QUERY_ASSISTANTS_PLIST_FILENAME); if (!file.exists()) { return; } NSDictionary<String, Object> plist = (NSDictionary<String, Object>) NSPropertyListSerialization.propertyListFromData( new NSData(new FileInputStream(file), 0), "UTF-8"); for (String id : plist.allKeys()) { NSDictionary<String, Object> asstInPlist = (NSDictionary<String, Object>) plist.objectForKey(id); NSArray<String> entities = (NSArray<String>) asstInPlist.objectForKey("entities"); String modelName = (String) asstInPlist.objectForKey("modelName"); boolean success = verifyClassInheritance(modelName, AbstractQueryAssistantModel.class); if (success) { QueryAssistantDescriptor qad = new QueryAssistantDescriptor(id, asstInPlist); assistants.setObjectForKey(qad, id); if (entities != null) { // Add the query assistant to each entity in the map. for (String entityName : entities) { NSMutableArray<String> ids = entitiesToIds.objectForKey(entityName); if (ids == null) { ids = new NSMutableArray<String>(); entitiesToIds.setObjectForKey(ids, entityName); } ids.addObject(id); } } else { // Add the query assistant to the "blank" array in the map. // We use a blank entry because we don't know which // entities will be in the map until we've processed them // all, so we just merge this array with the one for a // specific entity in the assistantsForEntity method. NSMutableArray<String> ids = entitiesToIds.objectForKey(""); if (ids == null) { ids = new NSMutableArray<String>(); entitiesToIds.setObjectForKey(ids, ""); } ids.addObject(id); } } } } //~ Public Methods ........................................................ // ---------------------------------------------------------- public NSArray<QueryAssistantDescriptor> assistantsForEntity(String entity) { NSMutableArray<QueryAssistantDescriptor> array = new NSMutableArray<QueryAssistantDescriptor>(); NSArray<String> ids; // Add the query assistants for this specific entity type. ids = entitiesToIds.objectForKey(entity); if (ids != null) { for (String id : ids) { array.addObject(assistantWithId(id)); } } // Add the query assistants that apply to all entity types. ids = entitiesToIds.objectForKey(""); if (ids != null) { for (String id : ids) { array.addObject(assistantWithId(id)); } } return array; } // ---------------------------------------------------------- public QueryAssistantDescriptor assistantWithId(String id) { return assistants.objectForKey(id); } // ---------------------------------------------------------- public NSArray<QueryAssistantDescriptor> allAssistants() { return assistants.allValues(); } //~ Private Methods ....................................................... // ---------------------------------------------------------- private boolean verifyClassInheritance(String className, Class<?> superclass) { Class<?> klass = null; try { klass = Class.forName(className); } catch(Exception e) { log.error("Could not find a class named " + className + ". This query assistant will not be available."); return false; } if(klass != null) { if(!superclass.isAssignableFrom(klass)) { log.error("The class " + className + " does not" + "inherit from " + superclass.getCanonicalName() + ". " + "This query assistant will not be available."); } } return true; } //~ Instance/static variables ............................................. private static final String QUERY_ASSISTANTS_PLIST_FILENAME = "QueryAssistants.plist"; private NSMutableDictionary<String, QueryAssistantDescriptor> assistants; private NSMutableDictionary<String, NSMutableArray<String>> entitiesToIds; private static QueryAssistantManager instance; private static Logger log = Logger.getLogger(QueryAssistantManager.class); }