Search in sources :

Example 1 with DefaultEntityState

use of org.qi4j.spi.entitystore.helpers.DefaultEntityState in project qi4j-sdk by Qi4j.

the class SQLEntityStoreMixin method queryAllEntities.

private void queryAllEntities(Module module, EntityStatesVisitor entityStatesVisitor) {
    Connection connection = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    UsecaseBuilder builder = UsecaseBuilder.buildUsecase("qi4j.entitystore.sql.visit");
    Usecase usecase = builder.withMetaInfo(CacheOptions.NEVER).newUsecase();
    final DefaultEntityStoreUnitOfWork uow = new DefaultEntityStoreUnitOfWork(entityStoreSPI, newUnitOfWorkId(), module, usecase, System.currentTimeMillis());
    try {
        connection = database.getConnection();
        ps = database.prepareGetAllEntitiesStatement(connection);
        database.populateGetAllEntitiesStatement(ps);
        rs = ps.executeQuery();
        while (rs.next()) {
            DefaultEntityState entityState = readEntityState(uow, database.getEntityValue(rs).getReader());
            if (!entityStatesVisitor.visit(entityState)) {
                return;
            }
        }
    } catch (SQLException ex) {
        throw new EntityStoreException(ex);
    } finally {
        SQLUtil.closeQuietly(rs);
        SQLUtil.closeQuietly(ps);
        SQLUtil.closeQuietly(connection);
    }
}
Also used : DefaultEntityState(org.qi4j.spi.entitystore.helpers.DefaultEntityState) SQLException(java.sql.SQLException) Connection(java.sql.Connection) ResultSet(java.sql.ResultSet) UsecaseBuilder(org.qi4j.api.usecase.UsecaseBuilder) DefaultEntityStoreUnitOfWork(org.qi4j.spi.entitystore.DefaultEntityStoreUnitOfWork) PreparedStatement(java.sql.PreparedStatement) Usecase(org.qi4j.api.usecase.Usecase) EntityStoreException(org.qi4j.spi.entitystore.EntityStoreException)

Example 2 with DefaultEntityState

use of org.qi4j.spi.entitystore.helpers.DefaultEntityState in project qi4j-sdk by Qi4j.

the class PreferencesEntityStoreMixin method applyChanges.

@Override
public StateCommitter applyChanges(final EntityStoreUnitOfWork unitofwork, final Iterable<EntityState> state) {
    return new StateCommitter() {

        @Override
        public void commit() {
            try {
                synchronized (root) {
                    for (EntityState entityState : state) {
                        DefaultEntityState state = (DefaultEntityState) entityState;
                        if (state.status().equals(EntityStatus.NEW)) {
                            Preferences entityPrefs = root.node(state.identity().identity());
                            writeEntityState(state, entityPrefs, unitofwork.identity(), unitofwork.currentTime());
                        } else if (state.status().equals(EntityStatus.UPDATED)) {
                            Preferences entityPrefs = root.node(state.identity().identity());
                            writeEntityState(state, entityPrefs, unitofwork.identity(), unitofwork.currentTime());
                        } else if (state.status().equals(EntityStatus.REMOVED)) {
                            root.node(state.identity().identity()).removeNode();
                        }
                    }
                    root.flush();
                }
            } catch (BackingStoreException e) {
                throw new EntityStoreException(e);
            }
        }

        @Override
        public void cancel() {
        }
    };
}
Also used : DefaultEntityState(org.qi4j.spi.entitystore.helpers.DefaultEntityState) BackingStoreException(java.util.prefs.BackingStoreException) StateCommitter(org.qi4j.spi.entitystore.StateCommitter) EntityState(org.qi4j.spi.entity.EntityState) DefaultEntityState(org.qi4j.spi.entitystore.helpers.DefaultEntityState) EntityStoreException(org.qi4j.spi.entitystore.EntityStoreException) Preferences(java.util.prefs.Preferences)

Example 3 with DefaultEntityState

use of org.qi4j.spi.entitystore.helpers.DefaultEntityState in project qi4j-sdk by Qi4j.

the class PreferencesEntityStoreMixin method entityStateOf.

