@Override @Transactional public <T> Records<T> getRelatedFieldValue( Long entityId, Long instanceId, String fieldName, QueryParams queryParams) { EntityDto entity = getEntity(entityId); validateCredentials(entity); String entityName = entity.getName(); MotechDataService service = getServiceForEntity(entity); Object instance = service.findById(instanceId); if (instance == null) { throw new ObjectNotFoundException(entityName, instanceId); } try { Collection<T> relatedAsColl = TypeHelper.asCollection(PropertyUtil.getProperty(instance, fieldName)); List<T> filtered = InMemoryQueryFilter.filter(relatedAsColl, queryParams); int recordCount = relatedAsColl.size(); int rowCount = (int) Math.ceil(recordCount / (double) queryParams.getPageSize()); return new Records<>(queryParams.getPage(), rowCount, recordCount, filtered); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { throw new ObjectReadException(entityName, e); } }
@Override public void revertInstanceFromTrash(Long entityId, Long instanceId) { EntityDto entity = getEntity(entityId); validateCredentials(entity); validateNonEditableProperty(entity); MotechDataService service = getServiceForEntity(entity); Object trash = service.findTrashInstanceById(instanceId, entityId); List<FieldRecord> fieldRecords = new LinkedList<>(); try { for (FieldDto field : entityService.getEntityFields(entity.getId())) { if (ID_FIELD_NAME.equalsIgnoreCase(field.getBasic().getDisplayName())) { continue; } Field f = FieldUtils.getField( trash.getClass(), StringUtils.uncapitalize(field.getBasic().getName()), true); FieldRecord record = new FieldRecord(field); record.setValue(f.get(trash)); fieldRecords.add(record); } Class<?> entityClass = getEntityClass(entity); Object newInstance = entityClass.newInstance(); updateFields(newInstance, fieldRecords, service, null); service.revertFromTrash(newInstance, trash); } catch (Exception e) { throw new RevertFromTrashException(entity.getName(), instanceId, e); } }
@Override public long countRecords(Long entityId) { EntityDto entity = getEntity(entityId); validateCredentialsForReading(entity); MotechDataService service = getServiceForEntity(entity); return service.count(); }
@Override public void deleteInstance(Long entityId, Long instanceId) { EntityDto entity = getEntity(entityId); validateCredentials(entity); validateNonEditableProperty(entity); MotechDataService service = getServiceForEntity(entity); service.delete(ID_FIELD_NAME, instanceId); }
@Test public void shouldCreateInstanceOfSubclassedEntityWithRelation() { mockEntity(SubclassSample.class, ENTITY_ID, entity); mockDataService(SubclassSample.class, motechDataService); when(motechDataService.retrieve("id", INSTANCE_ID)).thenReturn(new SubclassSample()); when(entityService.getEntityFieldsForUI(ENTITY_ID)) .thenReturn( asList( FieldTestHelper.fieldDto( 1L, "superclassInteger", Integer.class.getName(), "Superclass Integer", 7), FieldTestHelper.fieldDto( 2L, "subclassString", String.class.getName(), "Subclass String", "test"), FieldTestHelper.fieldDto( 3L, "superclassRelation", TypeDto.ONE_TO_ONE_RELATIONSHIP.getTypeClass(), "Superclass Relationship", null))); long relationEntityId = ANOTHER_ENTITY_ID; long relationInstanceId = INSTANCE_ID + 1; EntityDto relationEntity = mock(EntityDto.class); MotechDataService relationDataService = mock(MotechDataService.class); mockEntity(TestSample.class, relationEntityId, relationEntity); mockDataService(TestSample.class, relationDataService); TestSample relatedInstance = new TestSample("test sample", 42); when(relationDataService.retrieve("id", relationInstanceId)).thenReturn(relatedInstance); when(relationDataService.findById(relationInstanceId)).thenReturn(relatedInstance); RelationshipsUpdate relationshipsUpdate = new RelationshipsUpdate(); relationshipsUpdate.getAddedIds().add(relationInstanceId); EntityRecord createRecord = new EntityRecord( null, ENTITY_ID, asList( FieldTestHelper.fieldRecord("superclassInteger", Integer.class.getName(), "", 77), FieldTestHelper.fieldRecord( "subclassString", String.class.getName(), "", "test test"), FieldTestHelper.fieldRecord( TypeDto.ONE_TO_ONE_RELATIONSHIP, "superclassRelation", "", relationshipsUpdate))); ArgumentCaptor<SubclassSample> createCaptor = ArgumentCaptor.forClass(SubclassSample.class); instanceService.saveInstance(createRecord); verify(motechDataService).create(createCaptor.capture()); SubclassSample instance = createCaptor.getValue(); assertEquals(77, (int) instance.getSuperclassInteger()); assertEquals("test test", instance.getSubclassString()); assertNotNull(instance.getSuperclassRelation()); assertEquals(relatedInstance.getStrField(), instance.getSuperclassRelation().getStrField()); assertEquals(relatedInstance.getIntField(), instance.getSuperclassRelation().getIntField()); }
@Override public long countHistoryRecords(Long entityId, Long instanceId) { EntityDto entity = getEntity(entityId); validateCredentialsForReading(entity); MotechDataService service = getServiceForEntity(entity); Object instance = service.retrieve(ID_FIELD_NAME, instanceId); return historyService.countHistoryRecords(instance); }
@Override public Object getInstanceField(Long entityId, Long instanceId, String fieldName) { EntityDto entity = getEntity(entityId); MotechDataService service = getServiceForEntity(entity); validateCredentialsForReading(entity); Object instance = service.retrieve(ID_FIELD_NAME, instanceId); return service.getDetachedField(instance, fieldName); }
@Override public List<EntityRecord> getEntityRecords(Long entityId, QueryParams queryParams) { EntityDto entity = getEntity(entityId); validateCredentialsForReading(entity); List<FieldDto> fields = entityService.getEntityFields(entityId); MotechDataService service = getServiceForEntity(entity); List instances = service.retrieveAll(queryParams); return instancesToRecords(instances, entity, fields, service); }
@Override public HistoryRecord getHistoryRecord(Long entityId, Long instanceId, Long historyId) { EntityDto entity = getEntity(entityId); validateCredentialsForReading(entity); MotechDataService service = getServiceForEntity(entity); Object instance = service.retrieve(ID_FIELD_NAME, instanceId); Object historyInstance = historyService.getSingleHistoryInstance(instance, historyId); return convertToHistoryRecord(historyInstance, entity, instanceId, service); }
@Override public EntityRecord getEntityInstance(Long entityId, Long instanceId) { EntityDto entity = getEntity(entityId); validateCredentialsForReading(entity); MotechDataService service = getServiceForEntity(entity); Object instance = service.retrieve(ID_FIELD_NAME, instanceId); if (instance == null) { throw new ObjectNotFoundException(entity.getName(), instanceId); } List<FieldDto> fields = entityService.getEntityFields(entityId); return instanceToRecord(instance, entity, fields, service); }
@Override public List<HistoryRecord> getInstanceHistory( Long entityId, Long instanceId, QueryParams queryParams) { EntityDto entity = getEntity(entityId); validateCredentialsForReading(entity); MotechDataService service = getServiceForEntity(entity); Object instance = service.retrieve(ID_FIELD_NAME, instanceId); List history = historyService.getHistoryForInstance(instance, queryParams); List<HistoryRecord> result = new ArrayList<>(); for (Object o : history) { result.add(convertToHistoryRecord(o, entity, instanceId, service)); } return result; }
private void testUpdateCreate(boolean edit) throws ClassNotFoundException { final DateTime dtValue = DateUtil.now(); mockSampleFields(); mockDataService(); mockEntity(); when(motechDataService.retrieve("id", INSTANCE_ID)).thenReturn(new TestSample()); List<FieldRecord> fieldRecords = asList( FieldTestHelper.fieldRecord("strField", String.class.getName(), "", "this is a test"), FieldTestHelper.fieldRecord("intField", Integer.class.getName(), "", 16), FieldTestHelper.fieldRecord("timeField", Time.class.getName(), "", "10:17"), FieldTestHelper.fieldRecord("dtField", DateTime.class.getName(), "", dtValue)); Long id = (edit) ? INSTANCE_ID : null; EntityRecord record = new EntityRecord(id, ENTITY_ID, fieldRecords); MDSClassLoader.getInstance().loadClass(TestSample.class.getName()); instanceService.saveInstance(record); ArgumentCaptor<TestSample> captor = ArgumentCaptor.forClass(TestSample.class); if (edit) { verify(motechDataService).update(captor.capture()); } else { verify(motechDataService).create(captor.capture()); } TestSample sample = captor.getValue(); assertEquals("this is a test", sample.getStrField()); assertEquals(Integer.valueOf(16), sample.getIntField()); assertEquals(new Time(10, 17), sample.getTimeField()); assertEquals(dtValue, sample.getDtField()); }
private Object getProperty(Object instance, FieldDto field, MotechDataService service) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { String fieldName = StringUtils.uncapitalize(field.getBasic().getName()); PropertyDescriptor propertyDescriptor = PropertyUtil.getPropertyDescriptor(instance, fieldName); Method readMethod = propertyDescriptor.getReadMethod(); if (readMethod == null) { throw new NoSuchMethodException(String.format("No getter for field %s", fieldName)); } if (TypeDto.BLOB.getTypeClass().equals(field.getType().getTypeClass())) { return ArrayUtils.EMPTY_BYTE_OBJECT_ARRAY; } try { return readMethod.invoke(instance); } catch (InvocationTargetException e) { LOGGER.debug( "Invocation target exception thrown when retrieving field {}. This may indicate a non loaded field", fieldName, e); // fallback to the service return service.getDetachedField(instance, fieldName); } }
@Override @Transactional public Object saveInstance(EntityRecord entityRecord, Long deleteValueFieldId) { EntityDto entity = getEntity(entityRecord.getEntitySchemaId()); validateCredentials(entity); validateNonEditableProperty(entity); List<FieldDto> entityFields = getEntityFields(entityRecord.getEntitySchemaId()); try { MotechDataService service = getServiceForEntity(entity); Class<?> entityClass = getEntityClass(entity); boolean newObject = entityRecord.getId() == null; Object instance; if (newObject) { instance = entityClass.newInstance(); for (FieldDto entityField : entityFields) { if (entityField.getType().isMap() && entityField.getBasic().getDefaultValue() != null) { setInstanceFieldMap(instance, entityField); } } } else { instance = service.retrieve(ID_FIELD_NAME, entityRecord.getId()); if (instance == null) { throw new ObjectNotFoundException(entity.getName(), entityRecord.getId()); } } updateFields(instance, entityRecord.getFields(), service, deleteValueFieldId, !newObject); if (newObject) { return service.create(instance); } else { return service.update(instance); } } catch (Exception e) { if (entityRecord.getId() == null) { throw new ObjectCreateException(entity.getName(), e); } else { throw new ObjectUpdateException(entity.getName(), entityRecord.getId(), e); } } }
@Test public void shouldReturnRelatedInstances() { mockDataService(); mockAnotherEntity(); mockEntity(); mockSampleFields(); mockAnotherEntityFields(); mockTestClassEntity(); mockTestClassService(); mockTestClassFields(); when(serviceForAnotherSample.findById(INSTANCE_ID)).thenReturn(sampleForRelationshipTesting()); QueryParams queryParams = new QueryParams(1, 2, new Order(Constants.Util.ID_FIELD_NAME, Order.Direction.ASC)); Records<BasicEntityRecord> records = instanceService.getRelatedFieldValue( ANOTHER_ENTITY_ID, INSTANCE_ID, "testClasses", new RelationshipsUpdate(), queryParams); assertNotNull(records); assertEquals(Integer.valueOf(1), records.getPage()); // page 1 assertEquals(Integer.valueOf(2), records.getTotal()); // 2 pages total assertEquals(Integer.valueOf(3), records.getRecords()); // 3 records total assertEquals( asList(1L, 2L), extract(records.getRows(), on(BasicEntityRecord.class).getFieldByName("id").getValue())); RelationshipsUpdate filter = new RelationshipsUpdate(); filter.setRemovedIds(Arrays.asList(1L, 2L)); filter.setAddedIds(Arrays.asList(50L)); when(testClassMotechDataService.findByIds(filter.getAddedIds())) .thenReturn(Arrays.asList(new TestClass(50))); records = instanceService.getRelatedFieldValue( ANOTHER_ENTITY_ID, INSTANCE_ID, "testClasses", filter, queryParams); assertNotNull(records); assertEquals(Integer.valueOf(1), records.getPage()); // page 1 assertEquals(Integer.valueOf(1), records.getTotal()); // 1 page total assertEquals(Integer.valueOf(2), records.getRecords()); // 2 records total // 1L and 2L removed, 50L added assertEquals( asList(3L, 50L), extract(records.getRows(), on(BasicEntityRecord.class).getFieldByName("id").getValue())); }
@Test public void shouldCountAllEntities() { mockSampleFields(); mockDataService(); mockEntity(); when(motechDataService.count()).thenReturn(56L); assertEquals(56L, instanceService.countRecords(ENTITY_ID)); }
@Override public FieldRecord getInstanceValueAsRelatedField(Long entityId, Long fieldId, Long instanceId) { validateCredentialsForReading(getEntity(entityId)); try { FieldRecord fieldRecord; FieldDto field = entityService.getEntityFieldById(entityId, fieldId); MotechDataService service = DataServiceHelper.getDataService( bundleContext, field.getMetadata(RELATED_CLASS).getValue()); Object instance = service.findById(instanceId); if (instance == null) { throw new ObjectNotFoundException(service.getClassType().getName(), instanceId); } fieldRecord = new FieldRecord(field); fieldRecord.setValue( parseValueForDisplay(instance, field.getMetadata(Constants.MetadataKeys.RELATED_FIELD))); fieldRecord.setDisplayValue(instance.toString()); return fieldRecord; } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { throw new ObjectReadException(entityId, e); } }
@Test public void shouldLoadBlobField() throws InstanceNotFoundException { EntityDto entityDto = new EntityDto(); entityDto.setReadOnlySecurityMode(null); entityDto.setSecurityMode(null); entityDto.setClassName(TestSample.class.getName()); when(entityService.getEntity(ENTITY_ID + 1)).thenReturn(entityDto); mockDataService(); TestSample instance = Mockito.mock(TestSample.class); when(motechDataService.findById(ENTITY_ID + 1)).thenReturn(instance); instanceService.getInstanceField(12l, ENTITY_ID + 1, "blobField"); verify(motechDataService).getDetachedField(instance, "blobField"); }
@Test(expected = ObjectUpdateException.class) public void shouldThrowExceptionWhileUpdatingReadonlyField() throws ClassNotFoundException { mockDataService(); mockEntity(); when(motechDataService.retrieve("id", INSTANCE_ID)).thenReturn(new TestSample()); List<FieldRecord> fieldRecords = asList( FieldTestHelper.fieldRecord("strField", String.class.getName(), "", "CannotEditThis")); fieldRecords.get(0).setNonEditable(true); EntityRecord record = new EntityRecord(INSTANCE_ID, ENTITY_ID, fieldRecords); instanceService.saveInstance(record); }
private Object parseBlobValue( FieldRecord fieldRecord, MotechDataService service, String fieldName, Long deleteValueFieldId, Object instance) { Object parsedValue; if ((ArrayUtils.EMPTY_BYTE_OBJECT_ARRAY.equals(fieldRecord.getValue()) || ArrayUtils.EMPTY_BYTE_ARRAY.equals(fieldRecord.getValue())) && !fieldRecord.getId().equals(deleteValueFieldId)) { parsedValue = service.getDetachedField(instance, fieldName); } else { parsedValue = fieldRecord.getValue(); } return verifyParsedValue(parsedValue); }
@Test public void shouldReturnEntityInstance() { mockDataService(); mockSampleFields(); mockEntity(); when(motechDataService.retrieve("id", INSTANCE_ID)) .thenReturn(new TestSample("Hello world", 99)); EntityRecord record = instanceService.getEntityInstance(ENTITY_ID, INSTANCE_ID); assertNotNull(record); assertEquals(Long.valueOf(ENTITY_ID), record.getEntitySchemaId()); assertEquals(Long.valueOf(INSTANCE_ID), record.getId()); List<FieldRecord> fieldRecords = record.getFields(); assertCommonFieldRecordFields(fieldRecords); assertEquals( asList("Hello world", 99, null, null, null), extract(fieldRecords, on(FieldRecord.class).getValue())); }
@Test public void shouldUpdateRelatedFields() { TestSample test1 = new TestSample("someString", 4); TestSample test2 = new TestSample("otherString", 5); TestSample test3 = new TestSample("sample", 6); RelationshipsUpdate oneToOneUpdate = new RelationshipsUpdate(); oneToOneUpdate.getAddedIds().add(6L); RelationshipsUpdate oneToManyUpdate = buildRelationshipUpdate(); List<FieldRecord> fieldRecords = asList( FieldTestHelper.fieldRecord("title", String.class.getName(), "String field", "Default"), FieldTestHelper.fieldRecord( TypeDto.ONE_TO_MANY_RELATIONSHIP, "testSamples", "Related field", oneToManyUpdate), FieldTestHelper.fieldRecord( TypeDto.ONE_TO_ONE_RELATIONSHIP, "testSample", "Other Related field", oneToOneUpdate)); EntityRecord entityRecord = new EntityRecord(null, ANOTHER_ENTITY_ID, fieldRecords); mockSampleFields(); mockDataService(); mockEntity(); EntityDto entityWithRelatedField = mock(EntityDto.class); when(entityService.getEntity(ANOTHER_ENTITY_ID)).thenReturn(entityWithRelatedField); when(entityWithRelatedField.getClassName()).thenReturn(AnotherSample.class.getName()); when(entityWithRelatedField.getId()).thenReturn(ENTITY_ID + 1); ServiceReference serviceReferenceForClassWithRelatedField = mock(ServiceReference.class); MotechDataService serviceForClassWithRelatedField = mock(MotechDataService.class); when(bundleContext.getServiceReference( ClassName.getInterfaceName(AnotherSample.class.getName()))) .thenReturn(serviceReferenceForClassWithRelatedField); when(bundleContext.getService(serviceReferenceForClassWithRelatedField)) .thenReturn(serviceForClassWithRelatedField); when(motechDataService.findById(4L)).thenReturn(test1); when(motechDataService.findById(5L)).thenReturn(test2); when(motechDataService.findById(6L)).thenReturn(test3); when(motechDataService.findByIds(oneToManyUpdate.getAddedIds())) .thenReturn(Arrays.asList(test1, test2)); when(entityService.getEntityFieldsForUI(ANOTHER_ENTITY_ID)) .thenReturn( asList( FieldTestHelper.fieldDto( 5L, "title", String.class.getName(), "String field", "Default"), FieldTestHelper.fieldDto( 6L, "testSamples", TypeDto.ONE_TO_MANY_RELATIONSHIP.getTypeClass(), "Related field", null))); ArgumentCaptor<AnotherSample> captor = ArgumentCaptor.forClass(AnotherSample.class); instanceService.saveInstance(entityRecord, null); verify(serviceForClassWithRelatedField).create(captor.capture()); AnotherSample capturedValue = captor.getValue(); assertEquals(capturedValue.getTestSample(), test3); assertEquals(capturedValue.getTestSamples().size(), 3); assertEquals(capturedValue.getTitle(), "Default"); assertTrue(capturedValue.getTestSamples().contains(test1)); assertFalse(capturedValue.getTestSamples().contains(test3)); assertTrue(capturedValue.getTestSamples().contains(test2)); }
private Object findRelatedObjectById(Object id, MotechDataService service) { // We need parse id value to the long type return service.findById(TypeHelper.parseNumber(id, Long.class.getName()).longValue()); }