All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.hugegraph.define.UpdateStrategy Maven / Gradle / Ivy

There is a newer version: 1.5.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package org.apache.hugegraph.define;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.hugegraph.util.E;
import org.apache.hugegraph.util.NumericUtil;
import com.google.common.collect.Sets;

public enum UpdateStrategy {

    // Only number support sum
    SUM {
        @Override
        Object updatePropertyValue(Object oldProperty, Object newProperty) {
            // TODO: Improve performance? (like write a method in common module)
            BigDecimal oldNumber = new BigDecimal(oldProperty.toString());
            BigDecimal newNumber = new BigDecimal(newProperty.toString());
            return oldNumber.add(newNumber);
        }

        @Override
        void checkPropertyType(Object oldProperty, Object newProperty) {
            E.checkArgument(oldProperty instanceof Number &&
                            newProperty instanceof Number,
                            this.formatError(oldProperty, newProperty,
                                             "Number"));
        }
    },

    // Only Date & Number support compare
    BIGGER {
        @Override
        Object updatePropertyValue(Object oldProperty, Object newProperty) {
            return compareNumber(oldProperty, newProperty, BIGGER);
        }

        @Override
        void checkPropertyType(Object oldProperty, Object newProperty) {
            E.checkArgument((oldProperty instanceof Date ||
                             oldProperty instanceof Number) &&
                            (newProperty instanceof Date ||
                             newProperty instanceof Number),
                            this.formatError(oldProperty, newProperty,
                                             "Date or Number"));
        }
    },

    SMALLER {
        @Override
        Object updatePropertyValue(Object oldProperty, Object newProperty) {
            return compareNumber(oldProperty, newProperty, SMALLER);
        }

        @Override
        void checkPropertyType(Object oldProperty, Object newProperty) {
            E.checkArgument((oldProperty instanceof Date ||
                             oldProperty instanceof Number) &&
                            (newProperty instanceof Date ||
                             newProperty instanceof Number),
                            this.formatError(oldProperty, newProperty,
                                             "Date or Number"));
        }
    },

    // Only Set support union & intersection
    UNION {
        @Override
        Object updatePropertyValue(Object oldProperty, Object newProperty) {
            return combineSet(oldProperty, newProperty, UNION);
        }

        @Override
        void checkPropertyType(Object oldProperty, Object newProperty) {
            // JsonElements are always List-type, so allows two type now.
            this.checkCollectionType(oldProperty, newProperty);
        }
    },

    INTERSECTION {
        @Override
        Object updatePropertyValue(Object oldProperty, Object newProperty) {
            return combineSet(oldProperty, newProperty, INTERSECTION);
        }

        @Override
        void checkPropertyType(Object oldProperty, Object newProperty) {
            this.checkCollectionType(oldProperty, newProperty);
        }
    },

    // Batch update Set should use union because of higher efficiency
    APPEND {
        @Override
        @SuppressWarnings({ "rawtypes", "unchecked" })
        Object updatePropertyValue(Object oldProperty, Object newProperty) {
            ((Collection) oldProperty).addAll((Collection) newProperty);
            return oldProperty;
        }

        @Override
        void checkPropertyType(Object oldProperty, Object newProperty) {
            this.checkCollectionType(oldProperty, newProperty);
        }
    },

    ELIMINATE {
        @Override
        @SuppressWarnings({ "rawtypes", "unchecked" })
        Object updatePropertyValue(Object oldProperty, Object newProperty) {
            ((Collection) oldProperty).removeAll((Collection) newProperty);
            return oldProperty;
        }

        @Override
        void checkPropertyType(Object oldProperty, Object newProperty) {
            this.checkCollectionType(oldProperty, newProperty);
        }
    },

    OVERRIDE {
        @Override
        Object updatePropertyValue(Object oldProperty, Object newProperty) {
            return newProperty;
        }

        @Override
        void checkPropertyType(Object oldProperty, Object newProperty) {
            // Allow any type
        }
    };

    abstract Object updatePropertyValue(Object oldProperty, Object newProperty);

    abstract void checkPropertyType(Object oldProperty, Object newProperty);

    public Object checkAndUpdateProperty(Object oldProperty,
                                         Object newProperty) {
        this.checkPropertyType(oldProperty, newProperty);
        return this.updatePropertyValue(oldProperty, newProperty);
    }

    protected String formatError(Object oldProperty, Object newProperty,
                                 String className) {
        return String.format("Property type must be %s for strategy %s, " +
                             "but got type %s, %s", className, this,
                             oldProperty.getClass().getSimpleName(),
                             newProperty.getClass().getSimpleName());
    }

    protected void checkCollectionType(Object oldProperty,
                                       Object newProperty) {
        E.checkArgument((oldProperty instanceof Set ||
                         oldProperty instanceof List) &&
                        (newProperty instanceof Set ||
                         newProperty instanceof List),
                        this.formatError(oldProperty, newProperty,
                                         "Set or List"));
    }

    protected static Object compareNumber(Object oldProperty,
                                          Object newProperty,
                                          UpdateStrategy strategy) {
        Number oldNum = NumericUtil.convertToNumber(oldProperty);
        Number newNum = NumericUtil.convertToNumber(newProperty);
        int result = NumericUtil.compareNumber(oldNum, newNum);
        return strategy == BIGGER ? (result > 0 ? oldProperty : newProperty) :
                                    (result < 0 ? oldProperty : newProperty);
    }

    protected static Set combineSet(Object oldProperty, Object newProperty,
                                       UpdateStrategy strategy) {
        Set oldSet = oldProperty instanceof Set ?
                        (Set) oldProperty :
                        new HashSet<>((List) oldProperty);
        Set newSet = newProperty instanceof Set ?
                        (Set) newProperty :
                        new HashSet<>((List) newProperty);
        return strategy == UNION ? Sets.union(oldSet, newSet) :
                                   Sets.intersection(oldSet, newSet);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy