From a369ab678f655ec999e13f683f79000d553c49cf Mon Sep 17 00:00:00 2001 From: Mysaa Date: Sun, 4 Jul 2021 15:02:56 +0200 Subject: [PATCH] Ajout de la nature Gradle au projet. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Déplacement des classes «Util» de Murderator ici. Changement de la librairie Yaml pour eo-yaml Écriture du début du configurator. --- .gitignore | 1 + build.gradle | 25 +-- .../bernard/configurator/Configurator.java | 100 ++++++++++ .../bernard/configurator/YamlInterface.java | 11 ++ .../configurator/annotations/ConfigClass.java | 12 ++ .../configurator/annotations/Contrainte.java | 13 ++ .../configurator/annotations/Option.java | 22 +++ src/com/bernard/util/BytesUtils.java | 36 ++++ src/com/bernard/util/ConfiguredFrame.java | 34 ++-- src/com/bernard/util/ErrorDialog.java | 4 +- src/com/bernard/util/FuncUtils.java | 12 ++ src/com/bernard/util/ParseUtils.java | 184 ++++++++++++++++++ src/com/bernard/util/YamlUtils.java | 124 ++++++++++++ 13 files changed, 537 insertions(+), 41 deletions(-) create mode 100644 src/com/bernard/configurator/Configurator.java create mode 100644 src/com/bernard/configurator/YamlInterface.java create mode 100644 src/com/bernard/configurator/annotations/ConfigClass.java create mode 100644 src/com/bernard/configurator/annotations/Contrainte.java create mode 100644 src/com/bernard/configurator/annotations/Option.java create mode 100755 src/com/bernard/util/BytesUtils.java create mode 100644 src/com/bernard/util/FuncUtils.java create mode 100644 src/com/bernard/util/ParseUtils.java create mode 100755 src/com/bernard/util/YamlUtils.java diff --git a/.gitignore b/.gitignore index 7a3c30a..5ed2000 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ bin/ .classpath .settings .project +/.directory diff --git a/build.gradle b/build.gradle index 2d8b653..af60479 100644 --- a/build.gradle +++ b/build.gradle @@ -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' } -*/ diff --git a/src/com/bernard/configurator/Configurator.java b/src/com/bernard/configurator/Configurator.java new file mode 100644 index 0000000..f47d297 --- /dev/null +++ b/src/com/bernard/configurator/Configurator.java @@ -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,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 readYaml(YamlInput in, Class outClass) { + return null; + } + + +} diff --git a/src/com/bernard/configurator/YamlInterface.java b/src/com/bernard/configurator/YamlInterface.java new file mode 100644 index 0000000..c1f9956 --- /dev/null +++ b/src/com/bernard/configurator/YamlInterface.java @@ -0,0 +1,11 @@ +package com.bernard.configurator; + +import com.amihaiemil.eoyaml.YamlNode; + +public interface YamlInterface { + + YamlNode writeToNode(Object o); + + Object readNode(YamlNode node); + +} diff --git a/src/com/bernard/configurator/annotations/ConfigClass.java b/src/com/bernard/configurator/annotations/ConfigClass.java new file mode 100644 index 0000000..02cb2bf --- /dev/null +++ b/src/com/bernard/configurator/annotations/ConfigClass.java @@ -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; + +} diff --git a/src/com/bernard/configurator/annotations/Contrainte.java b/src/com/bernard/configurator/annotations/Contrainte.java new file mode 100644 index 0000000..c7a13ed --- /dev/null +++ b/src/com/bernard/configurator/annotations/Contrainte.java @@ -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> c(); + +} diff --git a/src/com/bernard/configurator/annotations/Option.java b/src/com/bernard/configurator/annotations/Option.java new file mode 100644 index 0000000..44456f6 --- /dev/null +++ b/src/com/bernard/configurator/annotations/Option.java @@ -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 yamlInterface() default YamlInterface.class; + +} diff --git a/src/com/bernard/util/BytesUtils.java b/src/com/bernard/util/BytesUtils.java new file mode 100755 index 0000000..111f637 --- /dev/null +++ b/src/com/bernard/util/BytesUtils.java @@ -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 toStream(ByteBuffer buffer){ + Builder 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(","))); + } + +} diff --git a/src/com/bernard/util/ConfiguredFrame.java b/src/com/bernard/util/ConfiguredFrame.java index 9c6e7ab..354d27c 100644 --- a/src/com/bernard/util/ConfiguredFrame.java +++ b/src/com/bernard/util/ConfiguredFrame.java @@ -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 extends JFrame implements ActionListener { @@ -18,8 +19,8 @@ public abstract class ConfiguredFrame 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 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�", "Le fichier n'a pas �t� trouv�"); }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�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."); } catch (ClassCastException e) { - error("Non correspondance","Le type génerique \"Configuration\" et l'objet configurationClass ne correspondent pas"); + error("Non correspondance","Le type g�nerique \"Configuration\" et l'objet configurationClass ne correspondent pas"); } } return null; @@ -82,11 +84,11 @@ public abstract class ConfiguredFrame 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 diff --git a/src/com/bernard/util/ErrorDialog.java b/src/com/bernard/util/ErrorDialog.java index fec0bbb..17d3b2f 100644 --- a/src/com/bernard/util/ErrorDialog.java +++ b/src/com/bernard/util/ErrorDialog.java @@ -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); diff --git a/src/com/bernard/util/FuncUtils.java b/src/com/bernard/util/FuncUtils.java new file mode 100644 index 0000000..6b83210 --- /dev/null +++ b/src/com/bernard/util/FuncUtils.java @@ -0,0 +1,12 @@ +package com.bernard.util; + +import java.util.function.Function; + +public class FuncUtils { + + public static final Function compose(Function f,Function g) { + return f.compose(g); + } + + +} diff --git a/src/com/bernard/util/ParseUtils.java b/src/com/bernard/util/ParseUtils.java new file mode 100644 index 0000000..a631450 --- /dev/null +++ b/src/com/bernard/util/ParseUtils.java @@ -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 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 Set union(Collection c1, Collection c2){ + Set 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 mappingStringKeys(YamlMapping mapping) throws IOException{ + return mapping.keys().stream().map(n ->n.asScalar().value()).collect(Collectors.toSet()); + } + + + public static Stream sequenceStream(YamlSequence sequence){ + return StreamSupport.stream(Spliterators.spliteratorUnknownSize(sequence.iterator(),Spliterator.ORDERED),false); + } + + public static Function wetherMapping(Function fnot,Function 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 YamlMapping setToMapSS(Set nodes, Function key, Function value) { + YamlMappingBuilder builder = Yaml.createYamlMappingBuilder(); + for(M n : nodes) + builder = builder.add(key.apply(n), value.apply(n)); + return builder.build(); + } + public static final YamlMapping setToMapSY(Set nodes, Function key, Function value) { + YamlMappingBuilder builder = Yaml.createYamlMappingBuilder(); + for(M n : nodes) + builder = builder.add(key.apply(n), value.apply(n)); + return builder.build(); + } + public static final YamlMapping setToMapYS(Set nodes, Function key, Function value) { + YamlMappingBuilder builder = Yaml.createYamlMappingBuilder(); + for(M n : nodes) + builder = builder.add(key.apply(n), value.apply(n)); + return builder.build(); + } + public static final YamlMapping setToMapYY(Set nodes, Function key, Function value) { + YamlMappingBuilder builder = Yaml.createYamlMappingBuilder(); + for(M n : nodes) + builder = builder.add(key.apply(n), value.apply(n)); + return builder.build(); + } + public static final YamlSequence setToSeqY(Set nodes) { + YamlSequenceBuilder builder = Yaml.createYamlSequenceBuilder(); + for(YamlNode n : nodes) + builder = builder.add(n); + return builder.build(); + } + + public static final YamlSequence setToSeqS(Set 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; + } + +} diff --git a/src/com/bernard/util/YamlUtils.java b/src/com/bernard/util/YamlUtils.java new file mode 100755 index 0000000..c4e68b4 --- /dev/null +++ b/src/com/bernard/util/YamlUtils.java @@ -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 nodes) { + YamlSequenceBuilder ysb = Yaml.createYamlSequenceBuilder(); + for(YamlNode n : nodes) + ysb = ysb.add(n); + return ysb.build(); + } + + public static final YamlSequence listToSeqString(List nodes) { + YamlSequenceBuilder ysb = Yaml.createYamlSequenceBuilder(); + for(String n : nodes) + ysb = ysb.add(n); + return ysb.build(); + } + + public static final YamlMapping mapToMapping(Map nodes) { + YamlMappingBuilder ysb = Yaml.createYamlMappingBuilder(); + for(Entry n : nodes.entrySet()) + ysb = ysb.add(n.getKey(),n.getValue()); + return ysb.build(); + } + + public static final YamlMapping mapToMapping(Map map,Function fKey,Function fVal) { + YamlMappingBuilder ysb = Yaml.createYamlMappingBuilder(); + for(Entry 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 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 the type of elements to be collected + * @param the type of the result + */ + static class CollectorImpl implements Collector { + private final Supplier supplier; + private final BiConsumer accumulator; + private final BinaryOperator combiner; + private final Function finisher; + private final Set characteristics; + + CollectorImpl(Supplier supplier, + BiConsumer accumulator, + BinaryOperator combiner, + Function finisher, + Set characteristics) { + this.supplier = supplier; + this.accumulator = accumulator; + this.combiner = combiner; + this.finisher = finisher; + this.characteristics = characteristics; + } + + @Override + public BiConsumer accumulator() { + return accumulator; + } + + @Override + public Supplier supplier() { + return supplier; + } + + @Override + public BinaryOperator combiner() { + return combiner; + } + + @Override + public Function finisher() { + return finisher; + } + + @Override + public Set characteristics() { + return characteristics; + } + } + +}