/*----------------------------------------------------------------------------
Copyright (c)2000 TogetherSoft LLC. Patents pending. All rights reserved.
----------------------------------------------------------------------------*/
package com.togethersoft.modules.genidl;
import com.togethersoft.openapi.scriptapi.UML.UMLClassifier;
import com.togethersoft.openapi.scriptapi.UML.UMLAssociation;
import com.togethersoft.openapi.scriptapi.UML.enums.UMLAttributeEnumeration;
import com.togethersoft.openapi.scriptapi.UML.enums.UMLAssociationEnumeration;
import com.togethersoft.modules.genidl.idl.ProcessTags;
/** The filler of struct type entities. structs, unions and exceptions are struct type entities. */
class StructFiller {
/** Modes */
public final static int STRUCT = 1;
public final static int UNION = 2;
public final static int EXCEPTION = 3;
/**
* Constructor.
* @see ScopeProcessor
* @see idl.ProcessTags
* @see IdlTypeConverter
* @see Complainer
*/
public StructFiller(ScopeProcessor scopeProcessor, ProcessTags tagsProcessor, ConfigLoader configLoader,
IdlTypeConverter typeConverter, Complainer complainer) {
myScopeProcessor = scopeProcessor;
myTagsProcessor = tagsProcessor;
myConfigLoader = configLoader;
myComplainer = complainer;
myTypeConverter = typeConverter;
tempTypes = "";
}
/**
* Sets fill mode.
* @param mode one of STRUCT, UNION or EXCEPTION
*/
public void setMode(int mode) {
myMode = mode;
}
public void setClassifier(UMLClassifier classifier) {
myClassifier = classifier;
}
/**
* Set which pass is going on.
* @param isFirst true if this is a first pass, gathering information
*/
public void setPass(boolean istFirst) {
isFirst = istFirst;
}
/** Sets the buffer to put generated declarations into */
public void setBuffer(StringBuffer buffer) {
myBuffer = buffer;
}
/** Sets the buffer to hold module-level typedefs */
public void setModuleBuffer(StringBuffer moduleBuffer) {
myModuleBuffer = moduleBuffer;
}
/**
* Sets base indent level
* @param indent String of spaces which is prepended to all generated code.
*/
public void setIndent(String indent) {
myIndent = indent;
}
/**
* Get locally generated typedef declarations.
* @return StringBuffer containing newly generated typedefs
*/
public StringBuffer getLocalTypedefs() {
return null; //FIXME
}
/** Do-it-all. */
public void process() {
myComplainer.produceInheritanceWarnings(myClassifier, entity());
if (myClassifier.hasProperty(IdlTags.IDLUNIONSELECTOR)) {
mySwitchTypeSpec = myTagsProcessor.getPropertyValue(myClassifier, IdlTags.IDLUNIONSELECTOR);
}
UMLAttributeEnumeration attributes = myClassifier.getAllAttributes();
idlModuleName = myTagsProcessor.getPropertyValue(myClassifier, IdlTags.IDLMODULE);
if (idlModuleName != null && !idlModuleName.equals("")) {
isInsideModule = true;
}
insertEntityHeader(myBuffer);
CaseLabelGenerator labelGenerator = null;
if (myMode == UNION) {
try {
labelGenerator = new CaseLabelGenerator(mySwitchTypeSpec);
}
catch(IllegalArgumentException iae) {
myComplainer.error(entity() + " " + myClassifier.getQualifiedName() + " has invalid switch type, ignored");
return;
}
}
myWrappingClass = getWrappingClass();
if (myWrappingClass != null) {
isNested = true;
myWrappingClassName = myWrappingClass.getQualifiedName();
}
AttributeFiller attributeFiller = new AttributeFiller(myScopeProcessor, myTagsProcessor, myConfigLoader,
myTypeConverter, myComplainer);
attributeFiller.setClassifier(myClassifier);
attributeFiller.setPass(false); // imitate second pass for we need attributes
attributeFiller.setStruct(true);
attributeFiller.setLabelGenerator(labelGenerator);
attributeFiller.setBuffer(myBuffer);
attributeFiller.setModuleBuffer(myModuleBuffer); // FIXME: make sure one day
attributeFiller.setIndent(myIndent);
attributeFiller.process();
myBuffer.insert(0, attributeFiller.getLocalTypedefs());
if (!isNested) {
processStandaloneUnion();
}
else {
processNestedUnion();
}
}
private void processStandaloneUnion() {
if (!isFirst) {
myBuffer.append("};\n");
}
if (!isInsideModule) {
if (isFirst) {
if (myMode == EXCEPTION) {
myScopeProcessor.addTypeFromClass("::" + getEntityName(), getEntityFile()); // "STRUCTS" and so alike
}
else {
myScopeProcessor.addException("::" + getEntityName(), "EXCEPTIONS");
}
return;
}
// FIXME: tempTypes?
myScopeProcessor.checkInnerTypes(tempTypes, "", getEntityFile());
if (!myScopeProcessor.getIncludes().equals("")) {
getGlobalEntityBuffer().insert(0, myScopeProcessor.getIncludes());
}
getGlobalEntityBuffer().append(myBuffer);
}
else {
// handle union inside module
if (isFirst) {
if (myMode == EXCEPTION) {
myScopeProcessor.addException(myScopeProcessor.getDestFQ(myClassifier, false),
myScopeProcessor.getFileName(myClassifier));
}
else {
myScopeProcessor.addTypeFromClass(myScopeProcessor.getDestFQ(myClassifier, false),
myScopeProcessor.getFileName(myClassifier));
}
return;
}
// FIXME: tempTypes ?
myScopeProcessor.checkInnerTypes(tempTypes, myScopeProcessor.getDestFQ(myClassifier, false),
myScopeProcessor.getFileName(myClassifier));
myScopeProcessor.prepareToFillFile();
String fileName = getEntityName();
StringBuffer outBuff = new StringBuffer();
if (myConfigLoader.isUseLongFileNames() && idlModuleName.equals("")) {
String scopeName = myTagsProcessor.processingTag_idlModule(idlModuleName);
myScopeProcessor.setFileName(scopeName + fileName);
}
else {
if (!idlModuleName.equals("")) {
myTagsProcessor.processingTag_idlModule(idlModuleName);
}
}
myScopeProcessor.createIdlFile(myScopeProcessor.getOutputDirectory());
myModuleBuffer = new StringBuffer();
//moduleTypedefs = new String(); FIXME: how come it is not used ever?
if (!idlModuleName.equals("")) {
myScopeProcessor.fillModuleStatements(outBuff, idlModuleName);
}
myModuleBuffer.append(myBuffer);
if (!myScopeProcessor.getIncludes().equals("")) {
outBuff.insert(0, myScopeProcessor.getIncludes());
}
myScopeProcessor.closeModules(myTagsProcessor.getPosition());
myTagsProcessor.resetSettings();
myScopeProcessor.closeIdlFile(myScopeProcessor.getOutputFileWriter(), outBuff, myClassifier,
myScopeProcessor.getFileName());
}
}
private void processNestedUnion() {
if (myMode == EXCEPTION) {
System.err.println("processNestedStruct: adding exception: " + myScopeProcessor.getDestFQ(myWrappingClass, false) +
"::" + getEntityName() + ", " + myScopeProcessor.getFileName(myWrappingClass));
myScopeProcessor.addException(myScopeProcessor.getDestFQ(myWrappingClass, false) + "::" + getEntityName(),
myScopeProcessor.getFileName(myWrappingClass));
}
if (isFirst) {
System.err.println("WRAPPING CLASS = " + myWrappingClass.getName());
myScopeProcessor.addTypeFromClass(myScopeProcessor.getDestFQ(myWrappingClass, false) + "::" + getEntityName(),
myScopeProcessor.getFileName(myWrappingClass));
myBuffer.append("};\n"); // close statements
StringBuffer curValue = myScopeProcessor.getNestedObjectDeclaration(myScopeProcessor.getDestFQ(myWrappingClass,
false));
if (curValue == null) {
curValue = new StringBuffer();
}
if (curValue.equals("")) {
myScopeProcessor.putNestedObjectDeclaration(myScopeProcessor.getDestFQ(myWrappingClass, false), myBuffer);
}
else {
myScopeProcessor.putNestedObjectDeclaration(myScopeProcessor.getDestFQ(myWrappingClass, false),
curValue.append(myBuffer));
}
myScopeProcessor.putNestedObject(myScopeProcessor.getDestFQ(myWrappingClass, false), myClassifier);
}
}
private UMLClassifier getWrappingClass() {
UMLAssociationEnumeration enum = myClassifier.getAssociations();
UMLAssociation assoc;
UMLClassifier wrapperClass = null;
while (enum.hasMoreElements()) {
assoc = enum.getNextUMLAssociation();
if (myTagsProcessor.getPropertyValue(assoc, IdlTags.STEREOTYPE).equals(IdlTags.NESTED)) {
wrapperClass = assoc.getDest();
}
}
return wrapperClass;
}
private String entity() {
switch (myMode) {
case UNION:
return "Union";
case EXCEPTION:
return "Exception";
}
return "Struct";
}
private String getEntityFile() {
switch (myMode) {
case UNION:
return "UNIONS";
case EXCEPTION:
return "EXCEPTIONS";
}
return "STRUCTS";
}
private void insertEntityHeader(StringBuffer buffer) {
String header = "";
switch (myMode) {
case STRUCT:
header = "struct " + getEntityName() + " {\n";
break;
case UNION:
header = "union " + getEntityName() + " switch(" + mySwitchTypeSpec + ") {\n";
break;
case EXCEPTION:
header = "exception " + getEntityName() + " {\n";
break;
}
buffer.append(header);
}
private StringBuffer getGlobalEntityBuffer() {
switch (myMode) {
case UNION:
return myScopeProcessor.getGlobalUnionsBuffer();
case EXCEPTION:
return myScopeProcessor.getGlobalExceptionsBuffer();
}
return myScopeProcessor.getGlobalStructsBuffer();
}
private String getEntityName() {
if (myEntityName == null) {
initEntityName();
}
return myEntityName;
}
private void initEntityName() {
myEntityName = myClassifier.getName();
if (IdlKeywords.isKeyword(myEntityName)) {
myEntityName += "_";
}
}
private ScopeProcessor myScopeProcessor;
private ProcessTags myTagsProcessor;
private ConfigLoader myConfigLoader;
private Complainer myComplainer;
private IdlTypeConverter myTypeConverter;
private UMLClassifier myClassifier;
private boolean isFirst; // Pass no.
private boolean isNested = false; // Validates myWrappingClass
private String myIndent; // Initial indent value
private StringBuffer myBuffer; // fill buffer
private StringBuffer myModuleBuffer; // outside module buffer
private UMLClassifier myWrappingClass; // former "destClass"
private String myWrappingClassName;
private String mySwitchTypeSpec;
private boolean isInsideModule;
private String idlModuleName;
private String tempTypes; // FIXME
/** Entity switch: is this struct, union or exception filler */
private int myMode;
/** Entity name. May differ from classifier name if it matches with a keyword */
private String myEntityName = null;
}
|