/*
* 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.deltaspike.data.impl.meta;
import org.apache.deltaspike.data.impl.RepositoryDefinitionException;
import org.apache.deltaspike.data.impl.meta.extractor.AnnotationMetadataExtractor;
import org.apache.deltaspike.data.impl.meta.extractor.MetadataExtractor;
import org.apache.deltaspike.data.impl.meta.extractor.TypeMetadataExtractor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Convenience class to access Repository and Repository method meta data.
* Acts as repository for Repository related meta data.
*/
public class RepositoryComponents
{
private final Map<Class<?>, RepositoryComponent> repos = new ConcurrentHashMap<Class<?>, RepositoryComponent>();
private final List<MetadataExtractor> extractors = Arrays.asList(new AnnotationMetadataExtractor(),
new TypeMetadataExtractor());
/**
* Add a Repository class to the meta data repository.
*
* @param repoClass The repo class.
*/
public void add(Class<?> repoClass)
{
RepositoryEntity entityClass = extractEntityMetaData(repoClass);
RepositoryComponent repo = new RepositoryComponent(repoClass, entityClass);
repos.put(repoClass, repo);
}
/**
* Repository access - lookup the Repository component meta data from a list of candidate classes.
* Depending on the implementation, proxy objects might have been modified so the actual class
* does not match the original Repository class.
*
* @param candidateClasses List of candidates to check.
* @return A {@link RepositoryComponent} corresponding to the repoClass parameter.
*/
public RepositoryComponent lookupComponent(List<Class<?>> candidateClasses)
{
for (Class<?> repoClass : candidateClasses)
{
if (repos.containsKey(repoClass))
{
return repos.get(repoClass);
}
}
throw new RuntimeException("Unknown Repository classes " + candidateClasses);
}
/**
* Repository access - lookup the Repository component meta data for a specific Repository class.
*
* @param repoClass The Repository class to lookup the method for
* @return A {@link RepositoryComponent} corresponding to the repoClass parameter.
*/
public RepositoryComponent lookupComponent(Class<?> repoClass)
{
if (repos.containsKey(repoClass))
{
return repos.get(repoClass);
}
throw new RuntimeException("Unknown Repository class " + repoClass.getName());
}
/**
* Repository access - lookup method information for a specific Repository class.
*
* @param repoClass The Repository class to lookup the method for
* @param method The Method object to get Repository meta data for.
* @return A {@link RepositoryMethod} corresponding to the method parameter.
*/
public RepositoryMethod lookupMethod(Class<?> repoClass, Method method)
{
return lookupComponent(repoClass).lookupMethod(method);
}
public RepositoryMethod lookupMethod(RepositoryComponent component, Method method)
{
return component.lookupMethod(method);
}
private RepositoryEntity extractEntityMetaData(Class<?> repoClass)
{
for (MetadataExtractor extractor : extractors)
{
RepositoryEntity entity = extractor.extract(repoClass);
if (entity != null)
{
return entity;
}
}
throw new RepositoryDefinitionException(repoClass);
}
public Map<Class<?>, RepositoryComponent> getRepositories()
{
return repos;
}
public void addAll(Map<Class<?>, RepositoryComponent> repositories)
{
this.repos.putAll(repositories);
}
}