OpenCyc as a database (continued): Improving code clarity using functional programming


Author: Dmitri Pissarenko

WWW: http://dapissarenko.com


Dmitri Pissarenko OpenCyc as a database (continued)

Table of Contents
1. Introduction
2. Refactoring DataAccessLayer.getDepartmentList (step 1)
3. Refactoring DataAccessLayer.getDepartmentList (step 2)
4. Appendix 1: Code changes in refactoring step 1
4.1. Refactoring DataAccessLayer.getCountryList (step 1)
4.2. Refactoring DataAccessLayer.getCivilServantsList (step 1)
4.3. Refactoring DataAccessLayer.getHeadOfDepartmentList (step 1)
4.4. Refactoring DataAccessLayer.getRabinovichRoles (step 1)
4.5. Refactoring DataAccessLayer.getCivilServantsWithSubordinates (step 1)
4.6. Refactoring DataAccessLayer.getBossOfBagaturLobo (step 1)
5. Appendix 2: Code changes in refactoring step 2
5.1. Refactoring DataAccessLayer.getCountryList (step 2)
5.2. Refactoring DataAccessLayer.getCivilServantsList (step 2)
5.3. Refactoring DataAccessLayer.getHeadOfDepartmentList (step 2)
5.4. Refactoring DataAccessLayer.getRabinovichRoles (step 2)
5.5. Refactoring DataAccessLayer.getCivilServantsWithSubordinates (step 2)
5.6. Refactoring DataAccessLayer.getBossOfBagaturLobo (step 2)
6. Appendix 3: Related materials

1. Introduction

In my article OpenCyc as a database I developed a simple application, which displays data from the OpenCyc database. In this paper, I want to show you how one can refactor the code of that application using functional programming techniques, which are now available in Java thanks to the Apache Commons Functor library.

We will improve the code of the DataAccessLayer class. The refactoring of the application proceeds in two steps:

  1. First, we replace the while loops by foreach constructs,
  2. then, we find commonalities in DataAccessLayer methods and extract them into separate functions.

Let's begin with step one.


2. Refactoring DataAccessLayer.getDepartmentList (step 1)

Look at the source code of the method DataAccessLayer.getDepartmentList:

public Collection getDepartmentList(CycConstant mt) 
    throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable departmentVariable = null;
        CycConstant item=null;
        DepartmentData departmentData=null;
        Collection collection=null;
        Iterator iterator=null;

        collection=new Vector();
        
        query = CycAccess.current().makeCycList(
		"(#$isa ?DEPARTMENT #$Department)");
        departmentVariable = 
		CycObjectFactory.makeCycVariable("?DEPARTMENT");
        
        response = CycAccess.current().askWithVariable(query, 
                departmentVariable, mt);
        
        iterator=response.iterator();
        while (iterator.hasNext())
        {
            item=(CycConstant)iterator.next();
            
            departmentData=new DepartmentData();
            departmentData.setName(item.getName());
            departmentData.setFieldOfWork(
	    	this.getPredicateValue("fieldOfWork", item, mt));
            collection.add(departmentData);
        }
        
        return collection;
        
    }

If you look at the other methods of this class (see Appendix 1), you will find that all of them have similar structure. In particular, each of the methods has the while loop, in the body of which CycConstants are converted into Java beans (e. g. DepartmentData in this example).

We can use mathematical notation for expressing what we want:

I = {i1, i2, ..., in}
i1, ..., in - instances of CycConstant
O = {o1, o2, ..., on}
o1, ..., on - instances of DepartmentData
ox=f(ix), f: CycConstant -> DepartmentData
=> O = {o1, o2, ..., on} = {f(i1), f(i2), ..., f(in)}

The input to the loop is a set of CycConstants, which we denote I = {i1, i2, ..., in} in our simple mathematical model and which is embodied in the response.iterator() iterator. The desired output of the loop is a set of instances of DepartmentData, which we denote O = {o1, o2, ..., on} in our mathematical model and which is embodied in the collection object.

Each element of the output set is the result of applying function f(ix) on an element of the input set. This function corresponds to the body of the while loop in the source code fragment above (except the collection.add(departmentData); statement). Function y=f(x) maps each x, which is a CycConstant to y, which is a DepartmentData.

If you look at other methods in Appendix 1, you will notice that all of them have the same structure - first a query is executed and then the results of the query (CycConstants) are wrapped into Java beans. Having our mathematical model in mind, we can note that

  1. input sets are different in different DataAccessLayer methods
  2. traversal/mapping mechanism (while loop) of input sets is the same in different DataAccessLayer methods
  3. function f(x) is different in different DataAccessLayer methods.

Now we extract the body of the while loop and put it into a separate class DepartmentDataFunction:

public class DepartmentDataFunction extends 
CycObjectConverter implements UnaryFunction {
    public DepartmentDataFunction() {
    }

    protected Object convertCycList(CycList cycList) {
        return null;
    }

    protected Object convertCycConstant(CycConstant constant) {
        DepartmentData departmentData = null;

        departmentData = new DepartmentData();
        departmentData.setName(constant.getName());

        departmentData.setFieldOfWork(this.getCycAccessHelper()
                .getPredicateValue("fieldOfWork", constant,
                        this.getMicrotheory()));

        return departmentData;

    }
}

The relevant method of this class, convertCycConstant, contains now our function f(x). What appears in our mathematical model as

y=f(x)

can be expressed in terms of this code fragment as

departmentData = DepartmentDataFunction.convertCycConstant(constant) y = DepartmentDataFunction.convertCycConstant(x).

I hope you forgive me this trade-off between consistency and clarity.

There remains only a small step to make, actually two small steps:

  1. apply the function on each element of the input set
  2. put the results into a new collection.

For both of these tasks we have pre-defined mechanisms in Apache Commons Functor library (both are defined in the class Algorithms):

  1. public static final Iterator apply(Iterator iter, UnaryFunction func) applies function func on each element of iterator iter and returns the resulting collection.
  2. public static Collection collect(Iterator iter) returns a collection of elements, contained in the iterator.

First, we use the apply method to obtain an iterator with instances of DepartmentData:

Algorithms.apply(response.iterator(), depDataFunc)

where response.iterator() is an iterator with CycConstants and depDataFunc our mapping function. Then, we simply convert the resulting iterator into a collection:

collection=Algorithms.collect(
	Algorithms.apply(response.iterator(), depDataFunc));
These two lines replace our while loop and the method as a whole is reduced to
public Collection getDepartmentList(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable departmentVariable = null;
        Collection collection=null;
        DepartmentDataFunction depDataFunc=null;
        
        query = CycAccess.current().makeCycList(
		"(#$isa ?DEPARTMENT #$Department)");
        departmentVariable = 
		CycObjectFactory.makeCycVariable("?DEPARTMENT");
        
        response = CycAccess.current().askWithVariable(query, 
                departmentVariable, mt);
        
        depDataFunc=new DepartmentDataFunction();
        depDataFunc.setMicrotheory(mt);
        depDataFunc.setPredicateValueGetter(this);
        
        collection=Algorithms.collect(
                Algorithms.apply(response.iterator(), depDataFunc));

        return collection;
    }

What advantages does this solution have compared with the original version?

First, we have removed an already implemented, general part (while loop for traversing the iterator) from application-specific code.

Second, we created a function, which encapsulates mapping from CycConstant to DepartmentDaTa. This improves both reuse (we could use this function, i. e. the body of the loop, in other contexts) and testability (it is easier to test the method DepartmentDataFunction.convertCycConstant than the whole loop construct).

Third, we reduced the complexity of the method (reduced the number of lines of code).

Analogous refactoring steps were performed on other methods of DataAccessLayer class. In Appendix 1, you will find the source code of all these methods before and after refactoring.


3. Refactoring DataAccessLayer.getDepartmentList (step 2)

If you look at the source code of refactored methods in Appendix 1, you will notice that all of them share some common statements. Look, for instance, in the source code of DataAccessLayer.getDepartmentList:

public Collection getDepartmentList(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable departmentVariable = null;
        Collection collection=null;
        DepartmentDataFunction depDataFunc=null;
        
        query = CycAccess.current().makeCycList(
		"(#$isa ?DEPARTMENT #$Department)");
		
        departmentVariable =
		CycObjectFactory.makeCycVariable("?DEPARTMENT");
        
        response = CycAccess.current().askWithVariable(query, 
                departmentVariable, mt);
        
        depDataFunc=new DepartmentDataFunction();
        depDataFunc.setMicrotheory(mt);
        depDataFunc.setPredicateValueGetter(this);
        
        collection=Algorithms.collect(
                Algorithms.apply(response.iterator(), depDataFunc));

        return collection;
    }

Creation of a query object, creation of a variable, getting the response of the database etc. can be easily extracted and put into a separate function. This makes sense because these code parts appear in every method of DataAccessLayer.

So we will create a method, which incorporates these commonalities:

protected Collection performQuery(CycConstant mt, String queryString,
String varName, UnaryFunction func) 
throws CycApiException, IOException {
        CycList query = null;
        CycList response = null;
        CycVariable var=null;
        Collection collection = null;

        query = CycAccess.current().makeCycList(queryString);

        var=CycObjectFactory.makeCycVariable(varName);
        
        response = CycAccess.current().askWithVariable(query, var, mt);

        collection = Algorithms.collect(
		Algorithms.apply(response.iterator(),
                func));

        return collection;

    }

Using this method our getDepartmentList becomes a little shorter:

public Collection getDepartmentList(CycConstant mt) 
throws CycApiException, IOException {
        Collection collection = null;
        DepartmentDataFunction depDataFunc = null;

        depDataFunc = new DepartmentDataFunction();
        depDataFunc.setMicrotheory(mt);
        depDataFunc.setCycAccessHelper(this);

        return performQuery(mt, "(#$isa ?DEPARTMENT #$Department)",
                "?DEPARTMENT", depDataFunc);
    }

I performed this refactoring step on all other methods of DataAccessLayer and you can look at the results in Appendix 2.


4. Appendix 1: Code changes in refactoring step 1


4.1. Refactoring DataAccessLayer.getCountryList (step 1)
4.2. Refactoring DataAccessLayer.getCivilServantsList (step 1)
4.3. Refactoring DataAccessLayer.getHeadOfDepartmentList (step 1)
4.4. Refactoring DataAccessLayer.getRabinovichRoles (step 1)
4.5. Refactoring DataAccessLayer.getCivilServantsWithSubordinates (step 1)
4.6. Refactoring DataAccessLayer.getBossOfBagaturLobo (step 1)

4.1. Refactoring DataAccessLayer.getCountryList (step 1)

Before refactoring

public Collection getCountryList(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable countryVariable = null;
        CycConstant item=null;
        CountryData countryData=null;
        Collection collection=null;
        Iterator iterator=null;

        collection=new Vector();
        
        query = CycAccess.current().makeCycList(
		"(#$isa ?COUNTRY #$Country)");
        countryVariable =
		CycObjectFactory.makeCycVariable("?COUNTRY");
        
        response = CycAccess.current().askWithVariable(query, 
                countryVariable, mt);
        
        iterator=response.iterator();
        while (iterator.hasNext())
        {
            item=(CycConstant)iterator.next();
            
            countryData=new CountryData();
            countryData.setCountryName(item.getName());
            countryData.setCountryComment(this.getComment(item, mt));
            
            collection.add(countryData);
        }
        
        return collection;
    }

After refactoring

public Collection getCountryList(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable countryVariable = null;
        CountryDataFunction func=null;        
        Collection collection=null;

        collection=new Vector();
        
        query = CycAccess.current().
		makeCycList("(#$isa ?COUNTRY #$Country)");
        countryVariable = 
		CycObjectFactory.makeCycVariable("?COUNTRY");
        
        response = CycAccess.current().askWithVariable(query, 
                countryVariable, mt);

        func=new CountryDataFunction();
        func.setMicrotheory(mt);
        func.setPredicateValueGetter(this);
        
        collection=Algorithms.collect(
                Algorithms.apply(response.iterator(), func));
        
        return collection;
    }


