org.usergrid.services.ServiceInfo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of usergrid-services Show documentation
Show all versions of usergrid-services Show documentation
Service layer for Usergrid system.
/*******************************************************************************
* Copyright 2012 Apigee Corporation
*
* 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 org.usergrid.services;
import static org.apache.commons.lang.StringUtils.capitalize;
import static org.apache.commons.lang.StringUtils.removeEnd;
import static org.apache.commons.lang.StringUtils.split;
import static org.usergrid.utils.InflectionUtils.pluralize;
import static org.usergrid.utils.InflectionUtils.singularize;
import static org.usergrid.utils.StringUtils.stringOrSubstringAfterLast;
import static org.usergrid.utils.StringUtils.stringOrSubstringBeforeFirst;
import static org.usergrid.utils.StringUtils.stringOrSubstringBeforeLast;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.usergrid.persistence.Schema;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;
public class ServiceInfo {
private final String name;
private final boolean rootService;
private final String rootType;
private final String containerType;
private final String collectionName;
private final String itemType;
private final List patterns;
private final List collections;
/**
* Pre calced since we cache this class
*/
private int hashCode;
public ServiceInfo(String name, boolean rootService, String rootType,
String containerType, String collectionName, String itemType,
List patterns, List collections) {
this.name = name;
this.rootService = rootService;
this.rootType = rootType;
this.containerType = containerType;
this.collectionName = collectionName;
this.itemType = itemType;
this.patterns = patterns;
this.collections = collections;
Hasher hasher = Hashing.md5().newHasher();
for(String pattern: patterns){
hasher.putString(pattern);
}
hashCode = hasher.hash().asInt();
}
public static String normalizeServicePattern(String s) {
if (s == null) {
return null;
}
s = s.trim().toLowerCase();
s = removeEnd(s, "/");
s = removeEnd(s, "/*");
if (!s.startsWith("/")) {
s = "/" + s;
}
return s;
}
public static List getPatterns(String servicePattern) {
String[] collections = split(servicePattern, "/*/");
return getPatterns(servicePattern, collections);
}
public static List getPatterns(String servicePattern,
String[] collections) {
if (collections == null) {
collections = split(servicePattern, "/*/");
}
List patterns = new ArrayList();
patterns.add(servicePattern);
if (servicePattern.indexOf(':') >= 0) {
patterns.add(removeTypeSpecifiers(collections));
}
String s = getFallbackPattern(collections, 0, collections.length - 1);
while (s != null) {
patterns.add(s);
s = getFallbackPattern(s);
}
return patterns;
}
private static String removeTypeSpecifiers(String[] collections) {
String s = "";
boolean first = true;
for (String collection : collections) {
if (!first) {
s += "/*";
}
first = false;
s += "/" + stringOrSubstringBeforeFirst(collection, ':');
}
return s;
}
private static String getFallbackPattern(String servicePattern) {
String[] collections = split(servicePattern, "/*/");
return getFallbackPattern(collections, 0, collections.length - 1);
}
private static String getFallbackPattern(String[] collections, int first,
int last) {
if (last < first) {
return null;
}
if ((last - first) == 1) {
if (!collections[first].startsWith("entities")) {
return "/entities:" + singularize(collections[first]) + "/*/"
+ collections[first + 1];
}
return null;
}
if ((last - first) == 0) {
if (!collections[first].startsWith("entities")) {
return "/entities:" + singularize(collections[first]);
}
return null;
}
int i = last - 1;
while (i >= first) {
if (collections[i].indexOf(':') > -1) {
break;
}
i--;
}
if (i >= first) {
String type = stringOrSubstringAfterLast(collections[i], ':');
String fallback = "/" + pluralize(type);
i++;
while (i <= last) {
fallback += "/*/" + collections[i];
i++;
}
return fallback;
}
String eType = determineType(collections, first, last - 1);
if (eType != "entity") {
return "/entities:" + eType + "/*/" + collections[last];
}
return "/entities/*/" + collections[last];
}
public static String determineType(String servicePattern) {
String[] collections = split(servicePattern, '/');
return determineType(collections, 0, collections.length - 1);
}
private static String determineType(String[] collections, int first,
int last) {
if (last < first) {
return null;
}
if (first == last) {
return singularize(stringOrSubstringAfterLast(collections[0], ':'));
}
int i = first + 1;
String containerType = singularize(collections[first]);
while (i <= last) {
String collectionName = stringOrSubstringBeforeFirst(
collections[i], ':');
String nextType = Schema.getDefaultSchema().getCollectionType(
containerType, collectionName);
if (nextType == null) {
if (collections[i].indexOf(':') >= 0) {
nextType = stringOrSubstringAfterLast(collections[i], ':');
} else if ((i < last) && (collections[last].indexOf(':') >= 0)) {
nextType = stringOrSubstringAfterLast(collections[last],
':');
} else {
return "entity";
}
}
containerType = nextType;
i++;
}
return containerType;
}
/**
* Hold servicePattern names in a fixed size cache
*/
private static LoadingCache servicePatternCache = CacheBuilder.newBuilder()
.maximumSize(5000)
.build(
new CacheLoader() {
public String load(String key) { // no checked exception
return _getClassName(key);
}
});
/**
* Delegates to _getClassName via a CacheLoader due to the expense of path name calculation
* @param servicePattern
* @return
*/
public static String getClassName(String servicePattern) {
try {
return servicePatternCache.get(servicePattern);
} catch (ExecutionException ee) {
ee.printStackTrace();
}
return _getClassName(servicePattern);
}
private static String _getClassName(String servicePattern) {
servicePattern = normalizeServicePattern(servicePattern);
String[] collections = split(servicePattern, "/*/");
if (collections[0].startsWith("entities")) {
if (collections.length == 1) {
return "generic.RootCollectionService";
}
if (collections[0].indexOf(':') < 0) {
return "generic.GenericConnectionsService";
}
String container = stringOrSubstringAfterLast(collections[0], ':');
String collectionName = stringOrSubstringBeforeFirst(
collections[1], ':');
if (Schema.getDefaultSchema().hasCollection(container,
collectionName)) {
return "generic.GenericCollectionService";
}
return "generic.GenericConnectionsService";
}
String packages = "";
String types = "";
if (collections.length == 1) {
packages = stringOrSubstringBeforeLast(
stringOrSubstringBeforeFirst(collections[0], ':'), '.')
+ ".";
} else {
for (int i = 0; i < collections.length; i++) {
if (i == 0) {
packages = stringOrSubstringBeforeFirst(collections[i], ':')
+ ".";
} else {
packages += stringOrSubstringBeforeLast(
stringOrSubstringBeforeFirst(collections[i], ':'),
'.')
+ ".";
}
if ((i < (collections.length - 1))
&& (collections[i].indexOf(':') >= 0)) {
types += capitalize(stringOrSubstringAfterLast(
stringOrSubstringAfterLast(collections[i], ':'),
'.'));
}
}
}
return packages
+ types
+ capitalize(stringOrSubstringAfterLast(
stringOrSubstringBeforeFirst(
collections[collections.length - 1], ':'), '.'))
+ "Service";
}
private static final Map serviceInfoCache = new LinkedHashMap();
public static ServiceInfo getServiceInfo(String servicePattern) {
if (servicePattern == null) {
return null;
}
servicePattern = normalizeServicePattern(servicePattern);
ServiceInfo info = serviceInfoCache.get(servicePattern);
if (info != null) {
return info;
}
String[] collections = split(servicePattern, "/*/");
if (collections.length == 0) {
return null;
}
String collectionName = stringOrSubstringBeforeFirst(
collections[collections.length - 1], ':');
if (collectionName == null) {
throw new NullPointerException("Collection name is null");
}
String ownerType = "entity";
String rootType = determineType(collections, 0, 0);
if (collections.length == 1) {
ownerType = "application";
}
if (collections.length > 1) {
ownerType = determineType(collections, 0, collections.length - 2);
}
String itemType = determineType(collections, 0, collections.length - 1);
List patterns = getPatterns(servicePattern, collections);
info = new ServiceInfo(servicePattern, collections.length == 1,
rootType, ownerType, collectionName, itemType, patterns,
Arrays.asList(collections));
serviceInfoCache.put(servicePattern, info);
return info;
}
public String getClassName() {
return getClassName(name);
}
public String getName() {
return name;
}
public boolean isRootService() {
return rootService;
}
public String getRootType() {
return rootType;
}
public boolean isGenericRootType() {
return ("entity".equals(rootType)) || ("entities".equals(rootType));
}
public String getContainerType() {
return containerType;
}
public boolean isContainerType() {
return ("entity".equals(containerType))
|| ("entities".equals(containerType));
}
public String getCollectionName() {
return collectionName;
}
public String getItemType() {
return itemType;
}
public boolean isGenericItemType() {
return "entity".equals(itemType);
}
public List getPatterns() {
return patterns;
}
public List getCollections() {
return collections;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if(obj instanceof ServiceInfo){
return hashCode == ((ServiceInfo)obj).hashCode;
}
return false;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return hashCode;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy