How to #link to overridden Enum method in JavaDoc? - java

Suppose I have an enum structure as follows:
public enum TransportMode {
BYCICLE {
#Override
public double speedFactor() { return .7; }
},
CAR {
#Override
public double speedFactor() { return 1; }
},
TRAIN {
/**
* Faster than train (see also {#link TransportMode#CAR#speedFactor()}).
*/
#Override
public double speedFactor() { return 1.3; }
};
public abstract double speedFactor();
}
When generating Javadoc with maven-source-plugin 3.0.1, I get the following warning:
[WARNING] D:\path\TransportMode.java:000: warning - Tag #see: can't
find CAR#speedFactor() in TransportMode
I get the same result when leaving out the class altogether.
Is this a bug? IntelliJ seems to resolve the path fine.

Related

what is '#CalledByNative("...")'?

How do I use #CalledByNative("...")? I need a callback from a webrtc lib.
If you know the class PeerConnection on it:
PeerConnection.java
Here is a old version of PeerConnection but it's almost same now
I call the function addStream, but I can't get the callback from it.
Please explain how calledbynative works!
PeerConnection.java
/*
* Copyright 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
package org.webrtc;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* Java-land version of the PeerConnection APIs; wraps the C++ API
* http://www.webrtc.org/reference/native-apis, which in turn is inspired by the
* JS APIs: http://dev.w3.org/2011/webrtc/editor/webrtc.html and
* http://www.w3.org/TR/mediacapture-streams/
*/
public class PeerConnection {
static {
System.loadLibrary("jingle_peerconnection_so");
}
/** Tracks PeerConnectionInterface::IceGatheringState */
public enum IceGatheringState { NEW, GATHERING, COMPLETE }
/** Tracks PeerConnectionInterface::IceConnectionState */
public enum IceConnectionState {
NEW,
CHECKING,
CONNECTED,
COMPLETED,
FAILED,
DISCONNECTED,
CLOSED
}
/** Tracks PeerConnectionInterface::SignalingState */
public enum SignalingState {
STABLE,
HAVE_LOCAL_OFFER,
HAVE_LOCAL_PRANSWER,
HAVE_REMOTE_OFFER,
HAVE_REMOTE_PRANSWER,
CLOSED
}
/** Java version of PeerConnectionObserver. */
public static interface Observer {
/** Triggered when the SignalingState changes. */
public void onSignalingChange(SignalingState newState);
/** Triggered when the IceConnectionState changes. */
public void onIceConnectionChange(IceConnectionState newState);
/** Triggered when the ICE connection receiving status changes. */
public void onIceConnectionReceivingChange(boolean receiving);
/** Triggered when the IceGatheringState changes. */
public void onIceGatheringChange(IceGatheringState newState);
/** Triggered when a new ICE candidate has been found. */
public void onIceCandidate(IceCandidate candidate);
/** Triggered when some ICE candidates have been removed. */
public void onIceCandidatesRemoved(IceCandidate[] candidates);
/** Triggered when media is received on a new stream from remote peer. */
public void onAddStream(MediaStream stream);
/** Triggered when a remote peer close a stream. */
public void onRemoveStream(MediaStream stream);
/** Triggered when a remote peer opens a DataChannel. */
public void onDataChannel(DataChannel dataChannel);
/** Triggered when renegotiation is necessary. */
public void onRenegotiationNeeded();
}
/** Java version of PeerConnectionInterface.IceServer. */
public static class IceServer {
public final String uri;
public final String username;
public final String password;
/** Convenience constructor for STUN servers. */
public IceServer(String uri) {
this(uri, "", "");
}
public IceServer(String uri, String username, String password) {
this.uri = uri;
this.username = username;
this.password = password;
}
public String toString() {
return uri + "[" + username + ":" + password + "]";
}
}
/** Java version of PeerConnectionInterface.IceTransportsType */
public enum IceTransportsType { NONE, RELAY, NOHOST, ALL }
/** Java version of PeerConnectionInterface.BundlePolicy */
public enum BundlePolicy { BALANCED, MAXBUNDLE, MAXCOMPAT }
/** Java version of PeerConnectionInterface.RtcpMuxPolicy */
public enum RtcpMuxPolicy { NEGOTIATE, REQUIRE }
/** Java version of PeerConnectionInterface.TcpCandidatePolicy */
public enum TcpCandidatePolicy { ENABLED, DISABLED }
/** Java version of PeerConnectionInterface.CandidateNetworkPolicy */
public enum CandidateNetworkPolicy { ALL, LOW_COST }
/** Java version of rtc::KeyType */
public enum KeyType { RSA, ECDSA }
/** Java version of PeerConnectionInterface.ContinualGatheringPolicy */
public enum ContinualGatheringPolicy { GATHER_ONCE, GATHER_CONTINUALLY }
/** Java version of PeerConnectionInterface.RTCConfiguration */
public static class RTCConfiguration {
public IceTransportsType iceTransportsType;
public List<IceServer> iceServers;
public BundlePolicy bundlePolicy;
public RtcpMuxPolicy rtcpMuxPolicy;
public TcpCandidatePolicy tcpCandidatePolicy;
public CandidateNetworkPolicy candidateNetworkPolicy;
public int audioJitterBufferMaxPackets;
public boolean audioJitterBufferFastAccelerate;
public int iceConnectionReceivingTimeout;
public int iceBackupCandidatePairPingInterval;
public KeyType keyType;
public ContinualGatheringPolicy continualGatheringPolicy;
public int iceCandidatePoolSize;
public boolean pruneTurnPorts;
public boolean presumeWritableWhenFullyRelayed;
public RTCConfiguration(List<IceServer> iceServers) {
iceTransportsType = IceTransportsType.ALL;
bundlePolicy = BundlePolicy.BALANCED;
rtcpMuxPolicy = RtcpMuxPolicy.NEGOTIATE;
tcpCandidatePolicy = TcpCandidatePolicy.ENABLED;
candidateNetworkPolicy = candidateNetworkPolicy.ALL;
this.iceServers = iceServers;
audioJitterBufferMaxPackets = 50;
audioJitterBufferFastAccelerate = false;
iceConnectionReceivingTimeout = -1;
iceBackupCandidatePairPingInterval = -1;
keyType = KeyType.ECDSA;
continualGatheringPolicy = ContinualGatheringPolicy.GATHER_ONCE;
iceCandidatePoolSize = 0;
pruneTurnPorts = false;
presumeWritableWhenFullyRelayed = false;
}
};
private final List<MediaStream> localStreams;
private final long nativePeerConnection;
private final long nativeObserver;
private List<RtpSender> senders;
private List<RtpReceiver> receivers;
PeerConnection(long nativePeerConnection, long nativeObserver) {
this.nativePeerConnection = nativePeerConnection;
this.nativeObserver = nativeObserver;
localStreams = new LinkedList<MediaStream>();
senders = new LinkedList<RtpSender>();
receivers = new LinkedList<RtpReceiver>();
}
// JsepInterface.
public native SessionDescription getLocalDescription();
public native SessionDescription getRemoteDescription();
public native DataChannel createDataChannel(String label, DataChannel.Init init);
public native void createOffer(SdpObserver observer, MediaConstraints constraints);
public native void createAnswer(SdpObserver observer, MediaConstraints constraints);
public native void setLocalDescription(SdpObserver observer, SessionDescription sdp);
public native void setRemoteDescription(SdpObserver observer, SessionDescription sdp);
public native boolean setConfiguration(RTCConfiguration config);
public boolean addIceCandidate(IceCandidate candidate) {
return nativeAddIceCandidate(candidate.sdpMid, candidate.sdpMLineIndex, candidate.sdp);
}
public boolean removeIceCandidates(final IceCandidate[] candidates) {
return nativeRemoveIceCandidates(candidates);
}
public boolean addStream(MediaStream stream) {
boolean ret = nativeAddLocalStream(stream.nativeStream);
if (!ret) {
return false;
}
localStreams.add(stream);
return true;
}
public void removeStream(MediaStream stream) {
nativeRemoveLocalStream(stream.nativeStream);
localStreams.remove(stream);
}
public RtpSender createSender(String kind, String stream_id) {
RtpSender new_sender = nativeCreateSender(kind, stream_id);
if (new_sender != null) {
senders.add(new_sender);
}
return new_sender;
}
// Note that calling getSenders will dispose of the senders previously
// returned (and same goes for getReceivers).
public List<RtpSender> getSenders() {
for (RtpSender sender : senders) {
sender.dispose();
}
senders = nativeGetSenders();
return Collections.unmodifiableList(senders);
}
public List<RtpReceiver> getReceivers() {
for (RtpReceiver receiver : receivers) {
receiver.dispose();
}
receivers = nativeGetReceivers();
return Collections.unmodifiableList(receivers);
}
public boolean getStats(StatsObserver observer, MediaStreamTrack track) {
return nativeGetStats(observer, (track == null) ? 0 : track.nativeTrack);
}
// Starts recording an RTC event log. Ownership of the file is transfered to
// the native code. If an RTC event log is already being recorded, it will be
// stopped and a new one will start using the provided file. Logging will
// continue until the stopRtcEventLog function is called. The max_size_bytes
// argument is ignored, it is added for future use.
public boolean startRtcEventLog(int file_descriptor, int max_size_bytes) {
return nativeStartRtcEventLog(file_descriptor, max_size_bytes);
}
// Stops recording an RTC event log. If no RTC event log is currently being
// recorded, this call will have no effect.
public void stopRtcEventLog() {
nativeStopRtcEventLog();
}
// TODO(fischman): add support for DTMF-related methods once that API
// stabilizes.
public native SignalingState signalingState();
public native IceConnectionState iceConnectionState();
public native IceGatheringState iceGatheringState();
public native void close();
public void dispose() {
close();
for (MediaStream stream : localStreams) {
nativeRemoveLocalStream(stream.nativeStream);
stream.dispose();
}
localStreams.clear();
for (RtpSender sender : senders) {
sender.dispose();
}
senders.clear();
for (RtpReceiver receiver : receivers) {
receiver.dispose();
}
receivers.clear();
freePeerConnection(nativePeerConnection);
freeObserver(nativeObserver);
}
private static native void freePeerConnection(long nativePeerConnection);
private static native void freeObserver(long nativeObserver);
private native boolean nativeAddIceCandidate(
String sdpMid, int sdpMLineIndex, String iceCandidateSdp);
private native boolean nativeRemoveIceCandidates(final IceCandidate[] candidates);
private native boolean nativeAddLocalStream(long nativeStream);
private native void nativeRemoveLocalStream(long nativeStream);
private native boolean nativeGetStats(StatsObserver observer, long nativeTrack);
private native RtpSender nativeCreateSender(String kind, String stream_id);
private native List<RtpSender> nativeGetSenders();
private native List<RtpReceiver> nativeGetReceivers();
private native boolean nativeStartRtcEventLog(int file_descriptor, int max_size_bytes);
private native void nativeStopRtcEventLog();
}
#CallByNative is an annotation used by the Google WebRtc Development team to specify mappings between Java and Native (C/C++) Stacks of WebRtc.
As said on there official WebRtc Chromium Git representation such as:
#CalledByNative is used by the JNI generator to create the necessary
JNI bindings and expose this method to native code.
Now if there is a question that how is it happening? How WebRtc Java code is inter-linked with WebRtc Native Code?
For this, I will suggest looking into the Native Code of WebRtc will help you most. You will learn more informative and relevant stuff from the Comments inside the native stack. On the other hand, you should also have the basic knowledge of
How Java Native Interface (JNI) works
How WebRtc Java and Native Stack is interrelated
To get detailed intuition of Java Native Interface, you can visit these references:
Java Native Interface Specification Contents
Java Native Interface Tips
Here I am giving you an example from PeerConnection.java. Let's say, we have a method inside PeerConnection.java class such as:
#CalledByNative("IceGatheringState")
static IceGatheringState fromNativeIndex(int nativeIndex) {
return values()[nativeIndex];
}
Now this method is mapped inside src/sdk/android/src/jni/pc/peer_connection.cc class such as:
static ScopedJavaLocalRef<jobject> JNI_PeerConnection_IceGatheringState(
JNIEnv* env,
const JavaParamRef<jobject>& j_pc) {
return Java_IceGatheringState_fromNativeIndex(
env, ExtractNativePC(env, j_pc)->ice_gathering_state());
}
If you follow the same technique by looking into both Java and Native Class of PeerConnection, you must found some other linkages of that kind. Now, what #CallByNative did here?
If you look, after loading library, #CallByNative basically do these two things such as:
Tells which inner class the method belongs to
Expose this Java method to the Native Code
Make JNI Bindings with Java and Native Code
These types of annotations are provided by Google Developers to make JNI easy and understandable while working with Pre-built libraries or your own compiled libraries such as libwebrtc.aar.
I did some investigation on this topic lately and I would like to share my results. I realized that it might have to do something with #Override methods and the "super" keyword in Java. I suppose when we try to call e.g. the override method onIceCandidate or onAddStream, which is located in the PeerConnection.java file, from the MainActivity.java class we write:
public class MainActivity extends AppCompatActivity implements View.OnClickListener, SignallingClient.SignalingInterface {
...
private void createPeerConnection() {
...
#Override
public void onIceCandidate(IceCandidate iceCandidate) {
super.onIceCandidate(iceCandidate);
onIceCandidateReceived(iceCandidate);
}
#Override
public void onAddStream(MediaStream mediaStream) {
showToast("Received Remote stream");
super.onAddStream(mediaStream);
gotRemoteStream(mediaStream);
}
...
}
...
}
Furthermore, the onAddStream and onIceCandidate are both override methods. If we trace those methods back by the help of the super keyword we get into the following file CustomPeerConnectionObserver.java:
class CustomPeerConnectionObserver implements PeerConnection.Observer {
...
#Override
public void onIceCandidate(IceCandidate iceCandidate) {
Log.d(logTag, "onIceCandidate() called with: iceCandidate = [" + iceCandidate + "]");
}
...
#Override
public void onAddStream(MediaStream mediaStream) {
Log.d(logTag, "onAddStream() called with: mediaStream = [" + mediaStream + "]");
}
...
}
At this point when we take a look at the class we see that it "implements" the PeerConnection.Observer. If we keep investigating a bit further, we realize that we are guided to our file PeerConnection.java:
public class PeerConnection {
...
public interface Observer {
...
#CalledByNative("Observer")
void onIceCandidate(IceCandidate var1);
...
#CalledByNative("Observer")
void onAddStream(MediaStream var1);
...
}
...
}
We get into the "interface" called Observer. So far I took the example from GitHub and I tried to comprehend how the application works. It is for Android, but I suppose we use Java, so there should not be a huge difference, correct me if I am wrong.
In conclusion, I suppose it somehow gets called automatically when a special event occurs and/or when it is mentioned/written as a #Override method, where we need it to be called. I also assume that the #CalledByNative tag could have impact on the method calls, i.e. addStream, also respectively in the example I provided above:
onIceCandidate
onAddStream.
I hope I was able to at least give you some reference points about my investigation on this behaviour, where you could pick up the trace and make further research. I am also looking forward that an expert could answer this good question on how #CalledByNative works.

