com.erudika.para.core.CoreUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.erudika.para.core.CoreUtils.java

Source

/*
 * Copyright 2013-2015 Erudika. http://erudika.com
 *
 * Licensed 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.
 *
 * For issues and patches go to: https://github.com/erudika
 */
package com.erudika.para.core;

import com.erudika.para.core.Votable.VoteValue;
import com.erudika.para.utils.Config;
import com.erudika.para.utils.Pager;
import com.erudika.para.utils.Utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;

/**
 * Provides some the basic functionality for domain objects.
 * @author Alex Bogdanovski [alex@erudika.com]
 * @see ParaObject
 */
public final class CoreUtils {

    private CoreUtils() {
    }

    public static String getObjectURI(ParaObject obj) {
        String defurl = "/".concat(obj.getPlural());
        return (obj.getId() != null) ? defurl.concat("/").concat(obj.getId()) : defurl;
    }

    public static String getName(String name, String id) {
        return (name == null) ? "ParaObject ".concat((id == null) ? System.currentTimeMillis() + "" : id) : name;
    }

    /**
     * Creates the object again (dangerous!).
     * Same as {@link com.erudika.para.persistence.DAO#create(com.erudika.para.core.ParaObject)}.
     * @param obj an object
     * @return the object id or null
     */
    public static String overwrite(ParaObject obj) {
        return overwrite(Config.APP_NAME_NS, obj);
    }

    /**
     * Creates the object again (dangerous!).
     * Same as {@link com.erudika.para.persistence.DAO#create(java.lang.String, com.erudika.para.core.ParaObject)}.
     * @param appid the app id
     * @param obj an object
     * @return the object id or null
     */
    public static String overwrite(String appid, ParaObject obj) {
        if (obj != null && obj.getId() != null) {
            if (obj.getUpdated() == null) {
                obj.setUpdated(System.currentTimeMillis());
            }
            return obj.getDao().create(appid, obj);
        }
        return null;
    }

    ///////////////////////////////////////
    //          TAGGING METHODS
    ///////////////////////////////////////

    /**
     * Adds any number of tags to the set of tags.
     * @param tag a tag, must not be null or empty
     * @param objectTags the object tags
     * @return a new list of tags
     */
    public static List<String> addTags(List<String> objectTags, String... tag) {
        if (tag != null && tag.length > 0) {
            Set<String> tagz;
            if (objectTags == null || objectTags.isEmpty()) {
                tagz = new HashSet<String>();
            } else {
                tagz = new HashSet<String>(objectTags);
            }
            for (String t : tag) {
                if (!StringUtils.isBlank(t)) {
                    tagz.add(Utils.noSpaces(Utils.stripAndTrim(t), "-"));
                }
            }
            tagz.remove(null);
            tagz.remove("");
            return new ArrayList<String>(tagz);
        }
        return objectTags;
    }

    /**
     * Removes a tag from the set of tags.
     * @param tag a tag, must not be null or empty
     * @param objectTags the object
     * @return a new list of tags
     */
    public static List<String> removeTags(List<String> objectTags, String... tag) {
        if (objectTags != null && tag != null && tag.length > 0) {
            Set<String> tagz = new HashSet<String>(objectTags);
            tagz.removeAll(Arrays.asList(tag));
            return new ArrayList<String>(tagz);
        }
        return objectTags;
    }

    ///////////////////////////////////////
    //         LINKER METHODS
    ///////////////////////////////////////

    /**
     * Links an object to this one in a many-to-many relationship.
     * Only a link is created. Objects are left untouched.
     * The type of the second object is automatically determined on read.
     * @param id2 link to the object with this id
     * @param obj the object to execute this method on
     * @return the id of the {@link com.erudika.para.core.Linker} object that is created
     */
    public static String link(ParaObject obj, String id2) {
        ParaObject second = obj.getDao().read(obj.getAppid(), id2);
        if (second == null || obj.getId() == null) {
            return null;
        }
        // auto correct the second type
        return obj.getDao().create(obj.getAppid(), new Linker(obj.getType(), second.getType(), obj.getId(), id2));
    }

