//==================================================================================================
// J a v a                                                                                     Java
// R e f l e c t i o n
// J i r k C o n s t r u c t o r
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This library 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 Library General Public License for more details (http://www.gnu.org).

/*DESCRIPTION*/
/* This module provides a class to build the Jirk++ representation of a Java constructor. */

// Package //---------------------------------------------------------------------------------------
package bpp.java.reflection;

// Inportation //-----------------------------------------------------------------------------------
import java.lang.reflect.*;
import java.util.*;

@SuppressWarnings("unchecked")

// J i r k C o n s t r u c t o r  Class //----------------------------------------------------------
/*CLASS JirkConstructor */
/* Represents a constructor of a Java class and its Jirk++ representation. */
public class JirkConstructor {
 //---------------------------------------------------------------------------------------Attributes
 protected JirkClass   atArgumentS[]; // Types of the arguments of the constructor.
 protected JirkClass   atClass;       // Class the constructor belongs to.
 protected Constructor atConstructor; // Reference of the constructor.
 //-----------------------------------------------------------------------------------BuildArguments
 // Builds a list of the types of the constructor's arguments.
 protected void buildArguments() {
  Class lcClassS[] = atConstructor.getParameterTypes();
  int   lcCounter  = 0;

  atArgumentS=new JirkClass[lcClassS.length];

  while (lcCounter<lcClassS.length) {
   atArgumentS[lcCounter]=new JirkClass(lcClassS[lcCounter]);
   ++lcCounter;
  }
 }
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD JirkConstructor */
 /* Builds an object representing a given constructor of a given class. */
 public JirkConstructor(JirkClass agClass,Constructor agConstructor) {
  atClass=agClass;
  atConstructor=agConstructor;
  buildArguments();
 }
 //----------------------------------------------------------------------------------------Signature
 /*METHOD JirkConstructor */ /* Returns the JNI signature of the constructor. */
 public String signature() {
  int    lcCounter = 0;
  String lcString  = "(";

  while (lcCounter<atArgumentS.length) {
   lcString+=atArgumentS[lcCounter].signature();
   lcCounter++;
  }

  return (lcString+")V");
 }
 //------------------------------------------------------------------------------------ArgumentTypes
 /*METHOD JirkConstructor */ /* Returns the types of the arguments of the constructor. */
 public JirkClass[] argumentTypes() { return (atArgumentS); }
 //-----------------------------------------------------------------------------------------IsPublic
 /*METHOD JirkConstructor */ /* Indicates if the constructor is public. */
 public boolean isPublic() { return (Modifier.isPublic(atConstructor.getModifiers())); }
 //--------------------------------------------------------------------------------------Declaration
 /*METHOD JirkConstructor */ /* Returns the Jirk++ declaration of the constructor. */
 public Vector declaration() {
  String lcString;

  int    lcCounter = 0;
  Vector lcLineS   = new Vector();

  lcString=" public_property static jyObject j_new(";

  if (argumentTypes().length==0) lcString+="void";
  else {
   while (lcCounter<argumentTypes().length) {
    if (!argumentTypes()[lcCounter].isArray()) lcString+="const ";
    lcString+=argumentTypes()[lcCounter].fullName()+" &";
    ++lcCounter;
    if (lcCounter<argumentTypes().length) lcString+=",";
   }
  }

  lcLineS.add(lcString+");");
  return (lcLineS);
 }
 //---------------------------------------------------------------------------------------Definition
 /*METHOD JirkConstructor */ /* Returns the Jirk++ definition of the constructor. */
 public Vector definition() {
  String lcString;

  String lcClass   = atClass.shortName()+"::atClassPointer()";
  int    lcCounter = 0;
  Vector lcLineS   = new Vector();

  lcString="property jyObject "+atClass.shortName()+"::j_new(";

  if (argumentTypes().length==0) lcString+="void";
  else {
   while (lcCounter<argumentTypes().length) {
    if (!argumentTypes()[lcCounter].isArray()) lcString+="const ";
    lcString+=argumentTypes()[lcCounter].fullName()+" & agValue"+(lcCounter+1);
    ++lcCounter;
    if (lcCounter<argumentTypes().length) lcString+=",";
   }
  }

  lcLineS.add(lcString+") {");

  lcLineS.add(" safe_static jyMethod lcConstructor = clContext().getConstructor"+
              "("+lcClass+",\""+signature()+"\");");

  lcCounter=0;

  while (lcCounter<argumentTypes().length) {
   if (argumentTypes()[lcCounter].isArray())
    lcLineS.add(" agValue"+(1+lcCounter)+".synchronizeJavaSide();");

   ++lcCounter;
  }

  lcString=" jyObject lcReturn = clContext().newObject("+lcClass+",lcConstructor";

  lcCounter=0;
  while (lcCounter<argumentTypes().length) {
   if (argumentTypes()[lcCounter].isPrimitive()) lcString+=",agValue"+(1+lcCounter);
   else lcString+=",agValue"+(1+lcCounter)+".jniPointer()";

   ++lcCounter;
  }

  lcLineS.add(lcString+");");
  lcCounter=0;

  while (lcCounter<argumentTypes().length) {
   if (argumentTypes()[lcCounter].isArray())
    lcLineS.add(" agValue"+(1+lcCounter)+".synchronizeNativeSide();");

   ++lcCounter;
  }

  lcLineS.add(" return (lcReturn);");
  lcLineS.add("}");
  return (lcLineS);
 }
}

// End //-------------------------------------------------------------------------------------------