4.2. Refactoring DataAccessLayer.getCivilServantsList (step 1)

Before refactoring

public Collection getCivilServantsList(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable civilServantVariable = null;
        CycConstant item=null;
        CivilServantData civilServantData=null;
        Collection collection=null;
        Iterator iterator=null;

        collection=new Vector();
        
        query = CycAccess.current().makeCycList(
		"(#$isa ?CIVIL_SERVANT #$CivilServant)");
		
        civilServantVariable = 	
		CycObjectFactory.makeCycVariable("?CIVIL_SERVANT");
        
        response = CycAccess.current().askWithVariable(query, 
                civilServantVariable, mt);
        
        iterator=response.iterator();
        while (iterator.hasNext())
        {
            item=(CycConstant)iterator.next();
            
            civilServantData=new CivilServantData();
            civilServantData.setFieldOfWork(
	    	this.getPredicateValue("fieldOfWork", item, mt));
            civilServantData.setGivenNames(
	    	this.getPredicateValue("givenNames", item, mt));
            civilServantData.setFamilyName(
	    	this.getPredicateValue("familyName", item, mt));
            
            collection.add(civilServantData);
        }
        
        return collection;
    }

After refactoring

public Collection getCivilServantsList(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable civilServantVariable = null;
        CivilServantDataFunction func=null;        
        Collection collection=null;
       
        query = CycAccess.current().makeCycList(
		"(#$isa ?CIVIL_SERVANT #$CivilServant)");
        civilServantVariable =
		CycObjectFactory.makeCycVariable("?CIVIL_SERVANT");
        
        response = CycAccess.current().askWithVariable(query, 
                civilServantVariable, mt);
        
        func=new CivilServantDataFunction();
        func.setMicrotheory(mt);
        func.setPredicateValueGetter(this);
        
        collection=Algorithms.collect(
		Algorithms.apply(response.iterator(), func));
        
        return collection;
    }

4.3. Refactoring DataAccessLayer.getHeadOfDepartmentList (step 1)

Before refactoring

public Collection getHeadOfDepartmentList(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable departmentVariable = null;
        CycVariable headVariable = null;
        CycList item=null;
        DepartmentData departmentData=null;
        Collection collection=null;
        ArrayList variables=null;
        Iterator iterator=null;
        CycConstant department=null;
        CycConstant head=null;
        String fullHeadName=null;

        collection=new Vector();
        
        query = CycAccess.current().makeCycList(
		"(#$headOfDepartment ?HEAD_OF_DEPARTMENT ?DEPARTMENT)");
        departmentVariable = 
		CycObjectFactory.makeCycVariable("?DEPARTMENT");
        headVariable = 
		CycObjectFactory.makeCycVariable("?HEAD_OF_DEPARTMENT");
        
        variables=new ArrayList();
        variables.add(departmentVariable);
        variables.add(headVariable);
        
        response = CycAccess.current().askWithVariables(query, 
                variables, mt);

        iterator=response.iterator();
        while (iterator.hasNext())
        {
            item=(CycList)iterator.next();
            
            head=(CycConstant)item.first();
            department=(CycConstant)item.second();
            fullHeadName=this.getFullHeadName(head, mt);
            
            departmentData=new DepartmentData();
            departmentData.setHeadOfDepartment(fullHeadName);
            departmentData.setName(department.getName());
              
            collection.add(departmentData);
        }
        
        return collection;
        
    }

After refactoring

public Collection getHeadOfDepartmentList(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable departmentVariable = null;
        CycVariable headVariable = null;
        DepartmentDataWithHeadFunction func=null;
        Collection collection=null;
        ArrayList variables=null;
       
        query = CycAccess.current().makeCycList(
		"(#$headOfDepartment ?HEAD_OF_DEPARTMENT ?DEPARTMENT)");
        departmentVariable = 
		CycObjectFactory.makeCycVariable("?DEPARTMENT");
        headVariable = 
		CycObjectFactory.makeCycVariable("?HEAD_OF_DEPARTMENT");
        
        variables=new ArrayList();
        variables.add(departmentVariable);
        variables.add(headVariable);
        
        response = CycAccess.current().askWithVariables(query, 
                variables, mt);
        
        func=new DepartmentDataWithHeadFunction();
        func.setCycAccessHelper(this);
        func.setMicrotheory(mt);
        
        collection=Algorithms.collect(
		Algorithms.apply(response.iterator(), func));
        
        return collection;
    }

