How to deserialize JSON with private constructor and interfaces as Builder? - java

I've searched the internet for something to similar to what I'm doing, but haven't found anything. I'm using interfaces in Java 8 to create a Builder pattern, like so:
public class UrlImmutable {
public final String parentUrl;
public final Double parentUrlSentiment;
public final Set<String> childUrls;
public final boolean isParentVendorUrl;
public final Map<TagClassification, Set<String>> parentUrlArticleTags;
private UrlImmutable(String parentUrl, Double parentUrlSentiment, Set<String> childUrls, boolean isParentVendorUrl,
Map<TagClassification, Set<String>> parentUrlArticleTags ) {
super();
this.parentUrl = parentUrl;
this.parentUrlSentiment = parentUrlSentiment;
this.childUrls = childUrls;
this.isParentVendorUrl = isParentVendorUrl;
this.parentUrlArticleTags = parentUrlArticleTags;
}
/** Our Interfaces for the Builder **/
public interface ParentUrlBuilder {
ParentUrlSentimentBuilder parentUrl(String parentUrl);
}
public interface ParentUrlSentimentBuilder {
ChildUrlBuilder parentUrlSentiment(Double parentUrlSentiment);
}
public interface ChildUrlBuilder {
IsVendorUrlBuilder childUrls(Set<String> childUrls);
}
public interface IsVendorUrlBuilder {
ParentUrlArticleTagsBuilder isParentVendorUrl(boolean isParentVendorUrl);
}
public interface ParentUrlArticleTagsBuilder {
UrlImmutable parentUrlArticleTags(Map<TagClassification,Set<String>> parentUrlArticleTags);
}
public static ParentUrlBuilder discoveredUrl() {
return parentUrl -> parentUrlSentiment -> childUrls -> isParentVendorUrl -> parentUrlArticleTags ->
new UrlImmutable(parentUrl, parentUrlSentiment, childUrls, isParentVendorUrl, parentUrlArticleTags);
}
}
And to construct this object, we do this:
UrlImmutable url =
UrlImmutable()
.parentUrl("http://www.google.com")
.parentUrlSentiment(10.5)
.childUrls(childUrls)
.isParentVendorUrl(true)
.parentUrlArticleTags(parentUrlArticleTags);
I can't seem to find the right combination of annotations for this. Any help much appreciated!

Related

A way of accessing Windows MMDevice API from Java?

