com.flexive.shared.content.FxPK.java Source code

Java tutorial

Introduction

Here is the source code for com.flexive.shared.content.FxPK.java

Source

/***************************************************************
 *  This file is part of the [fleXive](R) framework.
 *
 *  Copyright (c) 1999-2014
 *  UCS - unique computing solutions gmbh (http://www.ucs.at)
 *  All rights reserved
 *
 *  The [fleXive](R) project is free software; you can redistribute
 *  it and/or modify it under the terms of the GNU Lesser General Public
 *  License version 2.1 or higher as published by the Free Software Foundation.
 *
 *  The GNU Lesser General Public License can be found at
 *  http://www.gnu.org/licenses/lgpl.html.
 *  A copy is found in the textfile LGPL.txt and important notices to the
 *  license from the author are found in LICENSE.txt distributed with
 *  these libraries.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  For further information about UCS - unique computing solutions gmbh,
 *  please see the company website: http://www.ucs.at
 *
 *  For further information about [fleXive](R), please see the
 *  project website: http://www.flexive.org
 *
 *
 *  This copyright notice MUST APPEAR in all copies of the file!
 ***************************************************************/
package com.flexive.shared.content;

import com.flexive.shared.exceptions.FxInvalidParameterException;
import com.flexive.shared.structure.FxSelectListItem;
import com.flexive.shared.structure.TypeStorageMode;
import com.flexive.shared.value.FxReference;
import com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

/**
 * Primary key for FxContents
 *
 * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
 */
public class FxPK implements Serializable, Comparable<FxPK> {
    private static final Log LOG = LogFactory.getLog(FxPK.class);
    private static final long serialVersionUID = 8452775369399900087L;

    /**
     * Id to use for new instances (flags them as new)
     */
    public static final int NEW_ID = -1;

    /**
     * Constant to select the maximum available version
     */
    public static final int MAX = -1;

    /**
     * Constant to select the version whose workflow step is flagged as live
     *
     * @see com.flexive.shared.workflow.Step#isLiveStep()
     */
    public static final int LIVE = -2;

    protected long id;
    protected int version;

    /**
     * Ctor
     *
     * @param id      id
     * @param version version
     */
    public FxPK(long id, int version) {
        this.id = id;
        this.version = version;
        if (this.version < LIVE)
            throw new FxInvalidParameterException("version", LOG, "ex.content.pk.invalid.version", id, version)
                    .asRuntimeException();
    }

    /**
     * Ctor, version is initialized with <code>MAX</code>
     *
     * @param id id
     * @see #MAX
     */
    public FxPK(long id) {
        this.id = id;
        this.version = MAX;
    }

    /**
     * Constructor for new FxContents
     */
    public FxPK() {
        this.id = NEW_ID;
        this.version = 1;
    }

    /**
     * Is this primary key for a new FxContent?
     *
     * @return if this primary key is for a new FxContent
     */
    public boolean isNew() {
        return this.id == NEW_ID;
    }

    /**
     * Getter for the id
     *
     * @return id
     */
    public long getId() {
        return id;
    }

    /**
     * Getter for the version.
     * Can be an arbitrary number or a constant for maximum or live version
     *
     * @return version
     * @see #MAX
     * @see #LIVE
     */
    public int getVersion() {
        return version;
    }

    /**
     * Get the storage mode for this primary key.
     * This method is reserved for future uses when different storage modes will be implemented!
     *
     * @return storage mode
     */
    public TypeStorageMode getStorageMode() {
        return TypeStorageMode.Hierarchical;
    }

    /**
     * Create a new primary key
     *
     * @return a new primary key
     */
    public static FxPK createNewPK() {
        return new FxPK(-1);
    }

    /**
     * Does this primary key point to a distinct version or is it something like maximum or live version?
     *
     * @return distinct version
     */
    public boolean isDistinctVersion() {
        return this.version >= 0;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        String ver = "" + this.getVersion();
        if (getVersion() == LIVE)
            ver = "LIVE";
        else if (getVersion() == MAX)
            ver = "MAX";
        return (isNew() ? "NEW" : getId() + "." + ver);
    }

