/*
* Copyright 2006 Werner Guttmann, Ralf Joachim
*
* 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.
*/
package org.exolab.castor.builder.conflictresolution;
import java.util.Enumeration;
import org.exolab.castor.builder.SGStateInfo;
import org.exolab.castor.builder.binding.XPathHelper;
import org.exolab.castor.builder.info.ClassInfo;
import org.exolab.castor.builder.info.nature.XMLInfoNature;
import org.exolab.castor.util.dialog.ConsoleDialog;
import org.exolab.castor.xml.schema.Annotated;
import org.exolab.castor.xml.schema.SchemaNames;
import org.exolab.javasource.JClass;
/**
* An implementation of {@link ClassNameCRStrategy} that reports any conflict
* notifications to a console dialog, asking the user whether to stop code
* generation (as the conflict is not acceptable), or whether to proceed by
* overwriting an already existing class.
*
* @author <a href="mailto:werner DOT guttmann AT gmx DOT net">Werner Guttmann</a>
* @since 1.1
*/
public final class WarningViaDialogClassNameCRStrategy
extends BaseClassNameCRStrategy implements ClassNameCRStrategy {
/**
* Name of this strategy.
*/
public static final String NAME = "warnViaConsoleDialog";
/**
* The {@link ConsoleDialog} instance to use for output.
*/
private ConsoleDialog _dialog;
/**
* Creates an instance of this name conflict resolution strategy, that will
* use the specified {@link ConsoleDialog} instance to emit warnings to the
* user and ask about an approach to deal with them.
*/
public WarningViaDialogClassNameCRStrategy() {
// Nothing to do.
}
/**
* Handle a class name conflict between newClassInfo and conflict.
*
* @param state SourceGeneration state
* @param newClassInfo ClassInfo for the new class
* @param conflict JClass for the existing class
* @return the provided source generator state, as modified by the strategy
* @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy
* #dealWithClassNameConflict(org.exolab.castor.builder.SGStateInfo,
* org.exolab.castor.builder.info.ClassInfo,
* org.exolab.javasource.JClass)
*/
public SGStateInfo dealWithClassNameConflict(final SGStateInfo state,
final ClassInfo newClassInfo, final JClass conflict) {
if (!state.getSuppressNonFatalWarnings()) {
// -- if the ClassInfo are equal, we can just return
ClassInfo oldClassInfo = state.resolve(conflict);
if (oldClassInfo == newClassInfo) {
return state;
}
// -- Find the Schema structures that are conflicting
Annotated a1 = null;
Annotated a2 = null;
// Loop until we exhaust the Enumeration or until we have found both
Enumeration enumeration = state.keys();
while (enumeration.hasMoreElements() && (a1 == null || a2 == null)) {
Object key = enumeration.nextElement();
if (!(key instanceof Annotated)) {
continue;
}
ClassInfo cInfo = state.resolve(key);
if (newClassInfo == cInfo) {
a1 = (Annotated) key;
} else if (oldClassInfo == cInfo) {
a2 = (Annotated) key;
}
}
StringBuilder error = new StringBuilder(64);
error.append("Warning: A class name generation conflict has occured between ");
if (a1 != null) {
error.append(SchemaNames.getStructureName(a1));
error.append(" '");
error.append(XPathHelper.getSchemaLocation(a1));
} else {
if (newClassInfo.hasNature(XMLInfoNature.class.getName())) {
XMLInfoNature xmlNature = new XMLInfoNature(newClassInfo);
error.append(xmlNature.getNodeTypeName());
error.append(" '");
error.append(xmlNature.getNodeName());
}
}
error.append("' and ");
if (a2 != null) {
error.append(SchemaNames.getStructureName(a2));
error.append(" '");
error.append(XPathHelper.getSchemaLocation(a2));
} else {
if (oldClassInfo.hasNature(XMLInfoNature.class.getName())) {
XMLInfoNature xmlNature = new XMLInfoNature(oldClassInfo);
error.append(xmlNature.getNodeTypeName());
error.append(" '");
error.append(xmlNature.getNodeName());
}
}
error.append("'. Please use a Binding file to solve this problem.");
error.append("Continue anyway [not recommended] ");
char ch = _dialog
.confirm(error.toString(), "yn", "y = yes, n = no");
if (ch == 'n') {
state.setStatusCode(SGStateInfo.STOP_STATUS);
}
}
return state;
}
/**
* Returns the name of the strategy.
* @return the name of the strategy.
* @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy#getName()
*/
public String getName() {
return NAME;
}
/**
* Sets the console dialog to use with this strategy.
*
* @param dialog the console dialog to use with this strategy.
* @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy#
* setConsoleDialog(org.exolab.castor.util.dialog.ConsoleDialog)
*/
public void setConsoleDialog(final ConsoleDialog dialog) {
this._dialog = dialog;
}
/**
* Presents the user with a console dialog, asking for confirmation whether
* an existing file should be overwritten (or not).
*
* @param filename the filename to potentially overwrite.
* @return whether or not the file should be overwritten.
*
* @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy
* #dealWithFileOverwrite(java.lang.String, boolean)
*/
public boolean dealWithFileOverwrite(final String filename) {
boolean allowPrinting = true;
String message = filename + " already exists. overwrite";
char ch = _dialog.confirm(message, "yna", "y = yes, n = no, a = all");
switch (ch) {
case 'a':
getSingleClassGenerator().setPromptForOverwrite(false);
allowPrinting = true;
break;
case 'y':
allowPrinting = true;
break;
default:
allowPrinting = false;
break;
}
return allowPrinting;
}
/**
* Returns the {@link ConsoleDialog} instance in use.
* @return the {@link ConsoleDialog} used for output/feedback gathering.
*/
protected ConsoleDialog getConsoleDialog() {
return this._dialog;
}
}