I would like to use the MMDevice API from my Java app. What are my options?
I tried to use JNA. Looks like I can't use JNA Typelib parsing because there no types for this API (Is there a COM type library for Windows Core Audio). As suggested, I need to provide my own declarations of the API.
So I also tried both JNA examples with manual declarations but they give "Interface not supported HRESULT=80004002" error:
public class MMDeviceAPITest {
public static void test1() {
try {
Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
var obj = new Test1.MMDeviceEnumerator(); // exception E_NOINTERFACE (HRESULT: 80004002)
// ...
} finally {
Ole32.INSTANCE.CoUninitialize();
}
}
public static void test2() {
try {
Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
var factory = new Factory();
var obj = factory.createObject(Test2.MMDeviceEnumerator.class); // exception E_NOINTERFACE (HRESULT: 80004002)
var in = obj.queryInterface(Test2.IMMDeviceEnumerator.class);
// ...
} finally {
Ole32.INSTANCE.CoUninitialize();
}
}
}
interface Test1 {
class MMDeviceEnumerator extends COMLateBindingObject {
public MMDeviceEnumerator() {
super(new Guid.CLSID("bcde0395-e52f-467c-8e3d-c4579291692e"), true);
}
}
}
interface Test2 {
#ComObject(clsId = "bcde0395-e52f-467c-8e3d-c4579291692e")
interface MMDeviceEnumerator extends IUnknown {} // doesn't extend IUnknown in C sources, probably it's the problem...
#ComInterface(iid = "a95664d2-9614-4f35-a746-de8db63617e6")
interface IMMDeviceEnumerator extends IUnknown {}
}
Any ideas how I could access this API from Java? Can I somehow create working declarations for JNA? Or use another framework maybe?
My last idea is to create/find a micro native app/library that wraps the needed COM calls, so I could call this app/library easily (via subprocesses or simple JNA declarations). I'm new to COM world, but it sounds working for me...
The docs you linked show how to create using CoCreateInstance:
const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
hr = CoCreateInstance(
CLSID_MMDeviceEnumerator, NULL,
CLSCTX_ALL, IID_IMMDeviceEnumerator,
(void**)&pEnumerator);
This should get you somewhere close with JNA.
class MMDeviceEnumerator extends Unknown {
public static final CLSID CLSID_MMDeviceEnumerator = new CLSID("bcde0395-e52f-467c-8e3d-c4579291692e");
public static final GUID IID_IMMDeviceEnumerator = new GUID("a95664d2-9614-4f35-a746-de8db63617e6");
public MMDeviceEnumerator(Pointer p) {
super(p);
}
public static MMDeviceEnumerator create() {
PointerByReference pEnumerator = new PointerByReference();
HRESULT hres = Ole32.INSTANCE.CoCreateInstance(
CLSID_MMDeviceEnumerator, null,
WTypes.CLSCTX_ALL, IID_IMMDeviceEnumerator,
pEnumerator);
if (COMUtils.FAILED(hres)) {
return null;
}
return new MMDeviceEnumerator(pEnumerator.getValue());
}
// map functions as needed
}
I used the implementation of IWbemContext in JNA as a template above. You can consult that class for example COM function mappings.
For some reason I can't suggest edits to the answer of Daniel Widdis. The answer worked for me, many thanks! Just wanted to show how to map one method as an example:
class MMDeviceEnumerator extends Unknown {
public static final CLSID CLSID_MMDeviceEnumerator = new CLSID("bcde0395-e52f-467c-8e3d-c4579291692e");
public static final GUID IID_IMMDeviceEnumerator = new GUID("a95664d2-9614-4f35-a746-de8db63617e6");
public MMDeviceEnumerator(Pointer p) {
super(p);
}
public static MMDeviceEnumerator create() {
PointerByReference pEnumerator = new PointerByReference();
HRESULT hres = Ole32.INSTANCE.CoCreateInstance(
CLSID_MMDeviceEnumerator, null,
WTypes.CLSCTX_ALL, IID_IMMDeviceEnumerator, pEnumerator);
if (COMUtils.FAILED(hres)) {
return null;
}
return new MMDeviceEnumerator(pEnumerator.getValue());
}
public static final int EDataFlow_eRender = 0;
public static final int EDataFlow_eCapture = 1;
public static final int EDataFlow_eAll = 2;
public static final int EDataFlow_enum_count = 3;
public static final int DEVICE_STATE_ACTIVE = 0x1;
public static final int DEVICE_STATE_DISABLED = 0x2;
public static final int DEVICE_STATE_NOTPRESENT = 0x4;
public static final int DEVICE_STATE_UNPLUGGED = 0x8;
public static final int DEVICE_STATEMASK_ALL = 0xF;
public void EnumAudioEndpoints(int dataFlow, int dwStateMask, PointerByReference ppDevices) {
WinNT.HRESULT res = (WinNT.HRESULT) _invokeNativeObject(
3, // `EnumAudioEndpoints` is the 3rd method of `IMMDeviceEnumeratorVtbl` in `mmdeviceapi.h`
new Object[] { getPointer(), dataFlow, new WinDef.DWORD(dwStateMask), ppDevices},
WinNT.HRESULT.class
);
COMUtils.checkRC(res);
}
// map other functions as needed
}

Minecraft Forge Modding 1.18.1 Ore Generation Confusion

