/** * Creates a {@link PrettyExpression} for a class and component. This method may return a {@link * ConstantExpression} or a {@link LazyExpression}. * * @param clazz The class of the bean * @param component the component (property or method name) * @return The expression */ private PrettyExpression buildPrettyExpression(final Class<?> clazz, final String component) { if (log.isTraceEnabled()) { log.trace("Searching name of bean: " + clazz.getName()); } // get name from internal map build from @URLBeanName annotations and // previously resolved names String beanName = beanNameMap.get(clazz); // return a constant expression if (beanName != null) { if (log.isTraceEnabled()) { log.trace("Got bean name from @URLBeanName annotation: " + beanName); } return new ConstantExpression("#{" + beanName + "." + component + "}"); } // build a lazy expression else { if (log.isTraceEnabled()) { log.trace("Name of bean not found. Building lazy expression for: " + clazz.getName()); } return new LazyExpression(beanNameFinder, clazz, component); } }
/** * This method scans the supplied class for PrettyFaces annotations. The method must be called for * every class that should be scanner before finally calling {@link #build(PrettyConfigBuilder)}. * * @param clazz The class to scan */ public void processClass(final Class clazz) { // log class name on trace level if (log.isTraceEnabled()) { log.trace("Analyzing class: " + clazz.getName()); } try { // scan for PrettyAnnotation class // returns the mapping ID, if an annotation was found String[] classMappingIds = processClassMappingAnnotations(clazz); // scan for PrettyBean annotation processPrettyBeanAnnotation(clazz); // process annotations on public methods for (Method method : clazz.getMethods()) { processMethodAnnotations(method, classMappingIds); } // loop over fields to find URLQueryParameter annotations for (Field field : clazz.getDeclaredFields()) { processFieldAnnotations(field, classMappingIds); } } catch (NoClassDefFoundError e) { // reference to another class unknown to the classloader log.debug("Unable to process class '" + clazz.getName() + "': " + e.toString()); } }
/** * Checks the class for a {@link URLBeanName} annotation. * * @param clazz Class to scan */ private void processPrettyBeanAnnotation(final Class clazz) { // get reference to @URLMapping annotation URLBeanName prettyBean = (URLBeanName) clazz.getAnnotation(URLBeanName.class); // process annotation if it exists if (prettyBean != null) { // log class name if (log.isTraceEnabled()) { log.trace("Found @URLBeanName annotation on class: " + clazz.getName()); } // add bean to map beanNameMap.put(clazz, prettyBean.value()); } }
/** * This methods adds all mappings found to the supplied {@link PrettyConfigBuilder}. It should be * called after all classes has been scanned via {@link #processClass(Class)}. * * @param builder The builder to add the mappings to */ public void build(final PrettyConfigBuilder builder) { // process all actions found for (ActionSpec actionSpec : urlActions) { // create an action for each referenced mapping for (String mappingId : actionSpec.getMappingIds()) { // Get the mapping references by the action UrlMapping mapping = urlMappings.get(mappingId); /* * Fail for unresolved mappings. This may happen when the user places * invalid mapping IDs in the mappingId attribute of * * @URLAction or @URLQueryParameter */ if (mapping == null) { throw new IllegalArgumentException( "Unable to find the mapping '" + mappingId + "' referenced at method '" + actionSpec.getMethod().getName() + "' in class '" + actionSpec.getMethod().getDeclaringClass().getName() + "'."); } // build UrlMapping UrlAction urlAction = new UrlAction(); urlAction.setPhaseId(actionSpec.getPhaseId()); urlAction.setOnPostback(actionSpec.isOnPostback()); urlAction.setInheritable(actionSpec.isInheritable()); // try to get bean name Class clazz = actionSpec.getMethod().getDeclaringClass(); // build expression PrettyExpression expression = buildPrettyExpression(clazz, actionSpec.getMethod().getName()); urlAction.setAction(expression); // trace if (log.isTraceEnabled()) { log.trace( "Adding action expression '" + urlAction.getAction() + "' to mapping: " + mapping.getId()); } // register this action mapping.addAction(urlAction); } } for (QueryParamSpec queryParamSpec : queryParamList) { // create a query param for each referenced mapping for (String mappingId : queryParamSpec.getMappingIds()) { // Get the mapping references by the query param UrlMapping mapping = urlMappings.get(mappingId); // fail for unresolved mappings if (mapping == null) { throw new IllegalArgumentException( "Unable to find the mapping '" + mappingId + "' referenced at field '" + queryParamSpec.getFieldName() + "' in class '" + queryParamSpec.getOwnerClass().getName() + "'."); } // build UrlMapping QueryParameter queryParam = new QueryParameter(); queryParam.setName(queryParamSpec.getName()); queryParam.setOnError(queryParamSpec.getOnError()); queryParam.setConverterId(StringUtils.trimToNull(queryParamSpec.getConverterId())); queryParam.setValidatorIds(join(queryParamSpec.getValidatorIds(), " ")); queryParam.setOnPostback(queryParamSpec.isOnPostback()); // optional validator method if (!isBlank(queryParamSpec.getValidator())) { queryParam.setValidatorExpression(new ConstantExpression(queryParamSpec.getValidator())); } // try to get bean name Class<?> clazz = queryParamSpec.getOwnerClass(); // build expression PrettyExpression expression = buildPrettyExpression(clazz, queryParamSpec.getFieldName()); queryParam.setExpression(expression); // trace if (log.isTraceEnabled()) { log.trace( "Registered query-param '" + queryParam.getName() + "' to '" + expression + "' in mapping: " + mapping.getId()); } // register this action mapping.addQueryParam(queryParam); } } // finally register all mappings for (UrlMapping mapping : urlMappings.values()) { builder.addMapping(mapping); } }
/** * Process a single {@link URLMapping} annotation. * * @param clazz The class that the annotation was found on * @param mappingAnnotation The annotation to process * @return The mapping ID of the mapping found */ private String processPrettyMappingAnnotation( final Class clazz, final URLMapping mappingAnnotation) { // log class name if (log.isTraceEnabled()) { log.trace("Found @URLMapping annotation on class: " + clazz.getName()); } // create UrlMapping from annotation UrlMapping mapping = new UrlMapping(); mapping.setId(mappingAnnotation.id()); mapping.setParentId(mappingAnnotation.parentId()); mapping.setPattern(mappingAnnotation.pattern()); mapping.setViewId(mappingAnnotation.viewId()); mapping.setOutbound(mappingAnnotation.outbound()); mapping.setOnPostback(mappingAnnotation.onPostback()); // register mapping Object existingMapping = urlMappings.put(mapping.getId(), mapping); // fail if a mapping with this ID already existed if (existingMapping != null) { throw new IllegalArgumentException("Duplicated mapping id: " + mapping.getId()); } // At bean name to lookup map if it has been specified if ((mappingAnnotation.beanName() != null) && (mappingAnnotation.beanName().length() > 0)) { beanNameMap.put(clazz, mappingAnnotation.beanName()); } // process validations for (URLValidator validationAnnotation : mappingAnnotation.validation()) { // index attribute is required in this case if (validationAnnotation.index() < 0) { throw new IllegalArgumentException( "Please set the index of the path parameter you want to validate with the @URLValidator specified on mapping: " + mapping.getId()); } // prepare PathValidator PathValidator pathValidator = new PathValidator(); pathValidator.setIndex(validationAnnotation.index()); pathValidator.setOnError(validationAnnotation.onError()); pathValidator.setValidatorIds(join(validationAnnotation.validatorIds(), " ")); // optional validator method if (!isBlank(validationAnnotation.validator())) { pathValidator.setValidatorExpression( new ConstantExpression(validationAnnotation.validator())); } // add PathValidator to the mapping mapping.getPathValidators().add(pathValidator); } // process converters for (URLConverter converterAnnotation : mappingAnnotation.converter()) { // index attribute is required in this case if (converterAnnotation.index() < 0) { throw new IllegalArgumentException( "Please set the index of the path parameter you want to convert with the @URLConverter specified on mapping: " + mapping.getId()); } // prepare PathValidator PathConverter pathConverter = new PathConverter(); pathConverter.setIndex(converterAnnotation.index()); pathConverter.setConverterId(StringUtils.trimToNull(converterAnnotation.converterId())); // add PathValidator to the mapping mapping.addPathConverter(pathConverter); } // return mapping id return mapping.getId().trim(); }