Author: bpoussin Date: 2016-11-09 16:24:51 +0100 (Wed, 09 Nov 2016) New Revision: 4370 Url: http://forge.codelutin.com/projects/isis-fish/repository/revisions/4370 Log: work in progress: Evolution #8737: Export / Import des ?\195?\169l?\195?\169ments d'une r?\195?\169gion, soit pour import dans une autre r?\195?\169gion, soit pour fusion de deux r?\195?\169gions. Modified: trunk/src/main/java/fr/ifremer/isisfish/entities/RegionExportJson.java trunk/src/main/java/fr/ifremer/isisfish/entities/RegionImportJson.java trunk/src/main/java/fr/ifremer/isisfish/ui/input/InputHandler.java Modified: trunk/src/main/java/fr/ifremer/isisfish/entities/RegionExportJson.java =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/entities/RegionExportJson.java 2016-11-04 15:05:55 UTC (rev 4369) +++ trunk/src/main/java/fr/ifremer/isisfish/entities/RegionExportJson.java 2016-11-09 15:24:51 UTC (rev 4370) @@ -364,33 +364,4 @@ decorator = null; } - -// abstract public void visit(Cell v); -// abstract public void visit(EffortDescription v); -// abstract public void visit(FisheryRegion region); -// abstract public void visit(Gear v); -// abstract public void visit(Metier v); -// abstract public void visit(MetierSeasonInfo v); -// abstract public void visit(PopulationGroup v); -// abstract public void visit(Population v); -// abstract public void visit(PopulationSeasonInfo v); -// abstract public void visit(Port v); -// abstract public void visit(Season v); -// abstract public void visit(Selectivity v); -// abstract public void visit(SetOfVessels v); -// abstract public void visit(Species v); -// abstract public void visit(Strategy v); -// abstract public void visit(StrategyMonthInfo v); -// abstract public void visit(TargetSpecies v); -// abstract public void visit(TripType v); -// abstract public void visit(Variable v); -// abstract public void visit(VariableType v); -// abstract public void visit(VesselType v); -// abstract public void visit(Zone v); -// abstract public void visit(Equation v); -// abstract public void visit(MatrixND v); -// abstract public void visit(String v); -// abstract public void visit(int v); -// abstract public void visit(float v); - } Modified: trunk/src/main/java/fr/ifremer/isisfish/entities/RegionImportJson.java =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/entities/RegionImportJson.java 2016-11-04 15:05:55 UTC (rev 4369) +++ trunk/src/main/java/fr/ifremer/isisfish/entities/RegionImportJson.java 2016-11-09 15:24:51 UTC (rev 4370) @@ -1,15 +1,10 @@ package fr.ifremer.isisfish.entities; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.ObjectCodec; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; import fr.ifremer.isisfish.IsisFishDAOHelper; +import fr.ifremer.isisfish.IsisFishRuntimeException; import fr.ifremer.isisfish.types.Month; import fr.ifremer.isisfish.types.RangeOfValues; import fr.ifremer.isisfish.types.TimeUnit; @@ -18,15 +13,26 @@ import java.io.IOException; import java.io.Reader; import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.Map; import java.util.Map.Entry; +import java.util.Set; +import javax.swing.JComboBox; +import javax.swing.JOptionPane; +import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.math.matrix.MatrixND; import org.nuiton.topia.TopiaContext; +import org.nuiton.topia.persistence.EntityVisitor; +import org.nuiton.topia.persistence.TopiaDAO; import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.topia.persistence.TopiaId; /** * Classe permettant d'importer des données dans une region a partir d'un @@ -44,246 +50,255 @@ public class RegionImportJson { static public interface RegionMerge { - public TopiaEntity choice(TopiaEntity e); - } + static public enum AnwserType {ABORT, IMPORT, IMPORT_ALL_TYPE, IMPORT_ALL, REUSE, NONE}; - static public class RegionMergeDatabase implements RegionMerge { - protected TopiaContext tx; + static public class RegionMergeContext { + protected boolean abort = false; + protected boolean importAll = false; + protected Set<Class> importAllType = new HashSet<Class>(); + protected AnwserType lastAnswer = null; + protected TopiaEntity reuseEntity; + protected Class currentType; - public RegionMergeDatabase(TopiaContext tx) { - this.tx = tx; - } + public RegionMergeContext() { + } - @Override - public TopiaEntity choice(TopiaEntity e) { - TopiaEntity result; - - if (e instanceof FisheryRegion) { - result = choice((FisheryRegion)e); - } else if (e instanceof Cell) { - result = choice((Cell)e); - } else if (e instanceof Zone) { - result = choice((Zone)e); - } else if (e instanceof Port) { - result = choice((Port)e); - } else if (e instanceof Species) { - result = choice((Species)e); - } else if (e instanceof Population) { - result = choice((Population)e); - } else if (e instanceof Gear) { - result = choice((Gear)e); - } else if (e instanceof Metier) { - result = choice((Metier)e); - } else if (e instanceof TripType) { - result = choice((TripType)e); - } else if (e instanceof VesselType) { - result = choice((VesselType)e); - } else if (e instanceof SetOfVessels) { - result = choice((SetOfVessels)e); - } else if (e instanceof Strategy) { - result = choice((Strategy)e); - } else if (e instanceof Observation) { - result = choice((Observation)e); - } else { - log.info("Not supported entity type: " + e.getClass().getSimpleName()); - result = genericChoice(e); + public RegionMergeContext(boolean importAll) { + this.importAll = importAll; } - return result; - } + public TopiaEntity getReuseEntity() { + return reuseEntity; + } - protected TopiaEntity ask(TopiaEntity e, Collection<TopiaEntity> possible) { - System.out.println("Choice between:" + e + " and " + possible); - return e; // FIXME - } + public AnwserType getLastAnswer() { + return lastAnswer; + } - protected TopiaEntity genericChoice(TopiaEntity e) { - LinkedHashSet<TopiaEntity> possible = new LinkedHashSet<TopiaEntity>(); + protected void setLastAnswer(TopiaEntity e) { + this.lastAnswer = AnwserType.REUSE; + this.reuseEntity = e; + } - possible.add(tx.findByTopiaId(e.getTopiaId())); + protected void setLastAnswer(AnwserType lastAnswer) { + this.lastAnswer = lastAnswer; + switch (lastAnswer) { + case ABORT: + abort = true; + break; + case IMPORT_ALL_TYPE: + importAllType.add(currentType); + this.lastAnswer = AnwserType.IMPORT; + break; + case IMPORT_ALL: + importAll = true; + this.lastAnswer = AnwserType.IMPORT; + break; + default: + break; + } + } - TopiaEntity result = ask(e, possible); - return result; + public AnwserType initAnswer(Class type) { + lastAnswer = null; + currentType = type; + if (abort) { + lastAnswer = AnwserType.ABORT; + } else if (importAll || importAllType.contains(type)) { + lastAnswer = AnwserType.IMPORT; + } + return lastAnswer; + } } - protected TopiaEntity choice(FisheryRegion e) { - FisheryRegionDAO dao = IsisFishDAOHelper.getFisheryRegionDAO(tx); - LinkedHashSet<TopiaEntity> possible = new LinkedHashSet<TopiaEntity>(); + /** + * Ask how to merge entity + * @param context + * @param id + * @param toString + * @param details + * @return + */ + public RegionMergeContext choice(RegionMergeContext context, String id, String toString, Map<String, Object> details); + /** + * If exist return entity with id in parameter + * @param id + * @return null or TopiaEntity + */ + public TopiaEntity getEntity(String id); + } - possible.add(dao.findByTopiaId(e.getTopiaId())); - possible.addAll(dao.findAllByName(e.getName())); + static public class RegionMergeDatabase implements RegionMerge { + protected TopiaContext tx; - TopiaEntity result = ask(e, possible); - return result; + public RegionMergeDatabase(TopiaContext tx) { + this.tx = tx; } - protected TopiaEntity choice(Cell e) { - CellDAO dao = IsisFishDAOHelper.getCellDAO(tx); - LinkedHashSet<TopiaEntity> possible = new LinkedHashSet<TopiaEntity>(); - - possible.add(dao.findByTopiaId(e.getTopiaId())); - possible.addAll(dao.findAllByName(e.getName())); - - TopiaEntity result = ask(e, possible); + @Override + public TopiaEntity getEntity(String id) { + TopiaEntity result = tx.findByTopiaId(id); return result; } - - protected TopiaEntity choice(Zone e) { - ZoneDAO dao = IsisFishDAOHelper.getZoneDAO(tx); - LinkedHashSet<TopiaEntity> possible = new LinkedHashSet<TopiaEntity>(); - possible.add(dao.findByTopiaId(e.getTopiaId())); - possible.addAll(dao.findAllByName(e.getName())); + @Override + public RegionMergeContext choice(RegionMergeContext context, String id, String toString, Map<String, Object> details) { + Class type = TopiaId.getClassName(id); + if (context == null) { + context = new RegionMergeContext(); + } else { + context.initAnswer(type); + } - TopiaEntity result = ask(e, possible); - return result; - } + if (context.lastAnswer != null) { + return context; + } - protected TopiaEntity choice(Port e) { - PortDAO dao = IsisFishDAOHelper.getPortDAO(tx); - LinkedHashSet<TopiaEntity> possible = new LinkedHashSet<TopiaEntity>(); + TopiaDAO<TopiaEntity> dao = IsisFishDAOHelper.getDAO(tx, type); - possible.add(dao.findByTopiaId(e.getTopiaId())); - possible.addAll(dao.findAllByName(e.getName())); - - TopiaEntity result = ask(e, possible); - return result; - } - - protected TopiaEntity choice(Species e) { - SpeciesDAO dao = IsisFishDAOHelper.getSpeciesDAO(tx); LinkedHashSet<TopiaEntity> possible = new LinkedHashSet<TopiaEntity>(); - possible.add(dao.findByTopiaId(e.getTopiaId())); - possible.addAll(dao.findAllByName(e.getName())); + possible.add(dao.findByTopiaId(id)); + possible.addAll(dao.findAllByProperty("name", details.get("name"))); +// possible.addAll(dao.findAllByProperties(details)); - TopiaEntity result = ask(e, possible); - return result; - } + ask(context, toString, details, possible); - protected TopiaEntity choice(Population e) { - PopulationDAO dao = IsisFishDAOHelper.getPopulationDAO(tx); - LinkedHashSet<TopiaEntity> possible = new LinkedHashSet<TopiaEntity>(); - - possible.add(dao.findByTopiaId(e.getTopiaId())); - possible.addAll(dao.findAllByName(e.getName())); - - TopiaEntity result = ask(e, possible); - return result; + return context; } - protected TopiaEntity choice(Gear e) { - GearDAO dao = IsisFishDAOHelper.getGearDAO(tx); - LinkedHashSet<TopiaEntity> possible = new LinkedHashSet<TopiaEntity>(); + protected void ask(RegionMergeContext context, String toString, + Map<String, Object> details, Collection<TopiaEntity> possible) { + System.out.println("Choice between:" + toString + " and " + possible); - possible.add(dao.findByTopiaId(e.getTopiaId())); - possible.addAll(dao.findAllByName(e.getName())); + JComboBox select = new JComboBox(possible.toArray()); - TopiaEntity result = ask(e, possible); - return result; - } + Object[] options = new Object[] { + "None", // for null + "Reuse selected object", + "Import", + "Import All this type", + "Import All", + "Abort" + }; - protected TopiaEntity choice(Metier e) { - MetierDAO dao = IsisFishDAOHelper.getMetierDAO(tx); - LinkedHashSet<TopiaEntity> possible = new LinkedHashSet<TopiaEntity>(); - possible.add(dao.findByTopiaId(e.getTopiaId())); - possible.addAll(dao.findAllByName(e.getName())); + int result = JOptionPane.showOptionDialog(null, + new Object[]{ + String.format("You try to import '%s'", toString), + "Possible answer are:", + "None: don't import nor reuse object", + "Reuse: use object already in current Region (make your choice in next combobox).", + select, + "Import: import object from file.", + "Import All this type: auto answer Import for this question and all next question for same object type", + "Import All: auto answer Import for this question and all next question.", + "Abort: Cancel this import (import nothing)" + }, + "Make a choice", + JOptionPane.DEFAULT_OPTION, + JOptionPane.QUESTION_MESSAGE, + null, + options, + options[0]); - TopiaEntity result = ask(e, possible); - return result; + switch (result) { + case 0: + context.setLastAnswer(AnwserType.NONE); + break; + case 1: + context.setLastAnswer((TopiaEntity)select.getSelectedItem()); + break; + case 2: + context.setLastAnswer(AnwserType.IMPORT); + break; + case 3: + context.setLastAnswer(AnwserType.IMPORT_ALL_TYPE); + break; + case 4: + context.setLastAnswer(AnwserType.IMPORT_ALL); + break; + case 5: + context.setLastAnswer(AnwserType.ABORT); + break; + default: + ask(context, toString, details, possible); + break; + } } + } - protected TopiaEntity choice(TripType e) { - TripTypeDAO dao = IsisFishDAOHelper.getTripTypeDAO(tx); - LinkedHashSet<TopiaEntity> possible = new LinkedHashSet<TopiaEntity>(); - - possible.add(dao.findByTopiaId(e.getTopiaId())); - possible.addAll(dao.findAllByName(e.getName())); - - TopiaEntity result = ask(e, possible); - return result; + static public class RegionMergeImportAll implements RegionMerge { + @Override + public TopiaEntity getEntity(String id) { + return null; } - protected TopiaEntity choice(VesselType e) { - VesselTypeDAO dao = IsisFishDAOHelper.getVesselTypeDAO(tx); - LinkedHashSet<TopiaEntity> possible = new LinkedHashSet<TopiaEntity>(); - - possible.add(dao.findByTopiaId(e.getTopiaId())); - possible.addAll(dao.findAllByName(e.getName())); - - TopiaEntity result = ask(e, possible); - return result; + @Override + public RegionMergeContext choice(RegionMergeContext context, String id, String toString, Map<String, Object> details) { + if (context == null) { + context = new RegionMergeContext(); + } + context.setLastAnswer(AnwserType.IMPORT); + return context; } - protected TopiaEntity choice(SetOfVessels e) { - SetOfVesselsDAO dao = IsisFishDAOHelper.getSetOfVesselsDAO(tx); - LinkedHashSet<TopiaEntity> possible = new LinkedHashSet<TopiaEntity>(); - - possible.add(dao.findByTopiaId(e.getTopiaId())); - possible.addAll(dao.findAllByName(e.getName())); - - TopiaEntity result = ask(e, possible); - return result; - } - - protected TopiaEntity choice(Strategy e) { - StrategyDAO dao = IsisFishDAOHelper.getStrategyDAO(tx); - LinkedHashSet<TopiaEntity> possible = new LinkedHashSet<TopiaEntity>(); - - possible.add(dao.findByTopiaId(e.getTopiaId())); - possible.addAll(dao.findAllByName(e.getName())); - - TopiaEntity result = ask(e, possible); - return result; - } - - protected TopiaEntity choice(Observation e) { - ObservationDAO dao = IsisFishDAOHelper.getObservationDAO(tx); - LinkedHashSet<TopiaEntity> possible = new LinkedHashSet<TopiaEntity>(); - - possible.add(dao.findByTopiaId(e.getTopiaId())); - possible.addAll(dao.findAllByName(e.getName())); - - TopiaEntity result = ask(e, possible); - return result; - } } - static public class RegionMergeNoMerge implements RegionMerge { - @Override - public TopiaEntity choice(TopiaEntity e) { - return e; - } - } +// static protected class TopiaTypeResolver extends SimpleAbstractTypeResolver { +// static private Log log = LogFactory.getLog(TopiaTypeResolver.class); +// @Override +// public JavaType findTypeMapping(DeserializationConfig config, JavaType type) { +// JavaType result = super.findTypeMapping(config, type); +// if (result == null) { +// Class<?> src = type.getRawClass(); +// if (TopiaEntity.class.isAssignableFrom(src) && !src.getSimpleName().endsWith("Impl")) { +// try { +// Class<?> dest = Class.forName(src.getName() + "Impl"); +// result = config.getTypeFactory().constructSpecializedType(type, dest); +// } catch (ClassNotFoundException eee) { +// log.error("Can't create class for " + src.getName() + "Impl", eee); +// } +// } +// } +// return result; +// } +// } /** to use log facility, just put in your code: log.info(\"...\"); */ static private Log log = LogFactory.getLog(RegionImportJson.class); protected RegionMerge merge; + protected RegionMerge.RegionMergeContext mergeContext; protected JsonNode json; protected LinkedHashMap<String, TopiaEntity> entities; protected JsonNode jsonEntities; - protected ObjectMapper mapper; +// protected ObjectMapper mapper; + protected TopiaEntity currentEntity; /** * * @param r reader contains json - * @param merge use to choice entity in Json or entity in current region + * @param merge use to choice entity in Json or entity in current region, + * if no merge object is passed in arguement "import all" object in reader */ public RegionImportJson(Reader r, RegionMerge merge) { try { - this.merge = merge != null ? merge : new RegionMergeNoMerge(); + this.merge = merge != null ? merge : new RegionMergeImportAll(); + this.mergeContext = new RegionMerge.RegionMergeContext(); + entities = new LinkedHashMap<String, TopiaEntity>(); - mapper = new ObjectMapper(); - SimpleModule isisModule = new SimpleModule("IsisModule") - .addDeserializer(Month.class, new MonthJsonDeserializer()) - .addDeserializer(TimeUnit.class, new TimeUnitJsonDeserializer()) - .addDeserializer(RangeOfValues.class, new RangeOfValuesJsonDeserializer()) - .addDeserializer(MatrixND.class, new MatrixNDJsonDeserializer(this)) - .addDeserializer(TopiaEntity.class, new TopiaEntityJsonDeserializer(this)); - mapper.registerModule(isisModule); +// mapper = new ObjectMapper(); +// mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); +// SimpleModule isisModule = new SimpleModule("IsisModule"); +// isisModule.setAbstractTypes(new TopiaTypeResolver()); +// isisModule.addDeserializer(Month.class, new MonthJsonDeserializer()) +// .addDeserializer(TimeUnit.class, new TimeUnitJsonDeserializer()) +// .addDeserializer(RangeOfValues.class, new RangeOfValuesJsonDeserializer()) +// .addDeserializer(MatrixND.class, new MatrixNDJsonDeserializer(this)) +// .addDeserializer(TopiaEntity.class, new TopiaEntityJsonDeserializer(this)); +// mapper.registerModule(isisModule); ObjectMapper m = new ObjectMapper(); json = m.readTree(r); @@ -297,7 +312,7 @@ * Return all entities available in Json reader * @return */ - public Collection<TopiaEntity> getEntity() { + public Collection<TopiaEntity> getEntities() { try { JsonNode info = json.with("#info"); boolean isRegion = info.get("region").asBoolean(false); @@ -304,7 +319,9 @@ if (!isRegion) { // il n'y a qu'un objet dans le json, on le deserialize String rootId = info.get("rootId").asText(); - getEntity(rootId); + RegionVisitor v = new RegionVisitor(merge, mergeContext, rootId, entities, jsonEntities); + // no assigment, collect of entities is done during deserialize + v.loadEntity(); } else { // il y a toute une region, on lit les listes d'id des objets // principaux (cell, zone, port, ...) @@ -313,7 +330,9 @@ // les champs commencant par des # sont #info et #entities if (!field.getKey().startsWith("#")) { for (JsonNode id : field.getValue()) { - getEntity(id.asText()); + RegionVisitor v = new RegionVisitor(merge, mergeContext, id.asText(), entities, jsonEntities); + // no assigment, collect of entities is done during deserialize + v.loadEntity(); } } } @@ -325,104 +344,324 @@ } } - /** - * Return entity with given id. If not already converted, convert it and - * add it in global entities converted pool - * @param id - * @return - */ - public TopiaEntity getEntity(String id) { - try { - TopiaEntity result = entities.get(id); - if (result == null) { - JsonNode node = jsonEntities.get(id); - Class clazz = Class.forName(node.get("#class").asText()); - TopiaEntity o = (TopiaEntity)mapper.convertValue(node, clazz); - o = merge.choice(o); - entities.put(id, o); +// /** +// * Return entity with given id. If not already converted, convert it and +// * add it in global entities converted pool +// * @param id +// * @return +// */ +// private TopiaEntity getEntity(String id, DeserializationContext ctxt) { +// try { +// TopiaEntity result = entities.get(id); +// if (result == null) { +// JsonNode node = jsonEntities.get(id); +// +// Map<String, Object> details = new HashMap<String, Object>(); +// for (Iterator<Entry<String, JsonNode>> i = node.fields(); i.hasNext();) { +// Entry<String, JsonNode> e = i.next(); +// if (!e.getKey().startsWith("#")) { +// details.put(e.getKey(), e.getValue().asText()); +// } +// } +// +// TopiaEntity o; +// String toString = node.get("#toString").asText(); +// merge.choice(mergeContext, id, toString, details); +// switch (mergeContext.lastAnswer) { +// case ABORT: +// throw new IsisFishRuntimeException("Import aborted by user"); +// case NONE: +// o = null; +// break; +// case REUSE: +// o = mergeContext.getReuseEntity(); +// break; +// default: +// // import +// Class clazz = Class.forName(node.get("#class").asText()); +// o = (TopiaEntity)clazz.newInstance(); +// JavaType type = ctxt.constructType(clazz); +// JsonDeserializer<Object> des = ctxt.findNonContextualValueDeserializer(type); +// o = (TopiaEntity)des.deserialize(node.traverse(), ctxt, o); +//// o = (TopiaEntity)mapper.convertValue(node, clazz); +// break; +// } +// +// entities.put(id, o); +// } +// return result; +// } catch (Exception eee) { +// throw new RuntimeException(eee); +// } +// } + + static protected class RegionVisitor implements EntityVisitor { + + protected RegionMerge merge; + protected RegionMerge.RegionMergeContext mergeContext; + protected JsonNode nodeEntity; + protected TopiaEntity currentEntity; + protected LinkedHashMap<String, TopiaEntity> entities; + protected JsonNode jsonEntities; + + public RegionVisitor(RegionMerge merge, RegionMerge.RegionMergeContext mergeContext, + String idEntity, + LinkedHashMap<String, TopiaEntity> entities, JsonNode jsonEntities) { + this.merge = merge; + this.mergeContext = mergeContext; + this.nodeEntity = jsonEntities.get(idEntity); + this.entities = entities; + this.jsonEntities = jsonEntities; + } + + public TopiaEntity loadEntity() { + String id = nodeEntity.get("#id").asText(); + currentEntity = entities.get(id); + if (currentEntity == null) { + currentEntity = ask(id); } + return currentEntity; + } + + protected TopiaEntity convertJsonToEntity(JsonNode node) { + TopiaEntity result; + String id = node.get("#id").asText(); + String className = node.get("#class").asText(); + try { + // try to reuse entity + result = merge.getEntity(id); + if (result == null) { + // if no entity with same id, create new one + Class clazz = Class.forName(className); + result = (TopiaEntity)clazz.newInstance(); + result.setTopiaId(id); + } + // add in list save after import + entities.put(id, result); + + result.accept(this); + } catch (Exception eee) { + throw new IsisFishRuntimeException("Can't instanciate entity: " + className, eee); + } return result; - } catch (Exception eee) { - throw new RuntimeException(eee); } - } - private static class MatrixNDJsonDeserializer extends JsonDeserializer<MatrixND> { + protected TopiaEntity ask(String id) { + JsonNode node = jsonEntities.get(id); - protected MatrixCSVHelper matrixCSVHelper; - - public MatrixNDJsonDeserializer(final RegionImportJson importer) { - matrixCSVHelper = new MatrixCSVHelper(new EntitySemanticsDecorator( - new EntitySemanticsDecorator.EntityProvider() { - @Override - public Object findById(String id) { - Object result = importer.getEntity(id); - return result; + Map<String, Object> details = new HashMap<String, Object>(); + for (Iterator<Entry<String, JsonNode>> i = node.fields(); i.hasNext();) { + Entry<String, JsonNode> e = i.next(); + if (!e.getKey().startsWith("#")) { + details.put(e.getKey(), e.getValue().asText()); } - })); - } + } - @Override - public MatrixND deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { - ObjectCodec oc = p.getCodec(); - JsonNode node = oc.readTree(p); - String mat = node.asText(); - MatrixND result = matrixCSVHelper.readMatrix(mat); + TopiaEntity result; + String toString = node.get("#toString").asText(); + merge.choice(mergeContext, id, toString, details); + switch (mergeContext.lastAnswer) { + case ABORT: + throw new IsisFishRuntimeException("Import aborted by user"); + case NONE: + result = null; + break; + case REUSE: + result = mergeContext.getReuseEntity(); + break; + default: + result = convertJsonToEntity(node); + break; + } return result; } - } + protected Object readValue(Class<?> type, JsonNode value) { + Object result; + try { + if (value == null || value.isNull() || value.isMissingNode()) { + result = null; + } else if (TopiaEntity.class.isAssignableFrom(type)) { + String id = value.asText(); + RegionVisitor child = new RegionVisitor(merge, mergeContext, id, entities, jsonEntities); + result = child.loadEntity(); + } else if (MatrixND.class.isAssignableFrom(type)) { + String mat = value.asText(); - private static class TopiaEntityJsonDeserializer extends JsonDeserializer<TopiaEntity> { + MatrixCSVHelper matrixCSVHelper = new MatrixCSVHelper(new EntitySemanticsDecorator( + new EntitySemanticsDecorator.EntityProvider() { + @Override + public Object findById(String id) { + RegionVisitor child = new RegionVisitor(merge, mergeContext, id, entities, jsonEntities); + Object result = child.loadEntity(); + return result; + } + })); - protected RegionImportJson importer; + result = matrixCSVHelper.readMatrix(mat); - public TopiaEntityJsonDeserializer(RegionImportJson importer) { - this.importer = importer; + } else if (TimeUnit.class.isAssignableFrom(type)) { + result = new TimeUnit(value.asDouble()); + } else if (RangeOfValues.class.isAssignableFrom(type)) { + String v = value.asText(); + result = new RangeOfValues(v); + } else if (Month.class.isAssignableFrom(type)) { + int m = value.asInt(); + result = Month.MONTH[m]; + } else if (Class.class.isAssignableFrom(type)) { + String className = value.asText(); + result = Class.forName(className); + } else if (String.class.isAssignableFrom(type)) { + result = value.asText(); + } else if (Boolean.class.isAssignableFrom(type) || Boolean.TYPE.isAssignableFrom(type)) { + result = value.asBoolean(); + } else if (Number.class.isAssignableFrom(type) || type.isPrimitive()) { // Number must be after Boolean + // all other possible primitive type is number (void and char are not admited in json) + result = value.asDouble(); + } else { + String message = String.format("Unsupported type: '%s' value class '%s' value '%s'", type, value.getClass().getName(), value); + log.error(message); + throw new IsisFishRuntimeException(message); + } + } catch (Exception eee) { + throw new IsisFishRuntimeException("Can't convert json value:" + value, eee); + } + return result; } @Override - public TopiaEntity deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { - ObjectCodec oc = p.getCodec(); - JsonNode node = oc.readTree(p); - String id = node.asText(); - TopiaEntity result = importer.getEntity(id); - return result; + public void start(TopiaEntity entity) { } - } + @Override + public void end(TopiaEntity entity) { + } - private static class MonthJsonDeserializer extends JsonDeserializer<Month> { @Override - public Month deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { - ObjectCodec oc = p.getCodec(); - JsonNode node = oc.readTree(p); - int m = node.asInt(); - Month result = Month.MONTH[m]; - return result; + public void visit(TopiaEntity entity, String propertyName, Class<?> type, Object value) { + JsonNode jsonValue = nodeEntity.get(propertyName); + try { + value = readValue(type, jsonValue); + BeanUtils.setProperty(entity, propertyName, value); + } catch (Exception eee) { + throw new IsisFishRuntimeException(String.format("Can't set property '%s' from json value: '%s'", propertyName, jsonValue), eee); + } } - } - private static class TimeUnitJsonDeserializer extends JsonDeserializer<TimeUnit> { @Override - public TimeUnit deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { - ObjectCodec oc = p.getCodec(); - JsonNode node = oc.readTree(p); - int v = node.asInt(); - TimeUnit result = new TimeUnit(v); - return result; + public void visit(TopiaEntity entity, String propertyName, Class<?> collectionType, Class<?> type, Object value) { + JsonNode jsonValue = nodeEntity.get(propertyName); + try { + if (value != null) { + Collection c; + if (Set.class.isAssignableFrom(collectionType)) { + c = new HashSet(); + } else { + c = new LinkedList(); + } + for (JsonNode currentValue : jsonValue) { + Object v = readValue(type, currentValue); + c.add(v); + } + BeanUtils.setProperty(entity, propertyName, c); + } + } catch (Exception eee) { + throw new IsisFishRuntimeException(String.format("Can't set property '%s' from json value: '%s'", propertyName, jsonValue), eee); + } } - } - private static class RangeOfValuesJsonDeserializer extends JsonDeserializer<RangeOfValues> { @Override - public RangeOfValues deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { - ObjectCodec oc = p.getCodec(); - JsonNode node = oc.readTree(p); - String v = node.asText(); - RangeOfValues result = new RangeOfValues(v); - return result; + public void visit(TopiaEntity entity, String propertyName, Class<?> collectionType, Class<?> type, int index, Object value) { + throw new UnsupportedOperationException("FIXME a faire, implantation des properties array"); } + + @Override + public void clear() { + } } + + +// +// private static class MatrixNDJsonDeserializer extends JsonDeserializer<MatrixND> { +// +// protected RegionImportJson importer; +// +// public MatrixNDJsonDeserializer(final RegionImportJson importer) { +// this.importer = importer; +// } +// +// @Override +// public MatrixND deserialize(JsonParser p, final DeserializationContext ctxt) throws IOException, JsonProcessingException { +// ObjectCodec oc = p.getCodec(); +// JsonNode node = oc.readTree(p); +// String mat = node.asText(); +// +// MatrixCSVHelper matrixCSVHelper = new MatrixCSVHelper(new EntitySemanticsDecorator( +// new EntitySemanticsDecorator.EntityProvider() { +// @Override +// public Object findById(String id) { +// Object result = importer.getEntity(id, ctxt); +// return result; +// } +// })); +// +// MatrixND result = matrixCSVHelper.readMatrix(mat); +// return result; +// } +// +// } +// +// private static class TopiaEntityJsonDeserializer extends JsonDeserializer<TopiaEntity> { +// +// protected RegionImportJson importer; +// +// public TopiaEntityJsonDeserializer(RegionImportJson importer) { +// this.importer = importer; +// } +// +// @Override +// public TopiaEntity deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { +// ObjectCodec oc = p.getCodec(); +// JsonNode node = oc.readTree(p); +// String id = node.asText(); +// TopiaEntity result = importer.getEntity(id, ctxt); +// return result; +// } +// +// } +// +// private static class MonthJsonDeserializer extends JsonDeserializer<Month> { +// @Override +// public Month deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { +// ObjectCodec oc = p.getCodec(); +// JsonNode node = oc.readTree(p); +// int m = node.asInt(); +// Month result = Month.MONTH[m]; +// return result; +// } +// } +// +// private static class TimeUnitJsonDeserializer extends JsonDeserializer<TimeUnit> { +// @Override +// public TimeUnit deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { +// ObjectCodec oc = p.getCodec(); +// JsonNode node = oc.readTree(p); +// int v = node.asInt(); +// TimeUnit result = new TimeUnit(v); +// return result; +// } +// } +// +// private static class RangeOfValuesJsonDeserializer extends JsonDeserializer<RangeOfValues> { +// @Override +// public RangeOfValues deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { +// ObjectCodec oc = p.getCodec(); +// JsonNode node = oc.readTree(p); +// String v = node.asText(); +// RangeOfValues result = new RangeOfValues(v); +// return result; +// } +// } + } Modified: trunk/src/main/java/fr/ifremer/isisfish/ui/input/InputHandler.java =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/ui/input/InputHandler.java 2016-11-04 15:05:55 UTC (rev 4369) +++ trunk/src/main/java/fr/ifremer/isisfish/ui/input/InputHandler.java 2016-11-09 15:24:51 UTC (rev 4370) @@ -440,12 +440,15 @@ new GZIPInputStream(new FileInputStream(file)))) { RegionImportJson json = new RegionImportJson(new InputStreamReader(in, "UTF-8"), new RegionImportJson.RegionMergeDatabase(tx)); - Collection<TopiaEntity> entities = json.getEntity(); + Collection<TopiaEntity> entities = json.getEntities(); log.info("Entities to importe: " + entities.size()); for (TopiaEntity e : entities) { tx.add(e); } tx.commitTransaction(); + } catch (Exception eee) { + tx.rollbackTransaction(); + throw eee; } } } catch (Exception eee) {