Search in sources :

Example 76 with EntityCondition

use of org.apache.ofbiz.entity.condition.EntityCondition in project ofbiz-framework by apache.

the class FindServices method prepareFind.

/**
 * prepareFind
 *
 * This is a generic method that expects entity data affixed with special suffixes
 * to indicate their purpose in formulating an SQL query statement.
 */
public static Map<String, Object> prepareFind(DispatchContext dctx, Map<String, ?> context) {
    String entityName = (String) context.get("entityName");
    Delegator delegator = dctx.getDelegator();
    String orderBy = (String) context.get("orderBy");
    // Input
    Map<String, ?> inputFields = checkMap(context.get("inputFields"), String.class, Object.class);
    String noConditionFind = (String) context.get("noConditionFind");
    if (UtilValidate.isEmpty(noConditionFind)) {
        // try finding in inputFields Map
        noConditionFind = (String) inputFields.get("noConditionFind");
    }
    if (UtilValidate.isEmpty(noConditionFind)) {
        // Use configured default
        noConditionFind = EntityUtilProperties.getPropertyValue("widget", "widget.defaultNoConditionFind", delegator);
    }
    String filterByDate = (String) context.get("filterByDate");
    if (UtilValidate.isEmpty(filterByDate)) {
        // try finding in inputFields Map
        filterByDate = (String) inputFields.get("filterByDate");
    }
    Timestamp filterByDateValue = (Timestamp) context.get("filterByDateValue");
    String fromDateName = (String) context.get("fromDateName");
    String thruDateName = (String) context.get("thruDateName");
    Map<String, Object> queryStringMap = new LinkedHashMap<>();
    ModelEntity modelEntity = delegator.getModelEntity(entityName);
    List<EntityCondition> tmpList = createConditionList(inputFields, modelEntity.getFieldsUnmodifiable(), queryStringMap, delegator, context);
    /* the filter by date condition should only be added when there are other conditions or when
         * the user has specified a noConditionFind.  Otherwise, specifying filterByDate will become
         * its own condition.
         */
    if (tmpList.size() > 0 || "Y".equals(noConditionFind)) {
        if ("Y".equals(filterByDate)) {
            queryStringMap.put("filterByDate", filterByDate);
            if (UtilValidate.isEmpty(fromDateName)) {
                fromDateName = "fromDate";
            } else {
                queryStringMap.put("fromDateName", fromDateName);
            }
            if (UtilValidate.isEmpty(thruDateName)) {
                thruDateName = "thruDate";
            } else {
                queryStringMap.put("thruDateName", thruDateName);
            }
            if (UtilValidate.isEmpty(filterByDateValue)) {
                EntityCondition filterByDateCondition = EntityUtil.getFilterByDateExpr(fromDateName, thruDateName);
                tmpList.add(filterByDateCondition);
            } else {
                queryStringMap.put("filterByDateValue", filterByDateValue);
                EntityCondition filterByDateCondition = EntityUtil.getFilterByDateExpr(filterByDateValue, fromDateName, thruDateName);
                tmpList.add(filterByDateCondition);
            }
        }
    }
    EntityConditionList<EntityCondition> exprList = null;
    if (tmpList.size() > 0) {
        exprList = EntityCondition.makeCondition(tmpList);
    }
    List<String> orderByList = null;
    if (UtilValidate.isNotEmpty(orderBy)) {
        orderByList = StringUtil.split(orderBy, "|");
    }
    Map<String, Object> results = ServiceUtil.returnSuccess();
    queryStringMap.put("noConditionFind", noConditionFind);
    String queryString = UtilHttp.urlEncodeArgs(queryStringMap);
    results.put("queryString", queryString);
    results.put("queryStringMap", queryStringMap);
    results.put("orderByList", orderByList);
    results.put("entityConditionList", exprList);
    return results;
}
Also used : Delegator(org.apache.ofbiz.entity.Delegator) EntityCondition(org.apache.ofbiz.entity.condition.EntityCondition) ModelEntity(org.apache.ofbiz.entity.model.ModelEntity) Timestamp(java.sql.Timestamp) LinkedHashMap(java.util.LinkedHashMap)

Example 77 with EntityCondition

use of org.apache.ofbiz.entity.condition.EntityCondition in project ofbiz-framework by apache.

the class EntityTestSuite method testStoreByCondition.

/*
     * Tests the storeByCondition operation
     */
public void testStoreByCondition() throws Exception {
    flushAndRecreateTree("store-by-condition-a");
    flushAndRecreateTree("store-by-condition-b");
    // change the description of all the level1 nodes
    EntityCondition isLevel1 = EntityCondition.makeCondition("description", EntityOperator.LIKE, "store-by-condition-a:%");
    Map<String, String> fieldsToSet = UtilMisc.toMap("description", "store-by-condition-a:updated");
    delegator.storeByCondition("TestingNode", fieldsToSet, isLevel1);
    List<GenericValue> updatedNodes = EntityQuery.use(delegator).from("TestingNode").where(fieldsToSet).queryList();
    int n = updatedNodes.size();
    assertTrue("testStoreByCondition updated nodes > 0", n > 0);
}
Also used : GenericValue(org.apache.ofbiz.entity.GenericValue) EntityCondition(org.apache.ofbiz.entity.condition.EntityCondition)

Example 78 with EntityCondition

use of org.apache.ofbiz.entity.condition.EntityCondition in project ofbiz-framework by apache.

the class EntityTestSuite method testEntityCache.

/*
     * Tests the entity cache
     */
public void testEntityCache() throws Exception {
    // Test primary key cache
    delegator.removeByCondition("TestingType", EntityCondition.makeCondition("testingTypeId", EntityOperator.LIKE, "TEST-CACHE-%"));
    delegator.removeByCondition("TestingSubtype", EntityCondition.makeCondition("testingTypeId", EntityOperator.LIKE, "TEST-CACHE-%"));
    GenericValue testValue = EntityQuery.use(delegator).from("TestingType").where("testingTypeId", "TEST-CACHE-1").cache(true).queryOne();
    assertNull("No pre-existing type value", testValue);
    delegator.create("TestingType", "testingTypeId", "TEST-CACHE-1", "description", "Testing Type #Cache-1");
    testValue = EntityQuery.use(delegator).from("TestingType").where("testingTypeId", "TEST-CACHE-1").cache(true).queryOne();
    assertEquals("Retrieved from cache value has the correct description", "Testing Type #Cache-1", testValue.getString("description"));
    // Test immutable
    try {
        testValue.put("description", "New Testing Type #Cache-1");
        fail("Modified an immutable GenericValue");
    } catch (IllegalStateException e) {
    }
    try {
        testValue.remove("description");
        fail("Modified an immutable GenericValue");
    } catch (UnsupportedOperationException e) {
    }
    // Test entity value update operation updates the cache
    // Since the cache uses equals() and hashCode() methods, we test those as well
    int hashCode = testValue.hashCode();
    GenericValue originalValue = testValue;
    testValue = (GenericValue) testValue.clone();
    assertTrue("Cloned GenericValue equals original GenericValue", originalValue.equals(testValue));
    assertTrue("Cloned GenericValue has the same hash code", hashCode == testValue.hashCode());
    testValue.put("description", "New Testing Type #Cache-1");
    assertFalse("Modified GenericValue does not equal original GenericValue", originalValue.equals(testValue));
    assertTrue("Modified GenericValue has a different hash code", hashCode != testValue.hashCode());
    testValue.store();
    testValue = EntityQuery.use(delegator).from("TestingType").where("testingTypeId", "TEST-CACHE-1").cache(true).queryOne();
    assertEquals("Retrieved from cache value has the correct description", "New Testing Type #Cache-1", testValue.getString("description"));
    // Test storeByCondition updates the cache
    testValue = EntityQuery.use(delegator).from("TestingType").where("testingTypeId", "TEST-CACHE-1").cache(true).queryFirst();
    EntityCondition storeByCondition = EntityCondition.makeCondition(UtilMisc.toMap("testingTypeId", "TEST-CACHE-1", "lastUpdatedStamp", testValue.get("lastUpdatedStamp")));
    int qtyChanged = delegator.storeByCondition("TestingType", UtilMisc.toMap("description", "New Testing Type #Cache-0"), storeByCondition);
    assertEquals("Delegator.storeByCondition updated one value", 1, qtyChanged);
    testValue = EntityQuery.use(delegator).from("TestingType").where("testingTypeId", "TEST-CACHE-1").cache(true).queryFirst();
    assertEquals("Retrieved from cache value has the correct description", "New Testing Type #Cache-0", testValue.getString("description"));
    // Test removeByCondition updates the cache
    qtyChanged = delegator.removeByCondition("TestingType", storeByCondition);
    assertEquals("Delegator.removeByCondition removed one value", 1, qtyChanged);
    testValue = EntityQuery.use(delegator).from("TestingType").where("testingTypeId", "TEST-CACHE-1").cache(true).queryFirst();
    assertEquals("Retrieved from cache value is null", null, testValue);
    // Test entity value remove operation updates the cache
    testValue = delegator.create("TestingType", "testingTypeId", "TEST-CACHE-1", "description", "Testing Type #Cache-1");
    testValue.remove();
    testValue = EntityQuery.use(delegator).from("TestingType").where("testingTypeId", "TEST-CACHE-1").cache(true).queryOne();
    assertEquals("Retrieved from cache value is null", null, testValue);
    // Test entity condition cache
    List<GenericValue> testList = EntityQuery.use(delegator).from("TestingType").where(EntityCondition.makeCondition("description", EntityOperator.EQUALS, "Testing Type #Cache-2")).cache(true).queryList();
    assertEquals("Delegator findList returned no values", 0, testList.size());
    delegator.create("TestingType", "testingTypeId", "TEST-CACHE-2", "description", "Testing Type #Cache-2");
    testList = EntityQuery.use(delegator).from("TestingType").where(EntityCondition.makeCondition("description", EntityOperator.EQUALS, "Testing Type #Cache-2")).cache(true).queryList();
    assertEquals("Delegator findList returned one value", 1, testList.size());
    testValue = testList.get(0);
    assertEquals("Retrieved from cache value has the correct description", "Testing Type #Cache-2", testValue.getString("description"));
    // Test immutable
    try {
        testValue.put("description", "New Testing Type #2");
        fail("Modified an immutable GenericValue");
    } catch (IllegalStateException e) {
    }
    try {
        testValue.remove("description");
        fail("Modified an immutable GenericValue");
    } catch (UnsupportedOperationException e) {
    }
    // Test entity value create operation updates the cache
    testValue = (GenericValue) testValue.clone();
    testValue.put("testingTypeId", "TEST-CACHE-3");
    testValue.create();
    testList = EntityQuery.use(delegator).from("TestingType").where(EntityCondition.makeCondition("description", EntityOperator.EQUALS, "Testing Type #Cache-2")).cache(true).queryList();
    assertEquals("Delegator findList returned two values", 2, testList.size());
    // Test entity value update operation updates the cache
    testValue.put("description", "New Testing Type #Cache-3");
    testValue.store();
    testList = EntityQuery.use(delegator).from("TestingType").where(EntityCondition.makeCondition("description", EntityOperator.EQUALS, "Testing Type #Cache-2")).cache(true).queryList();
    assertEquals("Delegator findList returned one value", 1, testList.size());
    // Test entity value remove operation updates the cache
    testValue = testList.get(0);
    testValue = (GenericValue) testValue.clone();
    testValue.remove();
    testList = EntityQuery.use(delegator).from("TestingType").where(EntityCondition.makeCondition("description", EntityOperator.EQUALS, "Testing Type #Cache-2")).cache(true).queryList();
    assertEquals("Delegator findList returned empty list", 0, testList.size());
    // Test view entities in the pk cache - updating an entity should clear pk caches for all view entities containing that entity.
    testValue = EntityQuery.use(delegator).from("TestingSubtype").where("testingTypeId", "TEST-CACHE-3").cache(true).queryOne();
    assertNull("No pre-existing TestingSubtype", testValue);
    testValue = delegator.create("TestingSubtype", "testingTypeId", "TEST-CACHE-3", "subtypeDescription", "Testing Subtype #Cache-3");
    assertNotNull("TestingSubtype created", testValue);
    // Confirm member entity appears in the view
    testValue = EntityQuery.use(delegator).from("TestingViewPks").where("testingTypeId", "TEST-CACHE-3").cache(true).queryOne();
    assertEquals("View retrieved from cache has the correct member description", "Testing Subtype #Cache-3", testValue.getString("subtypeDescription"));
    testValue = EntityQuery.use(delegator).from("TestingSubtype").where("testingTypeId", "TEST-CACHE-3").cache(true).queryOne();
    // Modify member entity
    testValue = (GenericValue) testValue.clone();
    testValue.put("subtypeDescription", "New Testing Subtype #Cache-3");
    testValue.store();
    // Check if cached view contains the modification
    testValue = EntityQuery.use(delegator).from("TestingViewPks").where("testingTypeId", "TEST-CACHE-3").cache(true).queryOne();
    assertEquals("View retrieved from cache has the correct member description", "New Testing Subtype #Cache-3", testValue.getString("subtypeDescription"));
}
Also used : GenericValue(org.apache.ofbiz.entity.GenericValue) EntityCondition(org.apache.ofbiz.entity.condition.EntityCondition)

