/*
* Copyright 2005 Werner Guttmann
*
* 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.factory;
import java.util.Enumeration;
import org.castor.xml.JavaNaming;
import org.exolab.castor.builder.BuilderConfiguration;
import org.exolab.castor.builder.GroupNaming;
import org.exolab.castor.builder.SourceGenerator;
import org.exolab.castor.xml.schema.Annotated;
import org.exolab.castor.xml.schema.Annotation;
import org.exolab.castor.xml.schema.AttributeDecl;
import org.exolab.castor.xml.schema.Documentation;
import org.exolab.castor.xml.schema.ElementDecl;
import org.exolab.castor.xml.schema.Structure;
/**
* This class defines a base type for the source generator code factory classes.
*
* @author <a href="mailto:werner DOT guttmann AT gmx DOT net">Werner Guttmann</a>
* @version $Revision: 6287 $ $Date: $
*/
public class BaseFactory {
/** The BuilderConfiguration instance, for callbacks to obtain certain
* configured properties. */
private final BuilderConfiguration _config;
/** The type factory. */
private final FieldInfoFactory _infoFactory;
/** A GroupNaming helper class used to named anonymous groups. */
private GroupNaming _groupNaming = null;
/**
* The calling instance of {@link SourceGenerator}.
*/
private SourceGenerator _sourceGenerator;
/**
* Creates an instance of this class.
* @param config XML code generator configuration
* @param infoFactory the FieldInfoFactory to use
* @param groupNaming Group naming scheme to be used.
* @param sourceGenerator The calling source generator.
*/
public BaseFactory(final BuilderConfiguration config,
final FieldInfoFactory infoFactory,
final GroupNaming groupNaming,
final SourceGenerator sourceGenerator) {
if (config == null) {
String err = "The 'BuilderConfiguration' argument must not be null.";
throw new IllegalArgumentException(err);
}
_config = config;
if (infoFactory == null) {
this._infoFactory = new FieldInfoFactory();
} else {
this._infoFactory = infoFactory;
}
_groupNaming = groupNaming;
_sourceGenerator = sourceGenerator;
}
/**
* Get BuilderConfiguration instance, for callbacks to obtain certain configured properties.
*
* @return BuilderConfiguration instance.
*/
protected final BuilderConfiguration getConfig() {
return _config;
}
/**
* Get type factory.
*
* @return Type factory.
*/
protected final FieldInfoFactory getInfoFactory() {
return _infoFactory;
}
/**
* Normalizes the given string for use in comments.
*
* @param value
* the String to normalize
* @return the given string, normalized, for use in comments.
*/
protected final String normalize(final String value) {
if (value == null) {
return null;
}
char[] chars = value.toCharArray();
char[] newChars = new char[chars.length * 2];
int count = 0;
int i = 0;
boolean skip = false;
while (i < chars.length) {
char ch = chars[i++];
if ((ch == ' ') || (ch == '\t')) {
if ((!skip) && (count != 0)) {
newChars[count++] = ' ';
}
skip = true;
} else if (ch == '*') {
if (i < chars.length && chars[i] == '/') {
newChars[count++] = ch;
newChars[count++] = '\\';
}
} else {
if (count == 0) {
//-- ignore new lines only if count == 0
if ((ch == '\r') || (ch == '\n')) {
continue;
}
}
newChars[count++] = ch;
skip = false;
}
}
return new String(newChars, 0, count);
}
/**
* Returns the group naming helper class for naming nested anonymous groups.
*
* @return the group naming helper class for naming nested anonymous groups.
*/
public final GroupNaming getGroupNaming() {
return _groupNaming;
}
/**
* Sets the group naming helper class for naming nested anonymous groups.
* @param groupNaming the group naming helper class for naming nested anonymous groups.
*/
public final void setGroupNaming(final GroupNaming groupNaming) {
_groupNaming = groupNaming;
}
/**
* Returns the calling {@link SourceGenerator} instance.
* @return the calling source generator
*/
protected SourceGenerator getSourceGenerator() {
return _sourceGenerator;
}
/**
* Creates and returns a Javadoc comment from the given annotations.
* @param annotated The {@link Annotated} instance holding annotations.
* @return The Javadoc comment created from the annotations.
*/
protected String createComment(final Annotated annotated) {
//-- process annotations
Enumeration<Annotation> enumeration = annotated.getAnnotations();
if (enumeration.hasMoreElements()) {
//-- just use first annotation
return createComment(enumeration.nextElement());
}
//-- there were no annotations...try possible references
switch(annotated.getStructureType()) {
case Structure.ELEMENT:
ElementDecl elem = (ElementDecl) annotated;
if (elem.isReference()) {
return createComment(elem.getReference());
}
break;
case Structure.ATTRIBUTE:
AttributeDecl att = (AttributeDecl) annotated;
if (att.isReference()) {
return createComment(att.getReference());
}
break;
default:
break;
}
return null;
} //-- createComment
/**
* Creates and returns a Javadoc comment from a given {@link Annotation}.
* @param annotation The {@link Annotation} instance to be used for comment creation.
* @return The Javdoc comment assembled from the AnnotationItem instance
*/
private String createComment(final Annotation annotation) {
if (annotation == null) {
return null;
}
Enumeration<Documentation> enumeration = annotation.getDocumentation();
if (enumeration.hasMoreElements()) {
//-- just use first <info>
Documentation documentation = enumeration.nextElement();
return normalize(documentation.getContent());
}
return null;
}
/**
* Creates Comments from Schema annotations.
* @param annotated the Annotated structure to process
* @return the generated comment.
*
*/
// TODO: refactor to avoid duplication with createComment() methods
protected String extractCommentsFromAnnotations(final Annotated annotated) {
//-- process annotations
Enumeration<Annotation> enumeration = annotated.getAnnotations();
if (enumeration.hasMoreElements()) {
StringBuilder comment = new StringBuilder();
while (enumeration.hasMoreElements()) {
Annotation ann = enumeration.nextElement();
Enumeration<Documentation> documentations = ann.getDocumentation();
while (documentations.hasMoreElements()) {
Documentation documentation = documentations.nextElement();
String content = documentation.getContent();
if (content != null) {
comment.append(content);
}
}
}
return normalize(comment.toString());
}
return null;
}
/**
* To get the {@link JavaNaming} to be used.
* @return {@link JavaNaming} instance to be used
* @since 1.1.3
*/
public final JavaNaming getJavaNaming() {
return _config.getJavaNaming();
}
}