/** * Copyright 2011-2017 Asakusa Framework Team. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.asakusafw.compiler.flow.stage; import java.text.MessageFormat; import java.util.List; import com.asakusafw.compiler.common.JavaName; import com.asakusafw.compiler.common.Precondition; import com.asakusafw.compiler.flow.Compilable; import com.asakusafw.compiler.flow.DataClass; import com.asakusafw.compiler.flow.ShuffleDescription; import com.asakusafw.compiler.flow.plan.StageBlock; import com.asakusafw.vocabulary.flow.graph.FlowElementInput; /** * Represents detail of shuffle actions. */ public class ShuffleModel extends Compilable.Trait<CompiledShuffle> { private final StageBlock stageBlock; private final List<Segment> segments; /** * Creates a new instance. * @param stageBlock the target stage block * @param segments the shuffle segments * @throws IllegalArgumentException if the parameters are {@code null} */ public ShuffleModel(StageBlock stageBlock, List<Segment> segments) { Precondition.checkMustNotBeNull(stageBlock, "stageBlock"); //$NON-NLS-1$ Precondition.checkMustNotBeNull(segments, "segments"); //$NON-NLS-1$ this.stageBlock = stageBlock; this.segments = segments; } /** * Returns the target stage block. * @return the target stage block */ public StageBlock getStageBlock() { return stageBlock; } /** * Returns the segments in the target shuffle operation. * @return the shuffle segments */ public List<Segment> getSegments() { return segments; } /** * Returns a shuffle segment. * @param input the target input port * @return the shuffle segment that corresponds to the input port, or {@code null} if there is no such a segment * @throws IllegalArgumentException if the parameter is {@code null} */ public Segment findSegment(FlowElementInput input) { Precondition.checkMustNotBeNull(input, "input"); //$NON-NLS-1$ for (Segment segment : getSegments()) { if (segment.getPort().equals(input)) { return segment; } } return null; } @Override public String toString() { return MessageFormat.format( "Shuffle({0})", //$NON-NLS-1$ segments); } /** * Represents a shuffle action for each shuffle input. */ public static class Segment extends Compilable.Trait<CompiledShuffleFragment> { private final int elementId; private final int portId; private final ShuffleDescription description; private final FlowElementInput port; private final DataClass source; private final DataClass target; private final List<Term> terms; /** * Creates a new instance. * @param elementId the target element ID of this segment * @param portId the target port ID of this segment * @param description description of this segment * @param port the target input port * @param source the input type * @param target the output type * @param terms the terms of this segment * @throws IllegalArgumentException if the parameters are {@code null} */ public Segment( int elementId, int portId, ShuffleDescription description, FlowElementInput port, DataClass source, DataClass target, List<Term> terms) { Precondition.checkMustNotBeNull(description, "description"); //$NON-NLS-1$ Precondition.checkMustNotBeNull(port, "port"); //$NON-NLS-1$ Precondition.checkMustNotBeNull(source, "source"); //$NON-NLS-1$ Precondition.checkMustNotBeNull(target, "target"); //$NON-NLS-1$ Precondition.checkMustNotBeNull(terms, "terms"); //$NON-NLS-1$ this.elementId = elementId; this.portId = portId; this.description = description; this.port = port; this.source = source; this.target = target; this.terms = terms; } /** * Returns the target element ID. * @return the target element ID */ public int getElementId() { return elementId; } /** * Returns the target port ID. * @return the target port ID */ public int getPortId() { return portId; } /** * Returns a description of this segment behavior. * @return the segment description */ public ShuffleDescription getDescription() { return description; } /** * Returns the original element port. * @return the original element port */ public FlowElementInput getPort() { return port; } /** * Returns the input type. * @return the input type */ public DataClass getSource() { return source; } /** * Returns the output type. * @return the output type */ public DataClass getTarget() { return target; } /** * Returns the terms of this segment. * @return the terms */ public List<Term> getTerms() { return terms; } /** * Returns a term of this segment. * @param propertyName the target property name * @return the term which is corresponded to the target property, or {@code null} if there is no such the term * @throws IllegalArgumentException if the parameter is {@code null} */ public Term findTerm(String propertyName) { Precondition.checkMustNotBeNull(propertyName, "propertyName"); //$NON-NLS-1$ if (propertyName.trim().isEmpty()) { return null; } String name = JavaName.of(propertyName).toMemberName(); for (Term term : terms) { if (term.getSource().getName().equals(name)) { return term; } } return null; } @Override public String toString() { return MessageFormat.format( "ShuffleSegment({2})(port={0}, terms={1})", //$NON-NLS-1$ port, terms, portId); } } /** * Represents individual key properties in shuffle {@link Segment}. */ public static class Term { private final int termId; private final DataClass.Property source; private final Arrangement arrangement; /** * Creates a new instance. * @param termId the serial number * @param source the target property * @param arrangement arrangement of the target property * @throws IllegalArgumentException if the parameters are {@code null} */ public Term( int termId, DataClass.Property source, Arrangement arrangement) { Precondition.checkMustNotBeNull(source, "source"); //$NON-NLS-1$ Precondition.checkMustNotBeNull(arrangement, "arrangement"); //$NON-NLS-1$ this.termId = termId; this.source = source; this.arrangement = arrangement; } /** * Returns the serial number of this term in the owner {@link Segment}. * @return the serial number */ public int getTermId() { return termId; } /** * Returns the target property. * @return the target property */ public DataClass.Property getSource() { return source; } /** * Returns arrangement of {@link #getSource() the target property}. * @return arrangement of the target property */ public Arrangement getArrangement() { return arrangement; } @Override public String toString() { return MessageFormat.format( "{0} {1}", //$NON-NLS-1$ getSource().getName(), getArrangement()); } } /** * Represents kinds of arrangement for each property. */ public enum Arrangement { /** * Only grouping by its property. */ GROUPING, /** * Sort by its property with ascending order. */ ASCENDING, /** * Sort by its property with descending order. */ DESCENDING, } }