001/*
002 * Trident - A Multithreaded Server Alternative
003 * Copyright 2014 The TridentSDK Team
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package net.tridentsdk.server.data;
019
020import com.google.common.collect.Lists;
021import io.netty.buffer.ByteBuf;
022import net.tridentsdk.docs.Policy;
023import net.tridentsdk.server.netty.Codec;
024import net.tridentsdk.util.ArrayTool;
025
026import java.util.Collection;
027
028/**
029 * Builds the property attributes for entity packets
030 *
031 * @author The TridentSDK Team
032 */
033public class PropertyBuilder implements Writable {
034    private String key;
035    private double value;
036    @Policy(Policy.VOLATILE_ARRAY)
037    private volatile String[] modifiers;
038
039    /**
040     * Creates a 0 length property array
041     */
042    public PropertyBuilder() {
043        this.modifiers = new String[] { };
044    }
045
046    /**
047     * Creates a property array with the specified size
048     *
049     * @param size the size of the property array
050     */
051    public PropertyBuilder(int size) {
052        this.modifiers = new String[size];
053    }
054
055    /**
056     * The key of the property
057     *
058     * @return the property key
059     */
060    public String key() {
061        return this.key;
062    }
063
064    /**
065     * Sets the key of the property builder
066     *
067     * @param key the key to set
068     * @return the current instance
069     */
070    public PropertyBuilder setKey(String key) {
071        this.key = key;
072
073        return this;
074    }
075
076    /**
077     * Gets the value of the property builder
078     *
079     * @return the value of this property
080     */
081    public double value() {
082        return this.value;
083    }
084
085    /**
086     * Sets the value of the property builder
087     *
088     * @param value the value to set
089     * @return the current instance
090     */
091    public PropertyBuilder setValue(double value) {
092        this.value = value;
093
094        return this;
095    }
096
097    /**
098     * Gets the property array wrapped by the builder
099     *
100     * @return the property array
101     */
102    public String[] modifiers() {
103        return this.modifiers.clone();
104    }
105
106    /**
107     * Puts an attribute property at the given index
108     *
109     * @param index    the index to place the property at
110     * @param modifier the property to place
111     * @return the current instance
112     */
113    public PropertyBuilder addModifier(int index, String modifier) {
114        String[] modifiers = this.modifiers;
115        modifiers[index] = modifier;
116        String[] read = this.modifiers; // Flush caches, make entire array visible
117
118        return this;
119    }
120
121    /**
122     * Removes all null elements in the property array
123     *
124     * @return the current instance
125     */
126    public PropertyBuilder cleanup() {
127        Collection<String> list = Lists.newArrayList();
128
129        for (String value : this.modifiers) {
130            if (value != null) {
131                list.add(value);
132            }
133        }
134
135        this.modifiers = ArrayTool.using(list.toArray()).convertTo(String.class);
136        return this;
137    }
138
139    @Override
140    public void write(ByteBuf buf) {
141        this.cleanup();
142
143        Codec.writeString(buf, this.key);
144        buf.writeDouble(this.value);
145        Codec.writeVarInt32(buf, this.modifiers.length);
146
147        for (String s : this.modifiers)
148            Codec.writeString(buf, s);
149    }
150}