4.4. Refactoring DataAccessLayer.getRabinovichRoles (step 1)

Before refactoring

public String[] getRabinovichRoles(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable propertyVariable = null;
        Object item=null;
        Vector collection=null;
        Iterator iterator=null;

        collection=new Vector();
        
        query = CycAccess.current().makeCycList(
		"(#$isa #$MokiiNilovichRabinovich ?PROPERTY)");
        propertyVariable = 
		CycObjectFactory.makeCycVariable("?PROPERTY");
        
        response = CycAccess.current().askWithVariable(query, 
                propertyVariable, mt);

        iterator=response.iterator();
        while (iterator.hasNext())
        {
            item=iterator.next();
              
            collection.add(item.toString());
        }
        
        return (String[])collection.
		toArray(new String[collection.size()]);
    }

After refactoring

public String[] getRabinovichRoles(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable propertyVariable = null;
        Collection collection=null;
       
        query = CycAccess.current().makeCycList(
		"(#$isa #$MokiiNilovichRabinovich ?PROPERTY)");
        propertyVariable = 
		CycObjectFactory.makeCycVariable("?PROPERTY");
        
        response = CycAccess.current().
		askWithVariable(query, propertyVariable, mt);

        collection=Algorithms.collect(
		Algorithms.apply(response.iterator(), 
			new ToStringFunction()));
        
        return (String[])collection.
		toArray(new String[collection.size()]);
    }

4.5. Refactoring DataAccessLayer.getCivilServantsWithSubordinates (step 1)

Before refactoring

public CivilServantData[]
getCivilServantsWithSubordinates(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable bossVariable = null;
        CycVariable subordinateVariable=null;
        CycList item=null;
        CivilServantData civilServantData=null;
        ArrayList variables=null;
        Collection collection=null;
        Iterator iterator=null;

        collection=new Vector();
        
        query = CycAccess.current().makeCycList(
		"(#$superiors ?BOSS ?SUBORD)");
        bossVariable = 
		CycObjectFactory.makeCycVariable("?BOSS");
        subordinateVariable = 
		CycObjectFactory.makeCycVariable("?SUBORD");
        
        variables=new ArrayList();
        variables.add(bossVariable);
        variables.add(subordinateVariable);
        
        response = CycAccess.current().askWithVariables(query, 
                variables, mt);
        
        iterator=response.iterator();
        while (iterator.hasNext())
        {
            item=(CycList)iterator.next();
            
            civilServantData=new CivilServantData();
            civilServantData.setFieldOfWork(
	    	this.getPredicateValue("fieldOfWork", 
		(CycConstant)item.first(), mt));
            civilServantData.setGivenNames(
	    	this.getPredicateValue("givenNames", 
		(CycConstant)item.first(), mt));
            civilServantData.setFamilyName(
	    	this.getPredicateValue("familyName", 
		(CycConstant)item.first(), mt));
            
            collection.add(civilServantData);
        }
        
        return (CivilServantData[])collection.
		toArray(
			new CivilServantData[collection.size()]);
        
    }

After refactoring

public CivilServantData[]
getCivilServantsWithSubordinates(CycConstant mt)
throws CycApiException, IOException {
        CycList query = null;
        CycList response = null;
        CycVariable bossVariable = null;
        CycVariable subordinateVariable = null;
        CivilServantDataFunction func = null;
        ArrayList variables = null;
        Collection collection = null;

        collection = new Vector();

        query = CycAccess.current().makeCycList(
		"(#$superiors ?BOSS ?SUBORD)");
        bossVariable = 
		CycObjectFactory.makeCycVariable("?BOSS");
        subordinateVariable = 
		CycObjectFactory.makeCycVariable("?SUBORD");

        variables = new ArrayList();
        variables.add(bossVariable);
        variables.add(subordinateVariable);

        response = CycAccess.current().
		askWithVariables(query, variables, mt);

        func = new CivilServantDataFunction();
        func.setCycAccessHelper(this);
        func.setMicrotheory(mt);

        collection = Algorithms.collect(
		Algorithms.apply(Algorithms.apply(
                response.iterator(), new FirstFunction()), func));

        return (CivilServantData[]) collection
                .toArray(new CivilServantData[collection.size()]);
    }