This problem doesn't have a solution to me but I hope you will. I have only experienced forge modding in 1.16.5 and in 1.18.1, there is so much Confusion, My Brain is Literally Broken and I have Dizziness just looking at it. I followed a code from 1.17 from TurtyWurty and this is it:
public static final List<ConfiguredFeature<?, ?>> OVERWORLD_ORES = new ArrayList<>();
public static final List<ConfiguredFeature<?, ?>> END_ORES = new ArrayList<>();
public static final List<ConfiguredFeature<?, ?>> NETHER_ORES = new ArrayList<>();
public static final RuleTest END_TEST = new BlockMatchTest(Blocks.END_STONE);
public static void registerOres() {
ConfiguredFeature<?, ?> bronzeOre = Feature.ORE
.configured(new OreConfiguration(List.of(
OreConfiguration.target(OreFeatures.STONE_ORE_REPLACEABLES,
Blocks.GLOWSTONE.defaultBlockState())),
11));
bronzeOre.placed(commonOrePlacement(8, HeightRangePlacement.triangle(VerticalAnchor.bottom(), VerticalAnchor.aboveBottom(20))));
OVERWORLD_ORES.add(register("bronze_ore", bronzeOre));
}
private static <Config extends FeatureConfiguration> ConfiguredFeature<Config, ?> register(String name,
ConfiguredFeature<Config, ?> configuredFeature) {
return Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, new ResourceLocation(FendersMetalMod.MOD_ID, name),
configuredFeature);
}
#Mod.EventBusSubscriber(modid = FendersMetalMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public static class ForgeBusSubscriber {
#SubscribeEvent
public static void biomeLoading(BiomeLoadingEvent event) {
List<Supplier<ConfiguredFeature<?, ?>>> features = event.getGeneration()
.getFeatures(GenerationStep.Decoration.UNDERGROUND_ORES);
switch(event.getCategory()) {
default -> MetalOreGen.OVERWORLD_ORES.forEach(ore -> features.add(() -> ore));
}
}
}
private static List<PlacementModifier> orePlacement(PlacementModifier p_195347_, PlacementModifier p_195348_) {
return List.of(p_195347_, InSquarePlacement.spread(), p_195348_, BiomeFilter.biome());
}
private static List<PlacementModifier> commonOrePlacement(int p_195344_, PlacementModifier p_195345_) {
return orePlacement(CountPlacement.of(p_195344_), p_195345_);
}
But the code has a problem, see in this part of the code:
List<Supplier<ConfiguredFeature<?, ?>>> features = event.getGeneration()
.getFeatures(GenerationStep.Decoration.UNDERGROUND_ORES);
It has an error in which I don't know but I think that:
"event.getGeneration().getFeatures(GenerationStep.Decoration.UNDERGROUND_ORES);"
is not correct and should provide a "List<Supplier<ConfiguredFeature<?, ?>>>"
because "event.getGeneration().getFeatures(GenerationStep.Decoration.UNDERGROUND_ORES);"
is a "List<Supplier<PlacedFeature>>", not a "List<Supplier<ConfiguredFeature<?, ?>>>".
I tried to change it but there are more errors that would appear if I would Change it.

Generate code that calls static method from another class and uses several fields as arguments

