Ajout de la nature Gradle au projet.

Déplacement des classes «Util» de Murderator ici.
Changement de la librairie Yaml pour eo-yaml
Écriture du début du configurator.
This commit is contained in:
Mysaa 2021-07-04 15:02:56 +02:00
parent 40430271a7
commit a369ab678f
13 changed files with 537 additions and 41 deletions

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ bin/
.classpath
.settings
.project
/.directory

View File

@ -1,31 +1,10 @@
/*
* This build file was generated by the Gradle 'init' task.
*
* This generated file contains a commented-out sample Java project to get you started.
* For more details take a look at the Java Quickstart chapter in the Gradle
* user guide available at https://docs.gradle.org/4.4.1/userguide/tutorial_java_projects.html
*/
/*
// Apply the java plugin to add support for Java
apply plugin: 'java'
// In this section you declare where to find the dependencies of your project
repositories {
// Use 'jcenter' for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
// In this section you declare the dependencies for your production and test code
dependencies {
// The production code uses the SLF4J logging API at compile time
compile 'org.slf4j:slf4j-api:1.7.25'
// Declare the dependency for your favourite test framework you want to use in your tests.
// TestNG is also supported by the Gradle Test task. Just change the
// testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add
// 'test.useTestNG()' to your build script.
testCompile 'junit:junit:4.12'
implementation 'com.amihaiemil.web:eo-yaml:5.2.1'
}
*/

View File

@ -0,0 +1,100 @@
package com.bernard.configurator;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import com.amihaiemil.eoyaml.Yaml;
import com.amihaiemil.eoyaml.YamlInput;
import com.amihaiemil.eoyaml.YamlMappingBuilder;
import com.amihaiemil.eoyaml.YamlNode;
import com.bernard.configurator.annotations.ConfigClass;
import com.bernard.configurator.annotations.Option;
import com.bernard.util.ParseUtils;
public class Configurator {
private static Map<Class<?>,YamlInterface> yamlInterfaces = new HashMap<>();
public static void genInterfaces() {
yamlInterfaces.put(null, null);
}
public static YamlNode objectToNode(Object o) {
Class<?> theClass = o.getClass();
if(yamlInterfaces.containsKey(theClass)) {
return yamlInterfaces.get(theClass).writeToNode(o);
}else {
ConfigClass configClass = theClass.getAnnotation(ConfigClass.class);
if(configClass!=null) {
// On fait un mapping
YamlMappingBuilder ymb = Yaml.createYamlMappingBuilder();
ymb = ymb.add("class", theClass.getName());
Field[] fields = theClass.getFields(); //Seulement les accéssibles
for(Field f : fields) {
try {
Option option = f.getAnnotation(Option.class);
if(option!=null) {
if(option.yamlInterface() != YamlInterface.class) {
YamlInterface theInterface;
theInterface = option.yamlInterface().getConstructor().newInstance();
String name;
if(option.name().isBlank())
name = f.getName();
else
name = option.name();
ymb = ymb.add(name, theInterface.writeToNode(f.get(o)));
continue;
}
//On ne continue pas, même traitement que sans option
}else {
if(configClass.requireOption())
continue;
}
//Traitement récursif
ymb = ymb.add(f.getName(), objectToNode(f.get(o)));
} catch (InstantiationException
| IllegalAccessException
| IllegalArgumentException
| InvocationTargetException
| NoSuchMethodException
| SecurityException e) {
e.printStackTrace();
}
}
return ymb.build();
}else if(Serializable.class.isAssignableFrom(theClass)) {
// On a pas réussi à faire proprement, on va dump la version sérialisée en base 64
String toWrite = ParseUtils.toBase64((Serializable) o);
return Yaml.createYamlScalarBuilder()
.addLine(toWrite)
.buildFoldedBlockScalar("Objet écrit en base 64");
}else {
//XXX: prévenir peut-être
}
}
return null;
}
public static <T> T readYaml(YamlInput in, Class<? extends T> outClass) {
return null;
}
}