@Override
public EntityState entityStateOf(EntityStoreUnitOfWork unitOfWork, EntityReference identity) {
    try {
        DefaultEntityStoreUnitOfWork desuw = (DefaultEntityStoreUnitOfWork) unitOfWork;
        Module module = desuw.module();
        if (!root.nodeExists(identity.identity())) {
            throw new NoSuchEntityException(identity, UnknownType.class);
        }
        Preferences entityPrefs = root.node(identity.identity());
        String type = entityPrefs.get("type", null);
        EntityStatus status = EntityStatus.LOADED;
        EntityDescriptor entityDescriptor = module.entityDescriptor(type);
        if (entityDescriptor == null) {
            throw new EntityTypeNotFoundException(type);
        }
        Map<QualifiedName, Object> properties = new HashMap<>();
        Preferences propsPrefs = null;
        for (PropertyDescriptor persistentPropertyDescriptor : entityDescriptor.state().properties()) {
            if (persistentPropertyDescriptor.qualifiedName().name().equals("identity")) {
                // Fake identity property
                properties.put(persistentPropertyDescriptor.qualifiedName(), identity.identity());
                continue;
            }
            if (propsPrefs == null) {
                propsPrefs = entityPrefs.node("properties");
            }
            ValueType propertyType = persistentPropertyDescriptor.valueType();
            Class<?> mainType = propertyType.mainType();
            if (Number.class.isAssignableFrom(mainType)) {
                if (mainType.equals(Long.class)) {
                    properties.put(persistentPropertyDescriptor.qualifiedName(), this.getNumber(propsPrefs, persistentPropertyDescriptor, LONG_PARSER));
                } else if (mainType.equals(Integer.class)) {
                    properties.put(persistentPropertyDescriptor.qualifiedName(), this.getNumber(propsPrefs, persistentPropertyDescriptor, INT_PARSER));
                } else if (mainType.equals(Double.class)) {
                    properties.put(persistentPropertyDescriptor.qualifiedName(), this.getNumber(propsPrefs, persistentPropertyDescriptor, DOUBLE_PARSER));
                } else if (mainType.equals(Float.class)) {
                    properties.put(persistentPropertyDescriptor.qualifiedName(), this.getNumber(propsPrefs, persistentPropertyDescriptor, FLOAT_PARSER));
                } else {
                    // Load as string even though it's a number
                    String json = propsPrefs.get(persistentPropertyDescriptor.qualifiedName().name(), null);
                    Object value;
                    if (json == null) {
                        value = null;
                    } else {
                        value = valueSerialization.deserialize(persistentPropertyDescriptor.valueType(), json);
                    }
                    properties.put(persistentPropertyDescriptor.qualifiedName(), value);
                }
            } else if (mainType.equals(Boolean.class)) {
                Boolean initialValue = (Boolean) persistentPropertyDescriptor.initialValue(module);
                properties.put(persistentPropertyDescriptor.qualifiedName(), propsPrefs.getBoolean(persistentPropertyDescriptor.qualifiedName().name(), initialValue == null ? false : initialValue));
            } else if (propertyType instanceof ValueCompositeType || propertyType instanceof MapType || propertyType instanceof CollectionType || propertyType instanceof EnumType) {
                String json = propsPrefs.get(persistentPropertyDescriptor.qualifiedName().name(), null);
                Object value;
                if (json == null) {
                    value = null;
                } else {
                    value = valueSerialization.deserialize(persistentPropertyDescriptor.valueType(), json);
                }
                properties.put(persistentPropertyDescriptor.qualifiedName(), value);
            } else {
                String json = propsPrefs.get(persistentPropertyDescriptor.qualifiedName().name(), null);
                if (json == null) {
                    if (persistentPropertyDescriptor.initialValue(module) != null) {
                        properties.put(persistentPropertyDescriptor.qualifiedName(), persistentPropertyDescriptor.initialValue(module));
                    } else {
                        properties.put(persistentPropertyDescriptor.qualifiedName(), null);
                    }
                } else {
                    Object value = valueSerialization.deserialize(propertyType, json);
                    properties.put(persistentPropertyDescriptor.qualifiedName(), value);
                }
            }
        }
        // Associations
        Map<QualifiedName, EntityReference> associations = new HashMap<>();
        Preferences assocs = null;
        for (AssociationDescriptor associationType : entityDescriptor.state().associations()) {
            if (assocs == null) {
                assocs = entityPrefs.node("associations");
            }
            String associatedEntity = assocs.get(associationType.qualifiedName().name(), null);
            EntityReference value = associatedEntity == null ? null : EntityReference.parseEntityReference(associatedEntity);
            associations.put(associationType.qualifiedName(), value);
        }
        // ManyAssociations
        Map<QualifiedName, List<EntityReference>> manyAssociations = new HashMap<>();
        Preferences manyAssocs = null;
        for (AssociationDescriptor manyAssociationType : entityDescriptor.state().manyAssociations()) {
            if (manyAssocs == null) {
                manyAssocs = entityPrefs.node("manyassociations");
            }
            List<EntityReference> references = new ArrayList<>();
            String entityReferences = manyAssocs.get(manyAssociationType.qualifiedName().name(), null);
            if (entityReferences == null) {
                // ManyAssociation not found, default to empty one
                manyAssociations.put(manyAssociationType.qualifiedName(), references);
            } else {
                String[] refs = entityReferences.split("\n");
                for (String ref : refs) {
                    EntityReference value = ref == null ? null : EntityReference.parseEntityReference(ref);
                    references.add(value);
                }
                manyAssociations.put(manyAssociationType.qualifiedName(), references);
            }
        }
        // NamedAssociations
        Map<QualifiedName, Map<String, EntityReference>> namedAssociations = new HashMap<>();
        Preferences namedAssocs = null;
        for (AssociationDescriptor namedAssociationType : entityDescriptor.state().namedAssociations()) {
            if (namedAssocs == null) {
                namedAssocs = entityPrefs.node("namedassociations");
            }
            Map<String, EntityReference> references = new LinkedHashMap<>();
            String entityReferences = namedAssocs.get(namedAssociationType.qualifiedName().name(), null);
            if (entityReferences == null) {
                // NamedAssociation not found, default to empty one
                namedAssociations.put(namedAssociationType.qualifiedName(), references);
            } else {
                String[] namedRefs = entityReferences.split("\n");
                if (namedRefs.length % 2 != 0) {
                    throw new EntityStoreException("Invalid NamedAssociation storage format");
                }
                for (int idx = 0; idx < namedRefs.length; idx += 2) {
                    String name = namedRefs[idx];
                    String ref = namedRefs[idx + 1];
                    references.put(name, EntityReference.parseEntityReference(ref));
                }
                namedAssociations.put(namedAssociationType.qualifiedName(), references);
            }
        }
        return new DefaultEntityState(desuw, entityPrefs.get("version", ""), entityPrefs.getLong("modified", unitOfWork.currentTime()), identity, status, entityDescriptor, properties, associations, manyAssociations, namedAssociations);
    } catch (ValueSerializationException | BackingStoreException e) {
        throw new EntityStoreException(e);
    }
}
Also used : EntityTypeNotFoundException(org.qi4j.api.unitofwork.EntityTypeNotFoundException) DefaultEntityState(org.qi4j.spi.entitystore.helpers.DefaultEntityState) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) ValueSerializationException(org.qi4j.api.value.ValueSerializationException) AssociationDescriptor(org.qi4j.api.association.AssociationDescriptor) MapType(org.qi4j.api.type.MapType) LinkedHashMap(java.util.LinkedHashMap) EnumType(org.qi4j.api.type.EnumType) CollectionType(org.qi4j.api.type.CollectionType) EntityReference(org.qi4j.api.entity.EntityReference) DefaultEntityStoreUnitOfWork(org.qi4j.spi.entitystore.DefaultEntityStoreUnitOfWork) EntityStatus(org.qi4j.spi.entity.EntityStatus) List(java.util.List) ArrayList(java.util.ArrayList) EntityStoreException(org.qi4j.spi.entitystore.EntityStoreException) Preferences(java.util.prefs.Preferences) PropertyDescriptor(org.qi4j.api.property.PropertyDescriptor) ValueType(org.qi4j.api.type.ValueType) QualifiedName(org.qi4j.api.common.QualifiedName) BackingStoreException(java.util.prefs.BackingStoreException) NoSuchEntityException(org.qi4j.api.unitofwork.NoSuchEntityException) EntityDescriptor(org.qi4j.api.entity.EntityDescriptor) Module(org.qi4j.api.structure.Module) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ValueCompositeType(org.qi4j.api.type.ValueCompositeType)