I've been struggling for a while trying to find a solution to this problem. Hope you can help me out.
I'm trying to generate a method that calls a static method from another class using some already defined fields:
class Test {
private String someField;
private String otherField;
}
Expected result:
class Test {
private String someField;
private String otherField;
public String getCacheKey() {
return SimpleCacheKey.of(this.someField, this.otherField);
}
}
class SimpleCacheKey {
public static String of(final Object... values) {
// Some Operations
return computed_string;
}
}
I've tried several things, closest one:
public class ModelProcessor implements Plugin {
#Override
public Builder<?> apply(final Builder<?> builder,
final TypeDescription typeDescription,
final ClassFileLocator classFileLocator) {
return builder.defineMethod("getCacheKey", String.class, Visibility.PUBLIC)
.intercept(new SimpleCacheKeyImplementation());
}
#Override
public void close() throws IOException {
}
#Override
public boolean matches(final TypeDescription typeDefinitions) {
return true;
}
}
public class SimpleCacheKeyImplementation implements Implementation {
private static final MethodDescription SIMPLE_CACHE_KEY_OF = getOf();
#SneakyThrows
private static MethodDescription.ForLoadedMethod getOf() {
return new MethodDescription.ForLoadedMethod(SimpleCacheKey.class.getDeclaredMethod("of", Object[].class));
}
#Override
public InstrumentedType prepare(final InstrumentedType instrumentedType) {
return instrumentedType;
}
#Override
public ByteCodeAppender appender(final Target implementationTarget) {
final TypeDescription thisType = implementationTarget.getInstrumentedType();
return new ByteCodeAppender.Simple(Arrays.asList(
// first param
MethodVariableAccess.loadThis(),
this.getField(thisType, "someField"),
// second param
MethodVariableAccess.loadThis(),
this.getField(thisType, "otherField"),
// call of and return the result
MethodInvocation.invoke(SIMPLE_CACHE_KEY_OF),
MethodReturn.of(TypeDescription.STRING)
));
}
private StackManipulation getField(final TypeDescription thisType, final String name) {
return FieldAccess.forField(thisType.getDeclaredFields()
.filter(ElementMatchers.named(name))
.getOnly()
).read();
}
}
However, generated code is as follows (decompiled with Intellij Idea):
public String getCacheKey() {
String var10000 = this.name;
return SimpleCacheKey.of(this.someValue);
}
Changing the signature of SimpleCacheKey.of and trying to workaround the problem with a List is not an option.
You are calling a vararg method, java bytecode doesnt have that. So you need to create an actual array of the correct type to call the method.
#Override
public ByteCodeAppender appender(final Target implementationTarget) {
final TypeDescription thisType = implementationTarget.getInstrumentedType();
return new ByteCodeAppender.Simple(Arrays.asList(ArrayFactory.forType(TypeDescription.Generic.OBJECT)
.withValues(Arrays.asList( //
new StackManipulation.Compound(MethodVariableAccess.loadThis(),
this.getField(thisType, "field1")),
new StackManipulation.Compound(MethodVariableAccess.loadThis(),
this.getField(thisType, "field2")))
), MethodInvocation.invoke(SIMPLE_CACHE_KEY_OF) //
, MethodReturn.of(TypeDescription.STRING)));
}
Maybe byte-buddy has a special builder for that, but at least thats one way of doing that.
Imo: it is often a good approach to write a java version of the bytecode you want to generate. That way you can compare the javac bytecode and bytebuddy bytecode.

Generic static factory

I am getting a compilation error. I want my static method here to return a factory that creates and return Event<T> object. How can I fix this?
import com.lmax.disruptor.EventFactory;
public final class Event<T> {
private T event;
public T getEvent() {
return event;
}
public void setEvent(final T event) {
this.event = event;
}
public final static EventFactory<Event<T>> EVENT_FACTORY = new EventFactory<Event<T>>() {
public Event<T> newInstance() {
return new Event<T>();
}
};
}
Generic parameters of a class do not apply to static members.
The obvious solution is to use a method rather than a variable.
public static <U> EventFactory<Event<U>> factory() {
return new EventFactory<Event<U>>() {
public Event<U> newInstance() {
return new Event<U>();
}
};
}
The syntax is more concise in the current version of Java.
It is possible to use a the same instance of EventFactory stored in a static field, but that requires an unsafe cast.
You have:
public final class Event<T> {
...
public final static EventFactory<Event<T>> EVENT_FACTORY = ...
}
You cannot do this. T is a type that is associated with a specific instance of an Event<T>, and you cannot use it in a static context.
It's hard to give you good alternate options without knowing more about what exactly you are trying to do, as this is sort of an odd-looking factory implementation. I suppose you could do something like (put it in a method instead):
public final class Event<T> {
...
public static <U> EventFactory<Event<U>> createEventFactory () {
return new EventFactory<Event<U>>() {
public Event<U> newInstance() {
return new Event<U>();
}
};
};
}
And invoke it like:
EventFactory<Event<Integer>> factory = Event.<Integer>createEventFactory();
Or, if you don't want to be explicit (you don't really need to be, here):
EventFactory<Event<Integer>> factory = Event.createEventFactory();
Why don't you get rid of the whole static member of Event thing and either keep the factories separate, e.g.:
public final class GenericEventFactory<T> extends EventFactory<Event<T>> {
#Override public Event<T> newInstance() {
return new Event<T>();
}
}
And use, e.g., new GenericEventFactory<Integer>() where appropriate?

Java improving Builder pattern on a specific class