4.6. Refactoring DataAccessLayer.getBossOfBagaturLobo (step 1)

Before refactoring

public CivilServantData[] getBossOfBagaturLobo(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable bossVariable = null;
        CycConstant item=null;
        CivilServantData civilServantData=null;
        ArrayList variables=null;
        Collection collection=null;
        Iterator iterator=null;

        collection=new Vector();
        
        query = CycAccess.current().makeCycList(
		"(#$superiors ?BOSS #$BagaturLobo)");
        bossVariable = CycObjectFactory.makeCycVariable("?BOSS");
        
        response = CycAccess.current().
		askWithVariable(query, bossVariable, mt);
        
        iterator=response.iterator();
        while (iterator.hasNext())
        {
            item=(CycConstant)iterator.next();
            
            civilServantData=new CivilServantData();
            civilServantData.setFieldOfWork(
	    	this.getPredicateValue("fieldOfWork", item, mt));
            civilServantData.setGivenNames(
	    	this.getPredicateValue("givenNames", item, mt));
            civilServantData.setFamilyName(
	    	this.getPredicateValue("familyName", item, mt));
            
            collection.add(civilServantData);
        }
        
        return (CivilServantData[])collection.
		toArray(
		new CivilServantData[collection.size()]);
        
    }

After refactoring

public CivilServantData[] getBossOfBagaturLobo(CycConstant mt)
throws CycApiException, IOException {
        CycList query = null;
        CycList response = null;
        CycVariable bossVariable = null;
        CivilServantDataFunction func=null;        
        ArrayList variables = null;
        Collection collection = null;

        collection = new Vector();

        query = CycAccess.current().makeCycList(
                "(#$superiors ?BOSS #$BagaturLobo)");
        bossVariable = CycObjectFactory.makeCycVariable("?BOSS");

        response = CycAccess.current().
		askWithVariable(query, bossVariable, mt);
        
        func=new CivilServantDataFunction();
        func.setCycAccessHelper(this);
        func.setMicrotheory(mt);
        
        
        collection=Algorithms.collect(
		Algorithms.apply(response.iterator(), func));
        
        return (CivilServantData[]) collection
                .toArray(new CivilServantData[collection.size()]);
    }

5. Appendix 2: Code changes in refactoring step 2


5.1. Refactoring DataAccessLayer.getCountryList (step 2)
5.2. Refactoring DataAccessLayer.getCivilServantsList (step 2)
5.3. Refactoring DataAccessLayer.getHeadOfDepartmentList (step 2)
5.4. Refactoring DataAccessLayer.getRabinovichRoles (step 2)
5.5. Refactoring DataAccessLayer.getCivilServantsWithSubordinates (step 2)
5.6. Refactoring DataAccessLayer.getBossOfBagaturLobo (step 2)

5.1. Refactoring DataAccessLayer.getCountryList (step 1)

Before refactoring

public Collection getCountryList(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable countryVariable = null;
        CountryDataFunction func=null;        
        Collection collection=null;

        collection=new Vector();
        
        query = CycAccess.current().makeCycList(
		"(#$isa ?COUNTRY #$Country)");
        countryVariable = 
		CycObjectFactory.makeCycVariable("?COUNTRY");
        
        response = CycAccess.current().askWithVariable(query, 
                countryVariable, mt);

        func=new CountryDataFunction();
        func.setMicrotheory(mt);
        func.setPredicateValueGetter(this);
        
        collection=Algorithms.collect(
                Algorithms.apply(response.iterator(), func));
        
        return collection;
    }

After refactoring