Editing value of TableView column

I encountered problem I am unable to solve. Thing is, my TableView is already populated and I need for cells that match my criteria to set value zero. I have variable korZemljiste and if my condition is fullfilled cells in column colOsnovica need to be set to value 0.00.
Here is what I tried:
if (korZemljiste < 10000)
{
tblTabela.getItems().stream().forEach((o)
-> {
colOsnovica.setCellFactory(TextFieldTableCell.forTableColumn());
colOsnovica.setOnEditCommit(
new EventHandler<CellEditEvent<Nepokretnost, Number>>() {
#Override
public void handle(CellEditEvent<Nepokretnost, Number> t) {
((Nepokretnost) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setOsnovica(t.getNewValue());
}
});});}
Sorry, for ugly end of code, couldn't make to copy it properly.
This part I modified from Oracle example and I get error:
error: incompatible types: no instance(s) of type variable(s) S exist so that Callback<TableColumn<S,String>,TableCell<S,String>> conforms to Callback<TableColumn<Nepokretnost,Number>,TableCell<Nepokretnost,Number>>
colOsnovica.setCellFactory(TextFieldTableCell.forTableColumn());
where S is a type-variable:
S extends Object declared in method forTableColumn()
error: incompatible types: Number cannot be converted to double
).setOsnovica(t.getNewValue());
My TableView using <Nepokretnost, Number> form.
Note: I guess I don't need this example from Oracle site because I don't want to manually change contents of cell in column, I just want to set them to value 0.00.
Some easy solution anyone?
Thanks in advance.
For the first error, since your table column type is not a String, you cannot use the no-argument version of TextFieldTableCell.forTableColumn(). The underlying problem is that, to edit the cell, the text field provides a String and the data in the cell is a Number. You need to provide a converter, using the overloaded form of TextFieldTableCell.forTableColumn(...):
colOsnovica.setCellFactory(TextFieldTableCell.forTableColumn(new NumberStringConverter()));
For the second error, just replace t.getNewValue() (which returns a Number) with t.getNewValue().doubleValue() (which gets the double representation of the Number).
#james-d
Hm, my mistake. Class is simple, here it is:
package obracun;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
/**
*
* #author Dalibor
*/
public class Nepokretnost {
private final SimpleStringProperty tipNepokretnosti;
private final SimpleStringProperty zona;
private final SimpleStringProperty pravo;
private final SimpleDoubleProperty povrsina;
private final SimpleDoubleProperty amortizacija;
private final SimpleDoubleProperty osnovica;
private final SimpleDoubleProperty kredit;
private final SimpleDoubleProperty porez;
public Nepokretnost(String tipNepokretnosti, String zona, String pravo,
Double povrsina, double amortizacija, Double osnovica, Double kredit, Double porez) {
this.tipNepokretnosti = new SimpleStringProperty(tipNepokretnosti);
this.zona = new SimpleStringProperty(zona);
this.pravo = new SimpleStringProperty(pravo);
this.povrsina = new SimpleDoubleProperty(povrsina);
this.amortizacija = new SimpleDoubleProperty(amortizacija);
this.osnovica = new SimpleDoubleProperty(osnovica);
this.kredit = new SimpleDoubleProperty(kredit);
this.porez = new SimpleDoubleProperty(porez);
}
public String getTipNepokretnosti() {
return tipNepokretnosti.get();
}
public void setTipNepokretnosti(String tipNepokretnosti) {
this.tipNepokretnosti.set(tipNepokretnosti);
}
public String getZona() {
return zona.get();
}
public void setZona(String zona) {
this.zona.set(zona);
}
public String getPravo() {
return pravo.get();
}
public void setPravo(String pravo) {
this.pravo.set(pravo);
}
public double getPovrsina() {
return povrsina.get();
}
public void setPovrsina(double povrsina) {
this.povrsina.set(povrsina);
}
public double getAmortizacija() {
return amortizacija.get();
}
public void setAmortizacija(double amortizacija) {
this.amortizacija.set(amortizacija);
}
public double getOsnovica() {
return osnovica.get();
}
public void setOsnovica(double osnovica) {
this.osnovica.set(osnovica);
}
public double getKredit() {
return kredit.get();
}
public void setKredit(double kredit) {
this.kredit.set(kredit);
}
public double getPorez() {
return porez.get();
}
public void setPorez(double porez) {
this.porez.set(porez);
}
}
I didn't realized it is necessary to post class here. I had this application made before just in Swing. There I just changed contents of JTableView field. This is kinda different, thanks for help.
I posted and screenshot of app. On screenshot I already added elements in TableView I wanted. Code I posted in question is part of Calculate (Обрачун) button event handler. In this example calculation should change the contents of field Основица to 0.00.