currently I have got this class which implements the Builder pattern, for sake of readibility I have chosen to omit some methods, more precisely I only show the build methods of username.
package dao.constraint;
import java.util.Arrays;
public class AccountConstraint {
private Constraint<Range<Integer>> accountIdConstraint;
private Constraint<String> usernameConstraint;
private Constraint<String> passwordConstraint;
private Constraint<String> emailConstraint;
private AccountConstraint(Builder builder) {
this.accountIdConstraint = builder.accountIdConstraint;
this.usernameConstraint = builder.usernameConstraint;
this.passwordConstraint = builder.passwordConstraint;
this.emailConstraint = builder.emailConstraint;
}
public Constraint<Range<Integer>> getAccountIdConstraint() {
return accountIdConstraint;
}
public Constraint<String> getUsernameConstraint() {
return usernameConstraint;
}
public Constraint<String> getPasswordConstraint() {
return passwordConstraint;
}
public Constraint<String> getEmailConstraint() {
return emailConstraint;
}
public Constraint[] getConstraints() {
return Arrays.asList(this.getAccountIdConstraint(), this.getUsernameConstraint(), this.getPasswordConstraint(), this.getEmailConstraint()).toArray(new Constraint[4]);
}
public static class Builder {
private Constraint<Range<Integer>> accountIdConstraint;
private Constraint<String> usernameConstraint;
private Constraint<String> passwordConstraint;
private Constraint<String> emailConstraint;
public Builder() {
this.accountIdConstraint = null;
this.usernameConstraint = null;
this.passwordConstraint = null;
this.emailConstraint = null;
}
public Builder username(final String username) {
this.usernameConstraint = new Constraint<>(Operation.IS, true, username, "username");
return this;
}
public Builder notUsername(final String username) {
this.usernameConstraint = new Constraint<>(Operation.IS, false, username, "username");
return this;
}
public Builder usernameLike(final String username) {
this.usernameConstraint = new Constraint<>(Operation.LIKE, true, username, "username");
return this;
}
public Builder usernameNotLike(final String username) {
this.usernameConstraint = new Constraint<>(Operation.LIKE, false, username, "username");
return this;
}
public AccountConstraint build() {
return new AccountConstraint(this);
}
}
}
As you can see there is very subtle difference between AccountConstraint.Builder.username(String s) and AccountConstraint.Builder.notUsername(String s).
I would like to be able to write something like new AccountConstraint.Builder().not(username(s));. However as I know this is not valid Java syntax if username(String s) is not defined in the calling Java class. I neither wish to repeat the whole AccountConstraint.Builder() again to reach the username(String s) part. Any solutions?
Second question: Can AccountConstraint.getConstraints() be improved or written more simple?
Regards.
you could make not a method of your builder, setting a flag, which then negates the next constraint.
private boolean negate = false;
public Builder not() {
negate = true;
}
public Builder username(final String username) {
this.usernameConstraint = new Constraint<>(Operation.IS, !negate, username, "username");
negate = false;
return this;
}
For your second question:
public Constraint[] getConstraints() {
return Arrays.asList(this.getAccountIdConstraint(),
this.getUsernameConstraint(),
this.getPasswordConstraint(),
this.getEmailConstraint())
.toArray(new Constraint[4]);
}
can be re-written to :
public Constraint[] getConstraints() {
return new Constraint[] {
this.accountIdConstraint,
this.usernameConstraint,
this.passwordConstraint,
this.emailConstraint
};
}
But IMO, returning a List or Set would be better than an array.
What I find extremely elegant in this situations is to write a utility class with static factory methods like.
public static Constraint userName(...) { ... }
and to import static blabla.Utility.username;
Then you can write almost declarative human-readable queries in java. This is very much as for the hamcrest library for unit testing where you write something like.
Assert.assertThat(blabla, is(equalTo(nullValue()));
In this case Not should implement Constraint and just negates the nested (referenced) constraint like this:
public static Constraint not(Constraint negated) { return new Not(negated); }
this results in code like
PreparedStatement ps = new QueryBuilder()
.select()
.from(table("accounts")
.where(not(username(equalTo("blabla")))
.compile();
You can add static factories for boolean combinations:
.where(and(
.not(...),
.not(or(...))
Defining constraints like this (static factory methods as opposed to adding them to the builder) thus makes them easily composable.

Categories

Resources