/**
* Copyright (C) 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mujava.op;
import openjava.mop.*;
import java.util.*;
import java.lang.Integer;
/**
* <p>Description: </p>
* @author Yu-Seung Ma
* @version 1.0
*/
public class OverloadingHelper
{
int num = 0;
/**
* Determine whether the return types of two methods are of
* the same type
* @param m1 - method 1
* @param m2 - method 2
* @return true - same type
*/
public boolean sameReturnType(OJMethod m1, OJMethod m2)
{
return ( (m1.getReturnType()).equals(m2.getReturnType()));
}
/**
* Examine the compatibility of two parameters
* @param big_m
* @param small_m
* @return true - compatible
*/
public boolean compatibleParameter(OJMethod big_m, OJMethod small_m)
{
// m1 > m2
OJClass[] bigP = big_m.getParameterTypes();
OJClass[] smallP = small_m.getParameterTypes();
int length = bigP.length;
if (smallP.length > bigP.length)
return false;
if (smallP.length == 0)
return true;
boolean[] flag = new boolean[length];
for (int i=0; i<length; i++)
{
flag[i] = false;
}
int find_num = 0;
for (int i=0; i<smallP.length ; i++)
{
for (int j=0; j<bigP.length ; j++)
{
if ( (smallP[i].getName()).equals(bigP[j].getName()) && !flag[j])
{
flag[j] = true;
find_num++;
break;
}
}
}
if (find_num != smallP.length)
return false;
else
return true;
}
public Vector locationForParameterType(OJMethod big_m, OJMethod small_m)
{
int i, j;
Vector locInfo = new Vector();
ParameterTypeInfo par_info = null;
OJClass[] bigP = big_m.getParameterTypes();
OJClass[] smallP = small_m.getParameterTypes();
boolean[] check_flag = new boolean[smallP.length];
for (i=0; i<smallP.length ; i++)
{
check_flag[i] = false;
}
for ( i=0; i<smallP.length ; i++ )
{
if (!check_flag[i])
{
par_info = new ParameterTypeInfo();
par_info.type_name = smallP[i].getName();
par_info.sub_position.add(new Integer(i));
check_flag[i] = true;
for ( j=i+1; j<smallP.length; j++)
{
if (par_info.type_name.equals(smallP[j].getName()) )
{
par_info.sub_position.add(new Integer(j));
check_flag[j] = true;
}
}
for ( j=0; j<bigP.length ; j++)
{
if (par_info.type_name.equals(bigP[j].getName()) )
{
par_info.original_position.add(new Integer(j));
}
}
locInfo.add(par_info);
}
}
int n, r;
for (i=0; i<locInfo.size(); i++)
{
par_info = (ParameterTypeInfo)locInfo.elementAt(i);
n = par_info.original_position.size();
r = par_info.sub_position.size();
par_info.combination_num = getPermutationNum(n,r);
par_info.position = new int[par_info.combination_num][r];
int[] n_list = new int[n];
for (j=0; j<n; j++)
{
n_list[j] = j;
}
genEachPermutation(par_info.position, n_list, r, par_info.combination_num, 0);
}
return locInfo;
}
public int[][] genCompatibleLocations(OJMethod big_m, OJMethod small_m)
{
int i, num;
int[][] parIndex = null;
ParameterTypeInfo par_info;
Vector parTypeLocs = locationForParameterType(big_m, small_m);
if (parTypeLocs.size() == 0)
{
return null;
}
else
{
num = 1;
for ( i=0; i<parTypeLocs.size(); i++)
{
par_info = (ParameterTypeInfo)parTypeLocs.elementAt(i);
num = par_info.combination_num * num;
}
try
{
parIndex = new int[num][small_m.getParameterTypes().length];
genIndex(parIndex, parTypeLocs, num, 0, 0);
} catch (Exception e)
{
System.out.println("error : " + e);
}
return parIndex;
}
}
// Calculate nPr
public int getPermutationNum(int n, int r)
{
int result = 1;
for (int i=n; i>(n-r) ; i--)
{
result = result*i;
}
return result;
}
// nCr = n*(n-1)*(n-2) ... *(n-r+1)
public void genEachPermutation(int[][] list, int[] n, int r, int num, int start)
{
int i, j, repeat, index;
repeat = getPermutationNum(n.length-1, r-1);
index = start;
try
{
for (i=0; i<n.length; i++)
{
// nPr�� ������ ������ �κ��϶� n*(n-1)* ... *1
if (n.length == 2 && r == 2)
{
list[index][0] = n[i%2];
list[index][1] = n[(i+1)%2];
index++;
}
else
{ // nCr�� ������ ��
for (j=0; j<repeat; j++)
{
list[index][r-1] = n[i];
index++;
}
if (repeat != 1)
{
int[] sub_n = new int[n.length-1];
removeElement(n, sub_n, n[i]);
genEachPermutation(list, sub_n, r-1, repeat, start+i*repeat);
}
}
}
} catch (Exception e) {
System.err.println("error " + e);
}
}
// ------------------------------------------------------------
// list : permutation information for all parameter type
// parLoc : set of information for each parameter
// num : number of generated permutation
// parIndex : parameter Type index which to generate permutation
// start : start index for list
public void genIndex(int[][] list, Vector parLoc, int num, int parIndex, int start)
{
if (parIndex<parLoc.size())
{
ParameterTypeInfo par_info;
int i, j, k, temp;
int repeat,index;
int length = parLoc.size();
Integer original_value, sub_value;
repeat = 1;
for (i=length-1; i>parIndex; i--)
{
par_info = (ParameterTypeInfo)parLoc.elementAt(i);
repeat = par_info.combination_num*repeat;
}
index = start;
try
{
par_info = (ParameterTypeInfo)parLoc.elementAt(parIndex);
for (i=0; i<par_info.combination_num; i++)
{
for (j=0; j<repeat; j++)
{
for (k=0; k<par_info.sub_position.size(); k++)
{
temp = par_info.position[i][k];
original_value = (Integer)par_info.original_position.elementAt(temp);
sub_value = (Integer)par_info.sub_position.elementAt(k);
list[index][sub_value.intValue()] = original_value.intValue();
}
index++;
}
if ( repeat != 1)
{
genIndex(list, parLoc, repeat, parIndex+1, start+i*repeat);
}
}
} catch (Exception e) {
System.err.println("error " + e);
}
}
}
private void removeElement(int[] original, int[] target, int element)
{
int length = original.length;
int index = 0;
for (int i=0; i<length; i++)
{
if (original[i] != element)
{
target[index] = original[i];
index++;
}
}
}
}
/**
* Template containing parameters' type information
*/
class ParameterTypeInfo
{
String type_name = null;
Vector original_position = new Vector();
Vector sub_position = new Vector();
int combination_num = 0;
int[][] position = null;
}