printf error can't launch java eclipse

My printf contains an error. The rest of my code is done, but because of the error in my printf, I can't launch Java. Please help. My main class already done.
package id.web.aditya;
public class Roda {
private int diameter;
private String warna;
private String Merk;
private String Keterangan;
public String getMerk() {
return Merk;
}
public void setMerk(String merk) {
Merk = merk;
}
public int getDiameter() {
return diameter;
}
public void setDiameter(int diameter) {
this.diameter = diameter;
}
public String getWarna() {
return warna;
}
public void setWarna(String warna) {
this.warna = warna;
}
public String getKeterangan() {
return Keterangan;
}
public void setKeterangan(String keterangan) {
this.Keterangan = keterangan;
}
public void tampilanKeterangan(){
System.out.printf("Roda %s Merk: %s Warna: %s Diameter: %d \n ",
Keterangan, Merk, warna, diameter);
}
public void Berhenti(){
tampilanKeterangan();
System.out.println("Kurangi Kecepatan");
System.out.println("mulai berhenti..");
System.out.println("Akhirna berhenti");
System.out.println("--------------------");
}
public void berputar(){
tampilanKeterangan();
System.out.println("mulai berputar");
System.out.println("berputar");
System.out.println("berputar makin cepat");
System.out.println("----------------------");
}
}
package id.web.aditya;
public class Mobil {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Roda rodaUntukDitest = new Roda();
rodaUntukDitest.setDiameter(80);
rodaUntukDitest.setMerk("Achiles");
rodaUntukDitest.setWarna("Hitam");
rodaUntukDitest.setKeterangan("");
rodaUntukDitest.Berhenti();
rodaUntukDitest.berputar();
}
}
Exception in thread "main" java.lang.Error: Unresolved compilation
problem: The method printf(Locale, String, Object[]) in the type
PrintStream is not applicable for the arguments (String, String,
String, String, int)
String format feature is introduced in java 1.5. You are apparently using a java version or a compilation option prior to that version.
If you are using eclipse open the project properties (ALT + Enter on the project). Look at the tab java compiler.
Here you can set your compiler compliance level. You probably have a newer java version installed. In this case eclipse shows you the above mention error.
I would expect to show you something like "The method printf(String, String, String, String, Integer) is undefined for the type PrintStream". but it doesn't so this might be a little bit confusing.

