001/*
002 * Copyright (C) 2009 Christian Schulte <cs@schulte.it>
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without
006 * modification, are permitted provided that the following conditions
007 * are met:
008 *
009 *   o Redistributions of source code must retain the above copyright
010 *     notice, this list of conditions and the following disclaimer.
011 *
012 *   o Redistributions in binary form must reproduce the above copyright
013 *     notice, this list of conditions and the following disclaimer in
014 *     the documentation and/or other materials provided with the
015 *     distribution.
016 *
017 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
018 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
019 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
020 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
021 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
022 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
023 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
024 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
026 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027 *
028 * $JOMC: ShowModelCommand.java 5251 2016-04-25 19:46:04Z schulte $
029 *
030 */
031package org.jomc.cli.commands;
032
033import java.io.File;
034import java.io.IOException;
035import java.io.StringWriter;
036import java.util.Locale;
037import java.util.logging.Level;
038import javax.xml.bind.JAXBContext;
039import javax.xml.bind.JAXBException;
040import javax.xml.bind.Marshaller;
041import javax.xml.bind.util.JAXBSource;
042import javax.xml.transform.Source;
043import org.apache.commons.cli.CommandLine;
044import org.jomc.cli.commands.AbstractModletCommand.CommandLineClassLoader;
045import org.jomc.model.Instance;
046import org.jomc.model.Module;
047import org.jomc.model.Modules;
048import org.jomc.model.Specification;
049import org.jomc.model.modlet.ModelHelper;
050import org.jomc.modlet.Model;
051import org.jomc.modlet.ModelContext;
052import org.jomc.modlet.ModelException;
053import org.jomc.modlet.ModelValidationReport;
054import org.jomc.modlet.ObjectFactory;
055
056/**
057 * {@code show-model} command implementation.
058 *
059 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
060 */
061public final class ShowModelCommand extends AbstractModelCommand
062{
063
064    /**
065     * Creates a new {@code ShowModelCommand} instance.
066     */
067    public ShowModelCommand()
068    {
069        super();
070    }
071
072    @Override
073    public org.apache.commons.cli.Options getOptions()
074    {
075        final org.apache.commons.cli.Options options = super.getOptions();
076        options.addOption( Options.DOCUMENT_OPTION );
077        options.addOption( Options.DOCUMENT_ENCODING_OPTION );
078        options.addOption( Options.IMPLEMENTATION_OPTION );
079        options.addOption( Options.MODULE_OPTION );
080        options.addOption( Options.SPECIFICATION_OPTION );
081        return options;
082    }
083
084    public String getName()
085    {
086        return "show-model";
087    }
088
089    public String getAbbreviatedName()
090    {
091        return "sm";
092    }
093
094    public String getShortDescription( final Locale locale )
095    {
096        return Messages.getMessage( "showModelShortDescription" );
097    }
098
099    public String getLongDescription( final Locale locale )
100    {
101        return null;
102    }
103
104    protected void executeCommand( final CommandLine commandLine ) throws CommandExecutionException
105    {
106        if ( commandLine == null )
107        {
108            throw new NullPointerException( "commandLine" );
109        }
110
111        CommandLineClassLoader classLoader = null;
112
113        try
114        {
115            classLoader = new CommandLineClassLoader( commandLine );
116            final ModelContext context = this.createModelContext( commandLine, classLoader );
117            final Model model = this.getModel( context, commandLine );
118            final JAXBContext jaxbContext = context.createContext( model.getIdentifier() );
119            final Marshaller marshaller = context.createMarshaller( model.getIdentifier() );
120            final Source source = new JAXBSource( jaxbContext, new ObjectFactory().createModel( model ) );
121            final ModelValidationReport validationReport = context.validateModel( model.getIdentifier(), source );
122            final Modules modules = ModelHelper.getModules( model );
123            this.log( validationReport, marshaller );
124
125            if ( !validationReport.isModelValid() )
126            {
127                throw new CommandExecutionException( Messages.getMessage( "invalidModel",
128                                                                          this.getModel( commandLine ) ) );
129
130            }
131
132            final Model displayModel = new Model();
133            displayModel.setIdentifier( model.getIdentifier() );
134
135            boolean displayModules = true;
136
137            if ( commandLine.hasOption( Options.IMPLEMENTATION_OPTION.getOpt() ) )
138            {
139                final String identifier = commandLine.getOptionValue( Options.IMPLEMENTATION_OPTION.getOpt() );
140                final Instance instance = modules != null ? modules.getInstance( identifier ) : null;
141                displayModules = false;
142
143                if ( instance != null )
144                {
145                    displayModel.getAny().add( new org.jomc.model.ObjectFactory().createInstance( instance ) );
146                }
147                else if ( this.isLoggable( Level.WARNING ) )
148                {
149                    this.log( Level.WARNING,
150                              Messages.getMessage( "implementationNotFoundWarning", identifier ),
151                              null );
152
153                }
154            }
155
156            if ( commandLine.hasOption( Options.SPECIFICATION_OPTION.getOpt() ) )
157            {
158                final String identifier = commandLine.getOptionValue( Options.SPECIFICATION_OPTION.getOpt() );
159                final Specification specification = modules != null ? modules.getSpecification( identifier ) : null;
160                displayModules = false;
161
162                if ( specification != null )
163                {
164                    displayModel.getAny().add(
165                        new org.jomc.model.ObjectFactory().createSpecification( specification ) );
166
167                }
168                else if ( this.isLoggable( Level.WARNING ) )
169                {
170                    this.log( Level.WARNING,
171                              Messages.getMessage( "specificationNotFoundWarning", identifier ),
172                              null );
173
174                }
175            }
176
177            if ( commandLine.hasOption( Options.MODULE_OPTION.getOpt() ) )
178            {
179                final String moduleName = commandLine.getOptionValue( Options.MODULE_OPTION.getOpt() );
180                final Module m = modules != null ? modules.getModule( moduleName ) : null;
181                displayModules = false;
182
183                if ( m != null )
184                {
185                    displayModel.getAny().add( new org.jomc.model.ObjectFactory().createModule( m ) );
186                }
187                else if ( this.isLoggable( Level.WARNING ) )
188                {
189                    this.log( Level.WARNING,
190                              Messages.getMessage( "moduleNotFoundWarning", moduleName ),
191                              null );
192
193                }
194            }
195
196            if ( displayModules )
197            {
198                ModelHelper.setModules( displayModel, modules );
199            }
200
201            marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
202
203            if ( commandLine.hasOption( Options.DOCUMENT_ENCODING_OPTION.getOpt() ) )
204            {
205                marshaller.setProperty( Marshaller.JAXB_ENCODING,
206                                        commandLine.getOptionValue( Options.DOCUMENT_ENCODING_OPTION.getOpt() ) );
207
208            }
209
210            if ( commandLine.hasOption( Options.DOCUMENT_OPTION.getOpt() ) )
211            {
212                final File documentFile = new File( commandLine.getOptionValue( Options.DOCUMENT_OPTION.getOpt() ) );
213
214                if ( this.isLoggable( Level.INFO ) )
215                {
216                    this.log( Level.INFO,
217                              Messages.getMessage( "writingResource", documentFile.getAbsolutePath() ),
218                              null );
219
220                }
221
222                marshaller.marshal( new ObjectFactory().createModel( displayModel ), documentFile );
223            }
224            else if ( this.isLoggable( Level.INFO ) )
225            {
226                final StringWriter stringWriter = new StringWriter();
227                marshaller.marshal( new ObjectFactory().createModel( displayModel ), stringWriter );
228                this.log( Level.INFO, stringWriter.toString(), null );
229            }
230
231            classLoader.close();
232            classLoader = null;
233        }
234        catch ( final IOException e )
235        {
236            throw new CommandExecutionException( Messages.getMessage( e ), e );
237        }
238        catch ( final JAXBException e )
239        {
240            String message = Messages.getMessage( e );
241            if ( message == null )
242            {
243                message = Messages.getMessage( e.getLinkedException() );
244            }
245
246            throw new CommandExecutionException( message, e );
247        }
248        catch ( final ModelException e )
249        {
250            throw new CommandExecutionException( Messages.getMessage( e ), e );
251        }
252        finally
253        {
254            try
255            {
256                if ( classLoader != null )
257                {
258                    classLoader.close();
259                }
260            }
261            catch ( final IOException e )
262            {
263                this.log( Level.SEVERE, Messages.getMessage( e ), e );
264            }
265        }
266    }
267
268}