Traducción de C# a Java: Uso de la lógica del .NET Framework en el entorno Java

La traducción de algunos proyectos de un idioma a otro no sólo implica cambios en el código fuente, sino también en el entorno en el que se ejecuta el proyecto. CodePorting.Translator Java Class Library implementa dicho entorno sobre JCL (Java class library), manteniendo la lógica y la estructura de la biblioteca de clases .NET Framework, que hace que un proyecto traducido se sienta como en casa, ocultándolo de la implementación de la plataforma Java.

CodePorting.Translator Java Class Library

JCL (biblioteca de clases Java) difiere de la biblioteca de clases .NET en el diseño común, el manejo de excepciones y la lógica. Por lo tanto, si decidimos traducir nuestro código de C# a Java, no sería seguro simplemente reemplazar los nombres de las clases y funciones. Podría haber una solución para generar código envolvente, que reprodujera la lógica de la biblioteca de clases de .NET Framework. Pero, de esta forma el código Java resultante diferiría significativamente del código C# original, que no es lo que esperamos – queremos un traductor que mantenga la estructura original del programa. Aquí estamos llegando a la necesidad de implementar un reemplazo Java de la librería de clases de .NET Framework.

Cómo funciona

Empecemos por algo sencillo :

using System;

class Program
{
    public static void Main(string[] args)
    {
        Console.WriteLine("Hello, Example!");
    }
}

Tenemos aquí una clase de la biblioteca de clases de .NET Framework – System.Console.
¿Cómo se vería el código Java traducido?

import com.codeporting.ms.System.Console;

class Program
{
    public static void main(String[] args)
    {
        Console.writeLine("Hello, Example!");
    }
}

Como puede ver, el traductor sustituye la referencia de la clase C# System.Console a la clase Java com.codeporting.ms.System.Console, implementada en la CodePorting.Translator Java Class Library.

Bien, ahora veamos otro ejemplo :

using System;
using System.Collections.Generic;

class Program
{
    public static void Main(string[] args)
    {
        PrintList(new List<string> { "Hello, list!", "I have a list for you to print!" });
    }
    public static void PrintList(List<string> list)
    {
        foreach(var item in list) Console.WriteLine(item);
    }
}

El código Java traducido sería este :

import com.codeporting.ms.System.Collections.Generic.IGenericEnumerable;
import com.codeporting.ms.System.Collections.Generic.List;
import com.codeporting.ms.System.Console;
import com.codeporting.ms.System.IDisposable;
import java.util.Iterator;

class Program
{
    public static void main(String[] args)
    {
        List<String> tmp = new List<String>();
        tmp.addItem("Hello, list!");
        tmp.addItem("I have a list for you to print!");
        printList(tmp);
    }
    public static void printList(IGenericEnumerable<String> list)
    {
        //Foreach to while statement conversion
        Iterator<String> variable1 = list.iterator();
        try
        {
            while (variable1.hasNext())
            {
                String item = variable1.next();
                Console.writeLine(item);
            }
        }
        finally
        {
            if (variable1 != null)
            {
                ((IDisposable)variable1).dispose();
            }
        }
    }
}

Aquí vemos un beneficio más del uso de CodePorting.Translator Java Class Library – mantenemos relaciones entre abstracciones de C#. System.Collections.Generic.List implementa la interfaz IEnumerable, lo que nos permite iterar a través de ella usando el bucle foreach. Java tiene la interfaz java.lang.Iterable, y es similar a IEnumerable, pero tienen pequeñas diferencias en el diseño, que pueden llegar a ser decisivas para un proyecto grande.

Pureza de la API pública

Aunque tenemos una buena biblioteca para usar, un proyecto que traducimos necesita ser accesible y comprensible por los clientes, y ellos pueden preferir usar clases JCL. Sería bueno ocultar al mundo exterior que usamos CodePorting.Translator Java Class Library. Y, aquí tenemos otra interesante característica de CodePorting.Translator : ApiChange. ¿Qué hace esta función? Oculta métodos que utilizan CodePorting.Translator Java Class Library, creando métodos proxy que utilizan clases JCL. Veamos el ejemplo :

using System;
using System.Collections.Generic;
using System.Linq;

namespace Newspaper
{
    public class Article
    {
        public DateTime Published { get; set; }
        public string Content { get; set; }
    }

    public class Archive
    {
        List<Article> articles = new List<Article>();

        public void AddArticle(Article article)
        {
            articles.Add(article);
        }

        public IEnumerable<Article> GetArticlesForPeriod(DateTime start, DateTime end)
        {
            if(start > end || start > DateTime.Now)
            {
                return new Article[0];
            }
            return articles.Where(article => article.Published >= start && article.Published <= end);
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            var archive = new Archive();
            archive.AddArticle(
                new Article() {
                    Published = new DateTime(2012, 12, 20), Content = "End of the world comes tomorrow!" });
            archive.AddArticle(
                new Article() {
                    Published = new DateTime(2012, 12, 22), Content = "It was a huge joke..." });
            var articles = archive.GetArticlesForPeriod(
                new DateTime(2000, 1, 1),
                new DateTime(2012, 12, 21));
            foreach(var article in articles)
            {
                Console.WriteLine(article.Content);
            }
        }
    }
}

