String beginString = "// @@@begin ";
String endString = "// @@@end ";
String beginNameString = beginString + entityName;
String endNameString = endString + entityName;
ModuleSourceDefinition sourceDefinition = getSourceDefinition(moduleName);
if (sourceDefinition == null) {
return false;
}
Reader sourceReader = sourceDefinition.getSourceReader(null);
if (sourceReader == null) {
String message = "Couldn't read definition for \"" + entityName + "\".";
saveStatus.add(new Status(Status.Severity.ERROR, message));
return false;
}
BufferedReader bufferedReader = new BufferedReader(sourceReader);
try {
// The new file text..
StringBuilder newFileTextBuilder = new StringBuilder();
if (!scExists) {
// The gem does not exist. Simply append its text to the end of the file.
try {
// Add all the file text
for (String lineString = bufferedReader.readLine(); lineString != null; lineString = bufferedReader.readLine()) {
newFileTextBuilder.append(lineString + "\n");
}
} catch (IOException ioe) {
String message = "Couldn't read definition for \"" + entityName + "\".";
saveStatus.add(new Status(Status.Severity.ERROR, message, ioe));
return false;
}
// Add the gem definition.
newFileTextBuilder.append(getDefinition(definitionText, beginNameString, endNameString));
} else {
// The gem exists. Attempt to replace its text in the file.
// Read in all the file text
List<String> fileText = new ArrayList<String>();
int beginIndex = -1;
int endIndex = -1;
boolean shouldEatOneMoreLine = false;
try {
for (String lineString = bufferedReader.readLine(); lineString != null; lineString = bufferedReader.readLine()) {
// Add the text to the List
fileText.add(lineString);
int lineIndex = fileText.size() - 1; // ArrayList size is a (faster) variable lookup
// Keep track of where to replace the gem text
if (beginIndex < 0){
if (lineString.startsWith(beginNameString)) {
// Make sure that we didn't find part of another name
// Grab the part of the line string that starts with the gem name
String endLineString = lineString.substring(beginString.length());
// the first token should be the gem's name
StringTokenizer tokenizer = new StringTokenizer(endLineString);
if (tokenizer.hasMoreElements() && tokenizer.nextToken().equals(entityName.getQualifiedName())) {
beginIndex = lineIndex;
}
}
} else if (endIndex < 0) {
if (lineString.startsWith(endNameString)) {
// Make sure that we didn't find part of another name
// Grab the part of the line string that starts with the gem name
String endLineString = lineString.substring(endString.length());
// the first token should be the gem's name
StringTokenizer tokenizer = new StringTokenizer(endLineString);
if (tokenizer.hasMoreElements() && tokenizer.nextToken().equals(entityName.getQualifiedName())) {
endIndex = lineIndex;
}
}
}
// See if the line following the line with the end marker is blank.
if (endIndex >= 0 && lineIndex == endIndex + 1) {
// Convert to a char array
char[] charArray = lineString.toCharArray();
// Now check each character (if any) to see if they're whitespace
boolean isBlank = true;
for (int i = 0; i < charArray.length; i++) {
if (!Character.isWhitespace(charArray[i])) {
isBlank = false;
break;
}
}
shouldEatOneMoreLine = isBlank;
}
}
} catch (IOException ioe) {
String message = "Couldn't read definition for \"" + entityName + "\".";
saveStatus.add(new Status(Status.Severity.ERROR, message, ioe));
return false;
}
// Replace the line following the line with the end marker, if appropriate
if (shouldEatOneMoreLine) {
endIndex++;
}
if (beginIndex < 0 || endIndex < 0) {
// couldn't find where to replace the lines..
// the finally clause should take care of closing everything
String markersString;
if (beginIndex < 0 && endIndex < 0) {
markersString = "begin or end";
} else if (beginIndex < 0) {
markersString = "begin";
} else {
markersString = "end";
}
String message = "Couldn't find " + markersString + " marker for \"" + entityName + "\".";
saveStatus.add(new Status(Status.Severity.ERROR, message, null));
return false;
}
//
// Add all the file text
//
List<String> beforeText = fileText.subList(0, beginIndex);
List<String> afterText = fileText.subList(endIndex + 1, fileText.size());
// Add text appearing before the gem definition
for (final String writeString : beforeText) {
newFileTextBuilder.append(writeString + "\n");
}
// Add the gem definition
newFileTextBuilder.append(getDefinition(definitionText, beginNameString, endNameString));
// Add text appearing after the gem definition
for (final String writeString : afterText) {
newFileTextBuilder.append(writeString + "\n");
}
}
// Convert to a moduleSource.
final String newFileTextString = newFileTextBuilder.toString();
ModuleSourceDefinition sourceToSave = new StringModuleSourceDefinition(moduleName, newFileTextString);
// Save..
return saveSource(sourceToSave, saveStatus);
} finally {