/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.core.structure.menuitem; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import com.google.common.base.Preconditions; import com.enonic.cms.core.content.ContentKey; import com.enonic.cms.core.structure.menuitem.section.SectionContentEntity; /** * Oct 17, 2010 */ public class ContentsInSectionOrderer { public int orderSpace; private List<ContentKey> wantedOrder; private MenuItemEntity section; private final List<SectionContentEntity> approvedSectionContentsInWantedOrder = new ArrayList<SectionContentEntity>(); public ContentsInSectionOrderer( List<ContentKey> wantedOrder, MenuItemEntity section, int orderSpace ) { this.wantedOrder = wantedOrder; this.section = section; this.orderSpace = orderSpace; initializeSectionContentsInWantedOrder(); } private void initializeSectionContentsInWantedOrder() { final Map<ContentKey, SectionContentEntity> sectionContentsByContentKey = new HashMap<ContentKey, SectionContentEntity>(); for ( SectionContentEntity sectionContent : section.getSectionContents() ) { sectionContentsByContentKey.put( sectionContent.getContent().getKey(), sectionContent ); } for ( ContentKey contentKey : this.wantedOrder ) { SectionContentEntity currentSC = sectionContentsByContentKey.get( contentKey ); if ( currentSC != null && currentSC.isApproved() ) { approvedSectionContentsInWantedOrder.add( currentSC ); } } } public Set<SectionContentEntity> order() { final Set<SectionContentEntity> changedSectionContent = new HashSet<SectionContentEntity>(); if ( allHaveSameOrder( approvedSectionContentsInWantedOrder ) ) { resetOrder(); changedSectionContent.addAll( approvedSectionContentsInWantedOrder ); return changedSectionContent; } for ( int i = 0; i < approvedSectionContentsInWantedOrder.size(); i++ ) { final SectionContentEntity prevSC = i > 0 ? approvedSectionContentsInWantedOrder.get( i - 1 ) : null; final SectionContentEntity currSC = approvedSectionContentsInWantedOrder.get( i ); final SectionContentEntity nextSC = i < approvedSectionContentsInWantedOrder.size() - 1 ? approvedSectionContentsInWantedOrder.get( i + 1 ) : null; final SectionContentEntity nextNextSC = i < approvedSectionContentsInWantedOrder.size() - 2 ? approvedSectionContentsInWantedOrder.get( i + 2 ) : null; if ( !inOrder( prevSC, currSC, nextSC ) ) { // order no is after next one, must adjust this one int order; if ( prevSC == null ) { assert nextSC != null; order = nextSC.getOrder() - orderSpace; } else if ( nextSC == null ) { order = prevSC.getOrder() + orderSpace; } else { order = resolveNewOrderBetween( prevSC, nextSC ); int spaceBetweenPreviousOrderAndThisOrder = measureSpace( prevSC.getOrder(), order ); if ( nextNextSC != null && currSC.getOrder() > prevSC.getOrder() ) { int nextNewOrder = resolveNewOrderBetween( currSC, nextNextSC ); int spaceBetweenThisOrderAndNextNextOrder = measureSpace( currSC.getOrder(), nextNewOrder ); if ( spaceBetweenThisOrderAndNextNextOrder > spaceBetweenPreviousOrderAndThisOrder ) { // more space in between the next, so let us skip there.. continue; } } } if ( order != currSC.getOrder() ) { currSC.setOrder( order ); changedSectionContent.add( currSC ); } } } if ( !validOrderNumbers( approvedSectionContentsInWantedOrder ) ) { resetOrder(); changedSectionContent.addAll( approvedSectionContentsInWantedOrder ); } return changedSectionContent; } private int measureSpace( int orderA, int orderB ) { return orderB - orderA; } private boolean inOrder( final SectionContentEntity prevSC, final SectionContentEntity currSC, final SectionContentEntity nextSC ) { if ( prevSC != null && prevSC.getOrder() >= currSC.getOrder() ) { return false; } else if ( nextSC != null && nextSC.getOrder() <= currSC.getOrder() ) { return false; } return true; } private int resolveNewOrderBetween( SectionContentEntity prevSC, SectionContentEntity nextSC ) { Preconditions.checkNotNull( prevSC ); Preconditions.checkNotNull( nextSC ); if ( nextSC.getOrder() <= prevSC.getOrder() ) { return prevSC.getOrder() + orderSpace; } else { return resolveNewOrderBetween( prevSC.getOrder(), nextSC.getOrder() ); } } private int resolveNewOrderBetween( int orderPrev, int orderNext ) { int space = orderNext - orderPrev; int newOrder = orderPrev + ( space / 2 ); if ( !( newOrder > orderPrev && newOrder < orderNext ) ) { return orderPrev + orderSpace; } return newOrder; } private boolean validOrderNumbers( List<SectionContentEntity> sectionContents ) { Integer prevOrderNo = null; for ( SectionContentEntity sc : sectionContents ) { if ( prevOrderNo != null ) { if ( sc.getOrder() <= prevOrderNo ) { return false; } } prevOrderNo = sc.getOrder(); } return true; } private void resetOrder() { int prevOrderNo = 0; for ( SectionContentEntity sc : approvedSectionContentsInWantedOrder ) { int newOrder = prevOrderNo + orderSpace; sc.setOrder( newOrder ); prevOrderNo = newOrder; } } private boolean allHaveSameOrder( List<SectionContentEntity> list ) { if ( list.isEmpty() ) { return false; } else if ( list.size() == 1 ) { return false; } int currentOrder = list.get( 0 ).getOrder(); for ( int i = 1; i < list.size(); i++ ) { if ( currentOrder != list.get( i ).getOrder() ) { return false; } } return true; } }