View Javadoc
1   /*
2    * Copyright 2006 Werner Guttmann, Ralf Joachim
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.exolab.castor.builder.conflictresolution;
17  
18  import java.util.Enumeration;
19  
20  import org.exolab.castor.builder.SGStateInfo;
21  import org.exolab.castor.builder.binding.XPathHelper;
22  import org.exolab.castor.builder.info.ClassInfo;
23  import org.exolab.castor.builder.info.nature.XMLInfoNature;
24  import org.exolab.castor.util.dialog.ConsoleDialog;
25  import org.exolab.castor.xml.schema.Annotated;
26  import org.exolab.castor.xml.schema.SchemaNames;
27  import org.exolab.javasource.JClass;
28  
29  /**
30   * An implementation of {@link ClassNameCRStrategy} that reports any conflict
31   * notifications to a console dialog, asking the user whether to stop code
32   * generation (as the conflict is not acceptable), or whether to proceed by
33   * overwriting an already existing class.
34   *
35   * @author <a href="mailto:werner DOT guttmann AT gmx DOT net">Werner Guttmann</a>
36   * @since 1.1
37   */
38  public final class WarningViaDialogClassNameCRStrategy
39  extends BaseClassNameCRStrategy implements ClassNameCRStrategy {
40  
41      /**
42       * Name of this strategy.
43       */
44      public static final String NAME = "warnViaConsoleDialog";
45  
46      /**
47       * The {@link ConsoleDialog} instance to use for output.
48       */
49      private ConsoleDialog _dialog;
50  
51      /**
52       * Creates an instance of this name conflict resolution strategy, that will
53       * use the specified {@link ConsoleDialog} instance to emit warnings to the
54       * user and ask about an approach to deal with them.
55       */
56      public WarningViaDialogClassNameCRStrategy() {
57          // Nothing to do.
58      }
59  
60      /**
61       * Handle a class name conflict between newClassInfo and conflict.
62       *
63       * @param state SourceGeneration state
64       * @param newClassInfo ClassInfo for the new class
65       * @param conflict JClass for the existing class
66       * @return the provided source generator state, as modified by the strategy
67       * @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy
68       *      #dealWithClassNameConflict(org.exolab.castor.builder.SGStateInfo,
69       *      org.exolab.castor.builder.info.ClassInfo,
70       *      org.exolab.javasource.JClass)
71       */
72      public SGStateInfo dealWithClassNameConflict(final SGStateInfo state,
73              final ClassInfo newClassInfo, final JClass conflict) {
74          if (!state.getSuppressNonFatalWarnings()) {
75              // -- if the ClassInfo are equal, we can just return
76              ClassInfo oldClassInfo = state.resolve(conflict);
77              if (oldClassInfo == newClassInfo) {
78                  return state;
79              }
80  
81              // -- Find the Schema structures that are conflicting
82              Annotated a1 = null;
83              Annotated a2 = null;
84  
85              // Loop until we exhaust the Enumeration or until we have found both
86              Enumeration enumeration = state.keys();
87              while (enumeration.hasMoreElements() && (a1 == null || a2 == null)) {
88                  Object key = enumeration.nextElement();
89                  if (!(key instanceof Annotated)) {
90                      continue;
91                  }
92  
93                  ClassInfo cInfo = state.resolve(key);
94                  if (newClassInfo == cInfo) {
95                      a1 = (Annotated) key;
96                  } else if (oldClassInfo == cInfo) {
97                      a2 = (Annotated) key;
98                  }
99              }
100 
101             StringBuilder error = new StringBuilder(64);
102             error.append("Warning: A class name generation conflict has occured between ");
103             if (a1 != null) {
104                 error.append(SchemaNames.getStructureName(a1));
105                 error.append(" '");
106                 error.append(XPathHelper.getSchemaLocation(a1));
107             } else {
108                 if (newClassInfo.hasNature(XMLInfoNature.class.getName())) {
109                     XMLInfoNature xmlNature = new XMLInfoNature(newClassInfo);
110                     error.append(xmlNature.getNodeTypeName());
111                     error.append(" '");
112                     error.append(xmlNature.getNodeName());
113                 }
114             }
115             error.append("' and ");
116             if (a2 != null) {
117                 error.append(SchemaNames.getStructureName(a2));
118                 error.append(" '");
119                 error.append(XPathHelper.getSchemaLocation(a2));
120             } else {
121                 if (oldClassInfo.hasNature(XMLInfoNature.class.getName())) {
122                     XMLInfoNature xmlNature = new XMLInfoNature(oldClassInfo);
123                     error.append(xmlNature.getNodeTypeName());
124                     error.append(" '");
125                     error.append(xmlNature.getNodeName());
126                 }
127             }
128             error.append("'. Please use a Binding file to solve this problem.");
129             error.append("Continue anyway [not recommended] ");
130 
131             char ch = _dialog
132                     .confirm(error.toString(), "yn", "y = yes, n = no");
133             if (ch == 'n') {
134                 state.setStatusCode(SGStateInfo.STOP_STATUS);
135             }
136         }
137         return state;
138     }
139 
140     /**
141      * Returns the name of the strategy.
142      * @return the name of the strategy.
143      * @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy#getName()
144      */
145     public String getName() {
146         return NAME;
147     }
148 
149     /**
150      * Sets the console dialog to use with this strategy.
151      *
152      * @param dialog the console dialog to use with this strategy.
153      * @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy#
154      *      setConsoleDialog(org.exolab.castor.util.dialog.ConsoleDialog)
155      */
156     public void setConsoleDialog(final ConsoleDialog dialog) {
157         this._dialog = dialog;
158     }
159 
160     /**
161      * Presents the user with a console dialog, asking for confirmation whether
162      * an existing file should be overwritten (or not).
163      *
164      * @param filename the filename to potentially overwrite.
165      * @return whether or not the file should be overwritten.
166      *
167      * @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy
168      *      #dealWithFileOverwrite(java.lang.String, boolean)
169      */
170     public boolean dealWithFileOverwrite(final String filename) {
171         boolean allowPrinting = true;
172 
173         String message = filename + " already exists. overwrite";
174         char ch = _dialog.confirm(message, "yna", "y = yes, n = no, a = all");
175         switch (ch) {
176             case 'a':
177                 getSingleClassGenerator().setPromptForOverwrite(false);
178                 allowPrinting = true;
179                 break;
180             case 'y':
181                 allowPrinting = true;
182                 break;
183             default:
184                 allowPrinting = false;
185                 break;
186         }
187         return allowPrinting;
188     }
189 
190     /**
191      * Returns the {@link ConsoleDialog} instance in use.
192      * @return the {@link ConsoleDialog} used for output/feedback gathering.
193      */
194     protected ConsoleDialog getConsoleDialog() {
195         return this._dialog;
196     }
197 
198 }