Example 79 with EntityCondition

use of org.apache.ofbiz.entity.condition.EntityCondition in project ofbiz-framework by apache.

the class EntityTestSuite method testCountViews.

/*
     * Tests findByCondition and tests searching on a view-entity
     */
public void testCountViews() throws Exception {
    delegator.removeByCondition("Testing", EntityCondition.makeCondition("testingTypeId", EntityOperator.EQUALS, "TEST-COUNT-VIEW"));
    flushAndRecreateTree("count-views");
    createNodeMembers("TEST-COUNT-VIEW", "Testing Type #Count", "count-views");
    EntityCondition isNodeWithMember = EntityCondition.makeCondition(EntityCondition.makeCondition("testingId", EntityOperator.NOT_EQUAL, GenericEntity.NULL_FIELD), EntityOperator.AND, EntityCondition.makeCondition("description", EntityOperator.LIKE, "count-views:%"));
    List<GenericValue> nodeWithMembers = EntityQuery.use(delegator).from("TestingNodeAndMember").where(isNodeWithMember).queryList();
    for (GenericValue v : nodeWithMembers) {
        Map<String, Object> fields = v.getAllFields();
        Debug.logInfo("--------------------------", module);
        // For values of a map
        for (Map.Entry<String, Object> entry : fields.entrySet()) {
            String field = entry.getKey();
            Object value = entry.getValue();
            Debug.logInfo(field + " = " + ((value == null) ? "[null]" : value), module);
        }
    }
    long testingcount = EntityQuery.use(delegator).from("Testing").where("testingTypeId", "TEST-COUNT-VIEW").queryCount();
    assertEquals("Number of views should equal number of created entities in the test.", testingcount, nodeWithMembers.size());
}
Also used : GenericValue(org.apache.ofbiz.entity.GenericValue) EntityCondition(org.apache.ofbiz.entity.condition.EntityCondition) ConcurrentMap(java.util.concurrent.ConcurrentMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 80 with EntityCondition

use of org.apache.ofbiz.entity.condition.EntityCondition in project ofbiz-framework by apache.

the class SqlJdbcUtil method makeFromClause.

/**
 * Makes the FROM clause and when necessary the JOIN clause(s) as well
 */
public static String makeFromClause(ModelEntity modelEntity, ModelFieldTypeReader modelFieldTypeReader, Datasource datasourceInfo) throws GenericEntityException {
    StringBuilder sql = new StringBuilder(" FROM ");
    if (modelEntity instanceof ModelViewEntity) {
        ModelViewEntity modelViewEntity = (ModelViewEntity) modelEntity;
        if ("ansi".equals(datasourceInfo.getJoinStyle()) || "ansi-no-parenthesis".equals(datasourceInfo.getJoinStyle())) {
            boolean useParenthesis = true;
            if ("ansi-no-parenthesis".equals(datasourceInfo.getJoinStyle())) {
                useParenthesis = false;
            }
            // FROM clause: in this case will be a bunch of joins that correspond with the view-links
            // BIG NOTE on the JOIN clauses: the order of joins is determined by the order of the
            // view-links; for more flexible order we'll have to figure something else out and
            // extend the DTD for the nested view-link elements or something
            // At this point it is assumed that in each view-link the left hand alias will
            // either be the first alias in the series or will already be in a previous
            // view-link and already be in the big join; SO keep a set of all aliases
            // in the join so far and if the left entity alias isn't there yet, and this
            // isn't the first one, throw an exception
            Set<String> joinedAliasSet = new TreeSet<String>();
            // TODO: at view-link read time make sure they are ordered properly so that each
            // left hand alias after the first view-link has already been linked before
            StringBuilder openParens = null;
            if (useParenthesis)
                openParens = new StringBuilder();
            StringBuilder restOfStatement = new StringBuilder();
            for (int i = 0; i < modelViewEntity.getViewLinksSize(); i++) {
                // don't put starting parenthesis
                if (i > 0 && useParenthesis)
                    openParens.append('(');
                ModelViewEntity.ModelViewLink viewLink = modelViewEntity.getViewLink(i);
                ModelEntity linkEntity = modelViewEntity.getMemberModelEntity(viewLink.getEntityAlias());
                ModelEntity relLinkEntity = modelViewEntity.getMemberModelEntity(viewLink.getRelEntityAlias());
                if (i == 0) {
                    // this is the first referenced member alias, so keep track of it for future use...
                    restOfStatement.append(makeViewTable(linkEntity, modelFieldTypeReader, datasourceInfo));
                    // another possible one that some dbs might need, but not sure of any yet: restOfStatement.append(" AS ");
                    restOfStatement.append(" ");
                    restOfStatement.append(viewLink.getEntityAlias());
                    joinedAliasSet.add(viewLink.getEntityAlias());
                } else {
                    // make sure the left entity alias is already in the join...
                    if (!joinedAliasSet.contains(viewLink.getEntityAlias())) {
                        throw new GenericModelException("Tried to link the " + viewLink.getEntityAlias() + " alias to the " + viewLink.getRelEntityAlias() + " alias of the " + modelViewEntity.getEntityName() + " view-entity, but it is not the first view-link and has not been included in a previous view-link. In other words, the left/main alias isn't connected to the rest of the member-entities yet.");
                    }
                }
                // now put the rel (right) entity alias into the set that is in the join
                joinedAliasSet.add(viewLink.getRelEntityAlias());
                if (viewLink.isRelOptional()) {
                    restOfStatement.append(" LEFT OUTER JOIN ");
                } else {
                    restOfStatement.append(" INNER JOIN ");
                }
                restOfStatement.append(makeViewTable(relLinkEntity, modelFieldTypeReader, datasourceInfo));
                // another possible one that some dbs might need, but not sure of any yet: restOfStatement.append(" AS ");
                restOfStatement.append(" ");
                restOfStatement.append(viewLink.getRelEntityAlias());
                restOfStatement.append(" ON ");
                StringBuilder condBuffer = new StringBuilder();
                for (int j = 0; j < viewLink.getKeyMapsSize(); j++) {
                    ModelKeyMap keyMap = viewLink.getKeyMap(j);
                    ModelField linkField = linkEntity.getField(keyMap.getFieldName());
                    if (linkField == null) {
                        throw new GenericModelException("Invalid field name in view-link key-map for the " + viewLink.getEntityAlias() + " and the " + viewLink.getRelEntityAlias() + " member-entities of the " + modelViewEntity.getEntityName() + " view-entity; the field [" + keyMap.getFieldName() + "] does not exist on the [" + linkEntity.getEntityName() + "] entity.");
                    }
                    ModelField relLinkField = relLinkEntity.getField(keyMap.getRelFieldName());
                    if (relLinkField == null) {
                        throw new GenericModelException("Invalid related field name in view-link key-map for the " + viewLink.getEntityAlias() + " and the " + viewLink.getRelEntityAlias() + " member-entities of the " + modelViewEntity.getEntityName() + " view-entity; the field [" + keyMap.getRelFieldName() + "] does not exist on the [" + relLinkEntity.getEntityName() + "] entity.");
                    }
                    if (condBuffer.length() > 0) {
                        condBuffer.append(" AND ");
                    }
                    condBuffer.append(viewLink.getEntityAlias());
                    condBuffer.append(".");
                    condBuffer.append(linkField.getColName());
                    condBuffer.append(" = ");
                    condBuffer.append(viewLink.getRelEntityAlias());
                    condBuffer.append(".");
                    condBuffer.append(relLinkField.getColName());
                }
                if (condBuffer.length() == 0) {
                    throw new GenericModelException("No view-link/join key-maps found for the " + viewLink.getEntityAlias() + " and the " + viewLink.getRelEntityAlias() + " member-entities of the " + modelViewEntity.getEntityName() + " view-entity.");
                }
                ModelViewEntity.ViewEntityCondition viewEntityCondition = viewLink.getViewEntityCondition();
                if (viewEntityCondition != null) {
                    EntityCondition whereCondition = viewEntityCondition.getWhereCondition(modelFieldTypeReader, null);
                    condBuffer.append(" AND ");
                    condBuffer.append(whereCondition.makeWhereString(modelEntity, null, datasourceInfo));
                }
                restOfStatement.append(condBuffer.toString());
                // don't put ending parenthesis
                if (i < (modelViewEntity.getViewLinksSize() - 1) && useParenthesis)
                    restOfStatement.append(')');
            }
            if (useParenthesis)
                sql.append(openParens.toString());
            sql.append(restOfStatement.toString());
            // handle tables not included in view-link
            boolean fromEmpty = restOfStatement.length() == 0;
            for (String aliasName : modelViewEntity.getMemberModelMemberEntities().keySet()) {
                ModelEntity fromEntity = modelViewEntity.getMemberModelEntity(aliasName);
                if (!joinedAliasSet.contains(aliasName)) {
                    if (!fromEmpty)
                        sql.append(", ");
                    fromEmpty = false;
                    sql.append(makeViewTable(fromEntity, modelFieldTypeReader, datasourceInfo));
                    sql.append(" ");
                    sql.append(aliasName);
                }
            }
        } else if ("theta-oracle".equals(datasourceInfo.getJoinStyle()) || "theta-mssql".equals(datasourceInfo.getJoinStyle())) {
            // FROM clause
            Iterator<String> meIter = modelViewEntity.getMemberModelMemberEntities().keySet().iterator();
            while (meIter.hasNext()) {
                String aliasName = meIter.next();
                ModelEntity fromEntity = modelViewEntity.getMemberModelEntity(aliasName);
                sql.append(makeViewTable(fromEntity, modelFieldTypeReader, datasourceInfo));
                sql.append(" ");
                sql.append(aliasName);
                if (meIter.hasNext())
                    sql.append(", ");
            }
        // JOIN clause(s): none needed, all the work done in the where clause for theta-oracle
        } else {
            throw new GenericModelException("The join-style " + datasourceInfo.getJoinStyle() + " is not yet supported");
        }
    } else {
        sql.append(modelEntity.getTableName(datasourceInfo));
    }
    return sql.toString();
}
Also used : GenericModelException(org.apache.ofbiz.entity.GenericModelException) EntityCondition(org.apache.ofbiz.entity.condition.EntityCondition) ModelKeyMap(org.apache.ofbiz.entity.model.ModelKeyMap) ModelField(org.apache.ofbiz.entity.model.ModelField) TreeSet(java.util.TreeSet) ModelViewEntity(org.apache.ofbiz.entity.model.ModelViewEntity) Iterator(java.util.Iterator) ModelEntity(org.apache.ofbiz.entity.model.ModelEntity)

Aggregations

EntityCondition (org.apache.ofbiz.entity.condition.EntityCondition)118 GenericValue (org.apache.ofbiz.entity.GenericValue)96 GenericEntityException (org.apache.ofbiz.entity.GenericEntityException)78 Delegator (org.apache.ofbiz.entity.Delegator)60 LinkedList (java.util.LinkedList)58 Locale (java.util.Locale)43 Timestamp (java.sql.Timestamp)40 HashMap (java.util.HashMap)32 EntityListIterator (org.apache.ofbiz.entity.util.EntityListIterator)29 GenericServiceException (org.apache.ofbiz.service.GenericServiceException)26 LocalDispatcher (org.apache.ofbiz.service.LocalDispatcher)24 Map (java.util.Map)22 BigDecimal (java.math.BigDecimal)21 EntityExpr (org.apache.ofbiz.entity.condition.EntityExpr)18 EntityQuery (org.apache.ofbiz.entity.util.EntityQuery)14 GeneralException (org.apache.ofbiz.base.util.GeneralException)12 ArrayList (java.util.ArrayList)11 DynamicViewEntity (org.apache.ofbiz.entity.model.DynamicViewEntity)9 ModelKeyMap (org.apache.ofbiz.entity.model.ModelKeyMap)8 HashSet (java.util.HashSet)7