001: /*
002: * Copyright 2006 Werner Guttmann, Ralf Joachim
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.exolab.castor.builder.conflictresolution;
017:
018: import java.util.Enumeration;
019:
020: import org.exolab.castor.builder.SGStateInfo;
021: import org.exolab.castor.builder.binding.XPathHelper;
022: import org.exolab.castor.builder.info.ClassInfo;
023: import org.exolab.castor.util.dialog.ConsoleDialog;
024: import org.exolab.castor.xml.schema.Annotated;
025: import org.exolab.castor.xml.schema.SchemaNames;
026: import org.exolab.javasource.JClass;
027:
028: /**
029: * An implementation of {@link ClassNameCRStrategy} that reports any conflict
030: * notifications to a console dialog, asking the user whether to stop code
031: * generation (as the conflict is not acceptable), or whether to proceed by
032: * overwriting an already existing class.
033: *
034: * @author <a href="mailto:werner DOT guttmann AT gmx DOT net">Werner Guttmann</a>
035: * @since 1.1
036: */
037: public final class WarningViaDialogClassNameCRStrategy extends
038: BaseClassNameCRStrategy implements ClassNameCRStrategy {
039:
040: /**
041: * Name of this strategy.
042: */
043: public static final String NAME = "warnViaConsoleDialog";
044:
045: /**
046: * The {@link ConsoleDialog} instance to use for output.
047: */
048: private ConsoleDialog _dialog;
049:
050: /**
051: * Creates an instance of this name conflict resolution strategy, that will
052: * use the specified {@link ConsoleDialog} instance to emit warnings to the
053: * user and ask about an approach to deal with them.
054: */
055: public WarningViaDialogClassNameCRStrategy() {
056: // Nothing to do.
057: }
058:
059: /**
060: * Handle a class name conflict between newClassInfo and conflict.
061: *
062: * @param state SourceGeneration state
063: * @param newClassInfo ClassInfo for the new class
064: * @param conflict JClass for the existing class
065: * @return the provided source generator state, as modified by the strategy
066: * @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy
067: * #dealWithClassNameConflict(org.exolab.castor.builder.SGStateInfo,
068: * org.exolab.castor.builder.info.ClassInfo,
069: * org.exolab.javasource.JClass)
070: */
071: public SGStateInfo dealWithClassNameConflict(
072: final SGStateInfo state, final ClassInfo newClassInfo,
073: final JClass conflict) {
074: if (!state.getSuppressNonFatalWarnings()) {
075: // -- if the ClassInfo are equal, we can just return
076: ClassInfo oldClassInfo = state.resolve(conflict);
077: if (oldClassInfo == newClassInfo) {
078: return state;
079: }
080:
081: // -- Find the Schema structures that are conflicting
082: Annotated a1 = null;
083: Annotated a2 = null;
084:
085: // Loop until we exhaust the Enumeration or until we have found both
086: Enumeration enumeration = state.keys();
087: while (enumeration.hasMoreElements()
088: && (a1 == null || a2 == null)) {
089: Object key = enumeration.nextElement();
090: if (!(key instanceof Annotated)) {
091: continue;
092: }
093:
094: ClassInfo cInfo = state.resolve(key);
095: if (newClassInfo == cInfo) {
096: a1 = (Annotated) key;
097: } else if (oldClassInfo == cInfo) {
098: a2 = (Annotated) key;
099: }
100: }
101:
102: StringBuffer error = new StringBuffer();
103: error
104: .append("Warning: A class name generation conflict has occured between ");
105: if (a1 != null) {
106: error.append(SchemaNames.getStructureName(a1));
107: error.append(" '");
108: error.append(XPathHelper.getSchemaLocation(a1));
109: } else {
110: error.append(newClassInfo.getNodeTypeName());
111: error.append(" '");
112: error.append(newClassInfo.getNodeName());
113: }
114: error.append("' and ");
115: if (a2 != null) {
116: error.append(SchemaNames.getStructureName(a2));
117: error.append(" '");
118: error.append(XPathHelper.getSchemaLocation(a2));
119: } else {
120: error.append(oldClassInfo.getNodeTypeName());
121: error.append(" '");
122: error.append(oldClassInfo.getNodeName());
123: }
124: error
125: .append("'. Please use a Binding file to solve this problem.");
126: error.append("Continue anyway [not recommended] ");
127:
128: char ch = _dialog.confirm(error.toString(), "yn",
129: "y = yes, n = no");
130: if (ch == 'n') {
131: state.setStatusCode(SGStateInfo.STOP_STATUS);
132: }
133: }
134: return state;
135: }
136:
137: /**
138: * Returns the name of the strategy.
139: * @return the name of the strategy.
140: * @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy#getName()
141: */
142: public String getName() {
143: return NAME;
144: }
145:
146: /**
147: * Sets the console dialog to use with this strategy.
148: *
149: * @param dialog the console dialog to use with this strategy.
150: * @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy#
151: * setConsoleDialog(org.exolab.castor.util.dialog.ConsoleDialog)
152: */
153: public void setConsoleDialog(final ConsoleDialog dialog) {
154: this ._dialog = dialog;
155: }
156:
157: /**
158: * Presents the user with a console dialog, asking for confirmation whether
159: * an existing file should be overwritten (or not).
160: *
161: * @param filename the filename to potentially overwrite.
162: * @return whether or not the file should be overwritten.
163: *
164: * @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy
165: * #dealWithFileOverwrite(java.lang.String, boolean)
166: */
167: public boolean dealWithFileOverwrite(final String filename) {
168: boolean allowPrinting = true;
169:
170: String message = filename + " already exists. overwrite";
171: char ch = _dialog.confirm(message, "yna",
172: "y = yes, n = no, a = all");
173: switch (ch) {
174: case 'a':
175: getSingleClassGenerator().setPromptForOverwrite(false);
176: allowPrinting = true;
177: break;
178: case 'y':
179: allowPrinting = true;
180: break;
181: default:
182: allowPrinting = false;
183: break;
184: }
185: return allowPrinting;
186: }
187:
188: /**
189: * Returns the {@link ConsoleDialog} instance in use.
190: * @return the {@link ConsoleDialog} used for output/feedback gathering.
191: */
192: protected ConsoleDialog getConsoleDialog() {
193: return this._dialog;
194: }
195:
196: }
|