Skip to content

Commit

Permalink
Refactor strategies to functions instead of using inheritance (#311)
Browse files Browse the repository at this point in the history
* Refactor strategies to functions instead of using inheritance

Signed-off-by: Gyúróczki Gergő <gergonoorbi@gmail.com>

* Fix & refactor some stuff

Signed-off-by: Gyúróczki Gergő <gergonoorbi@gmail.com>

* Yiked optional method

Signed-off-by: Gyúróczki Gergő <gergonoorbi@gmail.com>

* Reduce diff size

Signed-off-by: Degubi <gergonoorbi@gmail.com>

* Remove unnecessary propertyName.length() from .substring call

Signed-off-by: Gyúróczki Gergő <gergonoorbi@gmail.com>

* Add basic benchmark for serializing a pojo with 10 fields

Signed-off-by: Gyúróczki Gergő <gergonoorbi@gmail.com>

* Fix wrong class name after renaming

Signed-off-by: Gyúróczki Gergő <gergonoorbi@gmail.com>
  • Loading branch information
Degubi authored and aguibert committed Sep 3, 2019
1 parent cebd1fd commit 764abb5
Show file tree
Hide file tree
Showing 19 changed files with 255 additions and 523 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,15 @@
*
* Contributors:
* Roman Grigoriadi
* Gyúróczki Gergő
******************************************************************************/
package org.eclipse.yasson.internal;

import org.eclipse.yasson.YassonProperties;
import org.eclipse.yasson.internal.model.ReverseTreeMap;
import org.eclipse.yasson.internal.model.customization.naming.DefaultNamingStrategies;
import org.eclipse.yasson.internal.model.customization.naming.IdentityStrategy;
import org.eclipse.yasson.internal.model.customization.ordering.AnyOrderStrategy;
import org.eclipse.yasson.internal.model.customization.ordering.LexicographicalOrderStrategy;
import org.eclipse.yasson.internal.model.customization.ordering.PropOrderStrategy;
import org.eclipse.yasson.internal.model.customization.ordering.PropertyOrdering;
import org.eclipse.yasson.internal.model.customization.ordering.ReverseOrderStrategy;
import org.eclipse.yasson.internal.model.PropertyModel;
import org.eclipse.yasson.internal.model.customization.PropertyOrdering;
import org.eclipse.yasson.internal.model.customization.StrategiesProvider;
import org.eclipse.yasson.internal.properties.MessageKeys;
import org.eclipse.yasson.internal.properties.Messages;
import org.eclipse.yasson.internal.serializer.JsonbDateFormatter;
Expand All @@ -38,12 +35,15 @@
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.function.Function;

/**
* Resolved properties from JSONB config.
Expand Down Expand Up @@ -156,22 +156,11 @@ private String getGlobalConfigJsonbDateFormat() {
}).orElse(JsonbDateFormat.DEFAULT_FORMAT);
}

private PropOrderStrategy initOrderStrategy() {
private Function<Collection<PropertyModel>, List<PropertyModel>> initOrderStrategy() {
Optional<String> strategy = getPropertyOrderStrategy();
if (strategy.isPresent()) {
switch (strategy.get()) {
case PropertyOrderStrategy.LEXICOGRAPHICAL:
return new LexicographicalOrderStrategy();
case PropertyOrderStrategy.REVERSE:
return new ReverseOrderStrategy();
case PropertyOrderStrategy.ANY:
return new AnyOrderStrategy();
default:
throw new JsonbException(Messages.getMessage(MessageKeys.PROPERTY_ORDER, strategy));
}
}
//default by spec
return new LexicographicalOrderStrategy();

return strategy.map(StrategiesProvider::getOrderingFunction)
.orElseGet(() -> StrategiesProvider.getOrderingFunction(PropertyOrderStrategy.LEXICOGRAPHICAL)); //default by spec
}

private Optional<String> getPropertyOrderStrategy() {
Expand All @@ -185,7 +174,7 @@ private Optional<String> getPropertyOrderStrategy() {
case PropertyOrderStrategy.LEXICOGRAPHICAL:
case PropertyOrderStrategy.REVERSE:
case PropertyOrderStrategy.ANY:
return Optional.of((String)strategy);
return Optional.of((String) strategy);
default:
throw new JsonbException(Messages.getMessage(MessageKeys.PROPERTY_ORDER, strategy));
}
Expand All @@ -196,16 +185,11 @@ private Optional<String> getPropertyOrderStrategy() {
private PropertyNamingStrategy initPropertyNamingStrategy() {
final Optional<Object> property = jsonbConfig.getProperty(JsonbConfig.PROPERTY_NAMING_STRATEGY);
if (!property.isPresent()) {
return new IdentityStrategy();
return StrategiesProvider.getPropertyNamingStrategy(PropertyNamingStrategy.IDENTITY);
}
Object propertyNamingStrategy = property.get();
if (propertyNamingStrategy instanceof String) {
String namingStrategyName = (String) propertyNamingStrategy;
final PropertyNamingStrategy foundNamingStrategy = DefaultNamingStrategies.getStrategy(namingStrategyName);
if (foundNamingStrategy == null) {
throw new JsonbException("No property naming strategy was found for: " + namingStrategyName);
}
return foundNamingStrategy;
return StrategiesProvider.getPropertyNamingStrategy((String) propertyNamingStrategy);
}
if (!(propertyNamingStrategy instanceof PropertyNamingStrategy)) {
throw new JsonbException(Messages.getMessage(MessageKeys.PROPERTY_NAMING_STRATEGY_INVALID));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
package org.eclipse.yasson.internal.model;

import org.eclipse.yasson.internal.ReflectionUtils;
import org.eclipse.yasson.internal.model.customization.naming.CaseInsensitiveStrategy;
import org.eclipse.yasson.internal.model.customization.StrategiesProvider;
import org.eclipse.yasson.internal.model.customization.ClassCustomization;

import javax.json.bind.config.PropertyNamingStrategy;
Expand Down Expand Up @@ -110,7 +110,7 @@ private PropertyModel searchProperty(ClassModel classModel, String jsonReadName)
*/
private boolean equalsReadName(String jsonName, PropertyModel propertyModel) {
final String propertyReadName = propertyModel.getReadName();
if (propertyNamingStrategy instanceof CaseInsensitiveStrategy) {
if (propertyNamingStrategy == StrategiesProvider.CASE_INSENSITIVE_STRATEGY) {
return jsonName.equalsIgnoreCase(propertyReadName);
}
return jsonName.equals(propertyReadName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,16 @@
*
* Contributors:
* Roman Grigoriadi
* Gyúróczki Gergő
******************************************************************************/
package org.eclipse.yasson.internal.model.customization.ordering;
package org.eclipse.yasson.internal.model.customization;

import org.eclipse.yasson.internal.model.ClassModel;
import org.eclipse.yasson.internal.model.PropertyModel;

import java.util.*;
import java.util.function.*;
import javax.json.bind.JsonbConfig;
import javax.json.bind.config.PropertyOrderStrategy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
* Order properties in bean object. {@link javax.json.bind.annotation.JsonbPropertyOrder} have always precedence.
Expand All @@ -31,16 +28,15 @@
*/
public class PropertyOrdering {

private PropOrderStrategy propertyOrderStrategy;
private final Function<Collection<PropertyModel>, List<PropertyModel>> propertyOrderStrategy;

/**
* Creates a new instance.
*
* @param propertyOrderStrategy Property order strategy. Must be not null.
*/
public PropertyOrdering(PropOrderStrategy propertyOrderStrategy) {
Objects.requireNonNull(propertyOrderStrategy);
this.propertyOrderStrategy = propertyOrderStrategy;
public PropertyOrdering(Function<Collection<PropertyModel>, List<PropertyModel>> propertyOrderStrategy) {
this.propertyOrderStrategy = Objects.requireNonNull(propertyOrderStrategy);
}

/**
Expand All @@ -67,17 +63,7 @@ public List<PropertyModel> orderProperties(List<PropertyModel> properties, Class
}
}

sortedProperties.addAll(propertyOrderStrategy.sortProperties(byReadName.values()));
sortedProperties.addAll(propertyOrderStrategy.apply(byReadName.values()));
return sortedProperties;

}

/**
* Returns a property order strategy from {@link JsonbConfig}.
*
* @return {@link PropOrderStrategy} or null if not present.
*/
public PropOrderStrategy getPropertyOrderStrategy() {
return propertyOrderStrategy;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*******************************************************************************
* Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Gyúróczki Gergő
******************************************************************************/
package org.eclipse.yasson.internal.model.customization;

import static java.util.stream.Collectors.toList;
import static java.util.Comparator.comparing;
import static javax.json.bind.config.PropertyNamingStrategy.*;
import static javax.json.bind.config.PropertyOrderStrategy.*;

import javax.json.bind.JsonbException;
import javax.json.bind.config.PropertyNamingStrategy;
import org.eclipse.yasson.internal.model.PropertyModel;
import org.eclipse.yasson.internal.properties.Messages;
import org.eclipse.yasson.internal.properties.MessageKeys;

import java.nio.CharBuffer;
import java.util.function.Function;
import java.util.*;

public final class StrategiesProvider {
private StrategiesProvider() {}

public static final PropertyNamingStrategy CASE_INSENSITIVE_STRATEGY = Objects::requireNonNull;

public static Function<Collection<PropertyModel>, List<PropertyModel>> getOrderingFunction(String strategy){
switch(strategy) {
case LEXICOGRAPHICAL:
return createSortingOrdererFunction(comparing(PropertyModel::getWriteName));
case ANY:
return ArrayList::new;
case REVERSE:
return createSortingOrdererFunction(comparing(PropertyModel::getWriteName).reversed());
default:
throw new JsonbException(Messages.getMessage(MessageKeys.PROPERTY_ORDER, strategy));
}
}

public static PropertyNamingStrategy getPropertyNamingStrategy(String strategy) {
switch(strategy) {
case LOWER_CASE_WITH_UNDERSCORES:
return createLowerCaseStrategyWithSeparator('_');
case LOWER_CASE_WITH_DASHES:
return createLowerCaseStrategyWithSeparator('-');
case UPPER_CAMEL_CASE:
return createUpperCamelCaseStrategy();
case UPPER_CAMEL_CASE_WITH_SPACES:
return createUpperCamelCaseWithSpaceStrategy();
case IDENTITY:
return Objects::requireNonNull;
case CASE_INSENSITIVE:
return CASE_INSENSITIVE_STRATEGY;
default:
throw new JsonbException("No property naming strategy was found for: " + strategy);
}
}


private static Function<Collection<PropertyModel>, List<PropertyModel>> createSortingOrdererFunction(Comparator<PropertyModel> comparator){
return props -> props.stream().sorted(comparator).collect(toList());
}

private static PropertyNamingStrategy createUpperCamelCaseStrategy() {
return propertyName -> {
Objects.requireNonNull(propertyName);
char first = Character.toUpperCase(propertyName.charAt(0));

return first + propertyName.substring(1);
};
}

private static PropertyNamingStrategy createUpperCamelCaseWithSpaceStrategy() {
return propertyName -> {
String upperCased = createUpperCamelCaseStrategy().translateName(propertyName);
CharBuffer buffer = CharBuffer.allocate(upperCased.length() * 2);
char last = Character.MIN_VALUE;

for(int i = 0; i < upperCased.length(); ++i) {
char current = upperCased.charAt(i);

if (i > 0 && Character.isUpperCase(current) && isLowerCaseCharacter(last)) {
buffer.append(' ');
}
last = current;
buffer.append(current);
}
return new String(buffer.array(), 0, buffer.position());
};
}

private static PropertyNamingStrategy createLowerCaseStrategyWithSeparator(char separator) {
return propertyName -> {
Objects.requireNonNull(propertyName);
CharBuffer charBuffer = CharBuffer.allocate(propertyName.length() * 2);
char last = Character.MIN_VALUE;

for(int i = 0; i < propertyName.length(); ++i) {
char current = propertyName.charAt(i);

if (i > 0 && Character.isUpperCase(current) && isLowerCaseCharacter(last)) {
charBuffer.append(separator);
}
last = current;
charBuffer.append(Character.toLowerCase(current));
}
return new String(charBuffer.array(), 0, charBuffer.position());
};
}

private static boolean isLowerCaseCharacter(char character) {
return Character.isAlphabetic(character) && Character.isLowerCase(character);
}
}

This file was deleted.

This file was deleted.

0 comments on commit 764abb5

Please sign in to comment.