1 /*
2 * Copyright 2006 Werner Guttmann
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.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.exolab.castor.builder.SGStateInfo;
23 import org.exolab.castor.builder.binding.XPathHelper;
24 import org.exolab.castor.builder.info.ClassInfo;
25 import org.exolab.castor.builder.info.nature.XMLInfoNature;
26 import org.exolab.castor.util.dialog.ConsoleDialog;
27 import org.exolab.castor.xml.schema.Annotated;
28 import org.exolab.castor.xml.schema.ElementDecl;
29 import org.exolab.castor.xml.schema.SchemaNames;
30 import org.exolab.javasource.JClass;
31
32 /**
33 * An implementation of {@link ClassNameCRStrategy} that
34 * reports any conflict notifications to a log file, basically
35 * stating what classes have been overwriten as a result of such
36 * a name conflict.
37 *
38 * @author <a href="mailto:werner DOT guttmann AT gmx DOT net">Werner Guttmann</a>
39 * @since 1.1
40 */
41 public final class InformViaLogClassNameCRStrategy
42 extends BaseClassNameCRStrategy implements ClassNameCRStrategy {
43
44 /** Logger instance used for logging naming conflicts. */
45 private static final Log LOG = LogFactory.getLog(InformViaLogClassNameCRStrategy.class);
46 /** Name of this strategy. */
47 public static final String NAME = "informViaLog";
48
49 /**
50 * Creates an instance of this name conflict resolution strategy, that will
51 * emit warnings to the user as part of a standard logging aproach.
52 */
53 public InformViaLogClassNameCRStrategy() {
54 // Nothing to do.
55 }
56
57 /**
58 * Handle a class name conflict between newClassInfo and conflict.
59 *
60 * @param state SourceGeneration state
61 * @param newClassInfo ClassInfo for the new class
62 * @param conflict JClass for the existing class
63 * @return the provided source generator state, as modified by the strategy
64 * @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy
65 * #dealWithClassNameConflict(org.exolab.castor.builder.SGStateInfo,
66 * org.exolab.castor.builder.info.ClassInfo,
67 * org.exolab.javasource.JClass)
68 */
69 public SGStateInfo dealWithClassNameConflict(final SGStateInfo state,
70 final ClassInfo newClassInfo, final JClass conflict) {
71 // If the ClassInfo are equal, we can just return
72 ClassInfo oldClassInfo = state.resolve(conflict);
73 if (oldClassInfo == newClassInfo) {
74 return state;
75 }
76
77 // Find the Schema structures that are conflicting
78 Annotated a1 = null;
79 Annotated a2 = null;
80
81 // Loop until we exhaust the Enumeration or until we have found both
82 Enumeration enumeration = state.keys();
83 while (enumeration.hasMoreElements() && (a1 == null || a2 == null)) {
84 Object key = enumeration.nextElement();
85 if (!(key instanceof Annotated)) {
86 continue;
87 }
88
89 ClassInfo cInfo = state.resolve(key);
90 if (newClassInfo == cInfo) {
91 a1 = (Annotated) key;
92 } else if (oldClassInfo == cInfo) {
93 a2 = (Annotated) key;
94 }
95 }
96
97 String annotated1XPath;
98 String annotated2XPath;
99
100 StringBuilder message = new StringBuilder();
101 message.append("Warning: A class name generation conflict has occured between ");
102
103 if (a1 != null) {
104 message.append(SchemaNames.getStructureName(a1));
105 message.append(" '");
106 if (a1 instanceof ElementDecl) {
107 ElementDecl element = (ElementDecl) a1;
108 annotated1XPath = XPathHelper.getSchemaLocation(a1) + "[/complexType:"
109 + element.getType().getName() + "]";
110 message.append(annotated1XPath);
111 } else {
112 message.append(XPathHelper.getSchemaLocation(a1));
113 }
114 } else {
115 if (newClassInfo.hasNature(XMLInfoNature.class.getName())) {
116 XMLInfoNature xmlNature = new XMLInfoNature(newClassInfo);
117 message.append(xmlNature.getNodeTypeName());
118 message.append(" '");
119 message.append(xmlNature.getNodeName());
120 }
121 }
122 message.append("' and ");
123 if (a2 != null) {
124 message.append(SchemaNames.getStructureName(a2));
125 message.append(" '");
126 if (a2 instanceof ElementDecl) {
127 ElementDecl element = (ElementDecl) a2;
128 annotated2XPath = XPathHelper.getSchemaLocation(a2) + "[/complexType:"
129 + element.getType().getName() + "]";
130 message.append(annotated2XPath);
131 } else {
132 message.append(XPathHelper.getSchemaLocation(a2));
133 }
134 } else {
135 if (oldClassInfo.hasNature(XMLInfoNature.class.getName())) {
136 XMLInfoNature xmlNature = new XMLInfoNature(oldClassInfo);
137 message.append(xmlNature.getNodeTypeName());
138 message.append(" '");
139 message.append(xmlNature.getNodeName());
140 }
141 }
142 message.append("'. Please use a Binding file to solve this problem.");
143 LOG.warn(message);
144 return state;
145 }
146
147 /**
148 * Returns the name of the strategy.
149 * @return the name of the strategy.
150 * @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy#getName()
151 */
152 public String getName() {
153 return NAME;
154 }
155
156 /**
157 * Sets the console dialog to use with this strategy.
158 *
159 * @param dialog the console dialog to use with this strategy.
160 * @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy#
161 * setConsoleDialog(org.exolab.castor.util.dialog.ConsoleDialog)
162 */
163 public void setConsoleDialog(final ConsoleDialog dialog) {
164 // No console dialog needed.
165 }
166
167 /**
168 * Presents the user with a console dialog, asking for confirmation whether
169 * an existing file should be overwritten (or not).
170 *
171 * @param filename the filename to potentially overwrite.
172 * @return whether or not the file should be overwritten.
173 *
174 * @see org.exolab.castor.builder.conflictresolution.ClassNameCRStrategy
175 * #dealWithFileOverwrite(java.lang.String, boolean)
176 */
177 public boolean dealWithFileOverwrite(final String filename) {
178 LOG.warn(filename + " already exists, but will be overwritten.");
179 return true;
180 }
181
182 }