View File

@ -0,0 +1,11 @@
package com.bernard.configurator;
import com.amihaiemil.eoyaml.YamlNode;
public interface YamlInterface {
YamlNode writeToNode(Object o);
Object readNode(YamlNode node);
}

View File

@ -0,0 +1,12 @@
package com.bernard.configurator.annotations;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Target;
@Target(TYPE)
public @interface ConfigClass {
boolean requireOption() default false;
}

View File

@ -0,0 +1,13 @@
package com.bernard.configurator.annotations;
import static java.lang.annotation.ElementType.FIELD;
import java.lang.annotation.Target;
import java.util.function.Predicate;
@Target(FIELD)
public @interface Contrainte {
Class<? extends Predicate<?>> c();
}

View File

@ -0,0 +1,22 @@
package com.bernard.configurator.annotations;
import static java.lang.annotation.ElementType.FIELD;
import java.lang.annotation.Target;
import com.bernard.configurator.YamlInterface;
@Target(FIELD)
public @interface Option {
//TODO: Pour l'instant, cette valeur est inutilisée
//Vide indique d'utiliser la valeur par défaut
String path() default "";
//Cette valeur indique d'utiliser le nom du champ
String name() default "";
//Cette valeur indique d'utiliser la map du Configurator
Class<? extends YamlInterface> yamlInterface() default YamlInterface.class;
}

View File

@ -0,0 +1,36 @@
package com.bernard.util;
import java.nio.ByteBuffer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.Stream.Builder;
public class BytesUtils {
public static String readString(ByteBuffer buffer) {
int stringLength = buffer.getInt();
byte[] stringData = new byte[stringLength];
buffer.get(stringData);
return new String(stringData);
}
public static void writeString(ByteBuffer buffer, String s) {
byte[] data = s.getBytes();
buffer.putInt(data.length);
buffer.put(data);
}
public static Stream<Byte> toStream(ByteBuffer buffer){
Builder<Byte> bldr = Stream.builder();
for(Byte b: buffer.array())
bldr.add(b);
return bldr.build();
}
public static void dump(ByteBuffer buffer) {
System.out.println(toStream(buffer).limit(buffer.position()).map(b -> Integer.toString(Byte.toUnsignedInt(b))).collect(Collectors.joining(",")));
}
}

View File

