/*******************************************************************************
* Copyright © 2011, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.edt.ide.ui.internal.record.conversion;
import java.util.ResourceBundle;
import org.eclipse.edt.compiler.internal.core.builder.DefaultProblemRequestor;
import org.eclipse.edt.compiler.internal.core.builder.IMarker;
import org.eclipse.edt.compiler.internal.core.builder.IProblemRequestor;
import org.eclipse.edt.compiler.internal.core.lookup.DefaultCompilerOptions;
import org.eclipse.edt.compiler.internal.core.validation.name.EGLNameValidator;
import org.eclipse.edt.ide.ui.internal.record.NewRecordWizardMessages;
import org.eclipse.edt.ide.ui.templates.parts.Field;
import org.eclipse.edt.ide.ui.templates.parts.Part;
import org.eclipse.edt.ide.ui.templates.parts.Record;
public abstract class PartsUtil {
static java.util.Map<String,String> _reservedConversionNames = new java.util.HashMap<String,String>();
static {
_reservedConversionNames.put("egl_value", "egl_value");//$NON-NLS-1$
}
static final String subChar = "";
private java.util.HashMap<String,String> _partNames = new java.util.HashMap<String,String>();
private int _aliasNumber = 0;
protected IMessageHandler _msgHandler = null;
protected PartsUtil( IMessageHandler msgHandler ) {
_msgHandler = msgHandler;
}
private class NameValidatorProblemRequestor extends DefaultProblemRequestor
{
int _problemKind = 0;
int _severity = 0;
String[] _inserts = new String[0];
ResourceBundle _bundle;
public NameValidatorProblemRequestor(){
}
@Override
public void acceptProblem(int startOffset, int endOffset, int severity, int problemKind, String[] inserts, ResourceBundle bundle) {
_bundle = bundle;
if (_problemKind ==0) {
_inserts = shiftInsertsIfNeccesary(problemKind, inserts);
_problemKind = problemKind;
_severity = severity;
}
if (_severity > IMarker.SEVERITY_WARNING) {
throw (new RuntimeException(getMessageFromBundle(problemKind, inserts, bundle)));
}
}
public int getProblemKind()
{
return _problemKind;
}
public void setProblemKind( int problemKind)
{
_problemKind = problemKind;
}
public String[] getInserts()
{
return _inserts;
}
public ResourceBundle getBundle()
{
return _bundle;
}
}
private String getName(String str, DefaultProblemRequestor problemRequestor) {
EGLNameValidator.validate(str, EGLNameValidator.PART, problemRequestor, DefaultCompilerOptions.getInstance());
return str;
}
public String getTypeName(String str) {
NameValidatorProblemRequestor problemRequestor = new NameValidatorProblemRequestor();
String name = fixName(str, null); // replace invalid characters with subChar
boolean isValidName = false;
while (!isValidName) {
try {
name = getName(name, problemRequestor);
isValidName = true;
}
catch (RuntimeException ex) {
if (problemRequestor.getProblemKind() == IProblemRequestor.RESERVED_WORD_NOT_ALLOWED) {
String newName = name + subChar + (++_aliasNumber);
_msgHandler.addMessage(NewRecordWizardMessages.bind(NewRecordWizardMessages.PartsUtil_reservedWordRenameMessage,new String[] {name, getFinalType(newName)}));
name = newName;
problemRequestor.setProblemKind(0);
} else {
throw (new RuntimeException(DefaultProblemRequestor.getMessageFromBundle(problemRequestor.getProblemKind(), problemRequestor.getInserts(), problemRequestor.getBundle())));
}
}
if (problemRequestor.getProblemKind() != 0) {
throw (new RuntimeException(DefaultProblemRequestor.getMessageFromBundle(problemRequestor.getProblemKind(), problemRequestor.getInserts(), problemRequestor.getBundle())));
}
}
return getFinalType(name);
}
protected void mergeRecords( Record oldrec, Record newrec ) {
// add fields from oldrec to new rec marking the fields as nullable
Field[] oldFields = oldrec.getFields();
for (int i=0; i<oldFields.length; i++) {
Field newField = newrec.getField(oldFields[i].getName());
if (newField == null) {
if (!oldFields[i].getType().isNullable() && !oldFields[i].getType().isReferenceType())
_msgHandler.addMessage(NewRecordWizardMessages.bind(NewRecordWizardMessages.PartsUtil_definedAsNullableMessage,new String[] {newrec.getName(), oldFields[i].getName()}));
oldFields[i].getType().setNullable(true);
newrec.addField(oldFields[i]);
}
else // propagate the old nullable setting to the new record field
newField.getType().setNullable(oldFields[i].getType().isNullable());
}
// set nullable new record fields that are missing from the old record
Field[] newFields = newrec.getFields();
for (int i=0; i<newFields.length; i++) {
if (oldrec.getField(newFields[i].getName()) == null) {
if (!newFields[i].getType().isNullable() && !newFields[i].getType().isReferenceType())
_msgHandler.addMessage(NewRecordWizardMessages.bind(NewRecordWizardMessages.PartsUtil_definedAsNullableMessage,new String[] {newrec.getName(), newFields[i].getName()}));
newFields[i].getType().setNullable(true);
}
}
}
public abstract Part[] process(Object node, Record wrapRec);
private boolean isNameCollision( String name, boolean isOriginalName, java.util.HashMap<String,String> fieldNames )
{
boolean isCollision = false;
// if (name has changed and the new name is the same as another field in the record
// or the name collides with another name already processed
// or the name collides with a reserved conversion name
isCollision = ((!isOriginalName && fieldNames.containsKey(name.toLowerCase())) ||
_partNames.containsKey(getFinalName(name).toLowerCase()) ||
_reservedConversionNames.containsKey(getFinalName(name).toLowerCase()));
return isCollision;
}
protected String getFieldName(String str, String recordName, java.util.HashMap<String,String> fieldNames )
{
NameValidatorProblemRequestor problemRequestor = new NameValidatorProblemRequestor();
String name = fixName(str, recordName); // replace invalid characters with subChar
boolean isValidName = false;
while (!isValidName)
{
try
{
if (isNameCollision(name, name.equals(str), fieldNames))
{
String newName = name + subChar + (++_aliasNumber);
_msgHandler.addMessage(NewRecordWizardMessages.bind(NewRecordWizardMessages.PartsUtil_renameFieldInUseMessage,new String[] {name, getFinalName(newName), recordName}));
name = newName;
}
name = getName(name, problemRequestor);
isValidName = true;
}
catch (RuntimeException ex)
{
if (problemRequestor.getProblemKind() == IProblemRequestor.RESERVED_WORD_NOT_ALLOWED)
{
String newName = name + subChar + (++_aliasNumber);
_msgHandler.addMessage(NewRecordWizardMessages.bind(NewRecordWizardMessages.PartsUtil_reservedWordRename2Message,new String[] {name, getFinalName(newName), recordName}));
name = newName;
problemRequestor.setProblemKind(0);
}
else
{
throw (new RuntimeException(DefaultProblemRequestor.getMessageFromBundle(problemRequestor.getProblemKind(), problemRequestor.getInserts(), problemRequestor.getBundle())));
}
}
if (problemRequestor.getProblemKind() != 0)
{
throw (new RuntimeException(DefaultProblemRequestor.getMessageFromBundle(problemRequestor.getProblemKind(), problemRequestor.getInserts(), problemRequestor.getBundle())));
}
}
name = getFinalName(name);
_partNames.put(name.toLowerCase(), name);
return name;
}
private String getFinalName(String name) {
if (name.equals(name.toUpperCase())) { // if all uppercase
return name.toLowerCase(); // lowercase the whole thing
}
// for mixed case or all lowercase, lowercase the first letter.
return name.substring(0, 1).toLowerCase() + name.substring(1);
}
private String getFinalType(String name)
{
if (!name.equals(name.toUpperCase()))
name = name.substring(0, 1).toUpperCase() + name.substring(1);
return name;
}
private String fixName(String name, String recordName) {
boolean isVAGCompatibility = false; //EGLVAGCompatibilitySetting.isVAGCompatibility();
StringBuffer eName = new StringBuffer(name);
// more special characters are allowed if VAGCompatibility is enabled
if (!isVAGCompatibility) {
if (!Character.isJavaIdentifierStart(eName.charAt(0))) {
// '$' and '_' are already allowed by isJavaIdentifierStart
eName.replace(1, 2, eName.substring(1, 2).toUpperCase());
eName.replace(0, 1, subChar);
}
for (int i = 1; i < eName.length(); i++) {
if (!Character.isJavaIdentifierPart(eName.charAt(i))) {
// '$' and '_' are already allowed by isJavaIdentifierPart
eName.replace(i+1, i + 2, eName.substring(i+1, i+2).toUpperCase());
eName.replace(i, i + 1, subChar);
i--; // backup and reprocess this character
}
}
} else { // in VAGCompatibility mode
if (!Character.isJavaIdentifierStart(eName.charAt(0))) {
// '$' and '_' are already allowed by isJavaIdentifierStart
eName.replace(1, 2, eName.substring(1, 2).toUpperCase());
eName.replace(0, 1, subChar);
}
for (int i = 1; i < eName.length(); i++) {
if (!Character.isJavaIdentifierPart(eName.charAt(i))) {
// '$' and '_' are already allowed by isJavaIdentifierPart
if (eName.charAt(i) != '-' && eName.charAt(i) != '@'
&& eName.charAt(i) != '#' && eName.charAt(i) != ' ') {
eName.replace(i+1, i + 2, eName.substring(i+1, i+2).toUpperCase());
eName.replace(i, i + 1, subChar);
i--; // reprocess that character
}
}
}
}
String newName = eName.toString();
if (!name.equalsIgnoreCase(newName))
{
_msgHandler.addMessage(NewRecordWizardMessages.bind(NewRecordWizardMessages.PartsUtil_invalidCharactersRenameMessage,new String[] {name, getFinalName(newName), ((recordName==null)?"":NewRecordWizardMessages.bind(NewRecordWizardMessages.PartsUtil_invalidCharactersRename2Message,new String[] {recordName}))}));
}
return newName;
}
}