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

Remove type reference from (by) option #311

Merged
merged 35 commits into from
Feb 8, 2019
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
63fa2a0
Deprecate type-related part of `FieldReference`
alexander-yevsyukov Feb 4, 2019
5370bba
Remove tests of deprecated methods
alexander-yevsyukov Feb 4, 2019
d384b69
Merge remote-tracking branch 'remotes/origin/remove-enrichment-option…
alexander-yevsyukov Feb 4, 2019
6525392
Migrate test method names
alexander-yevsyukov Feb 4, 2019
29eb19f
Merge remote-tracking branch 'remotes/origin/remove-enrichment-option…
alexander-yevsyukov Feb 4, 2019
63c9c01
Merge remote-tracking branch 'remotes/origin/distinct-repeated-field-…
alexander-yevsyukov Feb 4, 2019
f49fb2b
Shorten name, improve Javadoc
alexander-yevsyukov Feb 4, 2019
74b5e34
Merge remote-tracking branch 'remotes/origin/distinct-repeated-field-…
alexander-yevsyukov Feb 4, 2019
eb8bef3
Merge remote-tracking branch 'remotes/origin/remove-enrichment-option…
alexander-yevsyukov Feb 4, 2019
4e1e03e
Merge remote-tracking branch 'remotes/origin/master' into no-wildcard…
alexander-yevsyukov Feb 5, 2019
b7c9ad4
Merge in the options improvement branch
alexander-yevsyukov Feb 5, 2019
58d8439
Remove author tag
alexander-yevsyukov Feb 5, 2019
f75de74
Merge remote-tracking branch 'origin/no-wildcard-in-by' into no-wildc…
alexander-yevsyukov Feb 5, 2019
1e54030
Extract var
alexander-yevsyukov Feb 5, 2019
eafee39
Update options documentation
alexander-yevsyukov Feb 5, 2019
d0d37fc
Give examples numbers and titles
alexander-yevsyukov Feb 6, 2019
39b6589
Merge remote-tracking branch 'remotes/origin/master' into no-wildcard…
alexander-yevsyukov Feb 6, 2019
99172e8
Remove unused constant
alexander-yevsyukov Feb 6, 2019
e71856f
Reduce scope of warning suppression
alexander-yevsyukov Feb 6, 2019
6f986d7
Merge remote-tracking branch 'remotes/origin/master' into no-wildcard…
alexander-yevsyukov Feb 6, 2019
e743a72
Fix the description of external validation constraint
alexander-yevsyukov Feb 6, 2019
bacbf98
Merge remote-tracking branch 'remotes/origin/master' into no-wildcard…
alexander-yevsyukov Feb 6, 2019
9c409b2
Move FieldContext under `code.proto`
alexander-yevsyukov Feb 6, 2019
73e0ee7
Remove support of wildcard type reference in `FieldRef`
alexander-yevsyukov Feb 6, 2019
3050309
Remove support of wildcard type reference in `FieldRef`
alexander-yevsyukov Feb 6, 2019
960f04c
Import nested class
alexander-yevsyukov Feb 7, 2019
a45f90b
Improve field Javadoc
alexander-yevsyukov Feb 7, 2019
57cae4a
Restore type checking and check field presence when matching types
alexander-yevsyukov Feb 7, 2019
a0a29c7
Improve warning diags
alexander-yevsyukov Feb 7, 2019
02c11d8
Fix param spec
alexander-yevsyukov Feb 7, 2019
47adc7d
Merge remote-tracking branch 'remotes/origin/master' into no-wildcard…
alexander-yevsyukov Feb 8, 2019
51c45c9
Return version number to `SNAPSHOT`
alexander-yevsyukov Feb 8, 2019
df283b6
Merge remote-tracking branch 'remotes/origin/master' into no-wildcard…
alexander-yevsyukov Feb 8, 2019
8f671b5
Merge remote-tracking branch 'remotes/origin/master' into no-wildcard…
alexander-yevsyukov Feb 8, 2019
ce65373
Replace method reference
alexander-yevsyukov Feb 8, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,21 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package io.spine.validate;
package io.spine.code.proto;

import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.Descriptors.FieldDescriptor;
import io.spine.annotation.Internal;
import io.spine.base.FieldPath;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Lists.newLinkedList;
import static java.util.Collections.singleton;

