net.autosauler.ballance.server.model.AbstractStructuredData.java Source code

Java tutorial

Introduction

Here is the source code for net.autosauler.ballance.server.model.AbstractStructuredData.java

Source

/*******************************************************************************
 * Copyright 2011 Alex 'Ript' Malyshev <alexript@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 net.autosauler.ballance.server.model;

import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import net.autosauler.ballance.server.mongodb.Database;
import net.autosauler.ballance.shared.datatypes.DataTypes;
import net.autosauler.ballance.shared.datatypes.StructValues;
import net.autosauler.ballance.shared.datatypes.Structure;

import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.allen_sauer.gwt.log.client.Log;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;

/**
 * The Class AbstractStructuredData.
 * 
 * @author alexript
 */
public abstract class AbstractStructuredData {

    /** The tableprefix. */
    private final String tableprefix;

    /** The tablesuffix. */
    private final String tablesuffix;

    /** The tablename. */
    private final String tablename;

    /** The struct. */
    protected Structure struct;

    /** The values. */
    protected StructValues values;

    /** The Constant fieldname_domain. */
    protected static final String fieldname_domain = "domain";

    /** The Constant fieldname_username. */
    protected static final String fieldname_username = "username";

    /** The Constant fieldname_number. */
    protected static final String fieldname_number = "number";
    /** The Constant fieldname_createdate. */
    protected static final String fieldname_createdate = "createdate";

    /** The Constant fieldname_trash. */
    protected static final String fieldname_trash = "trash";

    /**
     * Instantiates a new structured data.
     * 
     * @param prefix
     *            the prefix
     * @param suffix
     *            the suffix
     * @param domain
     *            the domain
     */
    public AbstractStructuredData(String prefix, String suffix, String domain) {
        tableprefix = prefix;
        tablesuffix = suffix;
        tablename = prefix + "_" + suffix;

        initMetaStructure(domain);
        initDBStruct();

        setTrash(false);
    }

    /**
     * Adds the find all orders.
     * 
     * @param o
     *            the o
     */
    protected abstract void addFindAllOrders(final BasicDBObject o);

    /**
     * Adds the find all query parameters.
     * 
     * @param q
     *            the q
     */
    protected abstract void addFindAllQueryParameters(final BasicDBObject q);

    /**
     * Adds the find last number params.
     * 
     * @param w
     *            the w
     */
    protected abstract void addFindLastNumberParams(final BasicDBObject w);

    /**
     * Adds the get record params.
     * 
     * @param query
     *            the query
     */
    protected abstract void addGetRecordParams(final BasicDBObject query);

    /**
     * Creates the record.
     * 
     * @return true, if successful
     */
    private boolean createRecord() {

        boolean result = false;
        setNumber(findLastNumber());
        setCreatedate(new Date());
        onCreate();
        DB db = Database.get(getDomain());
        if (db != null) {
            BasicDBObject doc = (BasicDBObject) store(null);
            if (doc != null) {
                Database.retain();
                DBCollection coll = db.getCollection(getTableName());
                coll.insert(doc);
                Database.release();
                result = true;
            }
        }

        return result;
    }

    /**
     * Dump.
     * 
     * @return the string
     */
    public String dump() {
        StringBuilder sb = new StringBuilder();

        sb.append("<" + getPrefix() + " name=\"" + getSuffix() + "\">\n");

        sb.append(struct.toString());

        sb.append("<records>\n");

        Set<Long> numbers = findAll();
        Iterator<Long> i = numbers.iterator();
        while (i.hasNext()) {
            Long number = i.next();
            DBObject doc = getRecord(number);
            if (doc != null) {
                load(doc);
                sb.append(values.toString());
            }
        }

        sb.append("</records>\n");
        StringBuilder child = onDump();
        if (child != null) {
            sb.append(child.toString());
        }
        sb.append("</" + getPrefix() + ">\n");

        return sb.toString();
    }

