/******************************************************************************* * Copyright (c) 2010-present Sonatype, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stuart McCulloch (Sonatype, Inc.) - initial API and implementation *******************************************************************************/ package org.eclipse.sisu.plexus; import java.lang.reflect.Type; import java.util.List; import java.util.Map; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; import org.eclipse.sisu.inject.TypeArguments; import com.google.inject.Key; import com.google.inject.ProvisionException; import com.google.inject.TypeLiteral; import com.google.inject.name.Names; /** * Utility methods for dealing with Plexus roles. */ public final class Roles { // ---------------------------------------------------------------------- // Constants // ---------------------------------------------------------------------- private static final String MISSING_COMPONENT_ERROR = "No implementation for %s was bound."; private static final String MISSING_COMPONENT_WITH_HINT_ERROR = "No implementation for %s annotated with @Named(value=%s) was bound."; // ---------------------------------------------------------------------- // Constructors // ---------------------------------------------------------------------- private Roles() { // static utility class, not allowed to create instances } // ---------------------------------------------------------------------- // Utility methods // ---------------------------------------------------------------------- /** * Returns the canonical form of the given Plexus role-hint. * * @param role The Plexus role * @param hint The Plexus hint * @return Canonical role-hint denoting the same component as the given role-hint */ public static String canonicalRoleHint( final String role, final String hint ) { return Hints.isDefaultHint( hint ) ? role : role + ':' + hint; } /** * Returns the canonical role-hint for the given Plexus component. * * @param component The Plexus component * @return Canonical role-hint denoting the given component */ public static String canonicalRoleHint( final Component component ) { return canonicalRoleHint( component.role().getName(), component.hint() ); } /** * Deduces the role type based on the given @{@link Requirement} and expected type. * * @param requirement The Plexus requirement * @param asType The expected type * @return "Best-fit" role type */ public static TypeLiteral<?> roleType( final Requirement requirement, final TypeLiteral<?> asType ) { final Type role = requirement.role(); if ( role != Object.class && role != Map.class && role != List.class ) { return TypeLiteral.get( role ); } final Class<?> rawType = asType.getRawType(); if ( Map.class == rawType ) { // Map<String, T> --> T return TypeArguments.get( asType, 1 ); } if ( List.class == rawType ) { // List<T> --> T return TypeArguments.get( asType, 0 ); } return asType; } /** * Returns the component binding {@link Key} for the given Plexus component. * * @param component The Plexus component * @return Component binding key denoting the given component */ public static Key<?> componentKey( final Component component ) { return componentKey( component.role(), component.hint() ); } /** * Returns the component binding {@link Key} for the given Plexus role-hint. * * @param role The Plexus role * @param hint The Plexus hint * @return Component binding key denoting the given role-hint */ public static <T> Key<T> componentKey( final Class<T> role, final String hint ) { if ( Hints.isDefaultHint( hint ) ) { return Key.get( role ); } return Key.get( role, Names.named( Hints.canonicalHint( hint ) ) ); } /** * Returns the component binding {@link Key} for the given Plexus role-hint. * * @param role The Plexus role * @param hint The Plexus hint * @return Component binding key denoting the given role-hint */ @SuppressWarnings( "unchecked" ) public static <T> Key<T> componentKey( final TypeLiteral<T> role, final String hint ) { return (Key<T>) componentKey( role.getRawType(), hint ); } /** * Throws a {@link ProvisionException} detailing the missing Plexus component. * * @param role The Plexus role * @param hint The Plexus hint */ public static <T> T throwMissingComponentException( final TypeLiteral<T> role, final String hint ) { if ( Hints.isDefaultHint( hint ) ) { throw new ProvisionException( String.format( MISSING_COMPONENT_ERROR, role ) ); } throw new ProvisionException( String.format( MISSING_COMPONENT_WITH_HINT_ERROR, role, hint ) ); } /** * Removes any dashes from the name and converts it to camelCase. * * @param name The element name * @return CamelCased name with no dashes */ public static String camelizeName( final String name ) { StringBuilder buf = null; final int length = name.length(); for ( int i = 0; i < length; i++ ) { if ( '-' == name.charAt( i ) ) { buf = new StringBuilder( name.substring( 0, i ) ); break; } } if ( null == buf ) { return name; // nothing to camelize } boolean capitalize = true; for ( int i = buf.length() + 1; i < length; i++ ) { final char c = name.charAt( i ); if ( '-' == c ) { capitalize = true; } else if ( capitalize ) { buf.append( Character.toTitleCase( c ) ); capitalize = false; } else { buf.append( c ); } } return buf.toString(); } }