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 }