/******************************************************************************* * Copyright (c) 2013, 2014 CEA LIST 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: * E.D.Willink(CEA LIST) - Initial API and implementation *******************************************************************************/ package org.eclipse.ocl.examples.codegen.common; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.ocl.pivot.Constraint; import org.eclipse.ocl.pivot.Element; import org.eclipse.ocl.pivot.Operation; import org.eclipse.ocl.pivot.Property; import org.eclipse.ocl.pivot.TupleLiteralPart; import org.eclipse.ocl.pivot.TupleType; import org.eclipse.ocl.pivot.Type; import org.eclipse.ocl.pivot.Variable; public class NameQueries { public static abstract class NameAllocation<T> { private Map<T, String> mappings = new HashMap<T, String>(); private Set<String> used = new HashSet<String>(); protected abstract String computeUniqueText(T string); public String get(T string) { String uniqueString = mappings.get(string); if (uniqueString == null) { uniqueString = computeUniqueText(string); used.add(uniqueString); mappings.put(string, uniqueString); } return uniqueString; } protected boolean isUsed(String string) { return used.contains(string); } } public static class TuplePartAllocation { private Map<String, Map<Type, String>> mappings = new HashMap<String, Map<Type, String>>(); private Set<String> used = new HashSet<String>(); protected String computeUniqueText(String partName, Type partType) { StringBuilder s = new StringBuilder(); appendJavaCharacters(s, partName); s.append('_'); appendJavaCharacters(s, String.valueOf(partType)); if (isUsed(s.toString())) { for (int i = 1; true; i++) { if (!isUsed(s.toString() + '_' + Integer.toString(i))) { s.append(i); break; } } } return s.toString(); } public String get(String partName, Type partType) { Map<Type, String> typeMaps = mappings.get(partName); if (typeMaps == null) { typeMaps = new HashMap<Type, String>(); mappings.put(partName, typeMaps); } String uniqueString = typeMaps.get(partType); if (uniqueString == null) { uniqueString = computeUniqueText(partName, partType); used.add(uniqueString); typeMaps.put(partType, uniqueString); } return uniqueString; } protected boolean isUsed(String string) { return used.contains(string); } } private static Map<Element, NameAllocation<Constraint>> uniqueConstraints = new HashMap<Element, NameAllocation<Constraint>>(); private static Map<Element, NameAllocation<Operation>> uniqueOperations = new HashMap<Element, NameAllocation<Operation>>(); private static Map<Element, NameAllocation<org.eclipse.ocl.pivot.Package>> uniquePackages = new HashMap<Element, NameAllocation<org.eclipse.ocl.pivot.Package>>(); private static Map<Element, NameAllocation<Property>> uniqueProperties = new HashMap<Element, NameAllocation<Property>>(); private static Map<Element, NameAllocation<String>> uniqueStrings = new HashMap<Element, NameAllocation<String>>(); private static Map<Element, TuplePartAllocation> uniqueTupleParts = new HashMap<Element, TuplePartAllocation>(); private static Map<Element, NameAllocation<TupleType>> uniqueTupleTypes = new HashMap<Element, NameAllocation<TupleType>>(); private static Map<Element, NameAllocation<Type>> uniqueTypes = new HashMap<Element, NameAllocation<Type>>(); private static Map<Element, NameAllocation<Variable>> uniqueVariables = new HashMap<Element, NameAllocation<Variable>>(); protected static void appendJavaCharacters(StringBuilder s, String string) { for (int i = 0; i < string.length(); i++) { char c = string.charAt(i); if (Character.isJavaIdentifierPart(c)) { s.append(c); } else { s.append('_'); } } } protected static void appendJavaCharacters(StringBuilder s, String string, int iMax) { for (int i = 0; i < Math.min(iMax, string.length()); i++) { char c = string.charAt(i); if (Character.isJavaIdentifierPart(c)) { s.append(c); } else { s.append('_'); } } } /** * Return a valid Java identifier suffix encoding of string that is unique within the scope of element. */ public static String getUniqueText(Element context, Constraint constraint) { NameAllocation<Constraint> allocation = uniqueConstraints.get(context); if (allocation == null) { allocation = new NameAllocation<Constraint>() { @Override protected String computeUniqueText(Constraint constraint) { StringBuilder s = new StringBuilder(); String name = constraint.getName(); if (name == null) { @SuppressWarnings("unchecked") List<Constraint> constraints = (List<Constraint>) constraint.eContainer().eGet(constraint.eContainmentFeature()); name = Integer.toString(constraints.indexOf(constraint)); } appendJavaCharacters(s, name); if (isUsed(s.toString())) { s.append("___"); if (isUsed(s.toString())) { for (int i = 1; true; i++) { if (!isUsed(s.toString() + Integer.toString(i))) { s.append(i); break; } } } } return s.toString(); } }; uniqueConstraints.put(context, allocation); } return allocation.get(constraint); } /** * Return a valid Java identifier suffix encoding of an operation name that is unique within the scope of element. */ public static String getUniqueText(Element context, Operation operation) { NameAllocation<Operation> allocation = uniqueOperations.get(context); if (allocation == null) { allocation = new NameAllocation<Operation>() { @Override protected String computeUniqueText(Operation operation) { StringBuilder s = new StringBuilder(); appendJavaCharacters(s, operation.getOwningClass().getName()); s.append('_'); int arity = operation.getOwnedParameters().size(); String string = operation.getName(); for (int i = 0; i < string.length(); i++) { char c = string.charAt(i); if (Character.isJavaIdentifierPart(c)) { s.append(c); } else if (c == '=') { s.append("_eq_"); } else if (c == '+') { s.append("_add_"); } else if (c == '-') { if (arity == 0) { s.append("_neg_"); } else { s.append("_sub_"); } } else if (c == '/') { s.append("_div_"); } else if (c == '*') { s.append("_mul_"); } else if (c == '<') { s.append("_lt_"); } else if (c == '>') { s.append("_gt_"); } else { s.append('_'); } } if (isUsed(s.toString())) { for (int i = 1; true; i++) { if (!isUsed(s.toString() + '_' + Integer.toString(i))) { s.append(i); break; } } } return s.toString(); } }; uniqueOperations.put(context, allocation); } return allocation.get(operation); } /** * Return a valid Java identifier suffix encoding of a property name that is unique within the scope of element. */ public static String getUniqueText(Element context, org.eclipse.ocl.pivot.Package pkg) { NameAllocation<org.eclipse.ocl.pivot.Package> allocation = uniquePackages.get(context); if (allocation == null) { allocation = new NameAllocation<org.eclipse.ocl.pivot.Package>() { @Override protected String computeUniqueText(org.eclipse.ocl.pivot.Package pkg) { StringBuilder s = new StringBuilder(); appendJavaCharacters(s, pkg.getName()); if (isUsed(s.toString())) { for (int i = 1; true; i++) { if (!isUsed(s.toString() + '_' + Integer.toString(i))) { s.append(i); break; } } } return s.toString(); } }; uniquePackages.put(context, allocation); } return allocation.get(pkg); } /** * Return a valid Java identifier suffix encoding of a property name that is unique within the scope of element. */ public static String getUniqueText(Element context, Property property) { if (property.eContainer() instanceof TupleType) { TuplePartAllocation allocation = uniqueTupleParts.get(context); if (allocation == null) { allocation = new TuplePartAllocation(); uniqueTupleParts.put(context, allocation); } return allocation.get(property.getName(), property.getType()); } NameAllocation<Property> allocation = uniqueProperties.get(context); if (allocation == null) { allocation = new NameAllocation<Property>() { @Override protected String computeUniqueText(Property property) { StringBuilder s = new StringBuilder(); appendJavaCharacters(s, property.getOwningClass().getName()); s.append('_'); appendJavaCharacters(s, property.getName()); if (isUsed(s.toString())) { for (int i = 1; true; i++) { if (!isUsed(s.toString() + '_' + Integer.toString(i))) { s.append(i); break; } } } return s.toString(); } }; uniqueProperties.put(context, allocation); } return allocation.get(property); } /** * Return a valid Java identifier suffix encoding of string that is unique within the scope of element. */ public static String getUniqueText(Element context, String string) { NameAllocation<String> allocation = uniqueStrings.get(context); if (allocation == null) { allocation = new NameAllocation<String>() { @Override protected String computeUniqueText(String string) { StringBuilder s = new StringBuilder(); int iSize = string.length(); int iMax = 8; appendJavaCharacters(s, string, iMax); if ((iSize > 8) || isUsed(s.toString())) { s.append("___"); if (isUsed(s.toString())) { for (int i = 1; true; i++) { if (!isUsed(s.toString() + Integer.toString(i))) { s.append(i); break; } } } } return s.toString(); } }; uniqueStrings.put(context, allocation); } return allocation.get(string); } /** * Return a valid Java identifier suffix encoding of a property name that is unique within the scope of element. */ public static String getUniqueText(Element context, TupleLiteralPart part) { TuplePartAllocation allocation = uniqueTupleParts.get(context); if (allocation == null) { allocation = new TuplePartAllocation(); uniqueTupleParts.put(context, allocation); } return allocation.get(part.getName(), part.getType()); } /** * Return a valid Java identifier suffix encoding of a property name that is unique within the scope of element. */ public static String getUniqueText(Element context, TupleType type) { NameAllocation<TupleType> allocation = uniqueTupleTypes.get(context); if (allocation == null) { allocation = new NameAllocation<TupleType>() { @Override protected String computeUniqueText(TupleType type) { StringBuilder s = new StringBuilder(); String name = String.valueOf(type); appendJavaCharacters(s, name); if (isUsed(s.toString())) { for (int i = 1; true; i++) { if (!isUsed(s.toString() + '_' + Integer.toString(i))) { s.append(i); break; } } } return s.toString(); } }; uniqueTupleTypes.put(context, allocation); } return allocation.get(type); } /** * Return a valid Java identifier suffix encoding of a property name that is unique within the scope of element. */ public static String getUniqueText(Element context, Type type) { NameAllocation<Type> allocation = uniqueTypes.get(context); if (allocation == null) { allocation = new NameAllocation<Type>() { @Override protected String computeUniqueText(Type type) { StringBuilder s = new StringBuilder(); appendJavaCharacters(s, String.valueOf(type)); if (isUsed(s.toString())) { for (int i = 1; true; i++) { if (!isUsed(s.toString() + '_' + Integer.toString(i))) { s.append(i); break; } } } return s.toString(); } }; uniqueTypes.put(context, allocation); } return allocation.get(type); } /** * Return a valid Java identifier suffix encoding of a variable name that is unique within the scope of element. */ public static String getUniqueText(Element context, Variable variable) { NameAllocation<Variable> allocation = uniqueVariables.get(context); if (allocation == null) { allocation = new NameAllocation<Variable>() { @Override protected String computeUniqueText(Variable variable) { StringBuilder s = new StringBuilder(); appendJavaCharacters(s, variable.getName()); if (isUsed(s.toString())) { for (int i = 1; true; i++) { String suffix = '_' + Integer.toString(i); if (!isUsed(s.toString() + suffix)) { s.append(suffix); break; } } } return s.toString(); } }; uniqueVariables.put(context, allocation); } String string = allocation.get(variable); // System.out.println(string + " for " + variable); return string; } }