@Test
  public void testSpringCreation()
      throws JaloInvalidParameterException, JaloDuplicateCodeException,
          JaloGenericCreationException, JaloAbstractTypeException {
    final ComposedType unitType = TypeManager.getInstance().getComposedType(Unit.class);
    final ComposedType ct = TypeManager.getInstance().createComposedType(unitType, "MyUnit");
    ct.setJaloClass(MyUnit.class);

    final Map<String, Object> params = new HashMap<String, Object>();
    params.put(Unit.CODE, "code");
    params.put(Unit.UNITTYPE, "type");

    final MyUnit u = (MyUnit) ct.newInstance(params);

    assertEquals("<code>", u.getCode());
    assertEquals("type", u.getUnitType());
    assertTrue(u instanceof MySpringUnit);

    params.clear();
    params.put(Unit.CODE, "code2");
    params.put(Unit.UNITTYPE, "type");

    final Unit controlUnit = (Unit) unitType.newInstance(params);

    assertEquals("code2", controlUnit.getCode());
    assertEquals("type", controlUnit.getUnitType());
    assertFalse(controlUnit instanceof MyUnit);
  }
  @Before
  public void setUp() throws Exception {
    final CatalogManager catalogManager = CatalogManager.getInstance();

    final Catalog catalog = catalogManager.createCatalog("PartOfTest");
    srcCatalogVersion = catalogManager.createCatalogVersion(catalog, "ver1", null);
    srcCatalogVersion.setLanguages(Collections.singletonList(getOrCreateLanguage("de")));
    tgtCatalogVersion = catalogManager.createCatalogVersion(catalog, "ver2", null);
    tgtCatalogVersion.setLanguages(Collections.singletonList(getOrCreateLanguage("de")));

    LOG.info("Creating  product");
    final ComposedType composedType = TypeManager.getInstance().getComposedType(Product.class);

    final Product productOne = createProduct("Product-One", composedType);
    final Product productTwo = createProduct("Product-Two", composedType);

    LOG.info("Creating  product reference ");

    catalogManager.createProductReference("foo", productOne, productTwo, Integer.valueOf(1));

    LOG.info("Done catalog creation.");

    final Europe1PriceFactory europe1 = Europe1PriceFactory.getInstance();
    final Currency currency = C2LManager.getInstance().createCurrency("europe1/dr");
    final Unit unit = ProductManager.getInstance().createUnit(null, "europe1/u", "typ");
    final EnumerationValue enumValue =
        EnumerationManager.getInstance()
            .createEnumerationValue(Europe1Constants.TYPES.DISCOUNT_USER_GROUP, "test");

    priceRowSpy =
        Mockito.spy(
            europe1.createPriceRow(
                productTwo, null, null, enumValue, 0, currency, unit, 1, true, null, 0));
  }
  /** Test check if Overwriting of unique key attribute cache is working */
  @Test
  public void testOverwriteUniqueKeyAttributeCache() {

    final ComposedType priceRowComposedTypeSpy =
        Mockito.spy(TypeManager.getInstance().getComposedType(PriceRow.class));

    final CatalogManager catalogManager = CatalogManager.getInstance();

    final Map args = new HashMap();
    args.put(CatalogVersionSyncJob.CODE, "foo");
    args.put(CatalogVersionSyncJob.SOURCEVERSION, srcCatalogVersion);
    args.put(CatalogVersionSyncJob.TARGETVERSION, tgtCatalogVersion);
    args.put(CatalogVersionSyncJob.MAXTHREADS, Integer.valueOf(1));
    final CatalogVersionSyncJob job = catalogManager.createCatalogVersionSyncJob(args);

    final CatalogVersionSyncCronJob cjob = (CatalogVersionSyncCronJob) job.newExecution();

    ctx = Mockito.spy(new CatalogVersionSyncCopyContext(job, cjob, null));

    Mockito.when(priceRowComposedTypeSpy.getAttributeDescriptorsIncludingPrivate())
        .thenReturn(Collections.EMPTY_SET);
    Mockito.when(priceRowSpy.getComposedType()).thenReturn(priceRowComposedTypeSpy);

    ctx.queryNonCatalogItemCopy(priceRowSpy);
    ctx.queryCatalogItemCopy(priceRowSpy);
  }
  @SuppressWarnings("deprecation")
  protected static SyncItemJob setupStoreTemplateSyncJobs(
      final CatalogVersionSyncJobModel syncJobModel, final ModelService modelService) {
    // configure root types
    final SyncItemJob syncJob = modelService.getSource(syncJobModel);
    if (syncJob == null) {
      LOG.warn(
          "Could not setup catalog version synchronization job. Reason: Synchronization job not found.");

    } else {
      final List<ComposedType> rootTypes = new ArrayList<ComposedType>(2);
      final ComposedType cmsItemType =
          TypeManager.getInstance().getComposedType(Cms2Constants.TC.CMSITEM);
      rootTypes.add(cmsItemType);
      rootTypes.add(TypeManager.getInstance().getComposedType(Cms2Constants.TC.CMSRELATION));
      rootTypes.add(TypeManager.getInstance().getComposedType(Media.class));
      syncJob.setRootTypes(JaloSession.getCurrentSession().getSessionContext(), rootTypes);
      syncJob.setSyncLanguages(
          JaloSession.getCurrentSession().getSessionContext(),
          C2LManager.getInstance().getAllLanguages());

      final Collection<SyncAttributeDescriptorConfig> syncAttributeConfigs =
          syncJob.getSyncAttributeConfigurations();
      for (final SyncAttributeDescriptorConfig syncAttributeDescriptorConfig :
          syncAttributeConfigs) {
        final Type attributeType =
            syncAttributeDescriptorConfig.getAttributeDescriptor().getAttributeType();
        if ((syncAttributeDescriptorConfig
                    .getAttributeDescriptor()
                    .getEnclosingType()
                    .isAssignableFrom(cmsItemType)
                && cmsItemType.isAssignableFrom(attributeType))
            || ((attributeType instanceof CollectionType)
                && cmsItemType.isAssignableFrom(
                    ((CollectionType) attributeType).getElementType()))) {
          syncAttributeDescriptorConfig.setCopyByValue(true);
        }
      }
    }
    return syncJob;
  }
  @Test
  public void testExclusiveSync() {
    assertNull(catalogManager.getCounterpartItem(product1, tgt));
    assertNull(catalogManager.getCounterpartItem(product2, tgt));
    assertNull(catalogManager.getCounterpartItem(product3, tgt));

    final ComposedType pType = TypeManager.getInstance().getComposedType(Product.class);
    final AttributeDescriptor nameAd = pType.getAttributeDescriptorIncludingPrivate(Product.NAME);
    final AttributeDescriptor unitAd = pType.getAttributeDescriptorIncludingPrivate(Product.UNIT);

    final int threads = CatalogVersionSyncJob.getDefaultMaxThreads(jaloSession.getTenant()) * 2;

    final CatalogVersionSyncJob exclJob1 = createSyncJob("excl1", src, tgt, threads, true);
    exclJob1.setCreateNewItems(false); // don't create new items in full sync
    SyncAttributeDescriptorConfig nameCfg = exclJob1.getConfigFor(nameAd, true);
    nameCfg.setIncludedInSync(true); // +name
    SyncAttributeDescriptorConfig unitCfg = exclJob1.getConfigFor(unitAd, true);
    unitCfg.setIncludedInSync(false); // -unit

    final CatalogVersionSyncJob exclJob2 = createSyncJob("excl2", src, tgt, threads, true);
    exclJob2.setCreateNewItems(true); // don't create new items in full sync
    nameCfg = exclJob2.getConfigFor(nameAd, true);
    nameCfg.setIncludedInSync(false); // -name
    unitCfg = exclJob2.getConfigFor(unitAd, true);
    unitCfg.setIncludedInSync(true); // +unit

    // 1. run job1 -> no item should be copied

    final CatalogVersionSyncCronJob run1 = (CatalogVersionSyncCronJob) exclJob1.newExecution();
    exclJob1.configureFullVersionSync(run1);
    exclJob1.perform(run1, true);
    assertEquals(run1.getResult(), run1.getSuccessResult());

    assertNull(catalogManager.getCounterpartItem(product1, tgt));
    assertNull(catalogManager.getCounterpartItem(product2, tgt));
    assertNull(catalogManager.getCounterpartItem(product3, tgt));
    assertNull(catalogManager.getSynchronizedCopy(product1, exclJob1));
    assertNull(catalogManager.getSynchronizedCopy(product2, exclJob1));
    assertNull(catalogManager.getSynchronizedCopy(product3, exclJob1));

    // 2. run job2 -> now all products should be copied -> without name

    final CatalogVersionSyncCronJob run2 = (CatalogVersionSyncCronJob) exclJob2.newExecution();
    exclJob2.configureFullVersionSync(run2);
    exclJob2.perform(run2, true);
    assertEquals(run2.getResult(), run2.getSuccessResult());

    Product p1tgt = (Product) catalogManager.getSynchronizedCopy(product1, exclJob2);
    Product p2tgt = (Product) catalogManager.getSynchronizedCopy(product2, exclJob2);
    Product p3tgt = (Product) catalogManager.getSynchronizedCopy(product3, exclJob2);

    assertNotNull(p1tgt);
    assertNotNull(p2tgt);
    assertNotNull(p3tgt);
    assertNotSame(product1, p1tgt);
    assertNotSame(product2, p2tgt);
    assertNotSame(product3, p3tgt);

    assertEquals(product1.getCode(), p1tgt.getCode());
    assertEquals(product1.getUnit(), p1tgt.getUnit());
    assertNull(p1tgt.getName(deCtx));
    assertNull(p1tgt.getName(enCtx));

    assertEquals(product2.getCode(), p2tgt.getCode());
    assertEquals(product2.getUnit(), p2tgt.getUnit());
    assertNull(p2tgt.getName(deCtx));
    assertNull(p2tgt.getName(enCtx));

    assertEquals(product3.getCode(), p3tgt.getCode());
    assertEquals(product3.getUnit(), p3tgt.getUnit());
    assertNull(p3tgt.getName(deCtx));
    assertNull(p3tgt.getName(enCtx));

    List<ItemSyncTimestamp> p1ts = catalogManager.getSynchronizedCopies(product1);
    List<ItemSyncTimestamp> p2ts = catalogManager.getSynchronizedCopies(product2);
    List<ItemSyncTimestamp> p3ts = catalogManager.getSynchronizedCopies(product3);

    assertEquals(1, p1ts.size());
    assertEquals(1, p2ts.size());
    assertEquals(1, p3ts.size());

    final ItemSyncTimestamp itemSyncTimestamp1 = p1ts.get(0);
    final ItemSyncTimestamp itemSyncTimestamp2 = p2ts.get(0);
    final ItemSyncTimestamp itemSyncTimestamp3 = p3ts.get(0);

    assertEquals(src, itemSyncTimestamp1.getSourceVersion());
    assertEquals(tgt, itemSyncTimestamp1.getTargetVersion());
    assertEquals(product1, itemSyncTimestamp1.getSourceItem());
    assertEquals(p1tgt, itemSyncTimestamp1.getTargetItem());
    assertEquals(
        product1.getModificationTime(), itemSyncTimestamp1.getLastSyncSourceModifiedTime());
    assertEquals(false, itemSyncTimestamp1.isOutdatedAsPrimitive());
    assertEquals(exclJob2, itemSyncTimestamp1.getSyncJob());

    assertEquals(src, itemSyncTimestamp2.getSourceVersion());
    assertEquals(tgt, itemSyncTimestamp2.getTargetVersion());
    assertEquals(product2, itemSyncTimestamp2.getSourceItem());
    assertEquals(p2tgt, itemSyncTimestamp2.getTargetItem());
    assertEquals(
        product2.getModificationTime(), itemSyncTimestamp2.getLastSyncSourceModifiedTime());
    assertEquals(false, itemSyncTimestamp2.isOutdatedAsPrimitive());
    assertEquals(exclJob2, itemSyncTimestamp2.getSyncJob());

    assertEquals(src, itemSyncTimestamp3.getSourceVersion());
    assertEquals(tgt, itemSyncTimestamp3.getTargetVersion());
    assertEquals(product3, itemSyncTimestamp3.getSourceItem());
    assertEquals(p3tgt, itemSyncTimestamp3.getTargetItem());
    assertEquals(
        product3.getModificationTime(), itemSyncTimestamp3.getLastSyncSourceModifiedTime());
    assertEquals(false, itemSyncTimestamp3.isOutdatedAsPrimitive());
    assertEquals(exclJob2, itemSyncTimestamp3.getSyncJob());

    // 3. run job1 again -> now names should be copied as well

    final CatalogVersionSyncCronJob run3 = (CatalogVersionSyncCronJob) exclJob1.newExecution();
    exclJob1.configureFullVersionSync(run3);
    exclJob1.perform(run3, true);
    assertEquals(run3.getResult(), run3.getSuccessResult());

    p1tgt = (Product) catalogManager.getSynchronizedCopy(product1, exclJob1);
    p2tgt = (Product) catalogManager.getSynchronizedCopy(product2, exclJob1);
    p3tgt = (Product) catalogManager.getSynchronizedCopy(product3, exclJob1);

    assertEquals(product1.getCode(), p1tgt.getCode());
    assertEquals(product1.getUnit(), p1tgt.getUnit());
    assertEquals(product1.getName(deCtx), p1tgt.getName(deCtx));
    assertEquals(product1.getName(enCtx), p1tgt.getName(enCtx));

    assertEquals(product2.getCode(), p2tgt.getCode());
    assertEquals(product2.getUnit(), p2tgt.getUnit());
    assertEquals(product2.getName(deCtx), p2tgt.getName(deCtx));
    assertEquals(product2.getName(enCtx), p2tgt.getName(enCtx));

    assertEquals(product3.getCode(), p3tgt.getCode());
    assertEquals(product3.getUnit(), p3tgt.getUnit());
    assertEquals(product3.getName(deCtx), p3tgt.getName(deCtx));
    assertEquals(product3.getName(enCtx), p3tgt.getName(enCtx));

    p1ts = catalogManager.getSynchronizedCopies(product1);
    p2ts = catalogManager.getSynchronizedCopies(product2);
    p3ts = catalogManager.getSynchronizedCopies(product3);

    assertEquals(2, p1ts.size());
    assertEquals(2, p2ts.size());
    assertEquals(2, p3ts.size());

    final ItemSyncTimestamp t1j1 = getTS(p1ts, exclJob1);
    final ItemSyncTimestamp t1j2 = getTS(p1ts, exclJob2);

    ItemSyncTimestamp t2j1 = getTS(p2ts, exclJob1);
    ItemSyncTimestamp t2j2 = getTS(p2ts, exclJob2);

    final ItemSyncTimestamp t3j1 = getTS(p3ts, exclJob1);
    final ItemSyncTimestamp t3j2 = getTS(p3ts, exclJob2);

    assertNotNull(t1j1);
    assertNotNull(t1j2);
    assertNotSame(t1j1, t1j2);

    assertNotNull(t2j1);
    assertNotNull(t2j2);
    assertNotSame(t2j1, t2j2);

    assertNotNull(t3j1);
    assertNotNull(t3j2);
    assertNotSame(t3j1, t3j2);

    assertEquals(src, t1j1.getSourceVersion());
    assertEquals(tgt, t1j1.getTargetVersion());
    assertEquals(product1, t1j1.getSourceItem());
    assertEquals(p1tgt, t1j1.getTargetItem());
    assertEquals(product1.getModificationTime(), t1j1.getLastSyncSourceModifiedTime());
    assertEquals(false, t1j1.isOutdatedAsPrimitive());
    assertEquals(exclJob1, t1j1.getSyncJob());

    assertEquals(src, t1j2.getSourceVersion());
    assertEquals(tgt, t1j2.getTargetVersion());
    assertEquals(product1, t1j2.getSourceItem());
    assertEquals(p1tgt, t1j2.getTargetItem());
    assertEquals(product1.getModificationTime(), t1j2.getLastSyncSourceModifiedTime());
    assertEquals(false, t1j2.isOutdatedAsPrimitive());
    assertEquals(exclJob2, t1j2.getSyncJob());

    assertEquals(src, t2j1.getSourceVersion());
    assertEquals(tgt, t2j1.getTargetVersion());
    assertEquals(product2, t2j1.getSourceItem());
    assertEquals(p2tgt, t2j1.getTargetItem());
    assertEquals(product2.getModificationTime(), t2j1.getLastSyncSourceModifiedTime());
    assertEquals(false, t2j1.isOutdatedAsPrimitive());
    assertEquals(exclJob1, t2j1.getSyncJob());

    assertEquals(src, t2j2.getSourceVersion());
    assertEquals(tgt, t2j2.getTargetVersion());
    assertEquals(product2, t2j2.getSourceItem());
    assertEquals(p2tgt, t2j2.getTargetItem());
    assertEquals(product2.getModificationTime(), t2j2.getLastSyncSourceModifiedTime());
    assertEquals(false, t2j2.isOutdatedAsPrimitive());
    assertEquals(exclJob2, t2j2.getSyncJob());

    assertEquals(src, t3j1.getSourceVersion());
    assertEquals(tgt, t3j1.getTargetVersion());
    assertEquals(product3, t3j1.getSourceItem());
    assertEquals(p3tgt, t3j1.getTargetItem());
    assertEquals(product3.getModificationTime(), t3j1.getLastSyncSourceModifiedTime());
    assertEquals(false, t3j1.isOutdatedAsPrimitive());
    assertEquals(exclJob1, t3j1.getSyncJob());

    assertEquals(src, t3j2.getSourceVersion());
    assertEquals(tgt, t3j2.getTargetVersion());
    assertEquals(product3, t3j2.getSourceItem());
    assertEquals(p3tgt, t3j2.getTargetItem());
    assertEquals(product3.getModificationTime(), t3j2.getLastSyncSourceModifiedTime());
    assertEquals(false, t3j2.isOutdatedAsPrimitive());
    assertEquals(exclJob2, t3j2.getSyncJob());

    // sleep at least one seconds to avoid item having the same modification timestamp as before!!!
    try {
      Thread.sleep(1100);
    } catch (final InterruptedException e) {
      // ok
    }

    // now change name of one product
    product2.setName(enCtx, "foo");

    // 4. run job1 again -> should update name

    final CatalogVersionSyncCronJob run4 = (CatalogVersionSyncCronJob) exclJob1.newExecution();
    exclJob1.configureFullVersionSync(run4);
    exclJob1.perform(run4, true);
    assertEquals(run4.getResult(), run4.getSuccessResult());

    p2tgt = (Product) catalogManager.getSynchronizedCopy(product2, exclJob1);

    assertEquals(product2.getCode(), p2tgt.getCode());
    assertEquals(product2.getUnit(), p2tgt.getUnit());
    assertEquals(product2.getName(deCtx), p2tgt.getName(deCtx));
    assertEquals(product2.getName(enCtx), p2tgt.getName(enCtx));

    p2ts = catalogManager.getSynchronizedCopies(product2);

    assertEquals(2, p2ts.size());

    t2j1 = getTS(p2ts, exclJob1);
    t2j2 = getTS(p2ts, exclJob2);

    assertNotNull(t2j1);
    assertNotNull(t2j2);
    assertNotSame(t2j1, t2j2);

    assertEquals(src, t2j1.getSourceVersion());
    assertEquals(tgt, t2j1.getTargetVersion());
    assertEquals(product2, t2j1.getSourceItem());
    assertEquals(product2.getModificationTime(), t2j1.getLastSyncSourceModifiedTime());
    assertEquals(p2tgt, t2j1.getTargetItem());
    assertEquals(false, t2j1.isOutdatedAsPrimitive());
    assertEquals(exclJob1, t2j1.getSyncJob());

    assertEquals(src, t2j2.getSourceVersion());
    assertEquals(tgt, t2j2.getTargetVersion());
    assertEquals(product2, t2j2.getSourceItem());
    assertEquals(p2tgt, t2j2.getTargetItem());
    assertTrue(product2.getModificationTime().after(t2j2.getLastSyncSourceModifiedTime()));
    assertEquals(true, t2j2.isOutdatedAsPrimitive());
    assertEquals(exclJob2, t2j2.getSyncJob());

    // 5. run job2 again -> should update timestamp but change nothing else

    final CatalogVersionSyncCronJob run5 = (CatalogVersionSyncCronJob) exclJob2.newExecution();
    exclJob2.configureFullVersionSync(run5);
    exclJob2.perform(run5, true);
    assertEquals(run5.getResult(), run5.getSuccessResult());

    p2tgt = (Product) catalogManager.getSynchronizedCopy(product2, exclJob2);

    assertEquals(product2.getCode(), p2tgt.getCode());
    assertEquals(product2.getUnit(), p2tgt.getUnit());
    assertEquals(product2.getName(deCtx), p2tgt.getName(deCtx));
    assertEquals(product2.getName(enCtx), p2tgt.getName(enCtx));

    p2ts = catalogManager.getSynchronizedCopies(product2);

    assertEquals(2, p2ts.size());

    t2j1 = getTS(p2ts, exclJob1);
    t2j2 = getTS(p2ts, exclJob2);

    assertNotNull(t2j1);
    assertNotNull(t2j2);
    assertNotSame(t2j1, t2j2);

    assertEquals(src, t2j1.getSourceVersion());
    assertEquals(tgt, t2j1.getTargetVersion());
    assertEquals(product2, t2j1.getSourceItem());
    assertEquals(p2tgt, t2j1.getTargetItem());
    assertEquals(product2.getModificationTime(), t2j1.getLastSyncSourceModifiedTime());
    assertEquals(false, t2j1.isOutdatedAsPrimitive());
    assertEquals(exclJob1, t2j1.getSyncJob());

    assertEquals(src, t2j2.getSourceVersion());
    assertEquals(tgt, t2j2.getTargetVersion());
    assertEquals(product2, t2j2.getSourceItem());
    assertEquals(p2tgt, t2j2.getTargetItem());
    assertEquals(product2.getModificationTime(), t2j2.getLastSyncSourceModifiedTime());
    assertEquals(false, t2j2.isOutdatedAsPrimitive());
    assertEquals(exclJob2, t2j2.getSyncJob());
  }