package org.codehaus.mojo.pomtools.console.screens.custom; /* * Copyright 2005-2006 The Apache Software Foundation. * * Licensed 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. */ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.commons.beanutils.ConstructorUtils; import org.codehaus.mojo.pomtools.console.screens.AbstractModelScreen; import org.codehaus.mojo.pomtools.console.screens.ConfirmYesNoScreen; import org.codehaus.mojo.pomtools.console.screens.ScreenHelper; import org.codehaus.mojo.pomtools.console.screens.editors.EditListScreen; import org.codehaus.mojo.pomtools.console.screens.editors.EditObjectScreen; import org.codehaus.mojo.pomtools.console.toolkit.ConsoleEvent; import org.codehaus.mojo.pomtools.console.toolkit.ConsoleEventClosure; import org.codehaus.mojo.pomtools.console.toolkit.ConsoleExecutionException; import org.codehaus.mojo.pomtools.console.toolkit.ConsoleScreen; import org.codehaus.mojo.pomtools.console.toolkit.ConsoleScreenDisplay; import org.codehaus.mojo.pomtools.console.toolkit.event.ConsoleEventDispatcher; import org.codehaus.mojo.pomtools.console.toolkit.event.MatchingListener; import org.codehaus.mojo.pomtools.console.toolkit.event.NumericRangeListener; import org.codehaus.mojo.pomtools.console.toolkit.widgets.TableColumn; import org.codehaus.mojo.pomtools.console.toolkit.widgets.TableLayout; import org.codehaus.mojo.pomtools.helpers.ModelHelper; import org.codehaus.mojo.pomtools.versioning.VersionInfo; import org.codehaus.mojo.pomtools.wrapper.ListWrapper; import org.codehaus.mojo.pomtools.wrapper.ObjectWrapper; import org.codehaus.mojo.pomtools.wrapper.custom.DependencyWrapper; import org.codehaus.mojo.pomtools.wrapper.custom.ModelVersionRange; import org.codehaus.mojo.pomtools.wrapper.reflection.BeanField; import org.codehaus.mojo.pomtools.wrapper.reflection.ModelReflectionException; import org.codehaus.plexus.util.StringUtils; /** * * @author <a href="mailto:dhawkins@codehaus.org">David Hawkins</a> * @version $Id$ */ public class ListDependenciesScreen extends AbstractModelScreen { private static final Class[] LIST_EDITOR_SIGNATURE = new Class[] { ListWrapper.class, int.class }; private static final String KEY_LATEST_VERSION = "l"; private static final String KEY_TOGGLE_SNAPSHOTS = "t"; private static final String KEY_TRANSITIVE_DEPS = "v"; private List depsNotAtLatest = new ArrayList(); private boolean includeSnapshots = true; private final ListWrapper dependencies; private final List items; public ListDependenciesScreen( ObjectWrapper obj, BeanField field ) { super( field.getFieldName() ); dependencies = (ListWrapper) obj.getFieldValue( field ); this.items = dependencies.getItems(); } public ConsoleScreenDisplay getDisplay() throws ConsoleExecutionException { StringBuffer sb = new StringBuffer(); String title = "Dependencies (" + ( includeSnapshots ? "Including" : "Not including" ) + " snapshots in latest version determination)"; sb.append( getHeader( title ) ); if ( items != null && !items.isEmpty() ) { TableLayout tab = new TableLayout( getTerminal(), new TableColumn[] { new TableColumn( TableColumn.ALIGN_RIGHT, TableColumn.BOLD ), TableColumn.ALIGN_LEFT_COLUMN, TableColumn.ALIGN_LEFT_COLUMN, TableColumn.ALIGN_LEFT_COLUMN } ); depsNotAtLatest = new ArrayList(); for ( int i = 0; i < items.size(); i++ ) { ObjectWrapper wrappedObject = (ObjectWrapper) items.get( i ); DependencyWrapper dep = new DependencyWrapper( wrappedObject ); VersionInfo vinfo = dep.getLatestVersion( includeSnapshots ); String strVersion = dep.getVersion(); String versionDecorator = ""; boolean usingResolvedVersion = false; if ( strVersion == null ) { // Look to the fully resolved model to see if perhaps the version was specified in a parent pom. strVersion = dep.getResolvedVersion(); if ( strVersion != null ) { usingResolvedVersion = true; versionDecorator = " (inherited)"; } } ArrayList messages = new ArrayList(); if ( !dep.isValidArtifact() ) { if ( dep.isValidGroupIdArtifactId() ) { messages.add( "Error: Bad version specified" ); } else { messages.add( "Error: Unknown artifact" ); } } else if ( strVersion != null && !dep.isValidVersion( strVersion ) ) { messages.add( "Error: Invalid Version" ); } else { if ( vinfo != null ) { ModelVersionRange depRange = dep.getResolvedVersionRange(); if ( !depRange.containsVersion( vinfo.getArtifactVersion() ) ) { messages.add( "latest -> " + vinfo.getVersionString() ); if ( !usingResolvedVersion ) { depsNotAtLatest.add( dep ); } } } } if ( getModelContext().isShowUnparsedVersions() && !dep.getUnparsedVersions().isEmpty() ) { messages.add( "(contains unparsable)" ); } tab.add( new String[] { numberPrompt( i + 1 ), getModifiedLabel( dep.toString(), wrappedObject.isModified() ), StringUtils.defaultString( strVersion, ModelHelper.NULL ) + versionDecorator, StringUtils.join( messages.iterator(), ", " ) } ); } sb.append( tab.getOutput() ); OptionsPane options = new OptionsPane(); options.add( KEY_NEW_ITEM, "Add new dependency" ); options.add( KEY_TOGGLE_SNAPSHOTS, "Toggle resolve latest with snapshots. currently: " + ( includeSnapshots ? "ON" : "OFF" ) ); if ( !depsNotAtLatest.isEmpty() ) { options.add( KEY_LATEST_VERSION, "Set all to latest the version" ); } options.add( KEY_TRANSITIVE_DEPS, "View transitive dependencies" ); sb.append( options.getOutput() ); return createDisplay( sb.toString(), "Please select a dependency to configure" ); } else { sb.append( EditListScreen.NO_ITEMS ); OptionsPane options = new OptionsPane(); options.add( KEY_NEW_ITEM, "Add new dependency" ); sb.append( options.getOutput() ); return createDisplay( sb.toString(), "Select \"" + KEY_NEW_ITEM + "\" to add a new dependency" ); } } protected void setAllToLatest() { for ( Iterator i = depsNotAtLatest.iterator(); i.hasNext(); ) { DependencyWrapper dep = (DependencyWrapper) i.next(); dep.setToLatestVersion( includeSnapshots ); } depsNotAtLatest.clear(); } public ConsoleEventDispatcher getEventDispatcher() throws ConsoleExecutionException { ConsoleEventDispatcher ced = super.getDefaultEventDispatcher(); ced.addFirst( new MatchingListener( KEY_NEW_ITEM, "Add a new dependency" ) { public void processEvent( ConsoleEvent event ) throws ConsoleExecutionException { dependencies.createItem( null ); event.setNextScreen( getEditor( dependencies.size() - 1 ) ); } } ); if ( items != null && !items.isEmpty() ) { if ( !depsNotAtLatest.isEmpty() ) { String helpText = "Set all to the latest version available. " + "Note that this will not change the versions which are inherited from a parent."; ced.addFirst( new MatchingListener( KEY_LATEST_VERSION, helpText ) { public void processEvent( ConsoleEvent event ) throws ConsoleExecutionException { ConsoleEventClosure yesClosure = new ConsoleEventClosure() { public void execute( ConsoleEvent evt ) throws ConsoleExecutionException { setAllToLatest(); } }; event.setNextScreen( new ConfirmYesNoScreen( "Are you sure you want to set all " + "to the latest version?", yesClosure, null ) ); } } ); } ced.addFirst( new MatchingListener( KEY_TRANSITIVE_DEPS, "View transitive dependencies" ) { public void processEvent( ConsoleEvent event ) throws ConsoleExecutionException { event.setNextScreen( new ListTransitiveDependenciesScreen() ); } } ); ced.addFirst( new MatchingListener( KEY_TOGGLE_SNAPSHOTS, "Toggle the use of snapshots when resolving the latest version." ) { public void processEvent( ConsoleEvent event ) throws ConsoleExecutionException { includeSnapshots = !includeSnapshots; } } ); ced.addFirst( new NumericRangeListener( 1, items.size(), "Select a dependency to configure." ) { public void processEvent( ConsoleEvent event ) throws ConsoleExecutionException { int index = Integer.parseInt( event.getConsoleInput() ) - 1; event.setNextScreen( getEditor( index ) ); } } ); } return ced; } private ConsoleScreen getEditor( int index ) { ObjectWrapper obj = (ObjectWrapper) items.get( index ); String editorClassName = ScreenHelper.getFieldEditorSetting( obj.getFullName() ); if ( editorClassName != null ) { return createEditorScreen( editorClassName, index ); } else { return new EditObjectScreen( dependencies, index ); } } private ConsoleScreen createEditorScreen( String className, int index ) { try { Constructor con = ConstructorUtils.getAccessibleConstructor( Class.forName( className ), LIST_EDITOR_SIGNATURE ); return (ConsoleScreen) con.newInstance( new Object[] { dependencies, new Integer( index ) } ); } catch ( ClassNotFoundException e ) { throw new ModelReflectionException( e ); } catch ( IllegalArgumentException e ) { throw new ModelReflectionException( e ); } catch ( InstantiationException e ) { throw new ModelReflectionException( e ); } catch ( IllegalAccessException e ) { throw new ModelReflectionException( e ); } catch ( InvocationTargetException e ) { throw new ModelReflectionException( e ); } } }