@ -10,7 +10,8 @@ import java.io.FileNotFoundException;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import org.ho.yaml.Yaml;
import com.amihaiemil.eoyaml.Yaml;
import com.amihaiemil.eoyaml.YamlInput;
public abstract class ConfiguredFrame<Configuration> extends JFrame implements ActionListener {
@ -18,8 +19,8 @@ public abstract class ConfiguredFrame<Configuration> extends JFrame implements A
* Just for eclipse to shut up
*/
private static final long serialVersionUID = -2440841592914910177L;
private final String defaultConfigPath = "config.yml";
private Configuration config = getConfig();
//private final String defaultConfigPath = "config.yml";
//private YamlInput config = getConfig();
private Class<?> configurationClass;
public ConfiguredFrame(String title,int width,int height,Class<?> configClass) {
@ -51,26 +52,27 @@ public abstract class ConfiguredFrame<Configuration> extends JFrame implements A
return "config.yml";
}
@SuppressWarnings("unchecked")//Les tests sont faits
public Configuration getConfig(){
//Les tests sont faits
@SuppressWarnings("deprecation")
public YamlInput getConfig(){
File configFile = new File(getConfigPath());
if(configFile.exists()){
Configuration out;
YamlInput out;
try {
out = (Configuration)Yaml.load(configFile);
out = Yaml.createYamlInput(configFile);
return out;
} catch (FileNotFoundException e) {//TODO add others errors witch need to be catched
error("Fichier non trouvé", "Le fichier n'a pas été trouvé");
error("Fichier non trouv<EFBFBD>", "Le fichier n'a pas <20>t<EFBFBD> trouv<75>");
}catch(ClassCastException e){
error("Fichier corrompu","Le fichier de configuration (\""+configFile.getPath()+"\") est corrompu : supprimez ou remplacez le");
}
}else{
try {
return (Configuration) configurationClass.newInstance();
return (YamlInput) configurationClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
error("Impossible de créer le fichier de configuration","La configuration n'a pas pu être créée : verifiez que le paramêtre configClass représente une classe accessible et instanciable sans arguments.");
error("Impossible de cr<EFBFBD>er le fichier de configuration","La configuration n'a pas pu <EFBFBD>tre cr<63><72>e : verifiez que le param<61>tre configClass repr<70>sente une classe accessible et instanciable sans arguments.");
} catch (ClassCastException e) {
error("Non correspondance","Le type génerique \"Configuration\" et l'objet configurationClass ne correspondent pas");
error("Non correspondance","Le type g<EFBFBD>nerique \"Configuration\" et l'objet configurationClass ne correspondent pas");
}
}
return null;
@ -82,11 +84,11 @@ public abstract class ConfiguredFrame<Configuration> extends JFrame implements A
}
public void end(){
try {
Yaml.dump(config, new File(defaultConfigPath));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// try {
// Yaml.dump(config, new File(defaultConfigPath));
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// }
}
@Override

View File

@ -11,11 +11,11 @@ public class ErrorDialog extends JDialog{
*/
private static final long serialVersionUID = 5223556105926415144L;
private Exception exception;
//private Exception exception;
public ErrorDialog(Exception e,Frame f) {
super(f,"A "+e.getClass().getName()+" occured",true);
exception = e;
//exception = e;
this.setDefaultCloseOperation(JDialog.EXIT_ON_CLOSE);
this.setSize(500, 200);
this.setResizable(false);

View File

@ -0,0 +1,12 @@
package com.bernard.util;
import java.util.function.Function;
public class FuncUtils {
public static final <A,B,C> Function<A,C> compose(Function<B,C> f,Function<? super A,? extends B> g) {
return f.compose(g);
}
}

View File

@ -0,0 +1,184 @@
package com.bernard.util;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.time.Instant;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.Collection;
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import com.amihaiemil.eoyaml.Yaml;
import com.amihaiemil.eoyaml.YamlMapping;
import com.amihaiemil.eoyaml.YamlMappingBuilder;
import com.amihaiemil.eoyaml.YamlNode;
import com.amihaiemil.eoyaml.YamlSequence;
import com.amihaiemil.eoyaml.YamlSequenceBuilder;
public class ParseUtils {
static Pattern timeLengthPattern = Pattern.compile("^(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s?)?$");
public static long parseTimeLength(String tl) {
Matcher mtch = timeLengthPattern.matcher(tl);
if(!mtch.matches())throw new IllegalArgumentException("La chaine de caractères «"+tl+"» ne décrit pas un intervalle de temps normalisé");
int h = mtch.group(2)==null?0:Integer.parseInt(mtch.group(2));
int m = mtch.group(4)==null?0:Integer.parseInt(mtch.group(4));
int s = mtch.group(6)==null?0:Integer.parseInt(mtch.group(6));
return (h*3600+m*60+s)*1000;
}
public static <T> T watch(T el) {
System.out.println(el);
return el;
}
public static String dumpTimeLength(long t) {
long h=t/1000/3600, m=t/1000/60%60, s=t/1000%60;
return (h!=0?h+"h":"" )+ (m!=0?m+"m":"")+(s!=0?s+"s":"");
}
public static String dumpHourDate(long t) {
return DateTimeFormatter.ISO_LOCAL_TIME.format(LocalTime.ofInstant(Instant.ofEpochMilli(t-t%1000), ZoneId.systemDefault()));
}
public static <T> Set<T> union(Collection<T> c1, Collection<T> c2){
Set<T> out = c1.stream().collect(Collectors.toSet());
out.addAll(c2);
return out;
}
public static boolean isSubWord(String word, String subword) {
int i=0,j=0;
while(true) {
if(i==subword.length())return true;
if(j==word.length())return false;
if(subword.charAt(i)==word.charAt(j))i++;
j++;
}
}
public static boolean and(boolean[] bb) {
for(boolean b : bb)
if(!b)return false;
return true;
}
public static Set<String> mappingStringKeys(YamlMapping mapping) throws IOException{
return mapping.keys().stream().map(n ->n.asScalar().value()).collect(Collectors.toSet());
}
public static Stream<YamlNode> sequenceStream(YamlSequence sequence){
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(sequence.iterator(),Spliterator.ORDERED),false);
}
public static <T> Function<YamlNode,T> wetherMapping(Function<YamlNode,T> fnot,Function<YamlMapping,T> fyes){
return n -> (n instanceof YamlMapping)?fyes.apply((YamlMapping)n):fnot.apply(n);
}
public static Color randColor() {
return Color.getHSBColor((float) Math.random(), 1.0f, 1.0f);
}
public static Color randDarkColor() {
return Color.getHSBColor((float) Math.random(), 1.0f, 0.3f);
}
public static Color randDarkBlueColor() {
// 180° to 240°
return Color.getHSBColor( (float) (0.5f + 0.2f*Math.random()), 1.0f, 0.3f);
}
public static Color getContrastColor(Color color) {
double y = (299 * color.getRed() + 587 * color.getGreen() + 114 * color.getBlue()) / 1000;
return y >= 128 ? Color.black : Color.white;
}
public static final <M> YamlMapping setToMapSS(Set<M> nodes, Function<M,String> key, Function<M,String> value) {
YamlMappingBuilder builder = Yaml.createYamlMappingBuilder();
for(M n : nodes)
builder = builder.add(key.apply(n), value.apply(n));
return builder.build();
}
public static final <M> YamlMapping setToMapSY(Set<M> nodes, Function<M,String> key, Function<M,YamlNode> value) {
YamlMappingBuilder builder = Yaml.createYamlMappingBuilder();
for(M n : nodes)
builder = builder.add(key.apply(n), value.apply(n));
return builder.build();
}
public static final <M> YamlMapping setToMapYS(Set<M> nodes, Function<M,YamlNode> key, Function<M,String> value) {
YamlMappingBuilder builder = Yaml.createYamlMappingBuilder();
for(M n : nodes)
builder = builder.add(key.apply(n), value.apply(n));
return builder.build();
}
public static final <M> YamlMapping setToMapYY(Set<M> nodes, Function<M,YamlNode> key, Function<M,YamlNode> value) {
YamlMappingBuilder builder = Yaml.createYamlMappingBuilder();
for(M n : nodes)
builder = builder.add(key.apply(n), value.apply(n));
return builder.build();
}
public static final <M> YamlSequence setToSeqY(Set<YamlNode> nodes) {
YamlSequenceBuilder builder = Yaml.createYamlSequenceBuilder();
for(YamlNode n : nodes)
builder = builder.add(n);
return builder.build();
}
public static final <M> YamlSequence setToSeqS(Set<String> nodes) {
YamlSequenceBuilder builder = Yaml.createYamlSequenceBuilder();
for (String n : nodes)
builder = builder.add(n);
return builder.build();
}
public static final Object fromBase64(String s) throws ClassNotFoundException {
try {
byte[] data = Base64.getDecoder().decode(s);
ObjectInputStream ois;
ois = new ObjectInputStream(new ByteArrayInputStream(data));
Object o = ois.readObject();
ois.close();
return o;
} catch (IOException e) {
System.err.println("Erreur dans la lecture de la chaine de caractères");
e.printStackTrace();
}
return null;
}
public static final String toBase64(Serializable o) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos;
oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
return Base64.getEncoder().encodeToString(baos.toByteArray());
} catch (IOException e) {
System.err.println("Erreur dans l'écriture de la chaine de caractères");
e.printStackTrace();
}
return null;
}
}

View File

@ -0,0 +1,124 @@
package com.bernard.util;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import com.amihaiemil.eoyaml.Yaml;
import com.amihaiemil.eoyaml.YamlMapping;
import com.amihaiemil.eoyaml.YamlMappingBuilder;
import com.amihaiemil.eoyaml.YamlNode;
import com.amihaiemil.eoyaml.YamlSequence;
import com.amihaiemil.eoyaml.YamlSequenceBuilder;
public class YamlUtils {
public static final YamlSequence listToSeq(List<YamlNode> nodes) {
YamlSequenceBuilder ysb = Yaml.createYamlSequenceBuilder();
for(YamlNode n : nodes)
ysb = ysb.add(n);
return ysb.build();
}
public static final YamlSequence listToSeqString(List<String> nodes) {
YamlSequenceBuilder ysb = Yaml.createYamlSequenceBuilder();
for(String n : nodes)
ysb = ysb.add(n);
return ysb.build();
}
public static final YamlMapping mapToMapping(Map<YamlNode,YamlNode> nodes) {
YamlMappingBuilder ysb = Yaml.createYamlMappingBuilder();
for(Entry<YamlNode, YamlNode> n : nodes.entrySet())
ysb = ysb.add(n.getKey(),n.getValue());
return ysb.build();
}
public static final <A,B> YamlMapping mapToMapping(Map<A,B> map,Function<A,YamlNode> fKey,Function<B,YamlNode> fVal) {
YamlMappingBuilder ysb = Yaml.createYamlMappingBuilder();
for(Entry<A,B> e : map.entrySet())
ysb.add(fKey.apply(e.getKey()), fVal.apply(e.getValue()));
return ysb.build();
}
public static final YamlNode scalar(Object in) {
return Yaml.createYamlScalarBuilder().addLine(in.toString()).buildPlainScalar();
}
public static final YamlNode foldedScalar(String in) {
return Yaml.createYamlScalarBuilder().addLine(in).buildFoldedBlockScalar();
}
public static final YamlSequenceBuilder seqMerge(YamlSequenceBuilder ysba,YamlSequenceBuilder ysbb) {
for(YamlNode na : ysba.build().values())
ysbb = ysbb.add(na);
return ysbb;
}
public static final CollectorImpl<YamlNode, YamlSequenceBuilder, YamlSequence> sequenceCollector =
new CollectorImpl<>(
Yaml::createYamlSequenceBuilder,
YamlSequenceBuilder::add,
YamlUtils::seqMerge,
YamlSequenceBuilder::build,
Set.of(Collector.Characteristics.UNORDERED));
/**
* (Copied from Collectors class)
* Simple implementation class for {@code Collector}.
*
* @param <T> the type of elements to be collected
* @param <R> the type of the result
*/
static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
private final Supplier<A> supplier;
private final BiConsumer<A, T> accumulator;
private final BinaryOperator<A> combiner;
private final Function<A, R> finisher;
private final Set<Characteristics> characteristics;
CollectorImpl(Supplier<A> supplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Function<A,R> finisher,
Set<Characteristics> characteristics) {
this.supplier = supplier;
this.accumulator = accumulator;
this.combiner = combiner;
this.finisher = finisher;
this.characteristics = characteristics;
}
@Override
public BiConsumer<A, T> accumulator() {
return accumulator;
}
@Override
public Supplier<A> supplier() {
return supplier;
}
@Override
public BinaryOperator<A> combiner() {
return combiner;
}
@Override
public Function<A, R> finisher() {
return finisher;
}
@Override
public Set<Characteristics> characteristics() {
return characteristics;
}
}
}