com.netxforge.netxstudio.models.export.MasterDataExporterRevenge_sxssf.java Source code

Java tutorial

Introduction

Here is the source code for com.netxforge.netxstudio.models.export.MasterDataExporterRevenge_sxssf.java

Source

/*******************************************************************************
 * Copyright (c) Oct 27, 2011 NetXForge.
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details. You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>
 * 
 * Contributors: Christophe Bouhier - initial API and implementation and/or
 * initial documentation
 *******************************************************************************/
package com.netxforge.netxstudio.models.export;

import java.io.FileOutputStream;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.util.ObjectNotFoundException;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.netxforge.base.cdo.ICDOData;
import com.netxforge.netxstudio.library.LibraryPackage;
import com.netxforge.netxstudio.models.export.internal.ExportActivator;
import com.netxforge.netxstudio.scheduling.SchedulingPackage;

/**
 * A model exporter to Excel format, using the SXSSF functionality: </p> Files
 * will be flushed into the temp directory as determined when the JVM was
 * launched. This location can be changed with the property:
 * <code>-Djava.io.tempdir= [temp dir location]</code>
 * 
 * @see <a href="http://poi.apache.org/spreadsheet/how-to.html#sxssf">Apache POI
 *      SXSSF</a>
 * 
 * @author Christophe Bouhier
 */
public class MasterDataExporterRevenge_sxssf {

    private ICDOData dataProvider;
    private EPackage[] ePackages;

    private static final int INITIAL_CACHED_ROWS = 100;

    /** Our cache */
    private Map<EClass, List<EObject>> cache = Maps.newHashMap();

    /** Keeps track of the work per EClass */
    @SuppressWarnings("unused")
    private Map<EClass, Integer> workMap = Maps.newHashMap();

    /** Our Excel Streamed Workbook **/
    // private final XSSFWorkbook workBook = new XSSFWorkbook();
    SXSSFWorkbook workBook = new SXSSFWorkbook(INITIAL_CACHED_ROWS);

    /**
     * The export filer which is consulted for exporting classes and features
     * from the packages
     */
    private IExportFilter exportFilter;

    /** Our progress monitor */
    private IProgressMonitor monitor;