Override Setter in Subclass

I'm stuck with a problem here. I want to change the setter from a attribute from the superclass (parent class) in my subclass (child) however when I overide this method in my subclass I can't access my private attributes from the supperclass. And the point is, they have to stay private.
Superclass (problem: setMinimumVoorraad(int voorraad);)
package domein;
public abstract class Artikel implements Weegbaar
{
private String omschrijving;
private double prijs;
private int aantalInStock;
private int minimumVoorraad;
public Artikel(String omschrijving, double prijs, int aantalInStock, int minimumVoorraad)
{
this.setOmschrijving(omschrijving);
this.setPrijs(prijs);
this.setAantalInStock(aantalInStock);
this.setMinimumVoorraad(minimumVoorraad);
}
#Override
public String toString()
{
String output = String.format(" \n omschrijving: %s \n prijs: %f \n In stock %d (minimumvoorraad = %d) \n", this.omschrijving, this.prijs, this.aantalInStock, this.minimumVoorraad);
return output;
}
//----Getters----
public String getOmschrijving() {
return omschrijving;
}
public double getPrijs() {
return prijs;
}
public int getAantalInStock() {
return aantalInStock;
}
public int getMinimumVoorraad() {
return minimumVoorraad;
}
//----Setters----
public void setOmschrijving(String omschrijving) {
this.omschrijving = omschrijving;
}
public void setPrijs(double prijs) {
this.prijs = prijs;
}
public void setAantalInStock(int aantalInStock) {
this.aantalInStock = aantalInStock;
}
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad < 2)
this.minimumVoorraad = 3;
else
this.minimumVoorraad = minimumVoorraad;
}
}
Subclass
package domein;
public class Food extends Artikel
{
private String houdbaarheidsDatum;
private double nettoGewicht;
public Food(String omschrijving, double prijs, int aantalInStock, int minimumVoorraad, String houdbaarheidsDatum, double nettoGewicht)
{
super(omschrijving, prijs, aantalInStock, minimumVoorraad);
this.setHoudbaarheidsDatum(houdbaarheidsDatum);
this.setNettoGewicht(nettoGewicht);
}
#Override
public boolean isWeegbaar()
{
return true;
}
//----Getters----
public String getHoudbaarheidsDatum() {
return houdbaarheidsDatum;
}
public double getNettoGewicht() {
return nettoGewicht;
}
//----Setters----
public void setHoudbaarheidsDatum(String houdbaarheidsDatum) {
this.houdbaarheidsDatum = houdbaarheidsDatum;
}
public void setNettoGewicht(double nettoGewicht) {
this.nettoGewicht = nettoGewicht;
}
#Override
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad < 5)
this.minimumVoorraad = 6;
else
this.minimumVoorraad = minimumVoorraad;
}
}
Someone who can help me?
Thanks in advance.
One possibility is to implement the subclass's setter in terms of the superclass's setter (which, presumably, you do have access to).
For example, assuming the setter is setFoo, then the subclass's version might be:
public void setFoo(Foo f) {
// Do subclass stuff pre-setting, if any
super.setFoo(f);
// Do subclass stuff post-setting, if any
}
The answer given above by NPE is absolutely the best way to go about solving this problem. It is elegant and honors basic inheritance contracts between superclass and subclass. Even in your original post, the subclass is actually more restrictive than the superclass, so doing something like:
#Override
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad <= 5)
super.setMinimumVoorraad(6);
else
super.setMinimumVoorraad(minimumVoorraad);
}
exactly as NPE suggested would probably work. (Note how I modified your if test. Not sure if it's a typo, but in the original implementation 5 would be a valid minimum, but input like 4 would set it to 6.)
Other (possibly acceptable) patterns would be to:
Make the members in your Parent class protected, which would give visibility. (Realize that you did mention a private restriction; this pattern is solely mentioned to provide a more complete overall answer.)
Delegate the validation logic to another method (that is non-private). This way the child can override the validation method.
And now on to the (probably unacceptable) pattern of using Java reflection:
#Override
public void setMinimumVoorraad(int minimumVoorraad) {
try {
Field field = this.getClass().getSuperclass().getDeclaredField("minimumVoorraad");
field.setAccessible(true);
if(minimumVoorraad <= 5)
field.set(this, 6);
else
field.set(this, minimumVoorraad);
field.setAccessible(false);
}
catch(NoSuchFieldException | IllegalAccessException e) {
// do something
}
}
It's worth noting that if you never ever do this in your entire life you will probably be the better for it. Not only does it completely break all contracts, but it relies on hard-coded Strings to do field name lookups, which in and of itself is pretty painful. But it does exist. And no good answer (already given above by NPE) would be complete without an example of how not to do something...

How to avoid deprecation warnings for GWT HorizontalSplitPanel in NetBeans Java project?

Is it possible to avoid deprecation warning while compiling code with utility methods like:
public static void doSthForHorizontalSplitPanel(HorizontalSplitPanel hsp) {...}
and explicit declaration and/or creation of HorizontalSplitPanel widget, e.g.:
protected HorizontalSplitPanel main;
...
main = new HorizontalSplitPanel();
My goal is to eliminate these warnings without removing HorizontalSplitPanel usage, not giving global compiler flag (-Xlint:-deprecation) and with aid of minimal manual refactoring in terms of possible impact on code using HorizontalSplitPanel and my utility methods (i.e. as little code changes as possible).
Annotation #SuppressWarnings("deprecation") at method or class level seems not to work because of import HorizontalSplitPanel statements, replacement of deprecated HorizontalSplitPanel class in not an option (for now).
Is my goal possible to achieve at all? If so, what would be the best approach?
I'm using NetBeans 7.1, Java 1.6, GWT 2.3.
Standards mode and SplitlayoutPanel works better than the deprecated HorizontalSplitPanel.
Try this code you have to replace with HorizontalSplitPanel with HorizontalSplitLayoutPanel.
This code actually uses latest SplitLayoutPanel and the methods are equivalent to Deprecated HorizontalSplitPanel. The advantage is you don't have to change the code. Also pasted code for VerticalSplitPanel alternative VerticalSplitLayoutPanel. VerticalSplitLayoutPanel is unit tested and works fine.
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SplitLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* author: MKK
* Date: 4/29/13
* Time: 10:41 AM
* /**
*
* GWT depecrated HorizontalSplitpanel as of version 2.0.
* This is a wrapper class which extends new SplitLayoutPanel and has all the methods of deprecated old Splitpanels for
* seamless integration with existing code without breaking.
* Replacement of old HorizontalSplitLayoutPanel with new SplitLayoutPanel
*
*
*/
public class HorizontalSplitLayoutPanel extends SplitLayoutPanel{
private ScrollPanel leftScrollPanel = new ScrollPanel();
private ScrollPanel rightScrollPanel = new ScrollPanel();
private Widget leftWidget;
private Widget rightWidget;
public HorizontalSplitLayoutPanel(){
super();
init();
}
boolean dragged;
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
switch (DOM.eventGetType(event)) {
case Event.ONMOUSEDOWN:
dragged = true;
break;
case Event.ONMOUSEUP:
dragged = false;
break;
case Event.ONMOUSEMOVE:
break;
}
}
public boolean isResizing(){
return dragged;
}
private void init() {
setSize("100%", "100%");
addWest(leftScrollPanel, 300);
add(rightScrollPanel);
sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP );
}
public HorizontalSplitLayoutPanel(int splitterSize) {
super(splitterSize);
init();
}
public void setLeftWidget(Widget widget){
this.leftWidget = widget;
leftScrollPanel.clear();
leftScrollPanel.add(widget);
setSplitPosition("30%");
setWidgetToggleDisplayAllowed(leftScrollPanel,true);
}
public void setRightWidget(Widget widget){
try {
this.rightWidget = widget;
rightScrollPanel.clear();
rightScrollPanel.add(widget);
setSplitPosition("30%");
} catch (Exception e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
public void removeWidget(Widget widget){
try {
if( leftScrollPanel.getWidget()== widget){
leftScrollPanel.remove(widget);
return;
}
rightScrollPanel.remove(widget);
} catch (Exception e) {
}
}
public void setSplitPosition(String percent){
if( percent.toLowerCase().indexOf("px") > -1){
percent = percent.replace("px","").trim();
int p = Integer.parseInt(percent);
setSplitPosition(p);
return;
}
percent = percent.replace("%","").trim();
int p = Integer.parseInt(percent);
double size = (getOffsetWidth()*p)/100.0;
if( p < 1.0 ){
size = 600;
}
setWidgetSize(leftScrollPanel, size);
}
public void setSplitPosition(int pixels){
setWidgetSize(leftScrollPanel, pixels);
}
public void hideLeftWidget() {
leftScrollPanel.clear();
setWidgetMinSize(leftScrollPanel,0);
}
public void showLeftWidget(){
leftScrollPanel.add(leftWidget);
}
public void hideRightWidget() {
rightScrollPanel.clear();
setWidgetMinSize(rightScrollPanel,0);
}
public void showRightWidget(){
rightScrollPanel.add(rightWidget);
}
}
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SplitLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
/**
*
* GWT depecrated VerticalSplitPanel as of version 2.0.
* This is a wrapper class which extends new SplitLayoutPanel and has all the methods of deprecated old Splitpanels for
* seamless integration with existing code without breaking.
* Replacement of old VerticalSplitPanel with new SplitLayoutPanel
*
*
*/
public class VerticalSplitLayoutPanel extends SplitLayoutPanel {
private Widget topWidget;
private Widget bottomWidget;
private int offset=100;
private ScrollPanel topScrollPanel = new ScrollPanel();
private ScrollPanel bottomScrollPanel = new ScrollPanel();
public VerticalSplitLayoutPanel() {
super();
init();
}
public VerticalSplitLayoutPanel(int splitterSize) {
super(splitterSize);
init();
}
private void init() {
setSize("100%", "100%");
//int clientH = Window.getClientHeight()-offset;
// double size = clientH * 50/100;
addNorth(topScrollPanel, getOffsetHeight()/2.0);
add(bottomScrollPanel);
sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP );
}
boolean dragged;
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
switch (DOM.eventGetType(event)) {
case Event.ONMOUSEDOWN:
dragged = true;
break;
case Event.ONMOUSEUP:
dragged = false;
break;
case Event.ONMOUSEMOVE:
break;
}
}
public boolean isResizing(){
return dragged;
}
public void setTopWidget(Widget widget){
topScrollPanel.add(widget);
}
public void setBottomWidget(Widget widget){
bottomScrollPanel.add(widget);
}
public void removeWidget(Widget widget){
try {
if( topScrollPanel.getWidget()== widget){
topScrollPanel.remove(widget);
return;
}
bottomScrollPanel.remove(widget);
} catch (Exception e) {
}
}
public void setSplitPosition(String percent){
if( percent.toLowerCase().indexOf("px") > -1){
percent = percent.replace("px","").trim();
int p = Integer.parseInt(percent);
setSplitPosition(p);
return;
}
percent = percent.replace("%","").trim();
int p = Integer.parseInt(percent);
int oH = getOffsetHeight();
if( oH == 0 ){
oH = (Window.getClientHeight()-offset);
}
double h = (oH*p)/100.0;
setWidgetSize(topScrollPanel, h);
}
public void setSplitPosition(int pixels){
setWidgetSize(topScrollPanel, pixels);
}
public void setOffset(int size){
this.offset = size;
}
}
My approach is as follows.
Replace every usage of HorizontalSplitPanel with HorizontalSplitPanelWrapper defined below, then fix imports - this will eliminate import HorizontalSplitPanel and add import HorizontalSplitPanelWrapper. Done.
#SuppressWarnings("deprecation")
public class HorizontalSplitPanelWrapper implements IsWidget {
private Panel hsp = new com.google.gwt.user.client.ui.HorizontalSplitPanel();
public Widget asWidget() {
return hsp;
}
public com.google.gwt.user.client.Element getElement() {
return hsp.getElement();
}
public <H extends EventHandler> HandlerRegistration addHandler(final H handler, GwtEvent.Type<H> type) {
return hsp.addHandler(handler, type);
}
public boolean isResizing() {
return ((com.google.gwt.user.client.ui.HorizontalSplitPanel) hsp).isResizing();
}
public void setWidth(String width) {
hsp.setWidth(width);
}
public void setSplitPosition(String pos) {
((com.google.gwt.user.client.ui.HorizontalSplitPanel) hsp).setSplitPosition(pos);
}
public void add(IsWidget w) {
hsp.add(w);
}
}
Additional remarks.
My solution uses little trick with IsWidget interface from GWT - this minimizes code impact, because Widget can be substituted with implementation of IsWidget in most calls to GTW APIs.
Every method of HorizontalSplitPanel used in my code is now implemented by HorizontalSplitPanelWrapper and just delegated to internal HorizontalSplitPanel stored by hsp field.
There must be no declarations of fields and methods with HorizontalSplitPanel as type/param/result, as it will always yield deprecation warnings, regardless of #SuppressWarnings("deprecation"). Because of this, hsp field is declared as Panel.
If there are more methods of HorizontalSplitPanel used in rest of the code, there must be dummy delegator method in HorizontalSplitPanelWrapper for every one of them. Proper HorizontalSplitPanel object must be retrieved from field hsp with explicit cast in every such method.
That's it. No more deprecation warnings because of HorizontalSplitPanel, which still can be used.

Categories