1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xalan.internal.xsltc.compiler.util;
  22 
  23 import java.util.ArrayList;
  24 import java.util.List;
  25 
  26 /**
  27  * @author Jacek Ambroziak
  28  * @author Santiago Pericas-Geertsen
  29  * @LastModified: Oct 2017
  30  */
  31 public final class MethodType extends Type {
  32     private final Type _resultType;
  33     private final List<Type> _argsType;
  34 
  35     public MethodType(Type resultType) {
  36         _argsType = null;
  37         _resultType = resultType;
  38     }
  39 
  40     public MethodType(Type resultType, Type arg1) {
  41         if (arg1 != Type.Void) {
  42             _argsType = new ArrayList<>();
  43             _argsType.add(arg1);
  44         }
  45         else {
  46             _argsType = null;
  47         }
  48         _resultType = resultType;
  49     }
  50 
  51     public MethodType(Type resultType, Type arg1, Type arg2) {
  52         _argsType = new ArrayList<>(2);
  53         _argsType.add(arg1);
  54         _argsType.add(arg2);
  55         _resultType = resultType;
  56     }
  57 
  58     public MethodType(Type resultType, Type arg1, Type arg2, Type arg3) {
  59         _argsType = new ArrayList<>(3);
  60         _argsType.add(arg1);
  61         _argsType.add(arg2);
  62         _argsType.add(arg3);
  63         _resultType = resultType;
  64     }
  65 
  66     public MethodType(Type resultType, List<Type> argsType) {
  67         _resultType = resultType;
  68         _argsType = argsType.size() > 0 ? argsType : null;
  69     }
  70 
  71     public String toString() {
  72         StringBuffer result = new StringBuffer("method{");
  73         if (_argsType != null) {
  74             final int count = _argsType.size();
  75             for (int i=0; i<count; i++) {
  76                 result.append(_argsType.get(i));
  77                 if (i != (count-1)) result.append(',');
  78             }
  79         }
  80         else {
  81             result.append("void");
  82         }
  83         result.append('}');
  84         return result.toString();
  85     }
  86 
  87     public String toSignature() {
  88         return toSignature("");
  89     }
  90 
  91     /**
  92      * Returns the signature of this method that results by adding
  93      * <code>lastArgSig</code> to the end of the argument list.
  94      */
  95     public String toSignature(String lastArgSig) {
  96         final StringBuffer buffer = new StringBuffer();
  97         buffer.append('(');
  98         if (_argsType != null) {
  99             final int n = _argsType.size();
 100             for (int i = 0; i < n; i++) {
 101                 buffer.append((_argsType.get(i)).toSignature());
 102             }
 103         }
 104         return buffer
 105             .append(lastArgSig)
 106             .append(')')
 107             .append(_resultType.toSignature())
 108             .toString();
 109     }
 110 
 111     public com.sun.org.apache.bcel.internal.generic.Type toJCType() {
 112         return null;    // should never be called
 113     }
 114 
 115     public boolean identicalTo(Type other) {
 116         boolean result = false;
 117         if (other instanceof MethodType) {
 118             final MethodType temp = (MethodType) other;
 119             if (_resultType.identicalTo(temp._resultType)) {
 120                 final int len = argsCount();
 121                 result = len == temp.argsCount();
 122                 for (int i = 0; i < len && result; i++) {
 123                     final Type arg1 = _argsType.get(i);
 124                     final Type arg2 = temp._argsType.get(i);
 125                     result = arg1.identicalTo(arg2);
 126                 }
 127             }
 128         }
 129         return result;
 130     }
 131 
 132     public int distanceTo(Type other) {
 133         int result = Integer.MAX_VALUE;
 134         if (other instanceof MethodType) {
 135             final MethodType mtype = (MethodType) other;
 136             if (_argsType != null) {
 137                 final int len = _argsType.size();
 138                 if (len == mtype._argsType.size()) {
 139                     result = 0;
 140                     for (int i = 0; i < len; i++) {
 141                         Type arg1 = _argsType.get(i);
 142                         Type arg2 = mtype._argsType.get(i);
 143                         final int temp = arg1.distanceTo(arg2);
 144                         if (temp == Integer.MAX_VALUE) {
 145                             result = temp;  // return MAX_VALUE
 146                             break;
 147                         }
 148                         else {
 149                             result += arg1.distanceTo(arg2);
 150                         }
 151                     }
 152                 }
 153             }
 154             else if (mtype._argsType == null) {
 155                 result = 0;   // both methods have no args
 156             }
 157         }
 158         return result;
 159     }
 160 
 161     public Type resultType() {
 162         return _resultType;
 163     }
 164 
 165     public List<Type> argsType() {
 166         return _argsType;
 167     }
 168 
 169     public int argsCount() {
 170         return _argsType == null ? 0 : _argsType.size();
 171     }
 172 }