use of com.yahoo.elide.core.type.Type in project elide by yahoo.
the class ElideStandaloneConfigStoreTest method init.
@BeforeAll
public void init() throws Exception {
configRoot = Files.createTempDirectory("test");
settings = new ElideStandaloneTestSettings() {
@Override
public EntityDictionary getEntityDictionary(ServiceLocator injector, ClassScanner scanner, Optional<DynamicConfiguration> dynamicConfiguration, Set<Type<?>> entitiesToExclude) {
Map<String, Class<? extends Check>> checks = new HashMap<>();
if (getAnalyticProperties().enableDynamicModelConfigAPI()) {
checks.put(ConfigChecks.CAN_CREATE_CONFIG, ConfigChecks.CanCreate.class);
checks.put(ConfigChecks.CAN_READ_CONFIG, ConfigChecks.CanRead.class);
checks.put(ConfigChecks.CAN_DELETE_CONFIG, ConfigChecks.CanDelete.class);
checks.put(ConfigChecks.CAN_UPDATE_CONFIG, ConfigChecks.CanNotUpdate.class);
}
EntityDictionary dictionary = new EntityDictionary(// Checks
checks, // Role Checks
new HashMap<>(), new Injector() {
@Override
public void inject(Object entity) {
injector.inject(entity);
}
@Override
public <T> T instantiate(Class<T> cls) {
return injector.create(cls);
}
}, // Serde Lookup
CoerceUtil::lookup, entitiesToExclude, scanner);
dynamicConfiguration.map(DynamicConfiguration::getRoles).orElseGet(Collections::emptySet).forEach(role -> dictionary.addRoleCheck(role, new Role.RoleMemberCheck(role)));
return dictionary;
}
@Override
public ElideStandaloneAnalyticSettings getAnalyticProperties() {
return new ElideStandaloneAnalyticSettings() {
@Override
public boolean enableDynamicModelConfig() {
return true;
}
@Override
public boolean enableDynamicModelConfigAPI() {
return true;
}
@Override
public String getDynamicConfigPath() {
return configRoot.toFile().getAbsolutePath();
}
@Override
public boolean enableAggregationDataStore() {
return true;
}
@Override
public boolean enableMetaDataStore() {
return true;
}
};
}
};
elide = new ElideStandalone(settings);
elide.start(false);
}
use of com.yahoo.elide.core.type.Type in project elide by yahoo.
the class SwaggerBuilder method build.
/**
* Builds a swagger object.
* @return the constructed 'Swagger' object
*/
public Swagger build() {
/* Used to convert Elide POJOs into Swagger Model objects */
ModelConverters converters = ModelConverters.getInstance();
ModelConverter converter = new JsonApiModelResolver(dictionary);
converters.addConverter(converter);
String apiVersion = swagger.getInfo().getVersion();
if (apiVersion == null) {
apiVersion = NO_VERSION;
}
if (allClasses.isEmpty()) {
allClasses = dictionary.getBoundClassesByVersion(apiVersion);
} else {
allClasses = Sets.intersection(dictionary.getBoundClassesByVersion(apiVersion), allClasses);
if (allClasses.isEmpty()) {
throw new IllegalArgumentException("None of the provided classes are exported by Elide");
}
}
/*
* Create a Model for each Elide entity.
* Elide entity could be of ClassType or DynamicType.
* For ClassType, extract the class and pass it to ModelConverters#readAll method.
* ModelConverters#readAll doesn't support Elide Dynamic Type, so calling the
* JsonApiModelResolver#resolve method directly when its not a ClassType.
*/
Map<String, Model> models = new HashMap<>();
for (Type<?> clazz : allClasses) {
if (clazz instanceof ClassType) {
models.putAll(converters.readAll(((ClassType) clazz).getCls()));
} else {
ModelConverterContextImpl context = new ModelConverterContextImpl(Arrays.asList(converter));
context.resolve(clazz);
models.putAll(context.getDefinedModels());
}
}
swagger.setDefinitions(models);
rootClasses = allClasses.stream().filter(dictionary::isRoot).collect(Collectors.toSet());
/* Find all the paths starting from the root entities. */
Set<PathMetaData> pathData = rootClasses.stream().map(this::find).flatMap(Collection::stream).collect(Collectors.toSet());
/* Prune the discovered paths to remove redundant elements */
Set<PathMetaData> toRemove = new HashSet<>();
pathData.stream().collect(Collectors.groupingBy(PathMetaData::getRootType)).values().forEach(pathSet -> {
for (PathMetaData path : pathSet) {
for (PathMetaData compare : pathSet) {
/*
* We don't prune paths that are redundant with root collections to allow both BOTH
* root collection urls as well as relationship urls.
*/
if (compare.lineage.isEmpty() || path == compare) {
continue;
}
if (compare.shorterThan(path)) {
toRemove.add(path);
break;
}
}
}
});
pathData = Sets.difference(pathData, toRemove);
/* Each path constructs 3 URLs (collection, instance, and relationship) */
for (PathMetaData pathDatum : pathData) {
swagger.path(pathDatum.getCollectionUrl(), pathDatum.getCollectionPath());
swagger.path(pathDatum.getUrl(), pathDatum.getInstancePath());
/* We only construct relationship URLs if the entity is not a root collection */
if (!pathDatum.lineage.isEmpty()) {
swagger.path(pathDatum.getRelationshipUrl(), pathDatum.getRelationshipPath());
}
}
/* We create Swagger 'tags' for each entity so Swagger UI organizes the paths by entities */
List<Tag> tags = allClasses.stream().map((clazz) -> dictionary.getJsonAliasFor(clazz)).map((alias) -> new Tag().name(alias)).collect(Collectors.toList());
swagger.tags(tags);
return swagger;
}
use of com.yahoo.elide.core.type.Type in project elide by yahoo.
the class PersistentResource method buildIdFilterExpression.
/**
* Build an id filter expression for a particular entity type.
*
* @param ids Ids to include in the filter expression
* @param entityType Type of entity
* @return Filter expression for given ids and type.
*/
private static FilterExpression buildIdFilterExpression(List<String> ids, Type<?> entityType, EntityDictionary dictionary, RequestScope scope) {
Type<?> idType = dictionary.getIdType(entityType);
String idField = dictionary.getIdFieldName(entityType);
List<Object> coercedIds = ids.stream().filter(// these don't exist yet
id -> scope.getObjectById(entityType, id) == null).map(id -> CoerceUtil.coerce(id, idType)).collect(Collectors.toList());
/* construct a new SQL like filter expression, eg: book.id IN [1,2] */
FilterExpression idFilter = new InPredicate(new Path.PathElement(entityType, idType, idField), coercedIds);
return idFilter;
}
use of com.yahoo.elide.core.type.Type in project elide by yahoo.
the class SearchDataTransaction method search.
/**
* Perform the full-text search.
* @param entityType The class to search
* @param filterExpression The filter expression to apply
* @param sorting Optional sorting
* @param pagination Optional pagination
* @return A list of records of type entityClass.
*/
private <T> List<T> search(Type<?> entityType, FilterExpression filterExpression, Optional<Sorting> sorting, Optional<Pagination> pagination) {
Query query;
Class<?> entityClass = null;
if (entityType != null) {
Preconditions.checkState(entityType instanceof ClassType);
entityClass = ((ClassType) entityType).getCls();
}
try {
query = filterExpression.accept(new FilterExpressionToLuceneQuery(em, entityClass));
} catch (IllegalArgumentException e) {
throw new BadRequestException(e.getMessage());
}
FullTextQuery fullTextQuery = em.createFullTextQuery(query, entityClass);
if (mustSort(sorting)) {
fullTextQuery = fullTextQuery.setSort(buildSort(sorting.get(), entityType));
}
if (pagination.isPresent()) {
fullTextQuery = fullTextQuery.setMaxResults(pagination.get().getLimit());
fullTextQuery = fullTextQuery.setFirstResult(pagination.get().getOffset());
}
List<T[]> results = fullTextQuery.setProjection(ProjectionConstants.THIS).getResultList();
if (pagination.filter(Pagination::returnPageTotals).isPresent()) {
pagination.get().setPageTotals((long) fullTextQuery.getResultSize());
}
if (results.isEmpty()) {
return Collections.emptyList();
}
return results.stream().map(result -> result[0]).collect(Collectors.toList());
}
use of com.yahoo.elide.core.type.Type in project elide by yahoo.
the class NodeContainer method processFetch.
@Override
public Object processFetch(Environment context) {
EntityDictionary entityDictionary = context.requestScope.getDictionary();
NonEntityDictionary nonEntityDictionary = context.nonEntityDictionary;
Type parentClass = context.parentResource.getResourceType();
String fieldName = context.field.getName();
String idFieldName = entityDictionary.getIdFieldName(parentClass);
if (entityDictionary.isAttribute(parentClass, fieldName)) {
/* fetch attribute properties */
Attribute requested = context.requestScope.getProjectionInfo().getAttributeMap().getOrDefault(context.field.getSourceLocation(), null);
Object attribute = context.parentResource.getAttribute(requested);
if (attribute != null && nonEntityDictionary.hasBinding(EntityDictionary.getType(attribute))) {
return new NonEntityContainer(attribute);
}
if (attribute instanceof Map) {
return ((Map<Object, Object>) attribute).entrySet().stream().map(MapEntryContainer::new).collect(Collectors.toList());
}
if (attribute instanceof Collection) {
Type<?> innerType = entityDictionary.getParameterizedType(parentClass, fieldName);
if (nonEntityDictionary.hasBinding(innerType)) {
return ((Collection) attribute).stream().map(NonEntityContainer::new).collect(Collectors.toList());
}
}
return attribute;
}
if (entityDictionary.isRelation(parentClass, fieldName)) {
/* fetch relationship properties */
// get the relationship from constructed projections
Relationship relationship = context.requestScope.getProjectionInfo().getRelationshipMap().getOrDefault(context.field.getSourceLocation(), null);
if (relationship == null) {
throw new BadRequestException("Relationship doesn't have projection " + context.parentResource.getTypeName() + "." + fieldName);
}
return fetchRelationship(context, relationship);
}
if (Objects.equals(idFieldName, fieldName)) {
return new DeferredId(context.parentResource);
}
throw new BadRequestException("Unrecognized object: " + fieldName + " for: " + parentClass.getName() + " in node");
}
Aggregations