Example 4 with DefaultEntityState

use of org.qi4j.spi.entitystore.helpers.DefaultEntityState in project qi4j-sdk by Qi4j.

the class SQLEntityStoreMixin method readEntityState.

protected DefaultEntityState readEntityState(DefaultEntityStoreUnitOfWork unitOfWork, Reader entityState) throws EntityStoreException {
    try {
        Module module = unitOfWork.module();
        JSONObject jsonObject = new JSONObject(new JSONTokener(entityState));
        EntityStatus status = EntityStatus.LOADED;
        String version = jsonObject.getString(JSONKeys.VERSION);
        long modified = jsonObject.getLong(JSONKeys.MODIFIED);
        String identity = jsonObject.getString(JSONKeys.IDENTITY);
        // Check if version is correct
        String currentAppVersion = jsonObject.optString(JSONKeys.APPLICATION_VERSION, "0.0");
        if (!currentAppVersion.equals(application.version())) {
            if (migration != null) {
                migration.migrate(jsonObject, application.version(), this);
            } else {
                // Do nothing - set version to be correct
                jsonObject.put(JSONKeys.APPLICATION_VERSION, application.version());
            }
            LOGGER.trace("Updated version nr on {} from {} to {}", identity, currentAppVersion, application.version());
            // State changed
            status = EntityStatus.UPDATED;
        }
        String type = jsonObject.getString(JSONKeys.TYPE);
        EntityDescriptor entityDescriptor = module.entityDescriptor(type);
        if (entityDescriptor == null) {
            throw new EntityTypeNotFoundException(type);
        }
        Map<QualifiedName, Object> properties = new HashMap<>();
        JSONObject props = jsonObject.getJSONObject(JSONKeys.PROPERTIES);
        for (PropertyDescriptor propertyDescriptor : entityDescriptor.state().properties()) {
            Object jsonValue;
            try {
                jsonValue = props.get(propertyDescriptor.qualifiedName().name());
            } catch (JSONException e) {
                // Value not found, default it
                Object initialValue = propertyDescriptor.initialValue(module);
                properties.put(propertyDescriptor.qualifiedName(), initialValue);
                status = EntityStatus.UPDATED;
                continue;
            }
            if (JSONObject.NULL.equals(jsonValue)) {
                properties.put(propertyDescriptor.qualifiedName(), null);
            } else {
                Object value = valueSerialization.deserialize(propertyDescriptor.valueType(), jsonValue.toString());
                properties.put(propertyDescriptor.qualifiedName(), value);
            }
        }
        Map<QualifiedName, EntityReference> associations = new HashMap<>();
        JSONObject assocs = jsonObject.getJSONObject(JSONKeys.ASSOCIATIONS);
        for (AssociationDescriptor associationType : entityDescriptor.state().associations()) {
            try {
                Object jsonValue = assocs.get(associationType.qualifiedName().name());
                EntityReference value = jsonValue == JSONObject.NULL ? null : EntityReference.parseEntityReference((String) jsonValue);
                associations.put(associationType.qualifiedName(), value);
            } catch (JSONException e) {
                // Association not found, default it to null
                associations.put(associationType.qualifiedName(), null);
                status = EntityStatus.UPDATED;
            }
        }
        JSONObject manyAssocs = jsonObject.getJSONObject(JSONKeys.MANY_ASSOCIATIONS);
        Map<QualifiedName, List<EntityReference>> manyAssociations = new HashMap<>();
        for (AssociationDescriptor manyAssociationType : entityDescriptor.state().manyAssociations()) {
            List<EntityReference> references = new ArrayList<>();
            try {
                JSONArray jsonValues = manyAssocs.getJSONArray(manyAssociationType.qualifiedName().name());
                for (int i = 0; i < jsonValues.length(); i++) {
                    Object jsonValue = jsonValues.getString(i);
                    EntityReference value = jsonValue == JSONObject.NULL ? null : EntityReference.parseEntityReference((String) jsonValue);
                    references.add(value);
                }
                manyAssociations.put(manyAssociationType.qualifiedName(), references);
            } catch (JSONException e) {
                // ManyAssociation not found, default to empty one
                manyAssociations.put(manyAssociationType.qualifiedName(), references);
            }
        }
        JSONObject namedAssocs = jsonObject.has(JSONKeys.NAMED_ASSOCIATIONS) ? jsonObject.getJSONObject(JSONKeys.NAMED_ASSOCIATIONS) : new JSONObject();
        Map<QualifiedName, Map<String, EntityReference>> namedAssociations = new HashMap<>();
        for (AssociationDescriptor namedAssociationType : entityDescriptor.state().namedAssociations()) {
            Map<String, EntityReference> references = new LinkedHashMap<>();
            try {
                JSONObject jsonValues = namedAssocs.getJSONObject(namedAssociationType.qualifiedName().name());
                JSONArray names = jsonValues.names();
                if (names != null) {
                    for (int idx = 0; idx < names.length(); idx++) {
                        String name = names.getString(idx);
                        String jsonValue = jsonValues.getString(name);
                        references.put(name, EntityReference.parseEntityReference(jsonValue));
                    }
                }
                namedAssociations.put(namedAssociationType.qualifiedName(), references);
            } catch (JSONException e) {
                // NamedAssociation not found, default to empty one
                namedAssociations.put(namedAssociationType.qualifiedName(), references);
            }
        }
        return new DefaultEntityState(unitOfWork, version, modified, EntityReference.parseEntityReference(identity), status, entityDescriptor, properties, associations, manyAssociations, namedAssociations);
    } catch (JSONException e) {
        throw new EntityStoreException(e);
    }
}
Also used : EntityTypeNotFoundException(org.qi4j.api.unitofwork.EntityTypeNotFoundException) DefaultEntityState(org.qi4j.spi.entitystore.helpers.DefaultEntityState) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) AssociationDescriptor(org.qi4j.api.association.AssociationDescriptor) LinkedHashMap(java.util.LinkedHashMap) EntityReference(org.qi4j.api.entity.EntityReference) EntityStatus(org.qi4j.spi.entity.EntityStatus) List(java.util.List) ArrayList(java.util.ArrayList) EntityStoreException(org.qi4j.spi.entitystore.EntityStoreException) PropertyDescriptor(org.qi4j.api.property.PropertyDescriptor) QualifiedName(org.qi4j.api.common.QualifiedName) JSONArray(org.json.JSONArray) JSONException(org.json.JSONException) JSONTokener(org.json.JSONTokener) EntityDescriptor(org.qi4j.api.entity.EntityDescriptor) JSONObject(org.json.JSONObject) JSONObject(org.json.JSONObject) Module(org.qi4j.api.structure.Module) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap)

