| /******************************************************************************* |
| * Copyright (c) 2009, 2013 Borland Software 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: |
| * Alex Paperno |
| *******************************************************************************/ |
| package org.eclipse.m2m.internal.qvt.oml.stdlib; |
| |
| import org.eclipse.emf.ecore.EClassifier; |
| import org.eclipse.emf.ecore.EDataType; |
| import org.eclipse.emf.ecore.EDataType.Internal.ConversionDelegate; |
| import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.DictionaryType; |
| import org.eclipse.m2m.qvt.oml.util.Dictionary; |
| import org.eclipse.m2m.qvt.oml.util.Utils; |
| |
| /** |
| * @since 3.4 |
| */ |
| public class ConversionDictionary implements ConversionDelegate { |
| |
| final private DictionaryType fMyType; |
| |
| public ConversionDictionary(DictionaryType type) { |
| this.fMyType = type; |
| } |
| |
| public String convertToString(Object value) { |
| EClassifier keyType = fMyType.getKeyType(); |
| EClassifier elementType = fMyType.getElementType(); |
| if (!(value instanceof Dictionary<?, ?>) |
| || !(keyType instanceof EDataType) |
| || !(elementType instanceof EDataType)) { |
| return ""; //$NON-NLS-1$ |
| } |
| |
| // support nested declarations |
| ConversionUtils.setupConversionDelegate(keyType); |
| ConversionUtils.setupConversionDelegate(elementType); |
| |
| StringBuilder result = new StringBuilder(); |
| @SuppressWarnings("unchecked") |
| Dictionary<Object, Object> dictionary = (Dictionary<Object, Object>)value; |
| for (Object key : dictionary.keys()) { |
| if (result.length() > 0) { |
| result.append(", "); //$NON-NLS-1$ |
| } |
| String data = keyType.getEPackage().getEFactoryInstance().convertToString((EDataType)keyType, key); |
| if (ConversionUtils.isStringType(keyType)) { |
| data = escapeDictionaryElem(data); |
| } |
| result.append(data); |
| result.append("="); //$NON-NLS-1$ |
| data = elementType.getEPackage().getEFactoryInstance().convertToString((EDataType)elementType, dictionary.get(key)); |
| if (ConversionUtils.isStringType(elementType)) { |
| data = escapeDictionaryElem(data); |
| } |
| result.append(data); |
| } |
| return result.insert(0, "[").append("]").toString(); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| public Object createFromString(String literal) { |
| EClassifier keyType = fMyType.getKeyType(); |
| EClassifier elementType = fMyType.getElementType(); |
| if (!(keyType instanceof EDataType)) { |
| throw new IllegalArgumentException("Invalid datatype: " + keyType.getName()); //$NON-NLS-1$ |
| } |
| if (!(elementType instanceof EDataType)) { |
| throw new IllegalArgumentException("Invalid datatype: " + elementType.getName()); //$NON-NLS-1$ |
| } |
| |
| literal = literal.trim(); |
| if (literal.length() > 0 && literal.charAt(0) == '[') { |
| if (literal.charAt(literal.length()-1) != ']') { |
| throw new IllegalArgumentException("Invalid datatype: " + elementType.getName()); //$NON-NLS-1$ |
| } |
| literal = literal.substring(1, literal.length()-1); |
| } |
| |
| // support nested declarations |
| ConversionUtils.setupConversionDelegate(keyType); |
| ConversionUtils.setupConversionDelegate(elementType); |
| |
| Dictionary<Object, Object> result = Utils.createDictionary(); |
| for (int i = 0; i < literal.length(); ++i) { |
| int endIndex = extractDictionaryKey(literal, i); |
| Object key = ConversionUtils.createFromString(keyType, ConversionCollection.unescapeString(literal.substring(i, endIndex)).trim()); |
| i = endIndex+1; |
| endIndex = extractDictionaryValue(literal, i); |
| Object value = ConversionUtils.createFromString(elementType, ConversionCollection.unescapeString(literal.substring(i, endIndex)).trim()); |
| i = endIndex; |
| result.put(key, value); |
| } |
| return result; |
| } |
| |
| private static String escapeDictionaryElem(String literal) { |
| StringBuilder result = new StringBuilder(literal.length()); |
| for (int i = 0; i < literal.length(); ++i) { |
| char ch = literal.charAt(i); |
| switch (ch) { |
| case '\\': |
| case ',': |
| case '=': |
| case '[': |
| case ']': |
| result.append('\\'); |
| default: |
| result.append(ch); |
| } |
| } |
| return result.toString(); |
| } |
| |
| private static int extractDictionaryKey(String literal, int startIndex) { |
| int level = 0; |
| for (int i = startIndex; i < literal.length(); ++i) { |
| switch (literal.charAt(i)) { |
| case '\\': |
| ++i; |
| break; |
| case '[': |
| ++level; |
| break; |
| case ']': |
| --level; |
| break; |
| case '=': |
| if (level == 0) { |
| return i; |
| } |
| break; |
| } |
| } |
| throw new IllegalArgumentException("Invalid dictionary key: " + literal.substring(startIndex)); //$NON-NLS-1$ |
| } |
| |
| private static int extractDictionaryValue(String literal, int startIndex) { |
| int level = 0; |
| for (int i = startIndex; i < literal.length(); ++i) { |
| switch (literal.charAt(i)) { |
| case '\\': |
| ++i; |
| break; |
| case '[': |
| ++level; |
| break; |
| case ']': |
| --level; |
| break; |
| case ',': |
| if (level == 0) { |
| return i; |
| } |
| break; |
| } |
| } |
| return literal.length(); |
| } |
| |
| } |