001package org.clafer.ast.analysis;
002
003import java.util.HashMap;
004import java.util.Map;
005import org.clafer.ast.AstAbstractClafer;
006import org.clafer.ast.AstConcreteClafer;
007import org.clafer.ast.Card;
008
009/**
010 * Rewrites the model replacing unbounded high cardinalities with bounded
011 * effective high cardinalities.
012 *
013 * @author jimmy
014 */
015public class CardAnalyzer implements Analyzer {
016
017    @Override
018    public Analysis analyze(Analysis analysis) {
019        Map<AstConcreteClafer, Card> cardMap = new HashMap<>();
020        cardMap.put(analysis.getModel(), new Card(1, 1));
021        for (AstAbstractClafer abstractClafer : analysis.getAbstractClafers()) {
022            analyze(abstractClafer, cardMap, analysis);
023        }
024        for (AstConcreteClafer child : analysis.getModel().getChildren()) {
025            analyze(child, 1, cardMap, analysis);
026        }
027        return analysis.setCardMap(cardMap);
028    }
029
030    private static void analyze(AstAbstractClafer clafer, Map<AstConcreteClafer, Card> cardMap, Analysis analysis) {
031        Card globalCard = analysis.getGlobalCard(clafer);
032        for (AstConcreteClafer child : clafer.getChildren()) {
033            analyze(child, globalCard.getLow(), cardMap, analysis);
034        }
035    }
036
037    private static void analyze(AstConcreteClafer clafer, int parentlowGlobalCard, Map<AstConcreteClafer, Card> cardMap, Analysis analysis) {
038        int low = analysis.getCard(clafer).getLow();
039        int high = analysis.getCard(clafer).getHigh();
040        Card globalCard = analysis.getGlobalCard(clafer);
041
042        int evenlyDistributed = parentlowGlobalCard * low;
043        int rest = globalCard.getHigh() - evenlyDistributed;
044        cardMap.put(clafer, new Card(low, Math.min(high, low + rest)));
045
046        for (AstConcreteClafer child : clafer.getChildren()) {
047            analyze(child, globalCard.getLow(), cardMap, analysis);
048        }
049    }
050}