Puedes ver aquí una simple clase Archive que almacena algunos artículos y proporciona acceso a ellos, aplicando un filtro por la fecha en la que el artículo fue publicado. La clase System.DateTime forma parte de la librería de clases de .NET Framework, y, aunque podemos utilizarla en nuestro proyecto, nos gustaría ocultarla del mundo exterior :

Article.java

package Newspaper;

import com.codeporting.ms.System.DateTime;
import java.util.Date;

public class Article
{
    private DateTime auto_Published = new DateTime();
    final DateTime getPublishedInternal() { return auto_Published.Clone(); }
    public final Date getPublished() {
        return DateTime.toJava(getPublishedInternal());
    }
    final void setPublishedInternal(DateTime value) { auto_Published = value.Clone(); }
    public final void setPublished(Date value) {
        setPublishedInternal(DateTime.fromJava(value));
    }
    private String auto_Content;
    public final String getContent() { return auto_Content; }
    public final void setContent(String value) { auto_Content = value; }
}

Archive.java

package Newspaper;

import com.codeporting.ms.System.Collections.Generic.IGenericEnumerable;
import com.codeporting.ms.System.Collections.Generic.List;
import com.codeporting.ms.System.DateTime;
import com.codeporting.ms.System.Func;
import java.util.Date;

public class Archive
{
    private Archive[] Archive_this = {this};
    private List<Article> articles = new List<Article>();

    public final void addArticle(Article article)
    {
        articles.addItem(article);
    }

    final IGenericEnumerable<Article> getArticlesForPeriodInternal(DateTime start, DateTime end)
    {
        if(DateTime.op_GreaterThan(start, end) || DateTime.op_GreaterThan(start, DateTime.getNow()))
        {
            return com.codeporting.ms.System.Array.<Article>toGenericList(new Article[0]);
        }
        return articles.where(new Func<Article,Boolean>() {
            public String getDelegateId() {
                return System.identityHashCode(Archive_this[0]) + "-89480671";
            }
            public Boolean invoke(Newspaper.Article article) {
                return DateTime.op_GreaterThanOrEqual(article.getPublishedInternal(), start) 
                    && DateTime.op_LessThanOrEqual(article.getPublishedInternal(), end);
            }
        });
    }

    public final java.lang.Iterable<Article> getArticlesForPeriod(Date start, Date end)
    {
        IGenericEnumerable<Article> temp=getArticlesForPeriodInternal(
            DateTime.fromJava(start),
            DateTime.fromJava(end));
        java.util.ArrayList<Article> temp_java=new java.util.ArrayList<Article>();
        {
            com.codeporting.ms.System.Collections.Generic.IGenericEnumerator<Article> temp_iterator=temp.iterator();
            while(temp_iterator.hasNext())
            {
                Article element=temp_iterator.next();
                temp_java.add(element);
            }
        }
        return temp_java;
    }
}

Program.java

package Newspaper;

import com.codeporting.ms.System.Collections.Generic.IGenericEnumerable;
import com.codeporting.ms.System.Console;
import com.codeporting.ms.System.DateTime;
import com.codeporting.ms.System.IDisposable;
import java.util.Iterator;

public class Program
{
    public static void main(String[] args)
    {
        Archive archive = new Archive();
        Article tmp = new Article();
        tmp.setPublishedInternal(new DateTime(2012, 12, 20));
        tmp.setContent("End of the world comes tomorrow!" ) ;
        archive.addArticle(tmp);
        Article tmp_1 = new Article();
        tmp_1.setPublishedInternal(new DateTime(2012, 12, 22));
        tmp_1.setContent("It was a huge joke..." ) ;
        archive.addArticle(tmp_1);
        IGenericEnumerable<Article> articles = archive.getArticlesForPeriodInternal(
	        new DateTime(2000, 1, 1),
	        new DateTime(2012, 12, 21));
        //Foreach to while statement conversion
        Iterator<Article> variable1 = articles.iterator();
        try
        {
            while (variable1.hasNext())
            {
                Article article = variable1.next();
                Console.writeLine(article.getContent());
            }
        }
        finally
        {
            if (variable1 != null)
            {
                ((IDisposable)variable1).dispose();
            }
        }
    }
}

Traducido al código Java no proporciona acceso a CodePorting.Translator Java Class Library a través de public API, y el mundo Java exterior puede interactuar con nuestra clase Archive, utilizando métodos proxy públicos.

Lo que podemos concluir

CodePorting.Translator Java Class Library proporciona una capa de abstracción y control sobre JCL, que nos distrae de los detalles de implementación y nos permite pensar en los problemas que resolvemos.
También ayuda a mantener la estructura del código original, aumentando la comprensión y la transparencia del resultado de la traducción.

Artículos relacionados: