Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRILL-6633: Replace usage of Guava classes by JDK ones #1397

Closed
wants to merge 6 commits into from

Conversation

vvysotskyi
Copy link
Member

In the PR for DRILL-6422 was decided to create a separate Jira (DRILL-6633) for changes connected with replacing usage of some Guava classes by JDK ones.

In this PR revised most of the Guava classes and replaced their usage where possible.

@arina-ielchiieva
Copy link
Member

@vdiravka could you please review?

@kkhatua
Copy link
Contributor

kkhatua commented Jul 25, 2018

@arina-ielchiieva / @vvysotskyi The changes look trivial, but 682 files are a lot to review! Should this PR be broken up in parts?

@vvysotskyi
Copy link
Member Author

vvysotskyi commented Jul 26, 2018

@kkhatua, I don't see a reason for splitting the PR, even splitting changes for modules where they were made. Either single or multiple PRs should be reviewed in any case.

Since almost all of the changes are trivial, it wouldn't be a problem to do a cursory review.

Copy link
Member

@vdiravka vdiravka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drill project is bigger than I imagined :)

@@ -57,9 +57,9 @@ public static String getPrincipalFromParts(final String primary, final String in
public static String[] splitPrincipalIntoParts(final String principal) {
final String[] components = principal.split("[/@]");
checkState(components.length == 3);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider the substitution for Preconditions.checkState() is Validate.validState() from org.apache.commons commons-lang3 for all places in the project

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should leave it as it is since the goal of this PR is to replace guava usage by JDK where it is possible, but there is no sense to replace usage of one library by another.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vdiravka What is wrong with using guava Preconditions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing wrong with Guava Preconditions and with Apache Commons as well.
IMO the method names in Apache Commons are more clear.

But I've wrongly supposed that the purpose was to get rid Guava as much as possible.

We can leave Guava Preconditions, since it is already written and usage of it is more common.

}
}));
return primary.entrySet().stream()
.map((Function<Entry<K, Entry<Integer, V>>, Entry<K, V>>) entry ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you remove the type of lambda expession?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this, removed.

this.createAtBeginning = createAtBeginning;
this.deleteAtEnd = deleteAtEnd;
this.subDirs = Preconditions.checkNotNull(subDirs);
this.subDirs = Objects.requireNonNull(subDirs);

Preconditions.checkArgument(!subDirs.isEmpty(), "The list of subDirs is empty.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider the substitution for Preconditions.checkArgument() is Validate.isTrue() from org.apache.commons commons-lang3.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my previous comment

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While in this place Preconditions.checkNotNull() and Objects.requireNonNull() provide the same functionality, in general guava Preconditions supports template error message that Objects.requireNonNull does not support. I'd recommend keeping Preconditions.checkNotNull for consistency. IMO, it is necessary to remove deprecated guava classes, not all references to guava where similar functionality is provided by JDK.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Objects.requireNonNull is introduced mostly for Streams, but not for replacing Guava Preconditions.
From other hand they have the same implementation. Except Preconditions.checkNotNull() overloaded method with NPE error message formatting and Guava recommends to use Preconditions, see Guava master.

Looks like Calcite project replaces these methods, see Calcite master, but Apex doesn't replace them.

Since we stay with Guava it could be reasonably to follow their documentation.
But it is not critical, so I will leave the decision for you.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer using JDK things instead of third-party libraries, so I leave code with Objects.requireNonNull() (no additional changes in PR).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vrozov, I didn't correctly express my point of view: I don't see a reason for using methods from third-party libraries if JDK provides methods with exactly the same functionality. Such usages of third-party libraries should be prevented for the consistency.

Using methods from JDK is also helps to prevent problems with updating library versions, since the API of a third-party library may change, but JDK guarantees backward compatibility.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vvysotskyi I already explained reasons to keep Preconditions in my other comments. Here is the summary in random order:

  • The change does not remove the dependency on the guava library.
  • Preconditions are not deprecated by the guava team and provides a stable interface.
  • Preconditions functionality is much wider compared to JDK classes.
  • Using Preconditions will be more consistent with other checks like checkState or checkArgument and also with other Apache projects.
  • It avoids unnecessary changes and keeps original contributions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vvysotskyi arguments of both of you are really reasonable. But I prefer don't make changes without obvious benefit. If you insist, please describe the case and post it as [DISCUSSION] in Drill dev mailing list with a link to current PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with what @vrozov said; technically, there seems to be no clear benefit of replacing existing Preconditions. Personal preference should only apply to new contributions , not to old contributions (since the original contributor(s) could also have her/his preference).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you all for discussing this. I have reverted my changes where I replaced Preconditions.checkNotNull() with Objects.requireNonNull()

@@ -42,9 +44,6 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using of org.apache.commons.lang3.time.StopWatch everywhere

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same as for Preconditions.checkArgument()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree

@@ -30,7 +31,6 @@
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we replace ImmutableMap with HashMap in getConfig() method? Not sure that ImmutableMap is necessary. The method can return new HashMap(config)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume ImmutableMap was used here to prevent modification of the returned map. So I leave it as it is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@@ -106,7 +106,7 @@ public void testInvalidSpnegoConfig() throws Exception {
@Test
public void testSpnegoConfigOnlyKeytab() throws Exception {
try {
final DrillConfig newConfig = new DrillConfig(DrillConfig.create().withValue(ExecConstants.USER_AUTHENTICATION_ENABLED, ConfigValueFactory.fromAnyRef(true)).withValue(ExecConstants.AUTHENTICATION_MECHANISMS, ConfigValueFactory.fromIterable(Lists.newArrayList("plain"))).withValue(ExecConstants.HTTP_SPNEGO_KEYTAB, ConfigValueFactory.fromAnyRef(spnegoHelper.serverKeytab.toString())).withValue(ExecConstants.USER_AUTHENTICATOR_IMPL, ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE)));
final DrillConfig newConfig = new DrillConfig(DrillConfig.create().withValue(ExecConstants.USER_AUTHENTICATION_ENABLED, ConfigValueFactory.fromAnyRef(true)).withValue(ExecConstants.AUTHENTICATION_MECHANISMS, ConfigValueFactory.fromIterable(Collections.singletonList("plain"))).withValue(ExecConstants.HTTP_SPNEGO_KEYTAB, ConfigValueFactory.fromAnyRef(spnegoHelper.serverKeytab.toString())).withValue(ExecConstants.USER_AUTHENTICATOR_IMPL, ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formating

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -123,7 +123,7 @@ public void testSpnegoConfigOnlyKeytab() throws Exception {
@Test
public void testSpnegoConfigOnlyPrincipal() throws Exception {
try {
final DrillConfig newConfig = new DrillConfig(DrillConfig.create().withValue(ExecConstants.USER_AUTHENTICATION_ENABLED, ConfigValueFactory.fromAnyRef(true)).withValue(ExecConstants.AUTHENTICATION_MECHANISMS, ConfigValueFactory.fromIterable(Lists.newArrayList("plain"))).withValue(ExecConstants.HTTP_SPNEGO_PRINCIPAL, ConfigValueFactory.fromAnyRef(spnegoHelper.SERVER_PRINCIPAL)).withValue(ExecConstants.USER_AUTHENTICATOR_IMPL, ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE)));
final DrillConfig newConfig = new DrillConfig(DrillConfig.create().withValue(ExecConstants.USER_AUTHENTICATION_ENABLED, ConfigValueFactory.fromAnyRef(true)).withValue(ExecConstants.AUTHENTICATION_MECHANISMS, ConfigValueFactory.fromIterable(Collections.singletonList("plain"))).withValue(ExecConstants.HTTP_SPNEGO_PRINCIPAL, ConfigValueFactory.fromAnyRef(spnegoHelper.SERVER_PRINCIPAL)).withValue(ExecConstants.USER_AUTHENTICATOR_IMPL, ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -55,9 +55,6 @@
import org.apache.drill.jdbc.SqlTimeoutException;
import org.slf4j.Logger;

import com.google.common.collect.Queues;


class DrillCursor implements Cursor {

////////////////////////////////////////
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this crazy doc

} catch ( SQLException e ) {
throw new RuntimeException( e );
}
(Function<Connection, Void>) connection -> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly rename class name, Test should in the beginning of the name
Test annotation, proper test name

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that it is essential at least for current PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, there are a bunch of other tests in this package with a similar name.

"from cp.`employee.json` limit 1");

resultSet.next();
final Date date = resultSet.getDate(1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

finals?

Copy link
Member Author

@vvysotskyi vvysotskyi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vdiravka, thanks for the code review, I have addressed CR comments, could you please take a look again?

@@ -57,9 +57,9 @@ public static String getPrincipalFromParts(final String primary, final String in
public static String[] splitPrincipalIntoParts(final String principal) {
final String[] components = principal.split("[/@]");
checkState(components.length == 3);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should leave it as it is since the goal of this PR is to replace guava usage by JDK where it is possible, but there is no sense to replace usage of one library by another.

}
}));
return primary.entrySet().stream()
.map((Function<Entry<K, Entry<Integer, V>>, Entry<K, V>>) entry ->
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this, removed.

@@ -42,9 +44,6 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same as for Preconditions.checkArgument()

this.createAtBeginning = createAtBeginning;
this.deleteAtEnd = deleteAtEnd;
this.subDirs = Preconditions.checkNotNull(subDirs);
this.subDirs = Objects.requireNonNull(subDirs);

Preconditions.checkArgument(!subDirs.isEmpty(), "The list of subDirs is empty.");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my previous comment

@@ -30,7 +31,6 @@
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume ImmutableMap was used here to prevent modification of the returned map. So I leave it as it is.

@@ -242,7 +241,7 @@ public String getAdminUserGroups(OptionManager optionManager) {
// if this option has not been changed by the user then return the
// process user groups
if (adminUserGroups.equals(DEFAULT_ADMIN_USER_GROUPS)) {
adminUserGroups = Joiner.on(",").join(ImpersonationUtil.getProcessUserGroupNames());
adminUserGroups = String.join(",", ImpersonationUtil.getProcessUserGroupNames());
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you meant a comma inside the string literal, then I doubt that space will be useful there, since the result of this method is often split by ",". So I leave it as it is.

return builder.toString();
return function + args.stream()
.map(ExprNode::toString)
.collect(Collectors.joining(",", "(", ")"));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a space here may cause failures of tests with checks for the query plan. You may create a Jira for further improvement of the output, but I don't think that we should do it in the scope of this Jira.

@@ -106,7 +106,7 @@ public void testInvalidSpnegoConfig() throws Exception {
@Test
public void testSpnegoConfigOnlyKeytab() throws Exception {
try {
final DrillConfig newConfig = new DrillConfig(DrillConfig.create().withValue(ExecConstants.USER_AUTHENTICATION_ENABLED, ConfigValueFactory.fromAnyRef(true)).withValue(ExecConstants.AUTHENTICATION_MECHANISMS, ConfigValueFactory.fromIterable(Lists.newArrayList("plain"))).withValue(ExecConstants.HTTP_SPNEGO_KEYTAB, ConfigValueFactory.fromAnyRef(spnegoHelper.serverKeytab.toString())).withValue(ExecConstants.USER_AUTHENTICATOR_IMPL, ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE)));
final DrillConfig newConfig = new DrillConfig(DrillConfig.create().withValue(ExecConstants.USER_AUTHENTICATION_ENABLED, ConfigValueFactory.fromAnyRef(true)).withValue(ExecConstants.AUTHENTICATION_MECHANISMS, ConfigValueFactory.fromIterable(Collections.singletonList("plain"))).withValue(ExecConstants.HTTP_SPNEGO_KEYTAB, ConfigValueFactory.fromAnyRef(spnegoHelper.serverKeytab.toString())).withValue(ExecConstants.USER_AUTHENTICATOR_IMPL, ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE)));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -123,7 +123,7 @@ public void testSpnegoConfigOnlyKeytab() throws Exception {
@Test
public void testSpnegoConfigOnlyPrincipal() throws Exception {
try {
final DrillConfig newConfig = new DrillConfig(DrillConfig.create().withValue(ExecConstants.USER_AUTHENTICATION_ENABLED, ConfigValueFactory.fromAnyRef(true)).withValue(ExecConstants.AUTHENTICATION_MECHANISMS, ConfigValueFactory.fromIterable(Lists.newArrayList("plain"))).withValue(ExecConstants.HTTP_SPNEGO_PRINCIPAL, ConfigValueFactory.fromAnyRef(spnegoHelper.SERVER_PRINCIPAL)).withValue(ExecConstants.USER_AUTHENTICATOR_IMPL, ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE)));
final DrillConfig newConfig = new DrillConfig(DrillConfig.create().withValue(ExecConstants.USER_AUTHENTICATION_ENABLED, ConfigValueFactory.fromAnyRef(true)).withValue(ExecConstants.AUTHENTICATION_MECHANISMS, ConfigValueFactory.fromIterable(Collections.singletonList("plain"))).withValue(ExecConstants.HTTP_SPNEGO_PRINCIPAL, ConfigValueFactory.fromAnyRef(spnegoHelper.SERVER_PRINCIPAL)).withValue(ExecConstants.USER_AUTHENTICATOR_IMPL, ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE)));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

} catch ( SQLException e ) {
throw new RuntimeException( e );
}
(Function<Connection, Void>) connection -> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that it is essential at least for current PR.

@weijietong
Copy link

A question about this PR: what's the benefit we can gain with this replacement ?

@vvysotskyi
Copy link
Member Author

@weijietong, this PR is an intermediate step for #1264

@weijietong
Copy link

get it, thanks for the explanation.

@vvysotskyi
Copy link
Member Author

Besides the commit were addressed CR comments, I have added two commits: the first one contains changes in commits before the rebase (some of the commits added methods which I tried to replace, so replaced them again).
The second commit contains changes to ban some guava methods.

Copy link
Member

@vdiravka vdiravka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vvysotskyi Thanks for adding signatures.txt, it will be useful to avoid further usage of deprecated Guava methods. The changes looks good for me, I have left some minor comments, please consider them.

} catch ( SQLException e ) {
throw new RuntimeException( e );
}
(Function<Connection, Void>) connection -> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, there are a bunch of other tests in this package with a similar name.

@@ -57,9 +57,9 @@ public static String getPrincipalFromParts(final String primary, final String in
public static String[] splitPrincipalIntoParts(final String principal) {
final String[] components = principal.split("[/@]");
checkState(components.length == 3);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing wrong with Guava Preconditions and with Apache Commons as well.
IMO the method names in Apache Commons are more clear.

But I've wrongly supposed that the purpose was to get rid Guava as much as possible.

We can leave Guava Preconditions, since it is already written and usage of it is more common.

this.createAtBeginning = createAtBeginning;
this.deleteAtEnd = deleteAtEnd;
this.subDirs = Preconditions.checkNotNull(subDirs);
this.subDirs = Objects.requireNonNull(subDirs);

Preconditions.checkArgument(!subDirs.isEmpty(), "The list of subDirs is empty.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Objects.requireNonNull is introduced mostly for Streams, but not for replacing Guava Preconditions.
From other hand they have the same implementation. Except Preconditions.checkNotNull() overloaded method with NPE error message formatting and Guava recommends to use Preconditions, see Guava master.

Looks like Calcite project replaces these methods, see Calcite master, but Apex doesn't replace them.

Since we stay with Guava it could be reasonably to follow their documentation.
But it is not critical, so I will leave the decision for you.

@@ -42,9 +44,6 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree

@@ -30,7 +31,6 @@
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

version.setVersion(stat.getVersion());
return bytes;
}
return curator.getData().forPath(target);
} catch (final Exception ex) {
} catch (Exception ex) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ex is used rarelya and more widespread in other languages.
But ok, you can leave it.

currSpillDirs.add(currSpillPath);
String outputFile = Joiner.on("/").join(currSpillPath, spillCount++);
String outputFile = currSpillPath+ "/" + spillCount++;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String.valueOf(), but the statement will be longer, ok, let's leave it as is.

removedFields.add(field);
return true;
} else if (field.hasSchema()) {
Iterables.addAll(removedFields, field.getAssignedSchema().removeUnreadFields());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense.

@@ -242,7 +241,7 @@ public String getAdminUserGroups(OptionManager optionManager) {
// if this option has not been changed by the user then return the
// process user groups
if (adminUserGroups.equals(DEFAULT_ADMIN_USER_GROUPS)) {
adminUserGroups = Joiner.on(",").join(ImpersonationUtil.getProcessUserGroupNames());
adminUserGroups = String.join(",", ImpersonationUtil.getProcessUserGroupNames());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It depends on where adminUserGroups is used.
Ok, let's leave it as is

return builder.toString();
return function + args.stream()
.map(ExprNode::toString)
.collect(Collectors.joining(",", "(", ")"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not major issue. Let's leave it as is

Copy link
Member Author

@vvysotskyi vvysotskyi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vdiravka, thanks for reviewing all the changes, I have replaced usage of ImmutableMap.of() and ImmutableSet.of(), could you please take a look?

this.createAtBeginning = createAtBeginning;
this.deleteAtEnd = deleteAtEnd;
this.subDirs = Preconditions.checkNotNull(subDirs);
this.subDirs = Objects.requireNonNull(subDirs);

Preconditions.checkArgument(!subDirs.isEmpty(), "The list of subDirs is empty.");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer using JDK things instead of third-party libraries, so I leave code with Objects.requireNonNull() (no additional changes in PR).

@@ -62,16 +62,16 @@ public void testEncode() throws Exception {

@Test
public void testXpath_Double() throws Exception {
final String query = "select xpath_double ('<a><b>20</b><c>40</c></a>', 'a/b * a/c') as col \n" +
String query = "select xpath_double ('<a><b>20</b><c>40</c></a>', 'a/b * a/c') as col \n" +
"from hive.kv \n" +
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with you that the purpose of the test is not directly connected with limit 0, but it helps to highlight that the schema only is required.
Thanks for providing me with a chance to make the final decision :) I'll leave the code as it is.

@@ -162,7 +163,7 @@ public void setUp() throws UnknownHostException {
@Test
public void testMongoGroupScanAssignmentMix() throws UnknownHostException,
ExecutionSetupException {
final List<DrillbitEndpoint> endpoints = Lists.newArrayList();
final List<DrillbitEndpoint> endpoints = new ArrayList<>();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

Copy link
Member

@vdiravka vdiravka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 LGTM

Copy link
Member

@vrozov vrozov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to change Preconditions.checkNotNull to Objects.requireNonNull.

Copy link
Member Author

@vvysotskyi vvysotskyi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have reverted my changes connected with Preconditions.checkNotNull().
@vdiravka, @vrozov, could you please take a look again?

this.createAtBeginning = createAtBeginning;
this.deleteAtEnd = deleteAtEnd;
this.subDirs = Preconditions.checkNotNull(subDirs);
this.subDirs = Objects.requireNonNull(subDirs);

Preconditions.checkArgument(!subDirs.isEmpty(), "The list of subDirs is empty.");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you all for discussing this. I have reverted my changes where I replaced Preconditions.checkNotNull() with Objects.requireNonNull()

import com.google.common.base.Preconditions;

import java.util.Map;
import java.util.Objects;

public class ImmutableEntry<K, V> implements Map.Entry<K, V> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vvysotskyi In case you want to replace all Guava classes with JDK ones, why not first to replace Drill custom classes with the JDK equivalent?

Copy link
Member

@vdiravka vdiravka Aug 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. What about org.apache.drill.common.collections.Collectors? You have introduced it, when Drill has already used jdk8. Is it safe to replace this class with java.util.stream.Collectors or some methods only?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea of replacing Guava classes appeared during the work on #1264 and changes became larger than it was expected initially.

The idea of replacing Drill custom classes is good, but it beyond the scope of the current PR, so I think it would be better to address it in a separate Jira.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vdiravka The purpose of org.apache.drill.common.collections.Collectors is to use internal iterator with a functional interface instead of creating a stream. In many cases, I'd recommend to use Collectors and extend this class. Using streams is justified when processing thousands of elements, for a handful number of elements, Collectors is a better option, IMO.

@vvysotskyi Personally, I don't see why it is necessary to replace all Guava classes/methods with provided by JDK. IMO, the scope of PR should be to replace only removed and deprecated by Guava team API, so it can be reduced significantly.

I don't see why it is necessary to change ImmutableEntry class as part of this PR when it needs to be completely replaced with the one provided by JDK.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vrozov sounds reasonable. Thank you for the explanation.
Does it make sense to add this info to the JavaDoc for this class and to rename this class to avoid collision with jdk Collectors?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vdiravka Yes, please feel free to add any useful information that may be missing to java doc of the Collectors class and/or add missing functionality. I don't think that rename is necessary (use either one).

@@ -54,7 +51,7 @@
public class MapWithOrdinal<K, V> implements Map<K, V> {
private final static Logger logger = LoggerFactory.getLogger(MapWithOrdinal.class);

private final Map<K, Entry<Integer, V>> primary = Maps.newLinkedHashMap();
private final Map<K, Entry<Integer, V>> primary = new LinkedHashMap<>();
private final IntObjectHashMap<V> secondary = new IntObjectHashMap<>();

private final Map<K, V> delegate = new Map<K, V>() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vvysotskyi The same question as in #1264 what is the purpose (use case) of the class?

@arina-ielchiieva
Copy link
Member

@vrozov / @vdiravka this PR has been open for a month already. I think you all agree that Volodymyr has done enormous work, doing replacement is not the most interesting or rewarding part for the developer but Volodymyr did that, also he has already made changes after several rounds of code review. So let's not demotivate him unless you want to rework the PR yourself.
Please wrap up your comments (rather than adding new ones each day), highlight what should be done to get it merged. We cannot fix all Drill problems in one PR, so please agree on follow up Jira when possible. Let's target to merge the PR next week.

@vrozov
Copy link
Member

vrozov commented Aug 25, 2018

@arina-ielchiieva / @vvysotskyi I don't see a benefit of blindly replacing Guava classes/methods with JDK ones that provide equivalent or similar functionality. It should be sufficient to replace deprecated and unstable classes/methods. So, even though an enormous amount of work was done, I don't see how Drill and drill dev community benefit from that work. I already mentioned that in my review comments and also on the mailing list. IMO, it will be more beneficial for Drill customers to resolve DRILL-6422 and #1264.

@arina-ielchiieva:

  • I don't share your concern with PR being open for a month. In Apache PR may be open for much longer and there are multiple examples of PRs being open for 2, 3 and more month in Drill and other Apache projects.
  • I agree that it is not only possible but it is much better not to fix all problems in one PR. In some cases, instead of a follow up JIRA that may never be fixed, I'd prefer to see a pre-cursor JIRA and PR and this PR is an example where I'd like to see several Drill classes being removed or refactored first (due to a larger benefit that I see for removing those classes compared to removing Guava classes).

@vvysotskyi
Copy link
Member Author

The main aim for replacing usage of guava was code consistency. Except for methods, deprecated by guava team, there was a lot of other classes/methods, which without any risks may be replaced with JDK analogs. Among them a lot of functional interfaces (Supplier, Function etc.), utility methods etc.

This pull request took much more time and effort than it should, comparing to its benefit, so I don't want to work on it anymore.

@vvysotskyi vvysotskyi closed this Aug 27, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants