/******************************************************************************* * 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 - bugs 267917 *******************************************************************************/ package org.eclipse.m2m.internal.qvt.oml.stdlib; import java.util.Collection; import java.util.List; 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.ListType; import org.eclipse.m2m.qvt.oml.util.Utils; import org.eclipse.ocl.ecore.BagType; import org.eclipse.ocl.ecore.CollectionType; import org.eclipse.ocl.ecore.OrderedSetType; import org.eclipse.ocl.ecore.SequenceType; import org.eclipse.ocl.ecore.SetType; import org.eclipse.ocl.util.CollectionUtil; /** * @since 3.4 */ public class ConversionCollection implements ConversionDelegate { final private CollectionType fMyType; public ConversionCollection(CollectionType type) { this.fMyType = type; } public String convertToString(Object value) { EClassifier elementType = fMyType.getElementType(); if (!(value instanceof Collection<?>) || !(elementType instanceof EDataType)) { return ""; //$NON-NLS-1$ } // support nested declarations ConversionUtils.setupConversionDelegate(elementType); StringBuilder result = new StringBuilder(); @SuppressWarnings("unchecked") Collection<Object> collection = (Collection<Object>)value; for (Object element : collection) { if (result.length() > 0) { result.append(", "); //$NON-NLS-1$ } String data = elementType.getEPackage().getEFactoryInstance().convertToString((EDataType)elementType, element); if (ConversionUtils.isStringType(elementType)) { data = escapeCollectionElem(data); } result.append(data); } return result.insert(0, "[").append("]").toString(); //$NON-NLS-1$ //$NON-NLS-2$ } public Object createFromString(String literal) { EClassifier elementType = fMyType.getElementType(); 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(elementType); List<Object> result = Utils.createList(); for (int i = 0; i < literal.length(); ++i) { int endIndex = extractCollectionElement(literal, i); Object value = ConversionUtils.createFromString(elementType, unescapeString(literal.substring(i, endIndex)).trim()); result.add(value); i = endIndex; } if (fMyType instanceof ListType) { return result; } if (fMyType instanceof SetType) { return CollectionUtil.createNewSet(result); } if (fMyType instanceof OrderedSetType) { return CollectionUtil.createNewOrderedSet(result); } if (fMyType instanceof SequenceType) { return CollectionUtil.createNewSequence(result); } if (fMyType instanceof BagType) { return CollectionUtil.createNewBag(result); } throw new IllegalArgumentException("Invalid datatype: " + fMyType.getName()); //$NON-NLS-1$ } private static String escapeCollectionElem(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 ']': result.append('\\'); default: result.append(ch); } } return result.toString(); } static String unescapeString(String literal) { char[] convtBuf = new char[literal.length()]; int outLen = 0; for (int i = 0; i < literal.length(); ++i) { char ch = literal.charAt(i); switch (ch) { case '\\': ++i; if (i < literal.length()) { convtBuf[outLen] = literal.charAt(i); } break; default: convtBuf[outLen] = ch; } ++outLen; } return new String(convtBuf, 0, outLen); } private static int extractCollectionElement(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(); } }