    /**
     * Construct a primary key from a String
     *
     * @param value string value
     * @return primary key
     * @throws IllegalArgumentException if the string does not represent a valid PK value
     * @see #toString()
     */
    public static FxPK fromString(String value) {
        if (StringUtils.isNumeric(value)) {
            return new FxPK(Long.parseLong(value));
        } else if (value == null || "NEW".equals(value) || value.indexOf('.') <= 0) {
            return new FxPK();
        }
        String[] pk = value.split("\\.");
        if (pk == null || pk.length != 2)
            throw new IllegalArgumentException("Invalid PK value: " + value);
        long _id, _ver;
        try {
            _id = Long.parseLong(pk[0]);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException(e);
        }
        try {
            _ver = Integer.parseInt(pk[1]);
        } catch (NumberFormatException e) {
            if ("MAX".equals(pk[1]))
                _ver = MAX;
            else if ("LIVE".equals(pk[1]))
                _ver = LIVE;
            else
                throw new IllegalArgumentException("Illegal version: " + pk[1]);
        }
        return new FxPK(_id, (int) _ver);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        final int PRIME = 31;
        int result = 1;
        result = PRIME * result + (int) (id ^ (id >>> 32));
        result = PRIME * result + version;
        return result;
    }

    /**
     * {@inheritDoc}
     *
     * Note: FxPKs with generic version information like {@link FxPK#LIVE} or {@link FxPK#MAX}
     * will return "false" if they are checked for equality with FxPKs that contain a distinct
     * version information. Consider using {@link FxContent#matchesPk(FxPK)} if appropriate. 
     */
    @Override
    public boolean equals(Object obj) {
        if (obj == null || !getClass().equals(obj.getClass()))
            return false;
        final FxPK other = (FxPK) obj;
        return id == other.id && version == other.version;
    }

    /**
     * <p>Extract a PK from the given object. Useful for scripting or JSF-related
     * calls where the actual value type may vary.</p>
     * <p>Current, following types for <code>value</code> are supported:
     * <ul>
     * <li>{@link com.flexive.shared.content.FxPK FxPK} - trivial</li>
     * <li>{@link com.flexive.shared.value.FxReference FxReference} - return the PK contained in the "best translation" for the current user</li>
     * <li>{@link com.flexive.shared.structure.FxSelectListItem FxSelectListItem} - use the item's ID as an object ID and return the PK</li>
     * <li>{@link Long} - return a new PK for the given object ID</li>
     * <li>{@link String} - return a new PK based on the given PK string representation</li>
     * </ul>
     * </p>
     *
     * @param value the value to be interpreted as an FxPK obejct
     * @return the primary key
     */
    public static FxPK fromObject(Object value) {
        if (value instanceof FxPK) {
            return (FxPK) value;
        } else if (value instanceof FxReference) {
            return ((FxReference) value).getBestTranslation();
        } else if (value instanceof FxSelectListItem) {
            return new FxPK(((FxSelectListItem) value).getId());
        } else if (value instanceof Long) {
            return new FxPK((Long) value);
        } else if (value instanceof String) {
            return fromString((String) value);
        }
        throw new FxInvalidParameterException("VALUE", LOG, "ex.content.pk.fromObject.invalid", value,
                value.getClass()).asRuntimeException();
    }

    @Override
    public int compareTo(FxPK o) {
        return id > o.id ? 1 : id < o.id ? -1 : 0;
    }

    /**
     * Extracts the IDs of the given PK collection.
     *
     * @param pks   the PKs to be processed
     * @return      the IDs of the given PK collection.
     * @since 3.1
     */
    public static List<Long> getIds(Collection<? extends FxPK> pks) {
        final List<Long> result = Lists.newArrayListWithCapacity(pks.size());
        for (FxPK pk : pks) {
            result.add(pk.getId());
        }
        return result;
    }

    /**
     * Wrap the content IDs in FxPK objects.
     *
     * @param ids    the content IDs
     * @return       the FxPK wrappers
     * @since 3.2.0
     */
    public static List<FxPK> getPks(Collection<Long> ids) {
        final List<FxPK> result = Lists.newArrayListWithCapacity(ids.size());
        for (Long id : ids) {
            result.add(new FxPK(id));
        }
        return result;
    }
}