Example 5 with DefaultEntityState

use of org.qi4j.spi.entitystore.helpers.DefaultEntityState in project qi4j-sdk by Qi4j.

the class SQLEntityStoreMixin method applyChanges.

@Override
public StateCommitter applyChanges(final EntityStoreUnitOfWork unitofwork, final Iterable<EntityState> states) {
    return new StateCommitter() {

        @Override
        public void commit() {
            Connection connection = null;
            PreparedStatement insertPS = null;
            PreparedStatement updatePS = null;
            PreparedStatement removePS = null;
            try {
                connection = database.getConnection();
                connection.setAutoCommit(false);
                insertPS = database.prepareInsertEntityStatement(connection);
                updatePS = database.prepareUpdateEntityStatement(connection);
                removePS = database.prepareRemoveEntityStatement(connection);
                for (EntityState state : states) {
                    EntityStatus status = state.status();
                    DefaultEntityState defState = ((SQLEntityState) state).getDefaultEntityState();
                    Long entityPK = ((SQLEntityState) state).getEntityPK();
                    if (EntityStatus.REMOVED.equals(status)) {
                        database.populateRemoveEntityStatement(removePS, entityPK, state.identity());
                        removePS.addBatch();
                    } else {
                        StringWriter writer = new StringWriter();
                        writeEntityState(defState, writer, unitofwork.identity());
                        writer.flush();
                        if (EntityStatus.UPDATED.equals(status)) {
                            Long entityOptimisticLock = ((SQLEntityState) state).getEntityOptimisticLock();
                            database.populateUpdateEntityStatement(updatePS, entityPK, entityOptimisticLock, defState.identity(), writer.toString(), unitofwork.currentTime());
                            updatePS.addBatch();
                        } else if (EntityStatus.NEW.equals(status)) {
                            database.populateInsertEntityStatement(insertPS, defState.identity(), writer.toString(), unitofwork.currentTime());
                            insertPS.addBatch();
                        }
                    }
                }
                removePS.executeBatch();
                insertPS.executeBatch();
                updatePS.executeBatch();
                connection.commit();
            } catch (SQLException sqle) {
                SQLUtil.rollbackQuietly(connection);
                if (LOGGER.isDebugEnabled()) {
                    StringWriter sb = new StringWriter();
                    sb.append("SQLException during commit, logging nested exceptions before throwing EntityStoreException:\n");
                    SQLException e = sqle;
                    while (e != null) {
                        e.printStackTrace(new PrintWriter(sb, true));
                        e = e.getNextException();
                    }
                    LOGGER.debug(sb.toString());
                }
                throw new EntityStoreException(sqle);
            } catch (RuntimeException re) {
                SQLUtil.rollbackQuietly(connection);
                throw new EntityStoreException(re);
            } finally {
                SQLUtil.closeQuietly(insertPS);
                SQLUtil.closeQuietly(updatePS);
                SQLUtil.closeQuietly(removePS);
                SQLUtil.closeQuietly(connection);
            }
        }

        @Override
        public void cancel() {
        }
    };
}
Also used : SQLEntityState(org.qi4j.entitystore.sql.internal.SQLEntityState) DefaultSQLEntityState(org.qi4j.entitystore.sql.internal.SQLEntityState.DefaultSQLEntityState) DefaultEntityState(org.qi4j.spi.entitystore.helpers.DefaultEntityState) SQLException(java.sql.SQLException) Connection(java.sql.Connection) PreparedStatement(java.sql.PreparedStatement) SQLEntityState(org.qi4j.entitystore.sql.internal.SQLEntityState) EntityState(org.qi4j.spi.entity.EntityState) DefaultSQLEntityState(org.qi4j.entitystore.sql.internal.SQLEntityState.DefaultSQLEntityState) DefaultEntityState(org.qi4j.spi.entitystore.helpers.DefaultEntityState) StringWriter(java.io.StringWriter) EntityStatus(org.qi4j.spi.entity.EntityStatus) StateCommitter(org.qi4j.spi.entitystore.StateCommitter) EntityStoreException(org.qi4j.spi.entitystore.EntityStoreException) PrintWriter(java.io.PrintWriter)

Aggregations

EntityStoreException (org.qi4j.spi.entitystore.EntityStoreException)5 DefaultEntityState (org.qi4j.spi.entitystore.helpers.DefaultEntityState)5 EntityStatus (org.qi4j.spi.entity.EntityStatus)3 Connection (java.sql.Connection)2 PreparedStatement (java.sql.PreparedStatement)2 SQLException (java.sql.SQLException)2 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 LinkedHashMap (java.util.LinkedHashMap)2 List (java.util.List)2 Map (java.util.Map)2 BackingStoreException (java.util.prefs.BackingStoreException)2 Preferences (java.util.prefs.Preferences)2 AssociationDescriptor (org.qi4j.api.association.AssociationDescriptor)2 QualifiedName (org.qi4j.api.common.QualifiedName)2 EntityDescriptor (org.qi4j.api.entity.EntityDescriptor)2 EntityReference (org.qi4j.api.entity.EntityReference)2 PropertyDescriptor (org.qi4j.api.property.PropertyDescriptor)2 Module (org.qi4j.api.structure.Module)2 EntityTypeNotFoundException (org.qi4j.api.unitofwork.EntityTypeNotFoundException)2