use of com.yahoo.elide.swagger.property.Relationship in project elide by yahoo.
the class SwaggerBuilderTest method verifyDataRelationship.
/**
* Verifies that the given model is of type 'Data' containing a 'Relationship' with the
* correct type field.
* @param model The model to check
* @param refTypeName The type field to match against
*/
private void verifyDataRelationship(Model model, String refTypeName) {
assertTrue((model instanceof com.yahoo.elide.swagger.model.Data));
ArrayProperty data = (ArrayProperty) model.getProperties().get("data");
Relationship relation = (Relationship) data.getItems();
StringProperty type = (StringProperty) relation.getProperties().get("type");
assertTrue(type.getEnum().contains(refTypeName));
}
use of com.yahoo.elide.swagger.property.Relationship in project elide by yahoo.
the class JsonApiModelResolver method resolve.
@Override
public Model resolve(java.lang.reflect.Type type, ModelConverterContext context, Iterator<ModelConverter> next) {
if (!(type instanceof Class || type instanceof SimpleType || type instanceof Type)) {
return super.resolve(type, context, next);
}
Type<?> clazzType = null;
/*
* If an Elide entity is an attribute somewhere in a model, the ModelResolver will
* end up wrapping this as a SimpleType (rather than trying to resolve the entity class directly).
*/
if (type instanceof SimpleType) {
type = ((SimpleType) type).getRawClass();
clazzType = ClassType.of((Class<?>) type);
} else if (type instanceof Type) {
clazzType = (Type<?>) type;
} else if (type instanceof Class) {
clazzType = ClassType.of((Class<?>) type);
}
/* Not an entity managed by Elide, let Swagger convert it */
String typeAlias;
try {
typeAlias = dictionary.getJsonAliasFor(clazzType);
} catch (IllegalArgumentException e) {
return super.resolve(type, context, next);
}
Resource entitySchema = new Resource();
entitySchema.description(getModelDescription(clazzType));
entitySchema.setSecurityDescription(getClassPermissions(clazzType));
/* Populate the attributes */
List<String> attributeNames = dictionary.getAttributes(clazzType);
for (String attributeName : attributeNames) {
Type<?> attributeType = dictionary.getType(clazzType, attributeName);
Property attribute = processAttribute(clazzType, attributeName, attributeType, context, next);
entitySchema.addAttribute(attributeName, attribute);
}
/* Populate the relationships */
List<String> relationshipNames = dictionary.getRelationships(clazzType);
for (String relationshipName : relationshipNames) {
Type<?> relationshipType = dictionary.getParameterizedType(clazzType, relationshipName);
Relationship relationship = processRelationship(clazzType, relationshipName, relationshipType);
if (relationship != null) {
entitySchema.addRelationship(relationshipName, relationship);
}
}
entitySchema.name(typeAlias);
return entitySchema;
}
use of com.yahoo.elide.swagger.property.Relationship in project elide by yahoo.
the class SwaggerBuilderTest method verifyDataRelationship.
/**
* Verifies that the given property is of type 'Data' containing a 'Relationship' with the
* correct type field.
* @param property The property to check
* @param refTypeName The type field to match against
*/
private void verifyDataRelationship(Property property, String refTypeName) {
assertTrue((property instanceof Data));
ArrayProperty data = (ArrayProperty) ((Data) property).getProperties().get("data");
Relationship relation = (Relationship) data.getItems();
StringProperty type = (StringProperty) relation.getProperties().get("type");
assertTrue(type.getEnum().contains(refTypeName));
}
use of com.yahoo.elide.swagger.property.Relationship in project elide by yahoo.
the class JsonApiModelResolver method processRelationship.
private Relationship processRelationship(Type<?> clazz, String relationshipName, Type<?> relationshipClazz) {
Relationship relationship = null;
try {
relationship = new Relationship(dictionary.getJsonAliasFor(relationshipClazz));
/* Skip the relationship if it is not bound in the dictionary */
} catch (IllegalArgumentException e) {
return relationship;
}
String description = getFieldDescription(clazz, relationshipName);
String permissions = getFieldPermissions(clazz, relationshipName);
relationship.setDescription(StringUtils.defaultIfEmpty(joinNonEmpty("\n", description, permissions), null));
relationship.setExample((Object) StringUtils.defaultIfEmpty(getFieldExample(clazz, relationshipName), null));
relationship.setReadOnly(getFieldReadOnly(clazz, relationshipName));
relationship.setRequired(getFieldRequired(clazz, relationshipName));
return relationship;
}
use of com.yahoo.elide.swagger.property.Relationship 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;
}
Aggregations