    public void process(FileOutputStream fileOut, IProgressMonitor monitor) {

        this.monitor = monitor;

        try {
            if (ExportActivator.DEBUG) {
                ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION, "Starting export");
                ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION, "Creating SXSSF Workbook model");

                // As we flush to temp, print the flush directory here.
                String property = System.getProperty("java.io.tmpdir");

                if (property != null && !property.isEmpty()) {
                    ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION,
                            "Stream rows will be flushed in the temp directory: " + property);

                    ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION,
                            "in file: poi-sxxsf-sheet.xml");
                }
            }

            processPackages(ePackages);

            if (ExportActivator.DEBUG) {
                ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION, "Writing file");
            }

            workBook.write(fileOut);
            fileOut.close();
        } catch (final Exception e) {
            if (ExportActivator.DEBUG) {
                ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION, "Export exception", e);
            }
            throw new IllegalStateException(e);
        } finally {
            workBook.dispose();
        }
    }

    private void processPackages(EPackage[] ePackages) {

        if (exportFilter == null) {
            // bail it's mandatory for now.
            return;
        }

        final List<EClassifier> alphabetOrderedClassesFor = exportFilter
                .alphabetOrderedNonFilteredClassesFor(ePackages);

        int classWork = alphabetOrderedClassesFor.size();
        int totalWork = classWork * 2 + 10;

        // create a cache.
        SubMonitor subMon = SubMonitor.convert(monitor, totalWork);

        SubMonitor buildCacheMon = subMon.newChild(10);
        subMon.setTaskName("building Cache");
        buildCache(alphabetOrderedClassesFor);
        buildCacheMon.worked(10);

        // process the attributes for each classifier.
        SubMonitor processAttribMon = subMon.newChild(classWork);
        processAttribMon.setTaskName("Processing attribute sheets");
        for (EClassifier eClassifier : alphabetOrderedClassesFor) {
            processAttributeClassifier(eClassifier);
            processAttribMon.worked(1);
        }

        // process the references for each classifier.
        SubMonitor processMultiRefsMon = subMon.newChild(classWork);
        processMultiRefsMon.setTaskName("Processing reference sheets");
        for (EClassifier eClassifier : alphabetOrderedClassesFor) {
            processMultiRefClassifier(eClassifier);
            processMultiRefsMon.worked(1);
        }
    }

    /*
     * Populate a cache.
     */
    private int buildCache(List<EClassifier> alphabetOrderedClassesFor) {

        int totalWork = 0;

        if (ExportActivator.DEBUG) {
            ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION, "Building cache for classifiers:");
        }

        for (EClassifier eClassifier : alphabetOrderedClassesFor) {

            if (eClassifier instanceof EClass) {
                EClass eClass = (EClass) eClassifier;
                if (ExportActivator.DEBUG) {
                    ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION,
                            "-- EClass: " + eClass.getName());
                }
                // Handle - Non-direct resources in the export properly.
                if (eClassifier == LibraryPackage.Literals.NET_XRESOURCE) {
                    // all resources for
                    {
                        List<Resource> resources = dataProvider.getResources("/Node_");
                        for (Resource r : resources) {
                            totalWork += cacheForResource(r);
                        }
                    }
                    {
                        List<Resource> resources = dataProvider.getResources("/NodeType_");
                        for (Resource r : resources) {
                            totalWork += cacheForResource(r);
                        }
                    }

                } else {
                    Resource resource = null;

                    // For some classes we should use the super type to get the
                    // resource.
                    final EList<EClass> eAllSuperTypes = eClass.getEAllSuperTypes();
                    if (eAllSuperTypes.contains(SchedulingPackage.Literals.JOB)) {
                        int indexOf = eAllSuperTypes.indexOf(SchedulingPackage.Literals.JOB);
                        final EClass eClassJob = eAllSuperTypes.get(indexOf);
                        resource = dataProvider.getResource(eClassJob);

                    } else {
                        resource = dataProvider.getResource(eClass);
                    }

                    if (resource != null) {
                        totalWork += cacheForResource(resource);
                    }
                }
            }
        }
        if (ExportActivator.DEBUG) {
            ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION,
                    "Done, building cache for classifiers.");
        }
        return totalWork;
    }

    /**
     * Cache objects in this resource. objects with a class in the set export
     * filter are pruned.
     * 
     * 
     * @param resource
     */
    private int cacheForResource(Resource resource) {

        int resourceWork = 0;

        if (resource != null && resource.getContents().size() > 0) {
            final TreeIterator<EObject> allContents = resource.getAllContents();
            while (allContents.hasNext()) {

                final EObject closureObject;
                try {
                    closureObject = allContents.next();
                } catch (ObjectNotFoundException onfe) {
                    if (ExportActivator.DEBUG) {
                        ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION,
                                "-- skipping not found objec with ID: " + onfe.getID(), onfe);
                    }
                    continue;
                }

                final EClass objectClass = closureObject.eClass();

                // Make sure we don't cache closure objects which are dynamic.
                if (exportFilter.shouldFilterObject(objectClass)) {
                    // prune all sub objects.
                    allContents.prune();
                    if (ExportActivator.DEBUG) {
                        ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION,
                                "-- skipping & pruning nested object EClass: " + objectClass.getName());
                    }
                    continue;
                }

                final List<EObject> currentForClass;
                if (cache.containsKey(objectClass)) {
                    currentForClass = Lists.newArrayList(cache.get(objectClass));
                    // We could have duplicates, if the resource holds all
                    // objects from a super class. I.e. Job EClass.
                    if (!currentForClass.contains(closureObject)) {
                        currentForClass.add(closureObject);
                        cache.put(objectClass, currentForClass);
                        resourceWork++;
                    }
                } else {
                    currentForClass = Lists.newArrayList();
                    currentForClass.add(closureObject);
                    cache.put(objectClass, currentForClass);
                    resourceWork++;
                }

                if (ExportActivator.DEBUG) {
                    ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION,
                            "-- Added cache entry for type: " + objectClass.getName() + " , entry: "
                                    + closureObject);
                }

            }
        }
        return resourceWork;
    }

    private void processAttributeClassifier(EClassifier eClassifier) {
        if (ExportActivator.DEBUG) {
            ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION, "Start processing attributes");
        }

        if (eClassifier instanceof EClass) {
            // MARKER => Submonitor for processing attribute sheet.s.

            processAttributesClass((EClass) eClassifier);
        }
    }

    private void processMultiRefClassifier(EClassifier eClassifier) {
        if (ExportActivator.DEBUG) {
            ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION,
                    "Start processing multi references for classifier:" + eClassifier.getName());
        }
        if (eClassifier instanceof EClass) {
            // MARKER => Submonitor for processing multiref sheet.
            // We however don't have the number multi-ERefs?
            processMultiRefClass((EClass) eClassifier);
        }
    }

    private void processAttributesClass(EClass eClass) {

        if (ExportActivator.DEBUG) {
            ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION, "Outputing attributes sheet for: "
                    + eClass.getName() + " in package: " + eClass.getEPackage().getName());
        }
        final Sheet sheet = _generateAttributeWorksheet(eClass);

        // output the ID column.
        _generateID(sheet);

        // output all attributes columns.
        for (EAttribute eAttribute : filterAttributes(eClass)) {
            if (ExportActivator.DEBUG) {
                ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION,
                        "-- EAttribute: " + eAttribute.getName());
            }
            processAttribute(eAttribute, sheet);
        }

        // output all single-reference columns.
        for (EReference eReference : eClass.getEAllReferences()) {
            if (!eReference.isMany()) {
                if (ExportActivator.DEBUG) {
                    ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION,
                            "-- EReference: " + eReference.getName());
                }
                processReference(eReference, sheet);
            }
        }
        // Process the actual values here, get the EOBjects from the cache
        // first.
        final List<EObject> data = contextObjectsForClass(eClass);

        processAttributeData(data, sheet);

    }

    private void processMultiRefClass(EClass eClass) {
        List<EReference> multiRefs = this.filterMultiRefs(eClass);
        if (multiRefs.size() > 0) {
            Sheet sheet = _generateRefsWorksheet(eClass);
            _generateMultiReferenceSource(eClass, sheet);
            for (EReference eReference : multiRefs) {
                if (ExportActivator.DEBUG) {
                    ExportActivator.TRACE.trace(null, "-- EReference: " + eReference.getName());
                }
                processMultiReference(eReference, sheet);
            }

            if (ExportActivator.DEBUG) {
                ExportActivator.TRACE.trace(null,
                        "--  processing multi reference data for classifier:" + eClass.getName());
            }
            // Process the actual values here.
            List<EObject> data = contextObjectsForClass(eClass);
            processMultiRefData(data, sheet);
        }
    }

    private void processReference(EReference eReference, Sheet sheet) {
        _generateCell(eReference, sheet);

    }

    private void processAttribute(EAttribute eAttribute, Sheet sheet) {
        _generateCell(eAttribute, sheet);
    }

    private void processMultiReference(EReference eReference, Sheet sheet) {
        _generateMultiRefCell(eReference, sheet);

    }

    private void processAttributeData(List<EObject> data, Sheet sheet) {

        if (ExportActivator.DEBUG) {
            ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION, "Exporting data: ");
        }

        // We assume the attribute order for each data object.
        int objectCount = 2;
        for (EObject dataObject : data) {
            // Generate the Identifier.
            _generateIDCell(dataObject, objectCount, 0, sheet);

            int attributeCount = 1;
            for (EAttribute eAttribute : this.filterAttributes(dataObject.eClass())) {

                Object value = dataObject.eGet(eAttribute);

                // For many() attributes, where the list values are of type
                // String,
                // export as one string separated with newline. (\n).
                // http://work.netxforge.com/issues/311
                if (eAttribute.isMany() && value instanceof EList<?>) {
                    EList<?> list = (EList<?>) value;
                    if (!list.isEmpty()) {
                        // gamble we are of type string.
                        final StringBuffer sb = new StringBuffer();
                        for (Object o : list) {
                            if (o instanceof String) {
                                sb.append((String) o);
                            }
                        }
                        value = sb.toString();
                    } else {
                        value = "";
                    }
                }

                if (ExportActivator.DEBUG) {
                    ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION, "-- EObject (value):" + value);
                }
                _generateDataCell(value, objectCount, attributeCount, sheet);
                attributeCount++;
            }

            for (EReference eReference : dataObject.eClass().getEAllReferences()) {

                if (ExportActivator.DEBUG) {
                    ExportActivator.TRACE.trace(null, "-- EReference: " + eReference.getName());
                }
                // Export Check single reference which are set only.
                if (!eReference.isMany()) {
                    // Clean-external references, which might have corrupted the
                    // DB in the past, skipp this ref, when cleaned.
                    // bug ID?
                    if (!cleanRef(dataObject, eReference)) {

                        final Object refObject = dataObject.eGet(eReference);
                        String identifier = "";
                        if (refObject != null) {
                            identifier = this.contextObjectsIdentifier((EObject) refObject);

                        }
                        _generateDataCell(identifier, objectCount, attributeCount, sheet);
                        attributeCount++;
                    }
                }
            }
            objectCount++;
        }
    }

    private void processMultiRefData(List<EObject> data, Sheet sheet) {
        // We assume the attribute order for each data object.
        int objectCount = 2;
        for (EObject dataObject : data) {
            if (ExportActivator.DEBUG) {
                ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION, "-- EObject:" + dataObject);
            }
            int referenceCount = 1;
            for (EReference eReference : this.filterMultiRefs(dataObject.eClass())) {

                if (ExportActivator.DEBUG) {
                    ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION, "-- EReference:" + eReference);
                }

                // Clean external references for this multi-valued ref.

                cleanRef(dataObject, eReference);

                final Object collection = dataObject.eGet(eReference);
                int rowCount = objectCount;

                if (collection instanceof List<?>) {

                    if (ExportActivator.DEBUG) {
                        ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION, "-- EReference:"
                                + eReference + " collection size (After clean): " + ((List<?>) collection).size());
                    }

                    for (Object refObject : (List<?>) collection) {
                        String identifier = this.contextObjectsIdentifier(dataObject);

                        _generateDataCell(identifier, rowCount, 0, sheet);

                        String refIdentifier = this.contextObjectsIdentifier((EObject) refObject);
                        _generateDataCell(refIdentifier, rowCount, referenceCount, sheet);
                        rowCount++;
                    }
                }
                referenceCount++;
                objectCount = rowCount;
            }
        }
    }

    // Context setters.
    public void setDataProvider(ICDOData dataProvider) {
        this.dataProvider = dataProvider;
    }

    public void setPackagesToExport(EPackage[] ePackages) {
        this.ePackages = ePackages;
    }

    private List<EObject> contextObjectsForClass(EClass eClass) {
        final List<EObject> allObjectsForClass = fromCache(eClass);
        return allObjectsForClass;
    }

    private List<EObject> fromCache(EClass eClass) {
        if (cache.containsKey(eClass)) {
            return cache.get(eClass);
        } else {
            return Collections.emptyList();
        }
    }

    private String contextObjectsIdentifier(EObject eo) {
        if (eo instanceof CDOObject) {
            return ((CDOObject) eo).cdoID().toString();
        }
        return null;
    }

    private void _generateID(Sheet sheet) {
        // Generate name.
        {
            // Style, cell color.
            CellStyle attributeStyle = workBook.createCellStyle();
            attributeStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            attributeStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);

            // Style, font
            Font attributeFont = workBook.createFont();
            attributeFont.setFontName("Verdana");
            attributeFont.setColor(IndexedColors.BLUE.getIndex());
            attributeStyle.setFont(attributeFont);

            // Style, border.
            attributeStyle.setBorderBottom(CellStyle.BORDER_MEDIUM);

            Row row = sheet.getRow(0);
            if (row == null) {
                row = sheet.createRow(0);
            }
            short lastCellNum = row.getLastCellNum();
            if (lastCellNum == -1) {
                lastCellNum = 0;
            }
            Cell cell = row.createCell(lastCellNum);
            cell.setCellValue("ID");
            cell.setCellStyle(attributeStyle);
        }
        // Generate type
        {

            CellStyle typeStyle = workBook.createCellStyle();
            typeStyle.setBorderBottom(CellStyle.BORDER_MEDIUM);

            Row row = sheet.getRow(1);
            if (row == null) {
                row = sheet.createRow(1);
            }
            short lastCellNum = row.getLastCellNum();
            if (lastCellNum == -1) {
                lastCellNum = 0;
            }
            Cell cell = row.createCell(lastCellNum);
            cell.setCellStyle(typeStyle);
        }
    }

    // POI SECTION.
    private Sheet _generateAttributeWorksheet(EClass eClass) {
        return workBook.createSheet(eClass.getName());
    }

    private Sheet _generateRefsWorksheet(EClass eClass) {
        return workBook.createSheet(eClass.getName() + "_refs");
    }

    private void _generateCell(EAttribute eAttribute, Sheet sheet) {

        // Generate name.
        {
            // Style, cell color.
            CellStyle attributeStyle = workBook.createCellStyle();
            attributeStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            attributeStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);

            // Style, font
            Font attributeFont = workBook.createFont();
            attributeFont.setFontName("Verdana");
            attributeFont.setColor(IndexedColors.BLUE.getIndex());
            attributeStyle.setFont(attributeFont);

            // Style, border.
            attributeStyle.setBorderBottom(CellStyle.BORDER_MEDIUM);

            Row row = sheet.getRow(0);
            if (row == null) {
                row = sheet.createRow(0);
            }
            short lastCellNum = row.getLastCellNum();
            if (lastCellNum == -1) {
                lastCellNum = 0;
            }
            Cell cell = row.createCell(lastCellNum);
            cell.setCellValue(StringUtils.capitalize(eAttribute.getName()));
            cell.setCellStyle(attributeStyle);
        }
        // Generate type
        {

            CellStyle typeStyle = workBook.createCellStyle();
            typeStyle.setBorderBottom(CellStyle.BORDER_MEDIUM);

            Row row = sheet.getRow(1);
            if (row == null) {
                row = sheet.createRow(1);
            }
            short lastCellNum = row.getLastCellNum();
            if (lastCellNum == -1) {
                lastCellNum = 0;
            }
            Cell cell = row.createCell(lastCellNum);
            cell.setCellValue(eAttribute.getEType().getName());
            cell.setCellStyle(typeStyle);
        }
    }

    private void _generateCell(EReference eReference, Sheet sheet) {

        // Generate name.
        {
            // Style, cell color.
            CellStyle referenceStyle = workBook.createCellStyle();
            referenceStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            referenceStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);

            // Style, font
            Font referenceFont = workBook.createFont();
            referenceFont.setFontName("Verdana");
            referenceFont.setColor(IndexedColors.DARK_RED.getIndex());
            referenceStyle.setFont(referenceFont);

            // Style, border.
            referenceStyle.setBorderBottom(CellStyle.BORDER_MEDIUM);

            Row row = sheet.getRow(0);
            if (row == null) {
                row = sheet.createRow(0);
            }
            short lastCellNum = row.getLastCellNum();
            if (lastCellNum == -1) {
                lastCellNum = 0;
            }
            Cell cell = row.createCell(lastCellNum);
            cell.setCellValue(StringUtils.capitalize(eReference.getName()));
            cell.setCellStyle(referenceStyle);
        }
        // Generate type
        {

            CellStyle typeStyle = workBook.createCellStyle();
            typeStyle.setBorderBottom(CellStyle.BORDER_MEDIUM);

            Row row = sheet.getRow(1);
            if (row == null) {
                row = sheet.createRow(1);
            }
            short lastCellNum = row.getLastCellNum();
            if (lastCellNum == -1) {
                lastCellNum = 0;
            }
            Cell cell = row.createCell(lastCellNum);
            cell.setCellValue(eReference.getEType().getName());
            cell.setCellStyle(typeStyle);
        }
    }

    private void _generateMultiReferenceSource(EClass eClass, Sheet sheet) {
        // Generate name.
        {
            // Style, cell color.
            CellStyle referenceStyle = workBook.createCellStyle();
            referenceStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            referenceStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);

            // Style, font
            Font referenceFont = workBook.createFont();
            referenceFont.setFontName("Verdana");
            referenceFont.setColor(IndexedColors.DARK_RED.getIndex());
            referenceStyle.setFont(referenceFont);

            // Style, border.
            referenceStyle.setBorderBottom(CellStyle.BORDER_MEDIUM);

            Row row = sheet.getRow(0);
            if (row == null) {
                row = sheet.createRow(0);
            }
            short lastCellNum = row.getLastCellNum();
            if (lastCellNum == -1) {
                lastCellNum = 0;
            }
            Cell cell = row.createCell(lastCellNum);
            cell.setCellValue(StringUtils.capitalize(eClass.getName()));
            cell.setCellStyle(referenceStyle);
        }
        // Generate type
        {

            CellStyle typeStyle = workBook.createCellStyle();
            typeStyle.setBorderBottom(CellStyle.BORDER_MEDIUM);

            Row row = sheet.getRow(1);
            if (row == null) {
                row = sheet.createRow(1);
            }
            short lastCellNum = row.getLastCellNum();
            if (lastCellNum == -1) {
                lastCellNum = 0;
            }
            Cell cell = row.createCell(lastCellNum);
            cell.setCellStyle(typeStyle);
        }
    }

    private void _generateMultiRefCell(EReference eReference, Sheet sheet) {

        // Generate name.
        {
            // Style, cell color.
            CellStyle referenceStyle = workBook.createCellStyle();
            referenceStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            referenceStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);

            // Style, font
            Font referenceFont = workBook.createFont();
            referenceFont.setFontName("Verdana");
            referenceFont.setColor(IndexedColors.DARK_RED.getIndex());
            referenceStyle.setFont(referenceFont);

            // Style, border.
            referenceStyle.setBorderBottom(CellStyle.BORDER_MEDIUM);

            Row row = sheet.getRow(0);
            if (row == null) {
                row = sheet.createRow(0);
            }
            short lastCellNum = row.getLastCellNum();
            if (lastCellNum == -1) {
                lastCellNum = 0;
            }
            Cell cell = row.createCell(lastCellNum);
            cell.setCellValue(StringUtils.capitalize(eReference.getName()));
            cell.setCellStyle(referenceStyle);
        }
        // Generate type
        {

            CellStyle typeStyle = workBook.createCellStyle();
            typeStyle.setBorderBottom(CellStyle.BORDER_MEDIUM);

            Row row = sheet.getRow(1);
            if (row == null) {
                row = sheet.createRow(1);
            }
            short lastCellNum = row.getLastCellNum();
            if (lastCellNum == -1) {
                lastCellNum = 0;
            }
            Cell cell = row.createCell(lastCellNum);
            cell.setCellValue(eReference.getEType().getName());
            cell.setCellStyle(typeStyle);
        }
    }

    private void _generateIDCell(EObject dataObject, int rowCount, int cellCount, Sheet sheet) {
        Row row = sheet.getRow(rowCount);
        if (row == null) {
            row = sheet.createRow(rowCount);
        }
        Cell cell = row.createCell(cellCount);
        if (dataObject != null && dataObject instanceof CDOObject) {
            // What if we deal with a detached object?
            cell.setCellValue(((CDOObject) dataObject).cdoID().toString());
        }
    }

    private void _generateDataCell(Object value, int rowCount, int cellCount, Sheet sheet) {
        Row row = sheet.getRow(rowCount);
        if (row == null) {
            row = sheet.createRow(rowCount);
        }
        Cell cell = row.createCell(cellCount);
        if (value != null) {
            cell.setCellValue(value.toString());
        }

    }

    public List<EReference> filterMultiRefs(EClass eClass) {
        List<EReference> multiRefs = Lists.newArrayList();
        for (EReference eReference : eClass.getEAllReferences()) {
            if (eReference.isMany() && !eReference.isDerived()) {
                multiRefs.add(eReference);
            }
        }
        return multiRefs;
    }

    public List<EAttribute> filterAttributes(EClass eClass) {
        List<EAttribute> nonDerivedAttributes = Lists.newArrayList();
        for (EAttribute eAttribute : eClass.getEAllAttributes()) {
            if (!eAttribute.isDerived()) {
                nonDerivedAttributes.add(eAttribute);
            }
        }
        return nonDerivedAttributes;
    }

    public void setExportFilter(IExportFilter exportFilter) {
        this.exportFilter = exportFilter;
    }

    /**
     * Clean invalid (External) references from an object with the provided
     * {@link EReference reference}. If the reference is multi-valued, all
     * referenced objects are checked.
     * 
     * @param objectToCheck
     * @param eRef
     */
    private boolean cleanRef(EObject objectToCheck, EReference eRef) {

        boolean cleaned = false;

        if (eRef.isMany()) {
            Object eGet = objectToCheck.eGet(eRef);

            if (eGet == null) {
                return cleaned;
            }

            @SuppressWarnings("unchecked")
            final List<? extends EObject> collection = (List<? extends EObject>) eGet;
            if (ExportActivator.DEBUG) {
                ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION,
                        "-- checking external ref from object" + objectToCheck + "with reference" + eRef
                                + " collection size:" + collection.size());
            }

            // final List<EObject> toRemove = Lists.newArrayList();

            for (int i = 0; i < collection.size(); i++) {

                try {
                    collection.get(i);

                } catch (NullPointerException npe) {
                    // Clean-it.
                    CDOUtil.cleanStaleReference(objectToCheck, eRef, i);

                }

                // if (isExternal(eo, eRef)) {
                // if (ExportActivator.DEBUG) {
                // ExportActivator.TRACE.trace(
                // ExportActivator.TRACE_EXPORT_OPTION,
                // "-- cleaning external ref from object" + eo
                // + "with reference" + eRef);
                // }
                //
                // int index = collection.indexOf(eo);
                // toRemove.add(collection.get(index));
                // }
            }

            // for (EObject eo : toRemove) {
            // collection.remove(eo);
            // }

        } else {
            // final EObject eo = (EObject) objectToCheck.eGet(eRef);
            if (isExternal(objectToCheck, eRef)) {
                if (ExportActivator.DEBUG) {
                    ExportActivator.TRACE.trace(ExportActivator.TRACE_EXPORT_OPTION,
                            "-- cleaning external ref from object" + objectToCheck + "with reference" + eRef);
                    ;
                }
                CDOUtil.cleanStaleReference(objectToCheck, eRef);
                cleaned = true;
            }
        }
        return cleaned;
    }

    // Check if the object is external.
    private boolean isExternal(EObject eo, EReference eRef) {
        if (eo instanceof CDOObject) {
            // if(eRef ==
            // OperatorsPackage.Literals.NODE__ORIGINAL_NODE_TYPE_REF){
            // System.out.println("break here!");
            // }
            //
            // CDOObject cdoObject = CDOUtil.getCDOObject(eo);
            // if (cdoObject != null && cdoObject.cdoID() != null) {
            // return cdoObject.cdoID().isExternal();
            // } else {
            // return true;
            // }
            try {
                eo.eGet(eRef);
            } catch (Exception e) {
                return true;
            }
        }
        return false;

    }

}