/****************************************************************************** | |
* Copyright (c) 2006, 2010 VMware Inc. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* and Apache License v2.0 which accompanies this distribution. | |
* The Eclipse Public License is available at | |
* http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0 | |
* is available at http://www.opensource.org/licenses/apache2.0.php. | |
* You may elect to redistribute this code under either of these licenses. | |
* | |
* Contributors: | |
* VMware Inc. | |
*****************************************************************************/ | |
package org.eclipse.gemini.blueprint.blueprint.reflect; | |
import org.eclipse.gemini.blueprint.blueprint.reflect.SimpleCollectionMetadata.CollectionType; | |
import org.eclipse.gemini.blueprint.util.BeanReferenceFactoryBean; | |
import org.osgi.service.blueprint.reflect.MapEntry; | |
import org.osgi.service.blueprint.reflect.Metadata; | |
import org.osgi.service.blueprint.reflect.NonNullMetadata; | |
import org.osgi.service.blueprint.reflect.NullMetadata; | |
import org.springframework.beans.BeanMetadataElement; | |
import org.springframework.beans.factory.annotation.Value; | |
import org.springframework.beans.factory.config.*; | |
import org.springframework.beans.factory.support.*; | |
import java.util.*; | |
/** | |
* Adapter between Spring {@link BeanMetadataElement} and OSGi's Blueprint {@link Value}. | |
* | |
* @see BeanMetadataElementFactory | |
* @author Costin Leau | |
*/ | |
class ValueFactory { | |
private static final String BEAN_REF_FB_CLASS_NAME = BeanReferenceFactoryBean.class.getName(); | |
private static final String BEAN_REF_NAME_PROP = "targetBeanName"; | |
/** | |
* Creates the equivalent value for the given Spring metadata. Since Spring's metadata is a superset of the | |
* Blueprint spec, not all Spring types are supported. | |
* | |
* @param metadata | |
* @return | |
*/ | |
@SuppressWarnings("unchecked") | |
static Metadata buildValue(Object metadata) { | |
if (metadata instanceof BeanMetadataElement) { | |
// reference | |
if (metadata instanceof RuntimeBeanReference) { | |
RuntimeBeanReference reference = (RuntimeBeanReference) metadata; | |
// check the special case of nested references being promoted | |
return new SimpleRefMetadata(reference.getBeanName()); | |
} | |
// reference name | |
if (metadata instanceof RuntimeBeanNameReference) { | |
RuntimeBeanNameReference reference = (RuntimeBeanNameReference) metadata; | |
return new SimpleIdRefMetadata(reference.getBeanName()); | |
} | |
// typed String | |
if (metadata instanceof TypedStringValue) { | |
// check if it's a <null/> | |
TypedStringValue typedString = (TypedStringValue) metadata; | |
return (typedString.getValue() == null ? NullMetadata.NULL : new SimpleValueMetadata(typedString)); | |
} | |
// bean definition | |
if (metadata instanceof BeanDefinition) { | |
// check special alias case | |
BeanDefinition def = (BeanDefinition) metadata; | |
if (BEAN_REF_FB_CLASS_NAME.equals(def.getBeanClassName())) { | |
BeanDefinition unwrapped = ComponentMetadataFactory.unwrapImporterReference(def); | |
if (unwrapped != null) { | |
return ComponentMetadataFactory.buildMetadata(null, unwrapped); | |
} else { | |
return new SimpleRefMetadata((String) MetadataUtils.getValue(def.getPropertyValues(), | |
BEAN_REF_NAME_PROP)); | |
} | |
} | |
return MetadataFactory.buildComponentMetadataFor(null, def); | |
} | |
// bean definition holder (used for inner beans/components) | |
if (metadata instanceof BeanDefinitionHolder) { | |
BeanDefinitionHolder holder = (BeanDefinitionHolder) metadata; | |
// we ignore the name even though one was specified | |
return MetadataFactory.buildComponentMetadataFor(null, holder.getBeanDefinition()); | |
} | |
// managedXXX... | |
if (metadata instanceof ManagedArray) { | |
ManagedArray array = (ManagedArray) metadata; | |
return new SimpleCollectionMetadata(getMetadata(array), CollectionType.ARRAY, array | |
.getElementTypeName()); | |
} | |
if (metadata instanceof ManagedList) { | |
ManagedList list = (ManagedList) metadata; | |
return new SimpleCollectionMetadata(getMetadata(list), CollectionType.LIST, list.getElementTypeName()); | |
} | |
if (metadata instanceof ManagedSet) { | |
ManagedSet set = (ManagedSet) metadata; | |
return new SimpleCollectionMetadata(getMetadata(set), CollectionType.SET, set.getElementTypeName()); | |
} | |
if (metadata instanceof ManagedMap) { | |
ManagedMap<Object, Object> map = (ManagedMap) metadata; | |
return new SimpleMapMetadata(ValueFactory.getEntries(map), map.getKeyTypeName(), map.getValueTypeName()); | |
} | |
if (metadata instanceof ManagedProperties) { | |
ManagedProperties properties = (ManagedProperties) metadata; | |
return new SimplePropsMetadata(ValueFactory.getEntries(properties)); | |
} | |
throw new IllegalArgumentException("Unsupported metadata type " + metadata.getClass()); | |
} | |
// no metadata - probably some parser added the object directly | |
// try to convert it into a String | |
return new SimpleValueMetadata(null, metadata.toString()); | |
} | |
static <E> List<Metadata> getMetadata(Collection<E> collection) { | |
if (collection.isEmpty()) { | |
return Collections.emptyList(); | |
} | |
List<Metadata> list = new ArrayList<Metadata>(collection.size()); | |
for (Object value : collection) { | |
list.add(ValueFactory.buildValue(value)); | |
} | |
return Collections.unmodifiableList(list); | |
} | |
static <K, V> List<MapEntry> getEntries(Map<K, V> map) { | |
if (map.isEmpty()) | |
return Collections.emptyList(); | |
List<MapEntry> entries = new ArrayList<MapEntry>(map.size()); | |
// convert map objects | |
for (Map.Entry<K, V> entry : map.entrySet()) { | |
NonNullMetadata key = (NonNullMetadata) ValueFactory.buildValue(entry.getKey()); | |
Metadata value = (Metadata) ValueFactory.buildValue(entry.getValue()); | |
entries.add(new SimpleMapEntry(key, value)); | |
} | |
return Collections.unmodifiableList(entries); | |
} | |
} |