    /**
     * Unlinks an object from this one.
     * Only a link is deleted. Objects are left untouched.
     * @param type2 the other type
     * @param obj the object to execute this method on
     * @param id2 the other id
     */
    public static void unlink(ParaObject obj, String type2, String id2) {
        obj.getDao().delete(obj.getAppid(), new Linker(obj.getType(), type2, obj.getId(), id2));
    }

    /**
     * Unlinks all objects that are linked to this one.
     * @param obj the object to execute this method on
     * Deletes all {@link com.erudika.para.core.Linker} objects.
     * Only the links are deleted. Objects are left untouched.
     */
    public static void unlinkAll(ParaObject obj) {
        Map<String, Object> terms = new HashMap<String, Object>();
        // delete all links where id1 == id OR id2 == id
        terms.put("id1", obj.getId());
        terms.put("id2", obj.getId());
        obj.getDao().deleteAll(obj.getAppid(),
                obj.getSearch().findTerms(obj.getAppid(), Utils.type(Linker.class), terms, false));
    }

    /**
     * Returns a list of all Linker objects for a given object.
     * @param obj the object to execute this method on
     * @param type2 the other type
     * @param pager a {@link com.erudika.para.utils.Pager}
     * @return a list of Linker objects
     */
    public static List<Linker> getLinks(ParaObject obj, String type2, Pager... pager) {
        if (type2 == null) {
            return Collections.emptyList();
        }
        Linker link = new Linker(obj.getType(), type2, null, null);
        String idField = link.getIdFieldNameFor(obj.getType());
        Map<String, Object> terms = new HashMap<String, Object>();
        terms.put(Config._NAME, link.getName());
        terms.put(idField, obj.getId());
        return obj.getSearch().findTerms(obj.getAppid(), link.getType(), terms, true, pager);
    }

    /**
     * Checks if this object is linked to another.
     * @param type2 the other type
     * @param id2 the other id
     * @param obj the object to execute this method on
     * @return true if the two are linked
     */
    public static boolean isLinked(ParaObject obj, String type2, String id2) {
        if (type2 == null) {
            return false;
        }
        return obj.getDao().read(obj.getAppid(),
                new Linker(obj.getType(), type2, obj.getId(), id2).getId()) != null;
    }

    /**
     * Checks if a given object is linked to this one.
     * @param toObj the other object
     * @param obj the object to execute this method on
     * @return true if linked
     */
    public static boolean isLinked(ParaObject obj, ParaObject toObj) {
        if (toObj == null) {
            return false;
        }
        return isLinked(obj, toObj.getType(), toObj.getId());
    }

    /**
     * Count the total number of links between this object and another type of object.
     * @param type2 the other type of object
     * @param obj the object to execute this method on
     * @return the number of links for the given object
     */
    public static Long countLinks(ParaObject obj, String type2) {
        if (obj.getId() == null) {
            return 0L;
        }
        Linker link = new Linker(obj.getType(), type2, null, null);
        String idField = link.getIdFieldNameFor(obj.getType());
        Map<String, Object> terms = new HashMap<String, Object>();
        terms.put(Config._NAME, link.getName());
        terms.put(idField, obj.getId());
        return obj.getSearch().getCount(obj.getAppid(), link.getType(), terms);
    }

    /**
     * Count the total number of child objects for this object.
     * @param type2 the type of the other object
     * @param obj the object to execute this method on
     * @return the number of links
     */
    public static Long countChildren(ParaObject obj, String type2) {
        return obj.getSearch().getCount(obj.getAppid(), type2);
    }

    /**
     * Returns all child objects linked to this object.
     * @param <P> the type of children
     * @param type2 the type of children to look for
     * @param obj the object to execute this method on
     * @param pager a {@link com.erudika.para.utils.Pager}
     * @return a list of {@link ParaObject} in a one-to-many relationship with this object
     */
    public static <P extends ParaObject> List<P> getChildren(ParaObject obj, String type2, Pager... pager) {
        return getChildren(obj, type2, null, null, pager);
    }

