| /******************************************************************************* |
| * Copyright (c) 2015 BSI Business Systems Integration AG. |
| * 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: |
| * BSI Business Systems Integration AG - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.scout.sdk.core.sourcebuilder.type; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.TreeMap; |
| |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.commons.lang3.Validate; |
| import org.eclipse.scout.sdk.core.IJavaRuntimeTypes; |
| import org.eclipse.scout.sdk.core.importcollector.IImportCollector; |
| import org.eclipse.scout.sdk.core.importvalidator.IImportValidator; |
| import org.eclipse.scout.sdk.core.model.api.Flags; |
| import org.eclipse.scout.sdk.core.model.api.IField; |
| import org.eclipse.scout.sdk.core.model.api.IMethod; |
| import org.eclipse.scout.sdk.core.model.api.IType; |
| import org.eclipse.scout.sdk.core.model.api.ITypeParameter; |
| import org.eclipse.scout.sdk.core.signature.ISignatureConstants; |
| import org.eclipse.scout.sdk.core.signature.SignatureUtils; |
| import org.eclipse.scout.sdk.core.sourcebuilder.AbstractMemberSourceBuilder; |
| import org.eclipse.scout.sdk.core.sourcebuilder.ISourceBuilder; |
| import org.eclipse.scout.sdk.core.sourcebuilder.compilationunit.ICompilationUnitSourceBuilder; |
| import org.eclipse.scout.sdk.core.sourcebuilder.field.FieldSourceBuilder; |
| import org.eclipse.scout.sdk.core.sourcebuilder.field.IFieldSourceBuilder; |
| import org.eclipse.scout.sdk.core.sourcebuilder.method.IMethodSourceBuilder; |
| import org.eclipse.scout.sdk.core.sourcebuilder.method.MethodSourceBuilder; |
| import org.eclipse.scout.sdk.core.sourcebuilder.typeparameter.ITypeParameterSourceBuilder; |
| import org.eclipse.scout.sdk.core.sourcebuilder.typeparameter.TypeParameterSourceBuilder; |
| import org.eclipse.scout.sdk.core.util.CompositeObject; |
| import org.eclipse.scout.sdk.core.util.PropertyMap; |
| |
| /** |
| * <h3>{@link TypeSourceBuilder}</h3> |
| * |
| * @author Andreas Hoegger |
| * @since 3.10.0 2013-03-07 |
| */ |
| public class TypeSourceBuilder extends AbstractMemberSourceBuilder implements ITypeSourceBuilder { |
| private String m_superTypeSignature; |
| private String m_parentFullyQualifiedName; |
| private ISourceBuilder m_declaringElement; |
| private final List<ITypeParameterSourceBuilder> m_typeParameters = new ArrayList<>(); |
| private final List<String> m_interfaceSignatures = new ArrayList<>(); |
| private final List<IFieldSourceBuilder> m_fields = new ArrayList<>(); |
| private final Map<CompositeObject, IFieldSourceBuilder> m_sortedFields = new TreeMap<>(); |
| private final List<IMethodSourceBuilder> m_methods = new ArrayList<>(); |
| private final Map<CompositeObject, IMethodSourceBuilder> m_sortedMethods = new TreeMap<>(); |
| private final List<ITypeSourceBuilder> m_types = new ArrayList<>(); |
| private final Map<CompositeObject, ITypeSourceBuilder> m_sortedTypes = new TreeMap<>(); |
| |
| public TypeSourceBuilder(IType element) { |
| super(element); |
| for (ITypeParameter p : element.typeParameters()) { |
| addTypeParameter(new TypeParameterSourceBuilder(p)); |
| } |
| if (element.superClass() != null && !IJavaRuntimeTypes.Object.equals(element.superClass().name())) { |
| setSuperTypeSignature(SignatureUtils.getTypeSignature(element.superClass())); |
| } |
| for (IType i : element.superInterfaces()) { |
| addInterfaceSignature(SignatureUtils.getTypeSignature(i)); |
| } |
| for (IField field : element.fields().list()) { |
| addField(new FieldSourceBuilder(field)); |
| } |
| for (IMethod method : element.methods().list()) { |
| addMethod(new MethodSourceBuilder(method)); |
| } |
| for (IType type : element.innerTypes().list()) { |
| addType(new TypeSourceBuilder(type)); |
| } |
| } |
| |
| /** |
| * @param elementName |
| * @param parentBuilder |
| */ |
| public TypeSourceBuilder(String elementName) { |
| super(elementName); |
| } |
| |
| @Override |
| public void createSource(StringBuilder source, String lineDelimiter, PropertyMap context, IImportValidator validator) { |
| IImportCollector collector = new EnclosingTypeScopedImportCollector(validator.getImportCollector(), this); |
| validator.setImportCollector(collector); |
| |
| super.createSource(source, lineDelimiter, context, validator); |
| |
| if (Flags.isInterface(getFlags()) && getSuperTypeSignature() != null) { |
| throw new IllegalArgumentException("An interface can not have a superclass."); |
| } |
| |
| // type definition |
| source.append(Flags.toString(getFlags())).append(' '); |
| source.append(((getFlags() & Flags.AccInterface) != 0) ? ("interface ") : ("class ")); |
| source.append(getElementName()); |
| |
| // type parameters |
| if (!m_typeParameters.isEmpty()) { |
| source.append(ISignatureConstants.C_GENERIC_START); |
| for (ITypeParameterSourceBuilder p : m_typeParameters) { |
| p.createSource(source, lineDelimiter, context, validator); |
| source.append(", "); |
| } |
| source.setLength(source.length() - 2); |
| source.append(ISignatureConstants.C_GENERIC_END); |
| } |
| |
| // super type (extends) |
| if (!StringUtils.isEmpty(getSuperTypeSignature())) { |
| String superTypeRefName = validator.useSignature(getSuperTypeSignature()); |
| source.append(" extends ").append(superTypeRefName); |
| } |
| |
| // interfaces |
| Iterator<String> interfaceSigIterator = getInterfaceSignatures().iterator(); |
| if (interfaceSigIterator.hasNext()) { |
| source.append(((getFlags() & Flags.AccInterface) != 0) ? (" extends ") : (" implements ")); |
| source.append(validator.useSignature(interfaceSigIterator.next())); |
| while (interfaceSigIterator.hasNext()) { |
| source.append(", ").append(validator.useSignature(interfaceSigIterator.next())); |
| } |
| } |
| source.append(" {"); |
| createTypeContent(source, lineDelimiter, context, validator); |
| source.append(lineDelimiter); |
| source.append('}'); |
| } |
| |
| /** |
| * @param sourceBuilder |
| * @param icu |
| * @param lineDelimiter |
| * @param validator |
| * @ |
| */ |
| protected void createTypeContent(StringBuilder source, String lineDelimiter, PropertyMap context, IImportValidator validator) { |
| // fields |
| List<IFieldSourceBuilder> fieldSourceBuilders = getFields(); |
| if (!fieldSourceBuilders.isEmpty()) { |
| source.append(lineDelimiter); |
| for (IFieldSourceBuilder builder : fieldSourceBuilders) { |
| if (builder != null) { |
| source.append(lineDelimiter); |
| builder.createSource(source, lineDelimiter, context, validator); |
| } |
| } |
| } |
| // methods |
| List<IMethodSourceBuilder> methodSourceBuilders = getMethods(); |
| if (!methodSourceBuilders.isEmpty()) { |
| source.append(lineDelimiter); |
| for (IMethodSourceBuilder op : methodSourceBuilders) { |
| if (op != null) { |
| source.append(lineDelimiter); |
| op.createSource(source, lineDelimiter, context, validator); |
| } |
| } |
| } |
| // inner types |
| List<ITypeSourceBuilder> innerTypes = getTypes(); |
| if (!innerTypes.isEmpty()) { |
| source.append(lineDelimiter); |
| for (ITypeSourceBuilder op : innerTypes) { |
| if (op != null) { |
| source.append(lineDelimiter); |
| op.createSource(source, lineDelimiter, context, validator); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public void addTypeParameter(ITypeParameterSourceBuilder typeParameter) { |
| m_typeParameters.add(typeParameter); |
| } |
| |
| @Override |
| public boolean removeTypeParameter(String elementName) { |
| for (Iterator<ITypeParameterSourceBuilder> it = m_typeParameters.iterator(); it.hasNext();) { |
| if (elementName.equals(it.next().getElementName())) { |
| it.remove(); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public List<ITypeParameterSourceBuilder> getTypeParameters() { |
| return Collections.unmodifiableList(m_typeParameters); |
| } |
| |
| @Override |
| public void setSuperTypeSignature(String superTypeSignature) { |
| m_superTypeSignature = superTypeSignature; |
| } |
| |
| @Override |
| public String getSuperTypeSignature() { |
| return m_superTypeSignature; |
| } |
| |
| @Override |
| public void addInterfaceSignature(String interfaceSignature) { |
| m_interfaceSignatures.add(interfaceSignature); |
| } |
| |
| @Override |
| public boolean removeInterfaceSignature(String interfaceSignature) { |
| return m_interfaceSignatures.remove(interfaceSignature); |
| } |
| |
| @Override |
| public void setInterfaceSignatures(Collection<String> interfaceSignatures) { |
| m_interfaceSignatures.clear(); |
| if (interfaceSignatures != null) { |
| m_interfaceSignatures.addAll(interfaceSignatures); |
| } |
| } |
| |
| @Override |
| public List<String> getInterfaceSignatures() { |
| return m_interfaceSignatures; |
| } |
| |
| @Override |
| public void addField(IFieldSourceBuilder builder) { |
| if (builder == null) { |
| throw new IllegalArgumentException("Source builder can not be null."); |
| } |
| if (!m_sortedFields.isEmpty()) { |
| throw new IllegalStateException("This builder has already sorted field builder. A mix between sorted and unsorted field builders is not supported."); |
| } |
| m_fields.add(builder); |
| } |
| |
| @Override |
| public void addSortedField(CompositeObject sortKey, IFieldSourceBuilder builder) { |
| if (builder == null) { |
| throw new IllegalArgumentException("Source builder can not be null."); |
| } |
| if (!m_fields.isEmpty()) { |
| throw new IllegalStateException("This builder has already unsorted field builder. A mix between sorted and unsorted field builders is not supported."); |
| } |
| m_sortedFields.put(sortKey, builder); |
| } |
| |
| @Override |
| public boolean removeField(String elementName) { |
| for (Iterator<IFieldSourceBuilder> it = m_fields.iterator(); it.hasNext();) { |
| if (elementName.equals(it.next().getElementName())) { |
| it.remove(); |
| return true; |
| } |
| } |
| for (Iterator<IFieldSourceBuilder> it = m_sortedFields.values().iterator(); it.hasNext();) { |
| if (elementName.equals(it.next().getElementName())) { |
| it.remove(); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public List<IFieldSourceBuilder> getFields() { |
| List<IFieldSourceBuilder> ops = new ArrayList<>(m_fields.size() + m_sortedFields.size()); |
| ops.addAll(m_fields); |
| ops.addAll(m_sortedFields.values()); |
| return ops; |
| } |
| |
| @Override |
| public void addMethod(IMethodSourceBuilder builder) { |
| if (builder == null) { |
| throw new IllegalArgumentException("Source builder can not be null."); |
| } |
| if (!m_sortedMethods.isEmpty()) { |
| throw new IllegalStateException("This source builder has already sorted method builders. A mix between sorted and unsorted method builders is not supported."); |
| } |
| m_methods.add(builder); |
| } |
| |
| @Override |
| public void addSortedMethod(CompositeObject sortKey, IMethodSourceBuilder builder) { |
| if (builder == null) { |
| throw new IllegalArgumentException("Source builder can not be null."); |
| } |
| if (!m_methods.isEmpty()) { |
| throw new IllegalStateException("This source builder has already unsorted method builders. A mix between sorted and unsorted method builders is not supported."); |
| } |
| m_sortedMethods.put(sortKey, builder); |
| } |
| |
| @Override |
| public boolean removeMethod(String elementName) { |
| for (Iterator<IMethodSourceBuilder> it = m_methods.iterator(); it.hasNext();) { |
| if (elementName.equals(it.next().getElementName())) { |
| it.remove(); |
| return true; |
| } |
| } |
| for (Iterator<IMethodSourceBuilder> it = m_sortedMethods.values().iterator(); it.hasNext();) { |
| if (elementName.equals(it.next().getElementName())) { |
| it.remove(); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public IMethodSourceBuilder getMethod(String methodId) { |
| for (IMethodSourceBuilder msb : getMethods()) { |
| if (methodId.equals(msb.getMethodIdentifier())) { |
| return msb; |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public List<IMethodSourceBuilder> getMethods() { |
| List<IMethodSourceBuilder> builders = new ArrayList<>(m_methods.size() + m_sortedMethods.size()); |
| builders.addAll(m_methods); |
| builders.addAll(m_sortedMethods.values()); |
| return builders; |
| } |
| |
| @Override |
| public void addType(ITypeSourceBuilder builder) { |
| if (builder == null) { |
| throw new IllegalArgumentException("Source builder can not be null."); |
| } |
| if (!m_sortedTypes.isEmpty()) { |
| throw new IllegalStateException("This builder has already sorted inner type builders. A mix between sorted and unsorted inner type builders is not supported."); |
| } |
| m_types.add(builder); |
| builder.setDeclaringElement(this); |
| } |
| |
| @Override |
| public void addSortedType(CompositeObject sortKey, ITypeSourceBuilder builder) { |
| if (builder == null) { |
| throw new IllegalArgumentException("Source builder can not be null."); |
| } |
| if (!m_types.isEmpty()) { |
| throw new IllegalStateException("This builder has already unsorted inner type builders. A mix between sorted and unsorted inner type builders is not supported."); |
| } |
| m_sortedTypes.put(sortKey, builder); |
| builder.setDeclaringElement(this); |
| } |
| |
| @Override |
| public boolean removeType(String elementName) { |
| ITypeSourceBuilder builder = null; |
| for (Iterator<ITypeSourceBuilder> it = m_types.iterator(); it.hasNext();) { |
| builder = it.next(); |
| if (elementName.equals(builder.getElementName())) { |
| builder.setDeclaringElement(null); |
| it.remove(); |
| return true; |
| } |
| } |
| for (Iterator<ITypeSourceBuilder> it = m_sortedTypes.values().iterator(); it.hasNext();) { |
| builder = it.next(); |
| if (elementName.equals(builder.getElementName())) { |
| builder.setDeclaringElement(null); |
| it.remove(); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public List<ITypeSourceBuilder> getTypes() { |
| List<ITypeSourceBuilder> typeBuilders = new ArrayList<>(m_types.size() + m_sortedTypes.size()); |
| typeBuilders.addAll(m_types); |
| typeBuilders.addAll(m_sortedTypes.values()); |
| return typeBuilders; |
| } |
| |
| @Override |
| public ISourceBuilder getDeclaringElement() { |
| return m_declaringElement; |
| } |
| |
| @Override |
| public void setDeclaringElement(ISourceBuilder declaringElement) { |
| m_declaringElement = declaringElement; |
| } |
| |
| @Override |
| public String getFullyQualifiedName() { |
| ISourceBuilder parent = getDeclaringElement(); |
| StringBuilder sb = new StringBuilder(); |
| if (parent instanceof ITypeSourceBuilder) { |
| sb.append(((ITypeSourceBuilder) parent).getFullyQualifiedName()).append('$'); |
| } |
| else if (parent instanceof ICompilationUnitSourceBuilder) { |
| String packageName = ((ICompilationUnitSourceBuilder) parent).getPackageName(); |
| if (StringUtils.isNotBlank(packageName)) { |
| sb.append(packageName).append('.'); |
| } |
| } |
| else { |
| sb.append(Validate.notNull(getParentFullyQualifiedName())).append('$'); |
| } |
| sb.append(getElementName()); |
| return sb.toString(); |
| } |
| |
| @Override |
| public String getParentFullyQualifiedName() { |
| return m_parentFullyQualifiedName; |
| } |
| |
| @Override |
| public void setParentFullyQualifiedName(String parentFullyQualifiedName) { |
| m_parentFullyQualifiedName = parentFullyQualifiedName; |
| } |
| |
| } |