public Collection getCountryList(CycConstant mt) 
throws CycApiException, IOException {
        CountryDataFunction func = null;

        func = new CountryDataFunction();
        func.setMicrotheory(mt);
        func.setCycAccessHelper(this);

        return performQuery(mt, "(#$isa ?COUNTRY #$Country)",
                "?COUNTRY", func);
    }

5.2. Refactoring DataAccessLayer.getCivilServantsList (step 2)

Before refactoring

public Collection getCivilServantsList(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable civilServantVariable = null;
        CivilServantDataFunction func=null;        
        Collection collection=null;
       
        query = CycAccess.current().makeCycList(
		"(#$isa ?CIVIL_SERVANT #$CivilServant)");
        civilServantVariable =
		CycObjectFactory.makeCycVariable("?CIVIL_SERVANT");
        
        response = CycAccess.current().askWithVariable(query, 
                civilServantVariable, mt);
        
        func=new CivilServantDataFunction();
        func.setMicrotheory(mt);
        func.setPredicateValueGetter(this);
        
        collection=Algorithms.collect(
		Algorithms.apply(response.iterator(), func));
        
        return collection;
    }

After refactoring

public Collection getCivilServantsList(CycConstant mt)
            throws CycApiException, IOException {
        CivilServantDataFunction func = null;

        func = new CivilServantDataFunction();
        func.setMicrotheory(mt);
        func.setCycAccessHelper(this);

        return performQuery(mt, 
		"(#$isa ?CIVIL_SERVANT #$CivilServant)", 
		"?CIVIL_SERVANT", 
		func);
    }

5.3. Refactoring DataAccessLayer.getHeadOfDepartmentList (step 2)

Before refactoring

public Collection getHeadOfDepartmentList(CycConstant mt)
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable departmentVariable = null;
        CycVariable headVariable = null;
        DepartmentDataWithHeadFunction func=null;
        Collection collection=null;
        ArrayList variables=null;
       
        query = CycAccess.current().makeCycList(
		"(#$headOfDepartment ?HEAD_OF_DEPARTMENT ?DEPARTMENT)");
        departmentVariable = 
		CycObjectFactory.makeCycVariable("?DEPARTMENT");
        headVariable = 
		CycObjectFactory.makeCycVariable("?HEAD_OF_DEPARTMENT");
        
        variables=new ArrayList();
        variables.add(departmentVariable);
        variables.add(headVariable);
        
        response = CycAccess.current().askWithVariables(query, 
                variables, mt);
        
        func=new DepartmentDataWithHeadFunction();
        func.setCycAccessHelper(this);
        func.setMicrotheory(mt);
        
        collection=Algorithms.collect(
		Algorithms.apply(response.iterator(), func));
        
        return collection;
    }

After refactoring

public Collection getHeadOfDepartmentList(CycConstant mt)
throws CycApiException, IOException {
        DepartmentDataWithHeadFunction func = null;

        func = new DepartmentDataWithHeadFunction();
        func.setCycAccessHelper(this);
        func.setMicrotheory(mt);

        return performQuery(mt,
                "(#$headOfDepartment ?HEAD_OF_DEPARTMENT ?DEPARTMENT)",
                new String[] { "?DEPARTMENT", "?HEAD_OF_DEPARTMENT" }, 
		func);
    }

5.4. Refactoring DataAccessLayer.getRabinovichRoles (step 2)

Before refactoring

public String[] getRabinovichRoles(CycConstant mt) 
throws CycApiException, IOException
    {
        CycList query = null;
        CycList response = null;
        CycVariable propertyVariable = null;
        Collection collection=null;
       
        query = CycAccess.current().makeCycList(
	"(#$isa #$MokiiNilovichRabinovich ?PROPERTY)");
        propertyVariable = 
		CycObjectFactory.makeCycVariable("?PROPERTY");
        
        response = CycAccess.current().askWithVariable(query, 
                propertyVariable, mt);

        collection=Algorithms.collect(
		Algorithms.apply(response.iterator(), 
		new ToStringFunction()));
        
        return (String[])collection.
		toArray(new String[collection.size()]);
    }

After refactoring

