/** * Generates views based on annotations found in a repository class. If the repository class * extends org.ektorp.support.CouchDbRepositorySupport its handled type will also examined for * annotations eligible for view generation. * * @param repository * @return a Map with generated views. */ public Map<String, DesignDocument.View> generateViews(final Object repository) { final Map<String, DesignDocument.View> views = new HashMap<String, DesignDocument.View>(); final Class<?> repositoryClass = repository.getClass(); final Class<?> handledType = repository instanceof CouchDbRepositorySupport<?> ? ((CouchDbRepositorySupport<?>) repository).getHandledType() : null; createDeclaredViews(views, repositoryClass); eachMethod( repositoryClass, new Predicate<Method>() { public boolean apply(Method input) { if (hasAnnotation(input, GenerateView.class)) { generateView(views, input, handledType); } return false; } }); if (handledType != null) { views.putAll(generateViewsFromPersistentType(handledType)); } return views; }
private void generateView( Map<String, DesignDocument.View> views, Method me, Class<?> handledType) { String name = me.getName(); if (!name.startsWith("findBy") && !name.equals("getAll")) { throw new ViewGenerationException( String.format( "The method: %s in %s annotated with GenerateView does not conform to the naming convention of 'findByXxxx'", name, me.getDeclaringClass())); } Class<?> type = resolveReturnType(me); if (type == null) { if (handledType != null) { type = handledType; } else { throw new ViewGenerationException( "Could not resolve return type for method: %s in %s", me.getName(), me.getDeclaringClass()); } } String typeDiscriminator = resolveTypeDiscriminator(type); if (name.equals("getAll")) { if (typeDiscriminator.length() < 1) { throw new ViewGenerationException( String.format( "Cannot generate 'all' view for %s. No type discriminator could be resolved. Try annotate unique field(s) with @TypeDiscriminator", type.getDeclaringClass())); } views.put("all", generateAllView(typeDiscriminator)); return; } String finderName = name.substring(6); String fieldName = resolveFieldName(me, finderName); Method getter = findMethod(type, "get" + fieldName); if (getter == null) { // try pluralis fieldName += "s"; getter = findMethod(type, "get" + fieldName); } if (getter == null) { throw new ViewGenerationException( "Could not generate view for method %s. No get method found for property %s in %s", name, name.substring(6), type); } fieldName = firstCharToLowerCase(fieldName); DesignDocument.View view; if (isIterable(getter.getReturnType())) { view = generateFindByIterableView(fieldName, typeDiscriminator); } else { view = generateFindByView(fieldName, typeDiscriminator); } views.put("by_" + firstCharToLowerCase(finderName), view); }
private void addView( Map<String, DesignDocument.View> views, View input, Class<?> repositoryClass) { if (input.file().length() > 0) { views.put(input.name(), loadViewFromFile(views, input, repositoryClass)); } else { views.put(input.name(), DesignDocument.View.of(input)); } }
private void generateSetBasedDocRefView( Map<String, org.ektorp.support.DesignDocument.View> views, Member me, DocumentReferences referenceMetaData) { String fieldName = firstCharToLowerCase(me.getName()); String orderBy = referenceMetaData.orderBy(); String backRef = referenceMetaData.backReference(); if (backRef.length() == 0) { throw new ViewGenerationException( String.format( "The DocumentReferences annotation in %s must specify a backReference", me.getDeclaringClass())); } String viewName = NameConventions.backReferenceViewName(fieldName); String typeDiscriminator = resolveTypeDiscriminatorForBackReference(me); if (orderBy.length() > 0) { views.put( viewName, generateDocRefsAsSetWithOrderByView(backRef, fieldName, orderBy, typeDiscriminator)); } else { views.put(viewName, generateDocRefsAsSetView(backRef, fieldName, typeDiscriminator)); } }