com.jfinal.ext.kit.ModelFingerprint.java Source code

Java tutorial

Introduction

Here is the source code for com.jfinal.ext.kit.ModelFingerprint.java

Source

/**
 * Copyright (c) 2011-2013, kidzhou  (zhouleib1412@gmail.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.
 */
package com.jfinal.ext.kit;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.jfinal.log.Logger;
import com.jfinal.plugin.activerecord.*;
import org.apache.commons.codec.binary.Hex;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.security.MessageDigest;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;

public abstract class ModelFingerprint<M extends ModelFingerprint<M>> extends ModelExt<M> {

    private static Logger LOG = Logger.getLogger(ModelFingerprint.class);

    private String fingerprintColumnLabel = "fingerprint";

    private ConcurrentMap<String, Integer> map = null;

    private Set<Integer> deleting = null;

    private Set<String> CACHE = Sets.newHashSet();

    private String fingerprint;

    private Class<? extends ModelExt<M>> clazz;

    @SuppressWarnings("unchecked")
    public ModelFingerprint() {
        Type genericSuperclass = getClass().getGenericSuperclass();
        clazz = (Class<? extends ModelExt<M>>) ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
    }

    public String tableName() {
        return TableMapping.me().getTable(this.getClass()).getName();
    }

    public void init() {
        map = Maps.newConcurrentMap();
        Table tableInfo = TableMapping.me().getTable(clazz);
        if (!tableInfo.hasColumnLabel(fingerprintColumnLabel)) {
            throw new ActiveRecordException("fingerprintColumnLabel (" + fingerprintColumnLabel + ") is not exist");
        }
        LOG.info("begin load " + tableName() + " fingerprints");
        List<Record> records = Db.find("SELECT id, " + fingerprintColumnLabel + " FROM " + tableName());
        for (Record record : records) {
            map.put(record.getStr(fingerprintColumnLabel), record.getInt("id"));
        }
        LOG.info("end load " + tableName() + " fingerprints");
        deleting = Sets.newHashSet(map.values());
        LOG.info("loaded " + deleting.size() + " data");
    }

    public abstract List<String> fingerprintColumns();

    public abstract ModelFingerprint fingerprinter();

    public String calcFingerprint() {
        if (fingerprint == null) {
            StringBuilder sb = new StringBuilder();
            for (String col : fingerprintColumns()) {
                sb.append(get(col));
                sb.append("|");
            }
            sb.deleteCharAt(sb.length() - 1);
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
                fingerprint = Hex.encodeHexString(md.digest(sb.toString().getBytes()));
            } catch (Exception e) {
                fingerprint = "" + hashCode();
            }
        }
        return fingerprint;
    }

    public void compare(ModelFingerprint modelFingerprint) {
        if (map == null) {
            throw new IllegalStateException("modelFingerprint have not been initialized");
        }
        Integer id = map.get(modelFingerprint.calcFingerprint());
        if (id != null) {
            deleting.remove(id);
            modelFingerprint.set("id", id);
        } else if (CACHE.contains(modelFingerprint.getStr(fingerprintColumnLabel))) {
            modelFingerprint.set("id", -1);
        } else {
            CACHE.add(modelFingerprint.getStr(fingerprintColumnLabel));
        }
    }

    public ModelFingerprint addFingerprint() {
        set("fingerprint", calcFingerprint());
        return this;
    }

    public void saveWithFingerprint() {
        addFingerprint();
        fingerprinter().compare(this);
        if (get("id") == null) {
            save();
        }
    }

    public void removeExpired() {
        int size = deleting.size();
        LOG.info("delete " + size + "records");
        if (size != 0) {
            List<Integer> ids = Lists.newArrayList(deleting);
            int idSize = ids.size();
            int batchSize = 1000;
            int length = idSize / batchSize;
            if (idSize % batchSize != 0) {
                length++;
            }
            for (int i = 0; i < length; i++) {
                if (i == length - 1) {
                    String sql = "DELETE FROM " + tableName() + " WHERE id IN ("
                            + Joiner.on(", ").join(ids.subList(i * batchSize, ids.size()), ", ") + ")";
                    Db.update(sql);
                } else {
                    String sql = "DELETE FROM " + tableName() + " WHERE id IN ("
                            + Joiner.on(", ").join(ids.subList(i * batchSize, i * batchSize + batchSize), ", ")
                            + ")";
                    Db.update(sql);
                }
            }
        }
    }
}