public String[] getRabinovichRoles(CycConstant mt) 
throws CycApiException, IOException {
        Collection collection = null;

        collection = this.performQuery(mt,
                "(#$isa #$MokiiNilovichRabinovich ?PROPERTY)", 
		"?PROPERTY",
                new ToStringFunction());
        
        return (String[]) collection.
		toArray(
		new String[collection.size()]);
    }

5.5. Refactoring DataAccessLayer.getCivilServantsWithSubordinates (step 2)

Before refactoring

public CivilServantData[]
getCivilServantsWithSubordinates(CycConstant mt)
throws CycApiException, IOException {
        CycList query = null;
        CycList response = null;
        CycVariable bossVariable = null;
        CycVariable subordinateVariable = null;
        CivilServantDataFunction func = null;
        ArrayList variables = null;
        Collection collection = null;

        collection = new Vector();

        query = CycAccess.current().makeCycList(
		"(#$superiors ?BOSS ?SUBORD)");
        bossVariable = 
		CycObjectFactory.makeCycVariable("?BOSS");
        subordinateVariable = 
		CycObjectFactory.makeCycVariable("?SUBORD");

        variables = new ArrayList();
        variables.add(bossVariable);
        variables.add(subordinateVariable);

        response = 
		CycAccess.current().askWithVariables(query, variables, mt);

        func = new CivilServantDataFunction();
        func.setCycAccessHelper(this);
        func.setMicrotheory(mt);

        collection = Algorithms.collect(
		Algorithms.apply(Algorithms.apply(
                response.iterator(), new FirstFunction()), func));

        return (CivilServantData[]) collection
                .toArray(new CivilServantData[collection.size()]);
    }

After refactoring

public CivilServantData[]
getCivilServantsWithSubordinates(CycConstant mt)
throws CycApiException, IOException {
        CivilServantDataFunction convert = null;
        UnaryFunction first = null;
        CompositeUnaryFunction compositeFunction = null;
        Collection collection = null;

        first = new FirstFunction();

        convert = new CivilServantDataFunction();
        convert.setCycAccessHelper(this);
        convert.setMicrotheory(mt);

        compositeFunction = Composite.function(convert, first);

        collection = this.performQuery(mt, 
	"(#$superiors ?BOSS ?SUBORD)",
        new String[] { "?BOSS", "?SUBORD" }, 
	compositeFunction);

        return (CivilServantData[]) collection
                .toArray(new CivilServantData[collection.size()]);
    }

5.6. Refactoring DataAccessLayer.getBossOfBagaturLobo (step 2)

Before refactoring

public CivilServantData[] getBossOfBagaturLobo(CycConstant mt)
throws CycApiException, IOException {
        CycList query = null;
        CycList response = null;
        CycVariable bossVariable = null;
        CivilServantDataFunction func=null;        
        ArrayList variables = null;
        Collection collection = null;

        collection = new Vector();

        query = CycAccess.current().makeCycList(
                "(#$superiors ?BOSS #$BagaturLobo)");
        bossVariable = 
		CycObjectFactory.makeCycVariable("?BOSS");

        response = 
		CycAccess.current().askWithVariable(
			query, bossVariable, mt);
        
        func=new CivilServantDataFunction();
        func.setCycAccessHelper(this);
        func.setMicrotheory(mt);
        
        
        collection=Algorithms.collect(
		Algorithms.apply(response.iterator(), func));
        
        return (CivilServantData[]) collection
                .toArray(new CivilServantData[collection.size()]);
    }

After refactoring

public CivilServantData[] getBossOfBagaturLobo(CycConstant mt)
throws CycApiException, IOException {
        CivilServantDataFunction convert = null;
        Collection collection = null;

        convert = new CivilServantDataFunction();
        convert.setCycAccessHelper(this);
        convert.setMicrotheory(mt);

        collection = 
		this.performQuery(mt, 
		"(#$superiors ?BOSS #$BagaturLobo)",
                "?BOSS", 
		convert);

        return (CivilServantData[]) collection
                .toArray(
			new CivilServantData[collection.size()]);
    }

6. Appendix 3: Related materials