    /**
     * Find all.
     * 
     * @return the sets the
     */
    public Set<Long> findAll() {
        Set<Long> numbers = new HashSet<Long>();

        DB db = Database.get(getDomain());
        if (db != null) {
            Database.retain();
            DBCollection coll = db.getCollection(getTableName());
            BasicDBObject q = new BasicDBObject();
            BasicDBObject w = new BasicDBObject();
            q.put(fieldname_domain, getDomain());
            q.put(fieldname_trash, false);

            addFindAllQueryParameters(q);
            w.put("$query", q);

            BasicDBObject o = new BasicDBObject();
            o.put(fieldname_number, 1);
            addFindAllOrders(o);
            w.put("$orderby", o);

            DBCursor cur = coll.find(w);
            while (cur.hasNext()) {
                DBObject myDoc = cur.next();
                numbers.add((Long) myDoc.get(fieldname_number));
            }
            Database.release();
        }

        return numbers;
    }

    /**
     * Find last number.
     * 
     * @return the long
     */
    protected Long findLastNumber() {
        Long last = 0L;

        DB db = Database.get(getDomain());
        if (db != null) {
            Database.retain();
            DBCollection coll = db.getCollection(getTableName());
            BasicDBObject w = new BasicDBObject();
            w.put(fieldname_domain, getDomain());
            addFindLastNumberParams(w);
            BasicDBObject query = new BasicDBObject();
            query.put("$query", w);
            query.put("$orderby", new BasicDBObject(fieldname_number, -1));

            DBObject doc = null;
            try {
                doc = coll.findOne(query);
            } catch (com.mongodb.MongoException e) {
                last = 1L;
            }
            if (doc != null) {
                last = (Long) doc.get(fieldname_number) + 1L;
            }
            Database.release();
        }

        if (last.equals(0L)) {
            last = 1L;
        }

        return last;
    }

    /**
     * From map.
     * 
     * @param map
     *            the map
     */
    public void fromMap(HashMap<String, Object> map) {

        Set<String> names = struct.getNames();
        Iterator<String> i = names.iterator();
        while (i.hasNext()) {
            String name = i.next();
            if (!name.equals(fieldname_createdate) && !name.equals(fieldname_domain)
                    && !name.equals(fieldname_number) && !name.equals(fieldname_username)) {
                if (map.containsKey(name)) {
                    values.setObject(name, map.get(name));
                }
            }
        }
    }

    /**
     * Gets the.
     * 
     * @param number
     *            the number
     */
    protected void get(Long number) {
        DBObject doc = getRecord(number);
        if (doc != null) {
            load(doc);
        }
    }

    /**
     * Gets the createdate.
     * 
     * @return the createdate
     */
    public Date getCreatedate() {
        return (Date) values.get(fieldname_createdate);
    }

    /**
     * Gets the domain.
     * 
     * @return the domain
     */
    public String getDomain() {
        return (String) values.get(fieldname_domain);
    }

    /**
     * Gets the field value.
     * 
     * @param fieldname
     *            the fieldname
     * @return the field value
     */
    public Object getFieldValue(String fieldname) {
        return values.get(fieldname);
    }

    /**
     * Gets the number.
     * 
     * @return the number
     */
    public Long getNumber() {
        return (Long) values.get(fieldname_number);
    }

    /**
     * Gets the prefix.
     * 
     * @return the prefix
     */
    public String getPrefix() {
        return tableprefix;
    }

    /**
     * Gets the record.
     * 
     * @param number
     *            the number
     * @return the record
     */
    private DBObject getRecord(Long number) {
        DBObject doc = null;
        DB db = Database.get(getDomain());
        if (db != null) {
            Database.retain();
            DBCollection coll = db.getCollection(getTableName());
            BasicDBObject query = new BasicDBObject();
            query.put(fieldname_domain, getDomain());
            addGetRecordParams(query);
            query.put(fieldname_number, number);

            doc = coll.findOne(query);
            Database.release();
            onGetRecord(number);
        }

        return doc;
    }

