Skip to content

Commit

Permalink
feat(objectionary#636): hide fields of XmlClassProperties
Browse files Browse the repository at this point in the history
  • Loading branch information
volodya-lombrozo committed Sep 6, 2024
1 parent 4d4c76d commit 56f5db9
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,15 @@ public XML xml() {
*/
public Bytecode bytecode() {
try {
this.props.write(this.visitor, this.name);
this.visitor.visit(
this.props.version(),
this.props.access(),
this.name,
this.props.signature(),
this.props.supername(),
this.props.interfaces()
);

this.annotations.forEach(annotation -> annotation.write(this.visitor));
this.fields.forEach(field -> field.write(this.visitor));
this.methods.forEach(BytecodeMethod::write);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
package org.eolang.jeo.representation.bytecode;

import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eolang.jeo.representation.DefaultVersion;
import org.objectweb.asm.ClassVisitor;
Expand All @@ -33,6 +34,7 @@
* @since 0.1.0
*/
@ToString
@EqualsAndHashCode
public final class BytecodeClassProperties {

/**
Expand Down Expand Up @@ -68,6 +70,22 @@ public BytecodeClassProperties(final int access) {
this(new DefaultVersion().bytecode(), access, null, "java/lang/Object", new String[0]);
}

/**
* Constructor.
* @param access Access modifiers.
* @param signature Signature.
* @param supername Supername.
* @param interfaces Interfaces.
*/
public BytecodeClassProperties(
final int access,
final String signature,
final String supername,
final String... interfaces
) {
this(new DefaultVersion().bytecode(), access, signature, supername, interfaces);
}

/**
* Constructor.
* @param version Bytecode version.
Expand All @@ -91,6 +109,27 @@ public BytecodeClassProperties(
this.interfaces = interfaces.clone();
}


public int version() {
return this.version;
}

public int access() {
return this.access;
}

public String signature() {
return this.signature;
}

public String supername() {
return this.supername;
}

public String[] interfaces() {
return this.interfaces;
}

/**
* Start writing a class by using a class writer.
* @param visitor Class visitor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public Bytecode bytecode() {
final XmlClass clazz = program.top();
final BytecodeClass bytecode = new BytecodeClass(
new ClassName(program.pckg(), new PrefixedName(clazz.name()).decode()).full(),
clazz.properties().toBytecodeProperties(),
clazz.properties().bytecode(),
this.verify
);
clazz.annotations().ifPresent(bytecode::withAnnotations);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,6 @@
* XML representation of a class.
*
* @since 0.1.0
* @todo #627:30min Improve Encapsulation of XmlClassProperties.
* Currently we are exposing many methods like:
* - {@link XmlClassProperties#access()}
* - {@link XmlClassProperties#signature()}
* - {@link XmlClassProperties#supername()}
* - {@link XmlClassProperties#interfaces()}
* They are some sort of getters. This encapsulation violation tells us about poor design.
* We need to hide this methods and provide a better way to access this properties.
* Most probably the problem is deeper than just hiding the methods. We need to rethink the design.
*/
public final class XmlClassProperties {

Expand All @@ -53,31 +44,52 @@ public final class XmlClassProperties {
* Constructor.
* @param clazz XMl representation of a class.
*/
public XmlClassProperties(final XmlNode clazz) {
XmlClassProperties(final XmlNode clazz) {
this(clazz.asDocument());
}

/**
* Constructor.
* @param clazz XML representation of a class.
*/
public XmlClassProperties(final XMLDocument clazz) {
private XmlClassProperties(final XMLDocument clazz) {
this.clazz = clazz;
}

/**
* Convert to bytecode properties.
* @return Bytecode properties.
*/
public BytecodeClassProperties bytecode() {
try {
return new BytecodeClassProperties(
this.version(),
this.access(),
this.signature(),
this.supername(),
this.interfaces()
);
} catch (final IllegalArgumentException exception) {
throw new IllegalArgumentException(
String.format("Invalid class properties: %s", this.clazz),
exception
);
}
}

/**
* Retrieve 'access' modifiers of a class.
* @return Access modifiers.
*/
public int access() {
private int access() {
return new HexString(this.clazz.xpath("./o[@name='access']/text()").get(0)).decodeAsInt();
}

/**
* Retrieve 'signature' of a class.
* @return Signature.
*/
public String signature() {
private String signature() {
return this.clazz.xpath("./o[@name='signature']/text()")
.stream()
.map(HexString::new)
Expand All @@ -90,7 +102,7 @@ public String signature() {
* Retrieve 'supername' of a class.
* @return Supername.
*/
public String supername() {
private String supername() {
return this.clazz.xpath("./o[@name='supername']/text()")
.stream()
.map(HexString::new)
Expand All @@ -102,7 +114,7 @@ public String supername() {
* Retrieve 'interfaces' of a class.
* @return Interfaces.
*/
public String[] interfaces() {
private String[] interfaces() {
return this.clazz.xpath("./o[@name='interfaces']/o/text()")
.stream()
.map(HexString::new)
Expand All @@ -113,7 +125,7 @@ public String[] interfaces() {
* Retrieve bytecode 'version'.
* @return Bytecode version.
*/
int version() {
private int version() {
final List<String> version = this.clazz.xpath("./o[@name='version']/text()");
final int result;
if (version.isEmpty()) {
Expand All @@ -123,26 +135,5 @@ int version() {
}
return result;
}

/**
* Convert to bytecode properties.
* @return Bytecode properties.
*/
BytecodeClassProperties toBytecodeProperties() {
try {
return new BytecodeClassProperties(
this.version(),
this.access(),
this.signature(),
this.supername(),
this.interfaces()
);
} catch (final IllegalArgumentException exception) {
throw new IllegalArgumentException(
String.format("Invalid class properties: %s", this.clazz),
exception
);
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.jcabi.xml.XMLDocument;
import org.eolang.jeo.matchers.SameXml;
import org.eolang.jeo.representation.ClassName;
import org.eolang.jeo.representation.bytecode.BytecodeClassProperties;
import org.eolang.jeo.representation.xmir.XmlClass;
import org.eolang.jeo.representation.xmir.XmlNode;
import org.hamcrest.MatcherAssert;
Expand Down Expand Up @@ -125,24 +126,16 @@ void convertsToDirectives() throws ImpossibleModificationException {
Matchers.equalTo(name)
);
MatcherAssert.assertThat(
"Class access is not equal to expected",
clazz.properties().access(),
Matchers.equalTo(access)
);
MatcherAssert.assertThat(
"Class signature is not equal to expected",
clazz.properties().signature(),
Matchers.equalTo(signature)
);
MatcherAssert.assertThat(
"Class supername is not equal to expected",
clazz.properties().supername(),
Matchers.equalTo(supername)
);
MatcherAssert.assertThat(
"Class interface is not equal to expected",
clazz.properties().interfaces()[0],
Matchers.equalTo(interfce)
"Class properties are not equal to expected",
clazz.properties().bytecode(),
Matchers.equalTo(
new BytecodeClassProperties(
access,
signature,
supername,
interfce
)
)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ void retrievesAccessModifier() {
final int actual = new XmlClass(
"Language",
new DirectivesClassProperties(expected)
).properties().access();
).properties().bytecode().access();
MatcherAssert.assertThat(
String.format(
"Can't retrieve access modifier correctly, expected %d (public abstract class), got %d",
Expand All @@ -59,7 +59,7 @@ void retrievesSignature() {
final String expected = "Ljava/util/List<Ljava/lang/String;>;";
final String actual = new XmlClass(
new DirectivesClassProperties(0, expected)
).properties().signature();
).properties().bytecode().signature();
MatcherAssert.assertThat(
String.format(
"Can't retrieve signature correctly, expected %s, got %s",
Expand All @@ -76,6 +76,7 @@ void retrievesSupernameIfDefined() {
final String expected = "some/custom/Supername";
final String supername = new XmlClass(new DirectivesClassProperties(0, "", expected))
.properties()
.bytecode()
.supername();
MatcherAssert.assertThat(
String.format(
Expand All @@ -93,6 +94,7 @@ void retrievesSupernameIfItIsNotDefinedExplicitly() {
final String expected = "java/lang/Object";
final String supername = new XmlClass("DefaultClass")
.properties()
.bytecode()
.supername();
MatcherAssert.assertThat(
String.format(
Expand All @@ -110,6 +112,7 @@ void retrievesInterfacesIfTheyAreDefined() {
final String[] expected = {"java/util/List", "java/util/Collection"};
final String[] interfaces = new XmlClass(new DirectivesClassProperties(0, "", "", expected))
.properties()
.bytecode()
.interfaces();
MatcherAssert.assertThat(
String.format(
Expand All @@ -126,6 +129,7 @@ void retrievesInterfacesIfTheyAreDefined() {
void retrievesInterfacesIfTheyAreNotDefinedExplicitly() {
final String[] interfaces = new XmlClass("WithoutIntefaces")
.properties()
.bytecode()
.interfaces();
MatcherAssert.assertThat(
String.format(
Expand Down

0 comments on commit 56f5db9

Please sign in to comment.