diff --git a/src/com/massivecraft/massivecore/command/editor/CommandEditMap.java b/src/com/massivecraft/massivecore/command/editor/CommandEditMap.java new file mode 100644 index 00000000..a4c4d8ef --- /dev/null +++ b/src/com/massivecraft/massivecore/command/editor/CommandEditMap.java @@ -0,0 +1,28 @@ +package com.massivecraft.massivecore.command.editor; + +import com.massivecraft.massivecore.command.type.Type; + +import java.util.Map; + +public class CommandEditMap> extends CommandEditAbstract +{ + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public CommandEditMap(EditSettings settings, Property property, Type mapValueType) + { + // Super + super(settings, property, null); + + // Children + this.addChild(new CommandEditShow(settings, property)); + this.addChild(new CommandEditCreate(settings, property)); + this.addChild(new CommandEditDelete(settings, property)); + + this.addChild(new CommandEditMapPut(settings, property, mapValueType)); + this.addChild(new CommandEditMapRemove(settings, property, mapValueType)); + this.addChild(new CommandEditMapClear(settings, property, mapValueType)); + } + +} diff --git a/src/com/massivecraft/massivecore/command/editor/CommandEditMapAbstract.java b/src/com/massivecraft/massivecore/command/editor/CommandEditMapAbstract.java new file mode 100644 index 00000000..5fee944c --- /dev/null +++ b/src/com/massivecraft/massivecore/command/editor/CommandEditMapAbstract.java @@ -0,0 +1,112 @@ +package com.massivecraft.massivecore.command.editor; + +import com.massivecraft.massivecore.MassiveException; +import com.massivecraft.massivecore.command.requirement.RequirementEditorPropertyCreated; +import com.massivecraft.massivecore.command.type.Type; + +import java.util.Map; + +public abstract class CommandEditMapAbstract> extends CommandEditAbstract +{ + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public CommandEditMapAbstract(EditSettings settings, Property property, Type mapValueType) + { + // Super + super(settings, property, true); + this.setMapValueType(mapValueType); + + // Aliases + String alias = this.createCommandAlias(); + this.setAliases(alias); + + // Desc + this.setDesc(alias + " " + this.getPropertyName()); + + // Requirements + this.addRequirements(RequirementEditorPropertyCreated.get(true)); + } + + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // + + Type mapValueType = null; + public void setMapValueType(Type mapValueType) { this.mapValueType = mapValueType; } + + // -------------------------------------------- // + // SHORTCUTS > PROPERTY > TYPE + // -------------------------------------------- // + + // Only to be used with map type properties. + public Type getMapKeyType() + { + return this.getProperty().getValueType().getInnerType(); + } + + @SuppressWarnings("unchecked") + public Type getMapValueType() + { + return (Type) mapValueType; + } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @SuppressWarnings("unchecked") + @Override + public void perform() throws MassiveException + { + // Create + Map after = this.getShallowCopy(); + + // Alter + try + { + after = this.alter(after); + } + catch (MassiveException e) + { + throw e; + } + catch (Exception e) + { + throw new MassiveException().addMsg("%s", e.getMessage()); + } + + // Apply + this.attemptSet((V) after); + } + + // -------------------------------------------- // + // ABSTRACT + // -------------------------------------------- // + + public abstract Map alter(Map map) throws MassiveException; + + // -------------------------------------------- // + // UTIL + // -------------------------------------------- // + + @SuppressWarnings("unchecked") + public Map getShallowCopy() + { + // Create + V ret = this.getProperty().getRaw(this.getObject()); + if (ret == null) return null; + + // Fill + Map copy = (Map) this.getProperty().getValueType().createNewInstance(); + for (Map.Entry entry : ((Map) ret).entrySet()) + { + copy.put(entry.getKey(), entry.getValue()); + } + + // Return + return copy; + } + +} diff --git a/src/com/massivecraft/massivecore/command/editor/CommandEditMapClear.java b/src/com/massivecraft/massivecore/command/editor/CommandEditMapClear.java new file mode 100644 index 00000000..620edad4 --- /dev/null +++ b/src/com/massivecraft/massivecore/command/editor/CommandEditMapClear.java @@ -0,0 +1,34 @@ +package com.massivecraft.massivecore.command.editor; + +import com.massivecraft.massivecore.MassiveException; +import com.massivecraft.massivecore.command.type.Type; + +import java.util.Map; + +public class CommandEditMapClear> extends CommandEditMapAbstract +{ + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public CommandEditMapClear(EditSettings settings, Property property, Type mapValueType) + { + // Super + super(settings, property, mapValueType); + } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public Map alter(Map map) throws MassiveException + { + // Alter + map.clear(); + + // Return + return map; + } + +} diff --git a/src/com/massivecraft/massivecore/command/editor/CommandEditMapPut.java b/src/com/massivecraft/massivecore/command/editor/CommandEditMapPut.java new file mode 100644 index 00000000..5d753dae --- /dev/null +++ b/src/com/massivecraft/massivecore/command/editor/CommandEditMapPut.java @@ -0,0 +1,42 @@ +package com.massivecraft.massivecore.command.editor; + +import com.massivecraft.massivecore.MassiveException; +import com.massivecraft.massivecore.command.type.Type; + +import java.util.Map; + +public class CommandEditMapPut> extends CommandEditMapAbstract +{ + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public CommandEditMapPut(EditSettings settings, Property property, Type mapValueType) + { + // Super + super(settings, property, mapValueType); + + // Parameters + this.addParameter(this.getMapKeyType(), this.getMapKeyType().getTypeName()); + this.addParameter(this.getMapValueType(), this.getMapValueType().getTypeName()); + } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public Map alter(Map map) throws MassiveException + { + // Args + Object key = this.readArg(); + Object value = this.readArg(); + + // Alter + map.put(key, value); + + // Return + return map; + } + +} diff --git a/src/com/massivecraft/massivecore/command/editor/CommandEditMapRemove.java b/src/com/massivecraft/massivecore/command/editor/CommandEditMapRemove.java new file mode 100644 index 00000000..b01159c7 --- /dev/null +++ b/src/com/massivecraft/massivecore/command/editor/CommandEditMapRemove.java @@ -0,0 +1,40 @@ +package com.massivecraft.massivecore.command.editor; + +import com.massivecraft.massivecore.MassiveException; +import com.massivecraft.massivecore.command.type.Type; + +import java.util.Map; + +public class CommandEditMapRemove> extends CommandEditMapAbstract +{ + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public CommandEditMapRemove(EditSettings settings, Property property, Type mapValueType) + { + // Super + super(settings, property, mapValueType); + + // Parameters + this.addParameter(this.getMapKeyType(), this.getMapKeyType().getTypeName(), true); + } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public Map alter(Map map) throws MassiveException + { + // Args + Object key = this.readArg(); + + // Alter + map.remove(key); + + // Return + return map; + } + +} diff --git a/src/com/massivecraft/massivecore/command/editor/CommandEditShow.java b/src/com/massivecraft/massivecore/command/editor/CommandEditShow.java index 30ac72c5..ec506e3c 100644 --- a/src/com/massivecraft/massivecore/command/editor/CommandEditShow.java +++ b/src/com/massivecraft/massivecore/command/editor/CommandEditShow.java @@ -4,7 +4,7 @@ import java.util.Collection; import com.massivecraft.massivecore.MassiveException; -public class CommandEditShow> extends CommandEditAbstract +public class CommandEditShow extends CommandEditAbstract { // -------------------------------------------- // // CONSTRUCT diff --git a/src/com/massivecraft/massivecore/command/type/TypeAbstract.java b/src/com/massivecraft/massivecore/command/type/TypeAbstract.java index fdf3dae9..14355325 100644 --- a/src/com/massivecraft/massivecore/command/type/TypeAbstract.java +++ b/src/com/massivecraft/massivecore/command/type/TypeAbstract.java @@ -64,12 +64,12 @@ public abstract class TypeAbstract implements Type public , X extends Object> List getInnerTypes() { return (List) this.innerTypes; } @SuppressWarnings("unchecked") public Type getInnerType(int index) { return (Type) this.getInnerTypes().get(index); } - public Type getInnerType() { return this.getInnerType(0); }; + public Type getInnerType() { return this.getInnerType(0); } @SuppressWarnings({ "unchecked", "rawtypes" }) public void setInnerTypes(Collection> innerTypes) { this.innerTypes = new MassiveList(innerTypes); } public void setInnerTypes(Type... innerTypes) { this.setInnerTypes(Arrays.asList(innerTypes)); }; - public void setInnerType(Type innerType) { this.setInnerTypes(innerType); }; + public void setInnerType(Type innerType) { this.setInnerTypes(innerType); } // -------------------------------------------- // // WRITE VISUAL COLOR diff --git a/src/com/massivecraft/massivecore/command/type/collection/TypeMap.java b/src/com/massivecraft/massivecore/command/type/collection/TypeMap.java new file mode 100644 index 00000000..d4d75cd0 --- /dev/null +++ b/src/com/massivecraft/massivecore/command/type/collection/TypeMap.java @@ -0,0 +1,35 @@ +package com.massivecraft.massivecore.command.type.collection; + +import java.util.HashMap; +import java.util.Map; + +import com.massivecraft.massivecore.collections.MassiveMap; +import com.massivecraft.massivecore.command.type.Type; + +public class TypeMap extends TypeMapAbstract, K, V> +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + public static TypeMap get(Type keyType, Type valueType) + { + return new TypeMap(keyType, valueType); + } + + public TypeMap(Type keyType, Type valueType) + { + super(keyType, valueType); + } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public HashMap createNewInstance() + { + return new MassiveMap(); + } + +} diff --git a/src/com/massivecraft/massivecore/command/type/collection/TypeMapAbstract.java b/src/com/massivecraft/massivecore/command/type/collection/TypeMapAbstract.java new file mode 100644 index 00000000..cdc9d36b --- /dev/null +++ b/src/com/massivecraft/massivecore/command/type/collection/TypeMapAbstract.java @@ -0,0 +1,215 @@ +package com.massivecraft.massivecore.command.type.collection; + +import com.massivecraft.massivecore.MassiveException; +import com.massivecraft.massivecore.collections.MassiveList; +import com.massivecraft.massivecore.command.editor.CommandEditAbstract; +import com.massivecraft.massivecore.command.editor.CommandEditMap; +import com.massivecraft.massivecore.command.editor.EditSettings; +import com.massivecraft.massivecore.command.editor.Property; +import com.massivecraft.massivecore.command.type.Type; +import com.massivecraft.massivecore.command.type.TypeAbstract; +import com.massivecraft.massivecore.util.Txt; +import org.bukkit.command.CommandSender; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +public abstract class TypeMapAbstract, K, V> extends TypeAbstract +{ + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // + + private Type mapValueType = null; + public void setMapValueType(Type mapValueType) { this.mapValueType = mapValueType; } + public Type getMapValueType() { return mapValueType; } + + public void setMapKeyType(Type mapKeyType) { this.setInnerType(mapKeyType); } + public Type getMapKeyType() { return this.getInnerType(); } + + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public TypeMapAbstract(Type mapKeyType, Type mapValueType) + { + this.setMapKeyType(mapKeyType); + this.setMapValueType(mapValueType); + } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public String getTypeName() + { + return "Map: " + this.getMapKeyType().getTypeName() + " -> " + this.getMapValueType().getTypeName(); + } + + @Override + public String getVisualInner(C value, CommandSender sender) + { + // Empty + if (value.isEmpty()) return EMPTY; + + List parts = new MassiveList(); + + for (Entry entry : value.entrySet()) + { + K entryKey = entry.getKey(); + String visualKey = this.getMapKeyType().getVisual(entryKey, sender); + + V entryValue = entry.getValue(); + String visualValue = this.getMapValueType().getVisual(entryValue, sender); + + String part = Txt.parse("%s: %s", visualKey, visualValue); + parts.add(part); + } + + return Txt.implode(parts, "\n"); + } + + @Override + public String getNameInner(C value) + { + // Empty + if (value.isEmpty()) return EMPTY; + + // Create + StringBuilder builder = new StringBuilder(); + boolean first = true; + + // Fill + for (Entry entry : value.entrySet()) + { + if ( ! first) builder.append(", "); + + // Append key + K entryKey = entry.getKey(); + builder.append(this.getInnerType().getName(entryKey)); + + // Add Colon & Space + builder.append(':'); + builder.append(' '); + + // Append value + V entryValue = entry.getValue(); + builder.append(this.getMapValueType().getName(entryValue)); + first = false; + } + + // Return + return builder.toString(); + } + + @Override + public String getIdInner(C value) + { + // Empty + if (value.isEmpty()) return EMPTY; + + // Create + StringBuilder builder = new StringBuilder(); + boolean first = true; + + // Fill + for (Entry entry : value.entrySet()) + { + if ( ! first) builder.append(", "); + + // Append key + K entryKey = entry.getKey(); + builder.append(this.getInnerType().getId(entryKey)); + + // Add Colon & Space + builder.append(':'); + builder.append(' '); + + // Append value + V entryValue = entry.getValue(); + builder.append(this.getMapValueType().getId(entryValue)); + first = false; + } + + // Return + return builder.toString(); + } + + @Override + public C read(String arg, CommandSender sender) throws MassiveException + { + // Create + C ret = this.createNewInstance(); + + // Prepare + List args = new MassiveList<>(Txt.PATTERN_WHITESPACE.split(arg)); + if (args.size() % 2 != 0) + { + throw new MassiveException().setMsg("There must be an even amount of arguments for a map."); + } + + // Fill + for (Iterator it = args.iterator(); it.hasNext(); ) + { + // Get Key + String keyString = it.next(); + K key = this.getMapKeyType().read(keyString, sender); + + // Get Value + String valueString = it.next(); + V value = this.getMapValueType().read(valueString, sender); + + ret.put(key, value); + } + + // Return + return ret; + } + + @Override + public Collection getTabList(CommandSender sender, String arg) + { + // Because we accept multiple arguments pairs of the same type. + // The passed arg might be more than one. We only want the latest. + List args = TypeCollection.getArgs(arg); + String lastArg = args.isEmpty() ? null : args.get(args.size() - 1); + + // Type + Type type = args.size() % 2 == 1 ? this.getMapKeyType() : this.getMapValueType(); + + // Return + return type.getTabList(sender, lastArg); + } + + @Override + public List getTabListFiltered(CommandSender sender, String arg) + { + // Because we accept multiple arguments pairs of the same type. + // The passed arg might be more than one. We only want the latest. + List args = TypeCollection.getArgs(arg); + String lastArg = args.isEmpty() ? null : args.get(args.size() - 1); + + // Type + Type type = args.size() % 2 == 1 ? this.getMapKeyType() : this.getMapValueType(); + + // Return + return type.getTabListFiltered(sender, lastArg); + } + + @Override + public boolean allowSpaceAfterTab() + { + return this.getMapKeyType().allowSpaceAfterTab() && this.getMapValueType().allowSpaceAfterTab(); + } + + @Override + public CommandEditAbstract createEditCommand(EditSettings settings, Property property) + { + return new CommandEditMap(settings, property, this.getMapValueType()); + } + +}