org.apache.commons.weaver.model.ScanResult Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of commons-weaver-processor Show documentation
Show all versions of commons-weaver-processor Show documentation
Defines the Apache Commons Weaver SPI as well as the basic build-time
(filesystem-based) processors that detect, configure, and invoke
available modules.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.commons.weaver.model;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
import org.apache.commons.lang3.Validate;
import org.apache.commons.weaver.WeaveProcessor;
import org.apache.commons.weaver.spi.Weaver;
/**
* Encapsulates the result of scanning based on a {@link ScanRequest}. The
* scan results are available in a structure corresponding to the Java class
* hierarchy; i.e.:
*
*
* package
* |_class
* |_field
* |_method
* | |_method parameter
* |_constructor
* |_constructor parameter
*
*
* The tree of results can be iterated in this manner using
* {@link #getPackages()}. However, if a given {@link Weaver} is known not to
* handle packages but some other element, convenience methods are provided
* here giving direct access to the various elements that may have been
* discovered.
*
*/
public class ScanResult {
private abstract static class Projection implements
AnnotatedElements {
private final Iterable parents;
Projection(final Iterable parents) {
super();
this.parents = parents;
}
protected abstract Iterable childrenOf(PARENT parent);
@Override
public Iterator iterator() {
final Iterator parentIterator = parents.iterator();
return new Iterator() {
private Iterator children = nextChildren();
@Override
public synchronized boolean hasNext() {
return children != null;
}
@Override
public synchronized CHILD next() {
if (children == null) {
throw new NoSuchElementException();
}
try {
return children.next();
} finally {
if (!children.hasNext()) {
children = nextChildren();
}
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
private Iterator nextChildren() {
while (parentIterator.hasNext()) {
final Iterator prospect = childrenOf(parentIterator.next()).iterator();
if (prospect.hasNext()) {
return prospect;
}
}
return null;
}
};
}
@Override
public AnnotatedElements with(final Class extends Annotation> annotationType) {
return new AnnotatedWith(this, annotationType);
}
}
private static class AnnotatedWith implements AnnotatedElements {
final Iterable wrapped;
final Class extends Annotation> annotationType;
AnnotatedWith(final Iterable wrapped, final Class extends Annotation> annotationType) {
super();
this.wrapped = wrapped;
this.annotationType = annotationType;
}
@Override
public Iterator iterator() {
final Iterator iter = wrapped.iterator();
return new Iterator() {
W next = read();
private W read() {
while (iter.hasNext()) {
final W element = iter.next();
if (element.isAnnotationPresent(annotationType)) {
return element;
}
}
return null;
}
@Override
public boolean hasNext() {
return next != null;
}
@Override
public W next() {
if (next == null) {
throw new NoSuchElementException();
}
try {
return next;
} finally {
next = read();
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override
public AnnotatedElements with(final Class extends Annotation> annotationType) {
return new AnnotatedWith(this, annotationType);
}
}
private final ConcurrentNavigableMap packages =
new ConcurrentSkipListMap();
/**
* Public for use by {@link WeaveProcessor}.
* @param pkg to wrap
* @return {@link WeavablePackage}
*/
public WeavablePackage getWeavable(final Package pkg) {
final String key = pkg.getName();
if (packages.containsKey(key)) {
return packages.get(key);
}
final WeavablePackage result = new WeavablePackage(pkg);
final WeavablePackage faster = packages.putIfAbsent(key, result);
return faster == null ? result : faster;
}
/**
* Public for use by {@link WeaveProcessor}.
* @param cls to wrap
* @param type
* @return {@link WeavableClass}
*/
public WeavableClass getWeavable(final Class cls) {
return getWeavable(cls.getPackage()).getWeavable(cls);
}
/**
* Public for use by {@link WeaveProcessor}.
* @param fld to wrap
* @return {@link WeavableField}
*/
public WeavableField> getWeavable(final Field fld) {
return getWeavable(fld.getDeclaringClass()).getWeavable(fld);
}
/**
* Public for use by {@link WeaveProcessor}.
* @param methd to wrap
* @return {@link WeavableMethod}
*/
public WeavableMethod> getWeavable(final Method methd) {
return getWeavable(methd.getDeclaringClass()).getWeavable(methd);
}
/**
* Public for use by {@link WeaveProcessor}.
* @param ctor to wrap
* @param type
* @return {@link WeavableConstructor}
*/
public WeavableConstructor getWeavable(final Constructor ctor) {
return getWeavable(ctor.getDeclaringClass()).getWeavable(ctor);
}
/**
* Iterate or filter {@link WeavablePackage}s.
* @return {@link AnnotatedElements}
*/
public AnnotatedElements getPackages() {
return new AnnotatedElements() {
@Override
public Iterator iterator() {
return packages.values().iterator();
}
@Override
public AnnotatedElements with(final Class extends Annotation> annotationType) {
return new AnnotatedWith(packages.values(), annotationType);
}
};
}
/**
* Iterate or filter {@link WeavableClass}es.
* @return {@link AnnotatedElements}
*/
public AnnotatedElements> getClasses() {
return new Projection>(getPackages()) {
@Override
protected Iterable> childrenOf(final WeavablePackage parent) {
return parent.getClasses();
}
};
}
/**
* Iterate or filter {@link WeavableClass}es assignable to {@code supertype}.
* @param supertype {@link Class} whose subtypes are sought
* @return {@link AnnotatedElements}
*/
public AnnotatedElements> getClassesAssignableTo(final Class> supertype) {
Validate.notNull(supertype, "supertype");
return new Projection>(getPackages()) {
@Override
protected Iterable> childrenOf(final WeavablePackage parent) {
return parent.getClasses();
}
@Override
public Iterator> iterator() {
final Iterator> toWrap = super.iterator();
return new Iterator>() {
{
read();
}
private WeavableClass> next;
private void read() {
while (toWrap.hasNext()) {
final WeavableClass> test = toWrap.next();
if (supertype.isAssignableFrom(test.getTarget())) {
next = test;
return;
}
}
next = null;
}
@Override
public boolean hasNext() {
return next != null;
}
@Override
public WeavableClass> next() {
try {
return next;
} finally {
read();
}
}
@Override
public void remove() {
toWrap.remove();
}
};
}
};
}
/**
* Iterate or filter {@link WeavableField}s.
* @return {@link AnnotatedElements}
*/
public AnnotatedElements> getFields() {
return new Projection, WeavableField>>(getClasses()) {
@Override
protected Iterable> childrenOf(final WeavableClass> parent) {
@SuppressWarnings({ "unchecked", "rawtypes" })
final Iterable> result = ((WeavableClass) parent).getFields();
return result;
}
};
}
/**
* Iterate or filter {@link WeavableConstructor}s.
* @return {@link AnnotatedElements}
*/
public AnnotatedElements> getConstructors() {
return new Projection, WeavableConstructor>>(getClasses()) {
@Override
protected Iterable> childrenOf(final WeavableClass> parent) {
@SuppressWarnings({ "unchecked", "rawtypes" })
final Iterable> result = ((WeavableClass) parent).getConstructors();
return result;
}
};
}
/**
* Iterate or filter {@link WeavableMethod}s.
* @return {@link AnnotatedElements}
*/
public AnnotatedElements> getMethods() {
return new Projection, WeavableMethod>>(getClasses()) {
@Override
protected Iterable> childrenOf(final WeavableClass> parent) {
@SuppressWarnings({ "unchecked", "rawtypes" })
final Iterable> result = ((WeavableClass) parent).getMethods();
return result;
}
};
}
/**
* Iterate or filter {@link WeavableMethodParameter}s.
* @return {@link AnnotatedElements}
*/
public AnnotatedElements> getMethodParameters() {
return new Projection, WeavableMethodParameter>>(getMethods()) {
@Override
protected Iterable> childrenOf(final WeavableMethod> parent) {
@SuppressWarnings({ "unchecked", "rawtypes" })
final Iterable> result = ((WeavableMethod) parent).getParameters();
return result;
}
};
}
/**
* Iterate or filter {@link WeavableConstructorParameter}s.
* @return {@link AnnotatedElements}
*/
public AnnotatedElements> getConstructorParameters() {
return new Projection, WeavableConstructorParameter>>(getConstructors()) {
@Override
protected Iterable> childrenOf(final WeavableConstructor> parent) {
@SuppressWarnings({ "unchecked", "rawtypes" })
final Iterable> result = ((WeavableConstructor) parent).getParameters();
return result;
}
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy