org.eclipse.xtext.parsetree.reconstr.impl.CrossReferenceSerializer.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.xtext.parsetree.reconstr.impl.CrossReferenceSerializer.java

Source

/*******************************************************************************
 * Copyright (c) 2008 itemis AG (http://www.itemis.eu) 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
 *******************************************************************************/
package org.eclipse.xtext.parsetree.reconstr.impl;

import java.util.List;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.CrossReference;
import org.eclipse.xtext.GrammarUtil;
import org.eclipse.xtext.conversion.IValueConverterService;
import org.eclipse.xtext.conversion.ValueConverterException;
import org.eclipse.xtext.linking.ILinkingService;
import org.eclipse.xtext.linking.impl.LinkingHelper;
import org.eclipse.xtext.naming.IQualifiedNameConverter;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.parsetree.reconstr.ITokenSerializer;
import org.eclipse.xtext.parsetree.reconstr.ITokenSerializer.ICrossReferenceSerializer;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.IScopeProvider;
import org.eclipse.xtext.util.EmfFormatter;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;

/**
 * @author Moritz Eysholdt - Initial contribution and API
 */
public class CrossReferenceSerializer implements ICrossReferenceSerializer {

    @Inject
    private LinkingHelper linkingHelper;

    @Inject
    private ILinkingService linkingService;

    @Inject
    private IScopeProvider scopeProvider;

    @Inject
    private IValueConverterService valueConverter;

    @Inject
    private IQualifiedNameConverter qualifiedNameConverter;

    @Override
    public boolean equalsOrReplacesNode(EObject context, CrossReference crossref, EObject target, INode node) {
        if (crossref != node.getGrammarElement())
            return false;
        EReference ref = GrammarUtil.getReference(crossref);
        if (!ref.isMany())
            return true;
        List<EObject> objects = linkingService.getLinkedObjects(context, ref, node);
        return objects.contains(target);
    }

    protected String getConvertedValue(String unconverted, CrossReference grammarElement) {
        String ruleName = linkingHelper.getRuleNameFrom(grammarElement);
        if (ruleName == null)
            throw new IllegalStateException(
                    "Could not determine targeted rule name for " + EmfFormatter.objPath(grammarElement));
        return valueConverter.toString(unconverted, ruleName);
    }

    protected String getUnconvertedLinkText(EObject object, EReference reference, EObject context) {
        IScope scope = scopeProvider.getScope(context, reference);
        if (scope == null)
            return null;
        IEObjectDescription eObjectDescription = scope.getSingleElement(object);
        if (eObjectDescription != null) {
            return qualifiedNameConverter.toString(eObjectDescription.getName());
        }
        return null;
    }

    @Override
    public boolean isValid(EObject context, CrossReference crossref, EObject target, IErrorAcceptor errorAcceptor) {
        try {
            final EReference ref = GrammarUtil.getReference(crossref, context.eClass());
            String text = getUnconvertedLinkText(target, ref, context);
            if (text == null)
                return true; // maybe we'll find something useful in the node model later on?
            getConvertedValue(text, crossref);
            return true;
        } catch (ValueConverterException e) {
            if (errorAcceptor != null)
                errorAcceptor.error(e.getMessage());
            return false;
        }
    }

    @Override
    public String serializeCrossRef(EObject context, CrossReference grammarElement, final EObject target,
            INode node) {
        final EReference ref = GrammarUtil.getReference(grammarElement, context.eClass());
        String text = null;
        if (node != null) {
            List<EObject> objects = linkingService.getLinkedObjects(context, ref, node);
            if (Iterables.any(objects, new Predicate<EObject>() {
                private final URI targetURI = EcoreUtil.getURI(target);

                @Override
                public boolean apply(EObject input) {
                    return input == target || EcoreUtil.getURI(input).equals(targetURI);
                }
            }))
                return ITokenSerializer.KEEP_VALUE_FROM_NODE_MODEL;
        }
        text = getUnconvertedLinkText(target, ref, context);
        if (text != null)
            return getConvertedValue(text, grammarElement);
        if (node != null) {
            return linkingHelper.getCrossRefNodeAsString(node, false);
        }
        return null;
    }

}