* $LastChangedDate$
*/
public class CollectionSpaceJaxRsApplication extends Application
- implements ResourceMapHolder {
+ implements ResourceMapHolder, UriTemplateRegistryHolder {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> empty = new HashSet<Class<?>>();
private ResourceMap resourceMap = new ResourceMapImpl();
- private UriTemplateRegistry uriTemplateRegistry = new UriTemplateRegistry();
+ private static UriTemplateRegistry uriTemplateRegistry = new UriTemplateRegistry();
private ServletContext servletContext = null;
public CollectionSpaceJaxRsApplication() {
singletons.add(new IDResource());
+ buildUriTemplateRegistry();
// FIXME: Temporary for CSPACE-5271 - please remove once
// that issue is resolved
uriTemplateRegistry.dump();
private void addResourceToMapAndSingletons(ResourceBase resource) {
singletons.add(resource);
resourceMap.put(resource.getServiceName(), resource);
+ }
+
+ /**
+ * Build a registry of URI templates by querying each resource
+ * for its own entry in the registry.
+ *
+ * That entry consists of a tenant-qualified map of URI templates, each
+ * associated with a specific document type
+ */
+ private void buildUriTemplateRegistry() {
+ ResourceBase resource = null;
+ ResourceMap resources = getResourceMap();
+ for (Map.Entry<String, ResourceBase> entry : resources.entrySet()) {
+ resource = entry.getValue();
+ System.out.println(resource.getServiceName()); // for debugging
+ getUriTemplateRegistry().putAll(resource.getUriRegistryEntries());
+ getUriTemplateRegistry().dump(); // for debugging
+ }
// Contacts itself should not have an entry in the URI template registry;
// there should be a Contacts entry in that registry only for use in
// building URIs for resources that have contacts as a sub-resource
//
// FIXME: There may be a more elegant way to filter this out; or it may
// fall out during implementation of CSPACE-2698
- if (! (resource instanceof ContactResource)) {
- uriTemplateRegistry.putAll(resource.getUriTemplateMap());
- }
+ //
+ // final String CONTACT_DOCTYPE = "Contact";
+ // uriTemplateRegistry.remove(CONTACT_DOCTYPE);
}
+
@Override
public Set<Class<?>> getClasses() {
return resourceMap;
}
+ public UriTemplateRegistry getUriTemplateRegistry() {
+ return uriTemplateRegistry;
+ }
+
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
}
}
- public String getItemDocType() {
- return super.getDocType(getItemServiceName());
+ protected String getItemDocType(String tenantId) {
+ return super.getDocType(tenantId, getItemServiceName());
}
+ /**
+ * Constructs and returns a map of URI templates for the current resource,
+ * for the specified tenant
+ *
+ * @param tenantId a tenant ID
+ * @return a map of URI templates for the current resource, for the specified tenant
+ */
@Override
- public Map<String,StoredValuesUriTemplate> getUriTemplateMap() {
- // Get resource URI template from superclass
- Map<String,StoredValuesUriTemplate> uriTemplateMap = super.getUriTemplateMap();
- // Add item URI template, and return both templates in the map
- String itemDocType = getItemDocType();
- StoredValuesUriTemplate itemUriTemplate = getUriTemplate(UriTemplateFactory.ITEM);
+ protected Map<String,StoredValuesUriTemplate> getUriTemplateMap(String tenantId) {
+ // Get the resource URI template from the superclass
+ Map<String,StoredValuesUriTemplate> uriTemplateMap = super.getUriTemplateMap(tenantId);
+ // Add the item URI template here, and return both templates in the map
+ String itemDocType = getItemDocType(tenantId);
if (itemDocType == null) {
return uriTemplateMap; // return map as obtained from superclass
}
+ StoredValuesUriTemplate itemUriTemplate = getUriTemplate(UriTemplateFactory.ITEM);
if (itemUriTemplate == null) {
return uriTemplateMap; // return map as obtained from superclass
}
return getDocModelForAuthorityItem(repoSession, RefName.AuthorityItem.parse(refName));\r
}\r
\r
- public String getDocType() {\r
- return getDocType(getServiceName());\r
+ protected String getDocType(String tenantId) {\r
+ return getDocType(tenantId, getServiceName());\r
}\r
- \r
- // FIXME: The technique in getDocType(String) may well be a dreadful hack, just to get this initially working.\r
- //\r
- // Question:\r
- // At the point we're seeking to populate docTypes in the uriTemplateRegistry, during system startup,\r
- // we're not yet logged into any tenant, but instead it appears we are acting as the user SPRING_ADMIN.\r
- // Could this potentially suggest reasonable method(s), other than those below, which reads from\r
- // tenant bindings configuration for an arbitrary tenant, by which we can obtain the docType(s)\r
- // associated with the current resource?\r
\r
- public String getDocType(String serviceName) {\r
+ // FIXME: This method may properly belong in a different services package or class.\r
+ protected String getDocType(String tenantId, String serviceName) {\r
String docType = "";\r
- String anyTenantId = "";\r
- TenantBindingConfigReaderImpl reader = ServiceMain.getInstance().getTenantBindingConfigReader();\r
- // FIXME: Makes the likely unsupportable assumption that the list of service names and associated\r
- // document types is materially identical across tenants\r
- anyTenantId = getAnyTenantId(reader);\r
- if (Tools.notBlank(anyTenantId)) {\r
- ServiceBindingType sb = reader.getServiceBinding(anyTenantId, serviceName);\r
- docType = sb.getObject().getName(); // reads the Nuxeo Document Type from tenant bindings configuration\r
+ if (Tools.notBlank(tenantId)) {\r
+ ServiceBindingType sb = getTenantBindingsReader().getServiceBinding(tenantId, serviceName);\r
+ docType = sb.getObject().getName(); // Reads the Nuxeo Document Type from tenant bindings configuration\r
}\r
return docType;\r
}\r
\r
- public Map<String,StoredValuesUriTemplate> getUriTemplateMap() {\r
- Map<String,StoredValuesUriTemplate> uriTemplateMap = new HashMap<String,StoredValuesUriTemplate>();\r
- // Construct and return a resource URI template as the sole item in the map\r
- String docType = getDocType();\r
- StoredValuesUriTemplate resourceUriTemplate = getUriTemplate(UriTemplateFactory.RESOURCE);\r
+ /**\r
+ * Returns a UriRegistry entry: a map of tenant-qualified URI templates\r
+ * for the current resource, for all tenants\r
+ * \r
+ * @return a map of URI templates for the current resource, for all tenants\r
+ */\r
+ public HashMap<String,Map<String,StoredValuesUriTemplate>> getUriRegistryEntries() {\r
+ HashMap<String,Map<String,StoredValuesUriTemplate>> uriRegistryEntriesMap =\r
+ new HashMap<String, Map<String,StoredValuesUriTemplate>>();\r
+ List<String> tenantIds = getTenantIds();\r
+ for (String tenantId : tenantIds) {\r
+ uriRegistryEntriesMap.put(tenantId, getUriTemplateMap(tenantId));\r
+ }\r
+ return uriRegistryEntriesMap;\r
+ }\r
+ \r
+ \r
+ /**\r
+ * Constructs and returns a map of URI templates for the current resource,\r
+ * for the specified tenant\r
+ * \r
+ * @param tenantId a tenant ID\r
+ * @return a map of URI templates for the current resource, for the specified tenant\r
+ */\r
+ protected Map<String,StoredValuesUriTemplate> getUriTemplateMap(String tenantId) {\r
+ Map<String,StoredValuesUriTemplate> uriTemplateMap = new HashMap<String, StoredValuesUriTemplate>();\r
+ if (tenantId == null) {\r
+ return uriTemplateMap; // return an empty map\r
+ }\r
+ String docType = getDocType(tenantId);\r
if (docType == null) {\r
return uriTemplateMap; // return an empty map\r
}\r
+ StoredValuesUriTemplate resourceUriTemplate = getUriTemplate(UriTemplateFactory.RESOURCE);\r
if (resourceUriTemplate == null) {\r
return uriTemplateMap; // return an empty map\r
}\r
return uriTemplateMap;\r
}\r
\r
+ /**\r
+ * Returns a UriTemplate of the appropriate type, populated with the\r
+ * current service name as one of its stored values.\r
+ * \r
+ * @param type a UriTemplate type\r
+ * @return a UriTemplate of the appropriate type\r
+ */\r
protected StoredValuesUriTemplate getUriTemplate(UriTemplateFactory.UriTemplateType type) {\r
Map<String,String> storedValuesMap = new HashMap<String,String>();\r
storedValuesMap.put(UriTemplateFactory.SERVICENAME_VAR, getServiceName());\r
return template;\r
}\r
\r
- public String getAnyTenantId(TenantBindingConfigReaderImpl reader) {\r
- String anyTenantId = "";\r
- Hashtable<String, TenantBindingType> tenantBindings = reader.getTenantBindings();\r
+ /**\r
+ * Returns a list of tenant IDs, from tenant bindings configuration\r
+ * \r
+ * @return a list of tenant IDs\r
+ */\r
+ // FIXME: This method may properly belong in a different services package or class.\r
+ protected List<String> getTenantIds() {\r
+ List<String> tenantIds = new ArrayList<String>();\r
+ String tenantId;\r
+ Hashtable<String, TenantBindingType> tenantBindings =\r
+ getTenantBindingsReader().getTenantBindings();\r
if (tenantBindings != null && !tenantBindings.isEmpty()) {\r
Enumeration keys = tenantBindings.keys();\r
while (keys.hasMoreElements()) {\r
- anyTenantId = (String) keys.nextElement();\r
- if (Tools.notBlank(anyTenantId)) {\r
- break;\r
+ tenantId = (String) keys.nextElement();\r
+ if (Tools.notBlank(tenantId)) {\r
+ tenantIds.add(tenantId);\r
}\r
}\r
}\r
- return anyTenantId;\r
+ return tenantIds;\r
}\r
+ \r
+ /**\r
+ * Returns a reader for reading values from tenant bindings configuration\r
+ * \r
+ * @return a tenant bindings configuration reader\r
+ */\r
+ protected TenantBindingConfigReaderImpl getTenantBindingsReader() {\r
+ return ServiceMain.getInstance().getTenantBindingConfigReader();\r
+ }\r
+\r
\r
}\r
* replace variables within the template.
*
* In this subclass of UriTemplate, some of the values which will replace
- * variables in an internal URI template are static, and can be stored alongside
- * the URI template for reuse. Additional values that will replace variables
- * within the template are also dynamically accepted, and will be merged with
- * stored values when building URIs.
+ * variables in an internal URI template are typically stable / static, and
+ * can be stored alongside the URI template for reuse each time that a URI
+ * is built from the template. Additional values that will replace variables
+ * within the template on a one-off basis are also dynamically accepted,
+ * and will be merged with the previously-stored values when building URIs.
*/
public class StoredValuesUriTemplate extends UriTemplate {
}
/**
- * Builds a URI string from a combination of previously-stored values, if
- * any (such as static URI path components) and additional values, if any
- * (such as resource identifiers), both of which will replace variables
- * within the URI template.
+ * Builds a URI string from a combination of values previously stored
+ * along with the template, if any (typically stable URI path components,
+ * such as "intakes" and "personauthorities") and additional values, if any
+ * (typically CSIDs and URN-based resource identifiers), both of which will
+ * replace variables within the URI template.
*
* @param additionalValuesMap an optional map of values that will replace
* variables within the URI template
package org.collectionspace.services.common;\r
\r
import java.util.HashMap;\r
+import java.util.Map;\r
\r
/**\r
* UriTemplateRegistry.java\r
*\r
- * Maps document types to templates for building URIs, used in turn for\r
- * accessing instances of those documents.\r
+ * Maps document types to templates for building URIs, per tenant.\r
*/\r
-public class UriTemplateRegistry extends HashMap<String, StoredValuesUriTemplate> {\r
+public class UriTemplateRegistry extends HashMap<String, Map<String, StoredValuesUriTemplate>> {\r
\r
+ // For debugging\r
public void dump() {\r
- for (String docTypeKey : this.keySet()) {\r
- StoredValuesUriTemplate uriTemplate = this.get(docTypeKey);\r
- System.out.println("Key = " + docTypeKey + ", Value = " + uriTemplate.getUriTemplateType() + " : " + uriTemplate.toString());\r
+ for (String tenantId : this.keySet()) {\r
+ System.out.println("###############################");\r
+ System.out.println("Tenant ID = " + tenantId);\r
+ System.out.println("###############################");\r
+ for (Map.Entry<String, StoredValuesUriTemplate> uriTemplateEntry : this.get(tenantId).entrySet()) {\r
+ System.out.println("Key = " + uriTemplateEntry.getKey()\r
+ + ", Value = " + uriTemplateEntry.getValue().getUriTemplateType()\r
+ + " : " + uriTemplateEntry.getValue().toString());\r
+ }\r
}\r
}\r
}\r
--- /dev/null
+
+package org.collectionspace.services.common;
+
+public interface UriTemplateRegistryHolder {
+ public UriTemplateRegistry getUriTemplateRegistry();
+}
}
}
- public String getContactDocType() {
+ protected String getContactDocType() {
return ContactConstants.NUXEO_DOCTYPE;
}
- // This currently populates only one entry in the UriTemplateRegistry
+ /**
+ * Constructs and returns a map of URI templates for the current resource,
+ * for the specified tenant
+ *
+ * @param tenantId a tenant ID
+ * @return a map of URI templates for the current resource, for the specified tenant
+ */
+ // FIXME: This method currently populates only one entry in the UriTemplateRegistry
// for the Contacts docType, even though contacts can be a sub-resource of
// multiple authority item resources. (This method may be called more than once,
// but each time the existing item with the same key in the map is overwritten.)
@Override
- public Map<String,StoredValuesUriTemplate> getUriTemplateMap() {
- // Get resource and item URI templates from superclass
- Map<String,StoredValuesUriTemplate> uriTemplateMap = super.getUriTemplateMap();
- // Add contact URI template, and return all three templates in the map
+ protected Map<String,StoredValuesUriTemplate> getUriTemplateMap(String tenantId) {
+ // Get the resource and item URI templates from the superclass
+ Map<String,StoredValuesUriTemplate> uriTemplateMap = super.getUriTemplateMap(tenantId);
+ // Add the contact URI template here, and return all three templates in the map
String contactDocType = getContactDocType();
- StoredValuesUriTemplate contactUriTemplate = getUriTemplate(UriTemplateFactory.CONTACT);
if (contactDocType == null) {
return uriTemplateMap; // return map as obtained from superclass
}
+ StoredValuesUriTemplate contactUriTemplate = getUriTemplate(UriTemplateFactory.CONTACT);
if (contactUriTemplate == null) {
return uriTemplateMap; // return map as obtained from superclass
}