WestCoastProjects
WestCoastProjects

Reputation: 63231

Converting package object contents from scala to java

I have the unfortunate task of converting a networking library that I wrote couple years back from scala to java due to lack of offshore scala resources.

One of the tricker areas : converting the package object and its type aliases and case classes. Here is an excerpt:

package object xfer {

  type RawData = Array[Byte]
  type DataPtr = String

  type PackedData = RawData
//  type PackedData = (DataPtr, RawData, RawData)
//  type UnpackedData = (DataPtr, Any, RawData)
  type UnpackedData = Any

  case class TaggedEntry(tag: String, data: Array[Byte])

  case class TypedEntry[T](tag: String, t: T)

  case class XferWriteParams(tag: String, config: XferConfig, data: RawData, md5: RawData) {

    override def toString: DataPtr = s"XferWriteParams: config=$config datalen=${data.length}} md5len=${md5.length}}"
  }

As an example the RawData has 32 usages. I suppose that one approach could be to do simple Find/Replace of all 32 instances with byte[]: but is there a more elegant way?

For the case class'es .. I'm leery of creating another few top level files in this package for each of them - and likewise another few top level files in each of a dozen other packages .. but is there any alternative?

Upvotes: 2

Views: 55

Answers (1)

Andrey Tyukin
Andrey Tyukin

Reputation: 44967

ADT-esque trait-case-class clusters like

trait T
case class C1 extends T
case class C2 extends T

could be converted to an abstract base class T, with nested static classes C1, C2:

abstract class T {
  static class C1 extends T { ... }
  static class C2 extends T { ... }
}

This would at least eliminate the need to explode each such enumeration into thousand top-level classes in separate files.

For type-aliases, you might consider promoting them to full fledged wrapper classes, but you would have to be very careful whenever instantiating classes like RawData, using ==/equals, hashCode, or putting them in HashSets or HashMaps. Something like this might work:

class RawData {
    private final byte[] value;
    public RawData(byte[] v) { ... }
    public byte[] getValue() { ... }

    public static RawData of(byte[] value) {
      return new RawData(value);
    }

    @Override public int hashCode() {
        return value.hashCode();
    }
    @Override public boolean equals(Object other) {
        if (other instanceof RawData) {
            return value.equals(((RawData) other).value);
        } else {
            return false;
        }
    }
    @Override public String toString() {
        return String.valueOf(value);
    }
}

This would keep the signatures similar, and might even enhance type-safety to some extent. In cases where it is really performance critical, I'd propose to just find/replace all occurrences by byte[].

Upvotes: 2

Related Questions