    /**
     * Returns all child objects linked to this object.
     * @param <P> the type of children
     * @param type2 the type of children to look for
     * @param field the field name to use as filter
     * @param term the field value to use as filter
     * @param obj the object to execute this method on
     * @param pager a {@link com.erudika.para.utils.Pager}
     * @return a list of {@link ParaObject} in a one-to-many relationship with this object
     */
    public static <P extends ParaObject> List<P> getChildren(ParaObject obj, String type2, String field,
            String term, Pager... pager) {
        Map<String, Object> terms = new HashMap<String, Object>();
        if (!StringUtils.isBlank(field) && !StringUtils.isBlank(term)) {
            terms.put(field, term);
        }
        terms.put(Config._PARENTID, obj.getId());
        return obj.getSearch().findTerms(obj.getAppid(), type2, terms, true, pager);
    }

    /**
     * Deletes all child objects permanently.
     * @param obj the object to execute this method on
     * @param type2 the children's type.
     */
    public static void deleteChildren(ParaObject obj, String type2) {
        if (!StringUtils.isBlank(obj.getId())) {
            obj.getDao().deleteAll(obj.getAppid(), obj.getSearch().findTerms(obj.getAppid(), type2,
                    Collections.singletonMap(Config._PARENTID, obj.getId()), true));
        }
    }

    /**
     * Returns all objects linked to the given one. Only applicable to many-to-many relationships.
     * @param <P> type of linked objects
     * @param type2 type of linked objects to search for
     * @param obj the object to execute this method on
     * @param pager a {@link com.erudika.para.utils.Pager}
     * @return a list of linked objects
     */
    @SuppressWarnings("unchecked")
    public static <P extends ParaObject> List<P> getLinkedObjects(ParaObject obj, String type2, Pager... pager) {
        List<Linker> links = getLinks(obj, type2, pager);
        LinkedList<String> keys = new LinkedList<String>();
        for (Linker link : links) {
            if (link.isFirst(type2)) {
                keys.add(link.getId1());
            } else {
                keys.add(link.getId2());
            }
        }
        return new ArrayList<P>(
                (Collection<? extends P>) obj.getDao().readAll(obj.getAppid(), keys, true).values());
    }

    ///////////////////////////////////////
    //          VOTING METHODS
    ///////////////////////////////////////

    /**
     * Casts a vote on a given object.
     * @param votable the object to vote on
     * @param userid the voter
     * @param upDown up or down
     * @return true if the vote was successful
     */
    public static boolean vote(ParaObject votable, String userid, VoteValue upDown) {
        if (StringUtils.isBlank(userid) || votable == null || votable.getId() == null || upDown == null) {
            return false;
        }
        //no voting on your own stuff!
        if (userid.equals(votable.getCreatorid()) || userid.equals(votable.getId())) {
            return false;
        }

        Vote v = new Vote(userid, votable.getId(), upDown.toString());
        Vote saved = votable.getDao().read(votable.getAppid(), v.getId());
        boolean done = false;
        int vote = (upDown == VoteValue.UP) ? 1 : -1;

        if (saved != null) {
            boolean isUpvote = upDown.equals(VoteValue.UP);
            boolean wasUpvote = VoteValue.UP.toString().equals(saved.getValue());
            boolean voteHasChanged = isUpvote ^ wasUpvote;

            if (saved.isExpired()) {
                done = votable.getDao().create(votable.getAppid(), v) != null;
            } else if (saved.isAmendable() && voteHasChanged) {
                votable.getDao().delete(votable.getAppid(), saved);
                done = true;
            }
        } else {
            done = votable.getDao().create(votable.getAppid(), v) != null;
        }

        if (done) {
            synchronized (votable) {
                votable.setVotes(votable.getVotes() + vote);
            }
        }
        return done;
    }

}