    /**
     * Gets the suffix.
     * 
     * @return the suffix
     */
    public String getSuffix() {
        return tablesuffix;
    }

    /**
     * Gets the table name.
     * 
     * @return the table name
     */
    public String getTableName() {
        return tablename;
    }

    /**
     * Gets the username.
     * 
     * @return the username
     */
    public String getUsername() {
        return (String) values.get(fieldname_username);
    }

    /**
     * Inits the db struct.
     */
    private void initDBStruct() {
        DB db = Database.get(getDomain());
        if (db != null) {
            Database.retain();
            DBCollection coll = db.getCollection(getTableName());
            List<DBObject> indexes = coll.getIndexInfo();
            if (indexes.size() < 1) {
                BasicDBObject i = new BasicDBObject();
                i.put(fieldname_number, 1);
                coll.createIndex(i);

                i.put(fieldname_domain, 1);
                coll.createIndex(i);

                i.put(fieldname_trash, 1);
                coll.createIndex(i);

                onInitDbStruct(i, coll);

            }
            Database.release();
        }

    }

    /**
     * Inits the global structure (in classes Catalog or Document or some other
     * abstract class).
     */
    protected abstract void initGlobalStructure();

    /**
     * Inits the document structure.
     */
    private void initMetaStructure(String domain) {
        struct = new Structure();

        struct.add(fieldname_domain, DataTypes.DT_DOMAIN, "127.0.0.1");
        struct.add(fieldname_username, DataTypes.DT_STRING, "uncknown");
        struct.add(fieldname_number, DataTypes.DT_LONG, new Long(0L));
        struct.add(fieldname_createdate, DataTypes.DT_DATE, new Date());
        struct.add(fieldname_trash, DataTypes.DT_BOOLEAN, new Boolean(false));

        initGlobalStructure();

        initStructure(domain);

        values = new StructValues(struct);
        setDomain(domain);
    }

    /**
     * Inits the structure for The class.
     */
    protected abstract void initStructure(String domain);

    /**
     * Checks if is trash.
     * 
     * @return true, if is trash
     */
    public boolean isTrash() {
        return (Boolean) values.get(fieldname_trash);
    }

    /**
     * Load.
     * 
     * @param doc
     *            the doc
     */
    protected void load(DBObject doc) {
        Set<String> names = struct.getNames();
        Iterator<String> i = names.iterator();
        while (i.hasNext()) {
            String name = i.next();
            values.set(name, doc.get(name));
        }
    }

    /**
     * On create.
     */
    protected abstract void onCreate();

    /**
     * On dump.
     * 
     * @return the string builder
     */
    protected abstract StringBuilder onDump();

    /**
     * On get record.
     * 
     * @param number
     *            the number
     */
    protected abstract void onGetRecord(Long number);

    /**
     * On init db struct.
     * 
     * @param i
     *            the i
     * @param coll
     *            the coll
     */
    protected abstract void onInitDbStruct(final BasicDBObject i, final DBCollection coll);

    /**
     * On restore.
     * 
     * @param dump
     *            the dump
     */
    protected abstract void onRestore(Element dump);

    /**
     * On update.
     */
    protected abstract void onUpdate();

    /**
     * Restore.
     */
    public void restore() {
        setTrash(false);

    }

    /**
     * Restore.
     * 
     * @param dump
     *            the dump
     */
    public void restore(Element dump) {

        DB db = Database.get(getDomain());
        if (db != null) {
            DBCollection coll = db.getCollection(getTableName());
            Log.trace(getTableName());
            NodeList recordsets = dump.getElementsByTagName("records");

            for (int i = 0; i < recordsets.getLength(); i++) {
                Element recordset = (Element) recordsets.item(i);
                if (recordset.getParentNode() == dump) {
                    NodeList records = recordset.getElementsByTagName("record");
                    if (records.getLength() > 0) {

                        BasicDBObject q = new BasicDBObject();
                        q.put("domain", getDomain());
                        Database.retain();
                        coll.remove(q);

                        for (int j = 0; j < records.getLength(); j++) {
                            Log.trace("record");
                            BasicDBObject doc = new BasicDBObject();
                            Element record = (Element) records.item(j);
                            NodeList fields = record.getElementsByTagName("field");
                            for (int k = 0; k < fields.getLength(); k++) {
                                Element field = (Element) fields.item(k);
                                String name = field.getAttribute("name");
                                if (name.equals("domain")) {
                                    doc.put("domain", getDomain());
                                } else {

                                    int type = struct.getType(name);
                                    String sval = field.getAttribute("value");
                                    Log.error("field name=" + name + " value=" + sval);
                                    doc.put(name, DataTypes.fromString(type, sval));
                                }
                            }
                            Log.trace("insert");
                            coll.insert(doc);
                        }
                    }
                }
            }
            Database.release();

            onRestore(dump);
        }

    }

    /**
     * Save.
     * 
     * @return true, if successful
     */
    public boolean save() {

        boolean result = false;

        if (getNumber() < 1L) {
            result = createRecord();
        } else {
            result = updateRecord();
        }
        return result;
    }

    /**
     * Sets the createdate.
     * 
     * @param createdate
     *            the createdate to set
     */
    public void setCreatedate(Date createdate) {
        values.set(fieldname_createdate, createdate);
    }

    /**
     * Sets the domain.
     * 
     * @param domain
     *            the domain to set
     */
    public void setDomain(String domain) {
        values.set(fieldname_domain, domain);
    }

    /**
     * Sets the field value.
     * 
     * @param fieldname
     *            the fieldname
     * @param val
     *            the val
     */
    public void setFieldValue(String fieldname, Object val) {
        values.set(fieldname, val);
    }

    /**
     * Sets the number.
     * 
     * @param number
     *            the number to set
     */
    public void setNumber(Long number) {
        values.set(fieldname_number, number);
        onGetRecord(number);
    }

    /**
     * Sets the trash.
     * 
     * @param flag
     *            the new trash
     */
    public void setTrash(Boolean flag) {
        values.set(fieldname_trash, flag);
    }

    /**
     * Sets the username.
     * 
     * @param username
     *            the username to set
     */
    public void setUsername(String username) {
        values.set(fieldname_username, username);
    }

    /**
     * Store.
     * 
     * @param doc
     *            the doc
     * @return the dB object
     */
    private DBObject store(DBObject doc) {
        if (doc == null) {
            doc = new BasicDBObject();
        }

        Set<String> names = struct.getNames();
        Iterator<String> i = names.iterator();
        while (i.hasNext()) {
            String name = i.next();
            doc.put(name, values.get(name));
        }
        doc.put(fieldname_trash, isTrash());
        return doc;
    }

    /**
     * To map.
     * 
     * @return the hash map
     */
    public HashMap<String, Object> toMap() {
        HashMap<String, Object> map = new HashMap<String, Object>();

        Set<String> names = struct.getNames();
        Iterator<String> i = names.iterator();
        while (i.hasNext()) {
            String name = i.next();
            map.put(name, values.getObject(name));
        }

        return map;
    }

    /**
     * Trash.
     */
    public void trash() {
        setTrash(true);
    }

    /**
     * Update record.
     * 
     * @return true, if successful
     */
    private boolean updateRecord() {
        boolean result = false;
        DBObject doc = getRecord(getNumber());
        if (doc == null) {
            result = createRecord();
        } else {
            onUpdate();
            doc = store(doc);
            DB db = Database.get(getDomain());
            if (db != null) {
                Database.retain();
                DBCollection coll = db.getCollection(getTableName());
                coll.save(doc);
                Database.release();
                result = true;
            }
        }
        return result;
    }

}