/**
* Provides information about a proto field in the nesting hierarchy.
*/
@Internal
@Immutable
public final class FieldContext {

/**
Expand All @@ -58,16 +55,16 @@ public final class FieldContext {
* <p>The value of this field for the {@code value} field of the {@code UserId} is
* {@code [FieldDescriptor_for_id, FieldDescriptor_for_value]}.
*/
private final List<FieldDescriptor> descriptors;
private final ImmutableList<FieldDescriptor> descriptors;

/**
* Provides field names in the nesting hierarchy.
*/
private final FieldPath fieldPath;

private FieldContext(Iterable<FieldDescriptor> descriptors) {
this.descriptors = newLinkedList(descriptors);
this.fieldPath = fieldPathOf(descriptors);
private FieldContext(ImmutableList<FieldDescriptor> descriptors) {
this.descriptors = descriptors;
this.fieldPath = toPath(descriptors);
}

/**
Expand All @@ -77,16 +74,16 @@ private FieldContext(Iterable<FieldDescriptor> descriptors) {
* @return the field context
*/
public static FieldContext create(FieldDescriptor field) {
return new FieldContext(singleton(field));
return new FieldContext(ImmutableList.of(field));
}

/**
* Creates empty descriptor context.
*
* @return the descriptor context
*/
static FieldContext empty() {
return new FieldContext(Collections.emptyList());
public static FieldContext empty() {
return new FieldContext(ImmutableList.of());
}

/**
Expand All @@ -96,23 +93,26 @@ static FieldContext empty() {
* @return the child descriptor context
*/
public FieldContext forChild(FieldDescriptor child) {
List<FieldDescriptor> newDescriptors = newLinkedList(descriptors);
newDescriptors.add(child);
return new FieldContext(newDescriptors);
return new FieldContext(
ImmutableList.<FieldDescriptor>builder()
.addAll(descriptors)
.add(child)
.build()
);
}

/**
* Obtains target of this context.
*
* @return the target descriptor
*/
public FieldDescriptor getTarget() {
public FieldDescriptor target() {
checkState(!descriptors.isEmpty(), "Empty context cannot have a target.");
int targetIndex = descriptors.size() - 1;
return descriptors.get(targetIndex);
}

private Optional<FieldDescriptor> getTargetParent() {
private Optional<FieldDescriptor> targetParent() {
int targetParentIndex = descriptors.size() - 2;
boolean parentExists = targetParentIndex > -1;
return parentExists
Expand All @@ -125,7 +125,7 @@ private Optional<FieldDescriptor> getTargetParent() {
*
* @return the field path
*/
FieldPath getFieldPath() {
public FieldPath fieldPath() {
return fieldPath;
}

Expand All @@ -137,23 +137,32 @@ FieldPath getFieldPath() {
* @return {@code true} if this context has the same target and the same parent
*/
public boolean hasSameTargetAndParent(FieldContext other) {
String thisTargetName = getTarget().getFullName();
String otherTargetName = other.getTarget()
String thisTargetName = target().getFullName();
String otherTargetName = other.target()
.getFullName();
boolean sameTarget = thisTargetName.equals(otherTargetName);
if (!sameTarget) {
return false;
}
Optional<String> parentFromThis = getTargetParent()
Optional<String> parentFromThis = targetParent()
.map(FieldDescriptor::getFullName);
Optional<String> parentFromOther = other
.getTargetParent()
.targetParent()
.map(FieldDescriptor::getFullName);
boolean bothHaveParents = parentFromThis.isPresent() && parentFromOther.isPresent();
return bothHaveParents && parentFromThis.get()
.equals(parentFromOther.get());
}

private static FieldPath toPath(Iterable<FieldDescriptor> descriptors) {
FieldPath.Builder builder = FieldPath.newBuilder();
for (FieldDescriptor descriptor : descriptors) {
String fieldName = descriptor.getName();
builder = builder.addFieldName(fieldName);
}
return builder.build();
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand All @@ -172,13 +181,4 @@ public boolean equals(Object o) {
public int hashCode() {
return descriptors.hashCode();
}

private static FieldPath fieldPathOf(Iterable<FieldDescriptor> descriptors) {
FieldPath.Builder builder = FieldPath.newBuilder();
for (FieldDescriptor descriptor : descriptors) {
String fieldName = descriptor.getName();
builder = builder.addFieldName(fieldName);
}
return builder.build();
}
}
3 changes: 0 additions & 3 deletions base/src/main/java/io/spine/code/proto/FieldName.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ public final class FieldName extends AbstractFieldName implements UnderscoredNam

private static final long serialVersionUID = 0L;

/** A delimiter between a type name and a field name. */
public static final String TYPE_SEPARATOR = ".";

/**
* The separator is an underscore or a digit.
*
Expand Down
59 changes: 1 addition & 58 deletions base/src/main/java/io/spine/code/proto/ref/BuiltIn.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,52 +20,20 @@

package io.spine.code.proto.ref;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.Descriptors.Descriptor;

import java.util.Optional;
import java.util.stream.Stream;

import static com.google.common.base.Preconditions.checkArgument;
import static io.spine.util.Preconditions2.checkNotEmptyOrBlank;

/**
* Provides typical type references used for referencing types in proto definitions.
*
* <p>A type reference is usually used in a field reference
* <p>A type reference is usually used in a field reference.
*/
@Immutable
enum BuiltIn implements TypeRef {

/**
* Wildcard option used to reference all types.
*
* <p>A typical usage would be in a field reference in the {@code (by)} option to
* specify all types containing a field with a certain name. Consider the following message
* declaration:
* <pre>{@code
* message MyEnrichment {
* string enrichment_value = 1 [(by) = "*.my_id"];
* }}
* </pre>
* tells that the enrichment field is populated after the a field named {@code my_id}
* found in any type. This, in turn, means that the type {@code MyEnrichment} will be used
* for all the messages declaring a field with such name.
*
* <p>A special care should be taken for ensuring that such fields have the same type, and
* that an enrichment function is provided for obtaining enrichment field value from a source
* message field.
*/
ALL("*") {

/** Accepts all message types. */
@Override
public boolean test(Descriptor message) {
return true;
}
},

SELF("") {

/**
Expand Down Expand Up @@ -124,31 +92,6 @@ Optional<TypeRef> parse(String value) {
return Optional.empty();
}

/**
* Ensures that the passed value is:
* <ol>
* <li>not null
* <li>not empty or blank
* <li>not a wild card type reference in a suffix form
* (such as {@code '*CommonEventNameSuffix.field_name'}, which is not currently supported.
* </ol>
*/
@CanIgnoreReturnValue
static String checkTypeReference(String typeReference) {
checkNotEmptyOrBlank(typeReference);
String wildcard = ALL.value();
if (typeReference.startsWith(wildcard)) {
checkArgument(
typeReference.equals(wildcard),
"Referencing types with a suffix form (`%s`) in wildcard reference " +
"is not supported . " +
"Please use '%s.<field_name>' when referencing a field of many types.",
typeReference,
wildcard);
}
return typeReference;
}

/** Obtains the value of the reference. */
@Override
public String value() {
Expand Down
11 changes: 6 additions & 5 deletions base/src/main/java/io/spine/code/proto/ref/CompositeTypeRef.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,13 @@ static CompositeTypeRef parse(String value) {
}

private static TypeRef parsePart(String part) {
Parsing p = new Parsing(part, InPackage::parse, DirectTypeRef::parse);
Parsing parsing = new Parsing(part, InPackage::parse, DirectTypeRef::parse);
TypeRef result =
p.parse()
.orElseThrow(() -> newIllegalArgumentException(
"The value (`%s`) cannot be used in a composite type reference.", part
));
parsing.parse()
.orElseThrow(() -> newIllegalArgumentException(
"The value (`%s`) cannot be used in a composite type reference.",
part
));
return result;
}

Expand Down
5 changes: 2 additions & 3 deletions base/src/main/java/io/spine/code/proto/ref/DirectTypeRef.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import java.util.Optional;

import static com.google.common.base.Preconditions.checkNotNull;
import static io.spine.code.proto.ref.BuiltIn.ALL;
import static io.spine.code.proto.ref.BuiltIn.SELF;
import static java.util.stream.Collectors.toList;

Expand All @@ -54,10 +53,10 @@ public final class DirectTypeRef extends AbstractTypeRef {
*/
static Optional<TypeRef> parse(String value) {
checkNotNull(value);
if (value.equals(SELF.value())) {
if (value.contains(InPackage.WILDCARD)) {
return Optional.empty();
}
if (value.contains(ALL.value())) {
if (value.equals(SELF.value())) {
return Optional.empty();
}
TypeRef result = new DirectTypeRef(value);
Expand Down
Loading