com.googlecode.erca.framework.algo.ClfGenerator.java Source code

Java tutorial

Introduction

Here is the source code for com.googlecode.erca.framework.algo.ClfGenerator.java

Source

/*********************************************************************************
* Copyright (c) 2007, 2008 Jean-Rmy Falleri <jr.falleri@laposte.net>
* 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:
*    Jean-Rmy Falleri <jr.falleri@laposte.net> - initial API and implementation
*********************************************************************************/

package com.googlecode.erca.framework.algo;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.impl.SimpleLog;
import org.eclipse.emf.common.util.*;

import com.googlecode.erca.*;
import com.googlecode.erca.clf.*;
import com.googlecode.erca.framework.algo.filtering.ClfFilter;
import com.googlecode.erca.framework.algo.filtering.FilterManager;
import com.googlecode.erca.framework.algo.scaling.*;
import com.googlecode.erca.framework.io.ErcaIO;
import com.googlecode.erca.rcf.*;
import com.googlecode.exputils.NameGenerator;

/**
 * Generates a CLF from a RCF.
 * @author Jean-Rmy Falleri
 */
public class ClfGenerator {

    private final static Log logger = new SimpleLog("com.google.code.erca.framework.algo.ClfGenerator");

    private int stepNumber;

    private int maxStepNumber;

    private boolean saveDebugLattices;

    private File debugDir;

    private RelationalContextFamily rcf;

    private ConceptLatticeFamily clf;

    private NameGenerator nameGenerator;

    private List<ClfFilter> filters;

    public ClfGenerator(RelationalContextFamily rcf, int maxStepNumber, boolean saveDebugContexts, File debugDir) {
        this.rcf = rcf;
        this.maxStepNumber = maxStepNumber;
        this.saveDebugLattices = saveDebugContexts;
        this.debugDir = debugDir;
        this.nameGenerator = new NameGenerator("_");
        this.filters = new LinkedList<ClfFilter>();
    }

    /**
     * Adds a filter to the filter list.
     * @param name the filter class name.
     */
    public void addFilter(String name) {
        filters.add(FilterManager.getClfFilter(name));
    }

    /**
     * Applies all the filters on the CLF.
     */
    public void applyFilters() {
        for (ClfFilter f : filters)
            f.filter(clf);
    }

    /**
     * Creates a Concept Lattice Family generator using the given Relational Context
     * Family and a given maximum number of step. If the maximum number of step is -1,
     * the number of step is unbounded.
     * @param rcf a Relational Context Family.
     * @param maxStepNumber an int representing the maximum number of step of the RCA process.
     */
    public ClfGenerator(RelationalContextFamily rcf, int maxStepNumber) {
        this(rcf, maxStepNumber, false, null);
    }

    public ClfGenerator(RelationalContextFamily rcf) {
        this(rcf, -1);
    }

    public ClfGenerator(String rcfPath, int maxStepNumber) {
        this(ErcaIO.loadRCF(rcfPath), maxStepNumber);
    }

    public ClfGenerator(String rcfPath, int maxStepNumber, boolean saveDebugLattices, String debugPath) {
        this(ErcaIO.loadRCF(rcfPath), maxStepNumber, saveDebugLattices, new File(debugPath));
    }

    public ClfGenerator(String path) {
        this(path, -1);
    }

    /**
     * Build the CLF for the given RCF.
     * @throws IOException IOException.
     */
    public void generateClf() throws IOException {
        logger.info("Starting concept lattice family construction.");
        logger.info("Initializing lattices.");

        stepNumber = 0;

        this.clf = ClfFactory.eINSTANCE.createConceptLatticeFamily();

        for (FormalContext context : this.rcf.getFormalContexts())
            initializeLattice(context);

        HashMap<ConceptLattice, EList<Concept>> nextStepConcepts = initNextStepConcepts();
        HashMap<ConceptLattice, EList<Concept>> currentStepConcepts = new HashMap<ConceptLattice, EList<Concept>>();
        EList<Concept> newConcepts;

        logger.info("Starting relational construction process.");

        boolean stopProcess = (nextStepConcepts.isEmpty() || (maxStepNumber > 0 && stepNumber >= maxStepNumber));

        while (!stopProcess) {

            if (saveDebugLattices) {
                logger.debug("Saving debug informations.");
                String clfPath = debugDir.getAbsolutePath() + "/clf_" + stepNumber + ".clf";
                ErcaIO.saveErcaObject(clf, clfPath);
            }

            stepNumber++;

            logger.debug("Step number " + Integer.toString(stepNumber));

            int addedConcepts = 0;
            currentStepConcepts = nextStepConcepts;
            nextStepConcepts = new HashMap<ConceptLattice, EList<Concept>>();
            for (FormalContext context : this.rcf.getFormalContexts()) {
                ConceptLattice lattice = this.clf.getConceptLattice(context.getName());
                for (RelationalContext relation : this.rcf.getRelationalContexts(context)) {
                    ConceptLattice targetLattice = this.clf
                            .getConceptLattice(relation.getTargetContext().getName());
                    newConcepts = null;
                    newConcepts = scale(lattice, relation, currentStepConcepts.get(targetLattice));
                    if (newConcepts != null) {
                        addedConcepts += newConcepts.size();
                        // Sets the creation step attribute
                        for (Concept concept : newConcepts)
                            concept.setCreationStep(stepNumber);
                    }
                    if (newConcepts == null || newConcepts.isEmpty())
                        continue;
                    else if (nextStepConcepts.get(lattice) == null)
                        nextStepConcepts.put(lattice, newConcepts);
                    else
                        nextStepConcepts.get(lattice).addAll(newConcepts);
                }
            }

            logger.debug("Added concepts: " + Integer.toString(addedConcepts));

            stopProcess = (nextStepConcepts.isEmpty() || (maxStepNumber > 0 && stepNumber >= maxStepNumber));
        }

        clf.setStepNumber(stepNumber);

        applyFilters();
    }

    /**
     * Returns the RCF.
     * @return the RCF.
     */
    public RelationalContextFamily getRcf() {
        return this.rcf;
    }

    /**
     * Returns the CLF that has been created.
     * @return the CLF.
     */
    public ConceptLatticeFamily getClf() {
        return this.clf;
    }

    /**
     * Saves the CLF to the given path.
     * @param path a path.
     * @throws IOException IOException.
     */
    public void saveClf(String path) throws IOException {
        ErcaIO.saveErcaObject(this.clf, path);
    }

    private EList<Concept> scale(ConceptLattice lattice, RelationalContext relationalContext,
            EList<Concept> filteredConcepts) {
        if (filteredConcepts == null)
            return null;
        EList<Concept> addedConcepts = new BasicEList<Concept>();

        ScalingOperator sclOp = ScalingOperatorManager.getScalingOperator(relationalContext.getScalingOperator());

        for (Concept concept : filteredConcepts) {
            EList<Entity> extent = new BasicEList<Entity>();
            // Performs scaling.
            for (Entity entity : relationalContext.getSourceContext().getEntities()) {
                EList<Entity> linkedEntities = relationalContext.getTargetEntities(entity);
                if (sclOp.accept(linkedEntities, concept))
                    extent.add(entity);
            }

            if (!extent.isEmpty()) {
                Attribute attribute = scaleConcept(lattice, concept, relationalContext);
                EList<Concept> initialConcepts = new BasicEList<Concept>();
                initialConcepts.addAll(lattice.getConcepts());
                Concept addedConcept = AddExtent.addExtent(extent, lattice.getTop(), lattice, nameGenerator);
                for (Concept child : addedConcept.getAllChildren())
                    child.getIntent().add(attribute);
                EList<Concept> finalConcepts = new BasicEList<Concept>();
                finalConcepts.addAll(lattice.getConcepts());
                finalConcepts.removeAll(initialConcepts);
                addedConcepts.addAll(finalConcepts);
            }
        }

        if (addedConcepts.isEmpty())
            return null;
        else
            return addedConcepts;
    }

    private void initializeLattice(FormalContext context) {
        ConceptLattice lattice = AddExtent.createLattice(context, nameGenerator);
        this.clf.getConceptLattices().add(lattice);
    }

    private HashMap<ConceptLattice, EList<Concept>> initNextStepConcepts() {
        HashMap<ConceptLattice, EList<Concept>> nextStepConcepts = new HashMap<ConceptLattice, EList<Concept>>();
        for (ConceptLattice lattice : this.clf.getConceptLattices()) {
            EList<Concept> latticeNextStepConcepts = new BasicEList<Concept>();
            latticeNextStepConcepts.addAll(lattice.getConcepts());
            nextStepConcepts.put(lattice, latticeNextStepConcepts);
        }
        return nextStepConcepts;
    }

    private Attribute scaleConcept(ConceptLattice lattice, Concept concept, RelationalContext relation) {
        RelationalAttribute sclAttr = ErcaFactory.eINSTANCE.createRelationalAttribute();
        sclAttr.setName(relation.getName());
        sclAttr.setValue(concept);
        sclAttr.setScalingOperator(relation.getScalingOperator());

        if (lattice.getAttribute(sclAttr) != null)
            return lattice.getAttribute(sclAttr);
        else {
            lattice.getAttributes().add(sclAttr);
            return sclAttr;
        }
    }

}