/** * (C) Copyright 2013 Jabylon (http://www.jabylon.org) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.jabylon.properties.impl; import java.io.File; import java.util.Collection; import java.util.Locale; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.emf.common.notify.NotificationChain; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.jabylon.properties.DiffKind; import org.jabylon.properties.Project; import org.jabylon.properties.ProjectLocale; import org.jabylon.properties.ProjectVersion; import org.jabylon.properties.PropertiesFactory; import org.jabylon.properties.PropertiesPackage; import org.jabylon.properties.PropertyFile; import org.jabylon.properties.PropertyFileDescriptor; import org.jabylon.properties.PropertyFileDiff; import org.jabylon.properties.Resolvable; import org.jabylon.properties.Review; import org.jabylon.properties.ScanConfiguration; import org.jabylon.properties.types.PropertyScanner; import org.jabylon.properties.util.PropertyResourceUtil; import org.jabylon.properties.util.scanner.FullScanFileAcceptor; import org.jabylon.properties.util.scanner.PartialScanFileAcceptor; import org.jabylon.properties.util.scanner.WorkspaceScanner; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; /** * <!-- begin-user-doc --> An implementation of the model object ' * <em><b>Project Version</b></em>'. <!-- end-user-doc --> * <p> * The following features are implemented: * <ul> * <li>{@link org.jabylon.properties.impl.ProjectVersionImpl#getTemplate <em>Template</em>}</li> * <li>{@link org.jabylon.properties.impl.ProjectVersionImpl#isReadOnly <em>Read Only</em>}</li> * </ul> * </p> * * @generated */ public class ProjectVersionImpl extends ResolvableImpl<Project, ProjectLocale> implements ProjectVersion { /** * The default value of the '{@link #isReadOnly() <em>Read Only</em>}' attribute. * <!-- begin-user-doc --> * <!-- end-user-doc --> * @see #isReadOnly() * @generated * @ordered */ protected static final boolean READ_ONLY_EDEFAULT = false; /** * <!-- begin-user-doc --> <!-- end-user-doc --> * @generated */ protected ProjectVersionImpl() { super(); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * @generated */ @Override protected EClass eStaticClass() { return PropertiesPackage.Literals.PROJECT_VERSION; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * This is specialized for the more specific type known in this context. * @generated */ @Override public NotificationChain basicSetParent(Project newParent, NotificationChain msgs) { return super.basicSetParent(newParent, msgs); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * @generated */ public ProjectLocale getTemplate() { return (ProjectLocale)eDynamicGet(PropertiesPackage.PROJECT_VERSION__TEMPLATE, PropertiesPackage.Literals.PROJECT_VERSION__TEMPLATE, true, true); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * @generated */ public ProjectLocale basicGetTemplate() { return (ProjectLocale)eDynamicGet(PropertiesPackage.PROJECT_VERSION__TEMPLATE, PropertiesPackage.Literals.PROJECT_VERSION__TEMPLATE, false, true); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * @generated */ public void setTemplate(ProjectLocale newTemplate) { eDynamicSet(PropertiesPackage.PROJECT_VERSION__TEMPLATE, PropertiesPackage.Literals.PROJECT_VERSION__TEMPLATE, newTemplate); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ public boolean isReadOnly() { return (Boolean)eDynamicGet(PropertiesPackage.PROJECT_VERSION__READ_ONLY, PropertiesPackage.Literals.PROJECT_VERSION__READ_ONLY, true, true); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ public void setReadOnly(boolean newReadOnly) { eDynamicSet(PropertiesPackage.PROJECT_VERSION__READ_ONLY, PropertiesPackage.Literals.PROJECT_VERSION__READ_ONLY, newReadOnly); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated NOT */ public Project getProject() { return (Project) eContainer(); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated NOT */ public void fullScan(ScanConfiguration configuration) { fullScan(configuration, null); } public void fullScan(ScanConfiguration configuration, IProgressMonitor monitor) { Multimap<URI, Review> reviews = ArrayListMultimap.create(); /* * we need to save all manual reviews (suggestions) as they will not * be recreated automatically. * see https://github.com/jutzig/jabylon/issues/214 */ for (ProjectLocale locale : getChildren()) { for (PropertyFileDescriptor descriptor : locale.getDescriptors()) { for (Review review : descriptor.getReviews()) { if (Review.KIND_SUGGESTION.equals(review.getReviewType())) reviews.put(descriptor.getLocation(), review); } } } getChildren().clear(); setTemplate(null); WorkspaceScanner scanner = new WorkspaceScanner(); File baseDir = new File(absolutPath().path()).getAbsoluteFile(); SubMonitor subMonitor = SubMonitor.convert(monitor, "Scanning", 100); PropertyScanner propertyScanner = PropertyResourceUtil.createScanner(this); scanner.fullScan(new FullScanFileAcceptor(this, propertyScanner, configuration), baseDir, propertyScanner, configuration, subMonitor.newChild(50)); PropertyResourceUtil.createMissingDescriptorEntries(this, subMonitor.newChild(50)); for (ProjectLocale locale : getChildren()) { for (PropertyFileDescriptor descriptor : locale.getDescriptors()) { Collection<Review> currentReviews = reviews.get(descriptor.getLocation()); descriptor.getReviews().addAll(currentReviews); descriptor.updatePercentComplete(); } } } public ProjectLocale getProjectLocale(Locale locale) { if(locale==null) return getTemplate(); EList<ProjectLocale> locales = getChildren(); for (ProjectLocale projectLocale : locales) { if (locale.equals(projectLocale.getLocale())) return projectLocale; } return null; } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * * @generated NOT */ public void partialScan(ScanConfiguration configuration, PropertyFileDiff fileDiff) { // TODO: MOVE and COPY can be handled better // TODO: this can only handle updates in master locale so far. // translated files won't make it through the scanner PropertyScanner propertyScanner = PropertyResourceUtil.createScanner(this); WorkspaceScanner scanner = new WorkspaceScanner(); File baseDir = new File(absolutPath().path()).getAbsoluteFile(); // in case of a remove, the new path doesn't exist anymore String filePath = fileDiff.getKind() == DiffKind.REMOVE ? fileDiff.getOldPath() : fileDiff.getNewPath(); File singleFile = new File(baseDir, filePath); if (!scanner.partialScan(baseDir, propertyScanner, configuration, singleFile)) return; // no match -> no work switch (fileDiff.getKind()) { case MOVE: { deleteDescriptor(makeURI(fileDiff.getOldPath())); } case COPY: case ADD: { scanner.partialScan(new PartialScanFileAcceptor(this, propertyScanner, configuration), baseDir, propertyScanner, configuration,singleFile); break; } case MODIFY: { PropertyFileDescriptor descriptor = findDescriptor(makeURI(fileDiff.getNewPath())); if (descriptor != null) { PropertyFile properties = descriptor.loadProperties(); descriptor.setKeys(properties.getProperties().size()); descriptor.updatePercentComplete(); if(descriptor.isMaster()) { EList<PropertyFileDescriptor> descriptors = descriptor.getDerivedDescriptors(); for (PropertyFileDescriptor child : descriptors) { //update the percent complete of all translations child.updatePercentComplete(); } } } break; } case REMOVE: { deleteDescriptor(makeURI(fileDiff.getOldPath())); } } } /** * transforms a relative {@link PropertyFileDiff} path to a URI * @param diffPath * @return */ private URI makeURI(String diffPath) { //first normalize the path String path = diffPath.replace('\\', '/'); if(diffPath.startsWith("/")) return URI.createURI(diffPath,false); return URI.createURI("/"+path,false); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * @generated */ @Override public Object eGet(int featureID, boolean resolve, boolean coreType) { switch (featureID) { case PropertiesPackage.PROJECT_VERSION__TEMPLATE: if (resolve) return getTemplate(); return basicGetTemplate(); case PropertiesPackage.PROJECT_VERSION__READ_ONLY: return isReadOnly(); } return super.eGet(featureID, resolve, coreType); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * @generated */ @Override public void eSet(int featureID, Object newValue) { switch (featureID) { case PropertiesPackage.PROJECT_VERSION__TEMPLATE: setTemplate((ProjectLocale)newValue); return; case PropertiesPackage.PROJECT_VERSION__READ_ONLY: setReadOnly((Boolean)newValue); return; } super.eSet(featureID, newValue); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * @generated */ @Override public void eUnset(int featureID) { switch (featureID) { case PropertiesPackage.PROJECT_VERSION__TEMPLATE: setTemplate((ProjectLocale)null); return; case PropertiesPackage.PROJECT_VERSION__READ_ONLY: setReadOnly(READ_ONLY_EDEFAULT); return; } super.eUnset(featureID); } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * @generated */ @Override public boolean eIsSet(int featureID) { switch (featureID) { case PropertiesPackage.PROJECT_VERSION__TEMPLATE: return basicGetTemplate() != null; case PropertiesPackage.PROJECT_VERSION__READ_ONLY: return isReadOnly() != READ_ONLY_EDEFAULT; } return super.eIsSet(featureID); } private void deleteDescriptor(URI uri) { PropertyFileDescriptor descriptor = findDescriptor(uri); if (descriptor != null) PropertyResourceUtil.removeDescriptor(descriptor); } @Override public Resolvable resolveChild(URI path) { if (path.segmentCount() == 0 || relativePath().equals(path)) return this; String localeSegment = path.segment(0); ProjectLocale projectLocale = null; if (localeSegment.equals("template")) projectLocale = getTemplate(); else { Locale locale = (Locale) PropertiesFactory.eINSTANCE.createFromString(PropertiesPackage.Literals.LOCALE, localeSegment); if (locale == null) return null; projectLocale = getProjectLocale(locale); } if (path.segmentCount() == 1) return projectLocale; String[] segments = path.segments(); String[] remainder = new String[segments.length - 1]; System.arraycopy(segments, 1, remainder, 0, remainder.length); URI shorterURI = URI.createHierarchicalURI(remainder, null, null); return projectLocale.resolveChild(shorterURI); } protected PropertyFileDescriptor findDescriptor(URI path) { PropertyScanner scanner = PropertyResourceUtil.createScanner(this); Locale variant = scanner.getLocale(new File(path.path())); ProjectLocale locale = variant == null ? getTemplate() : getProjectLocale(variant); if (locale == null) return null; EList<PropertyFileDescriptor> descriptors = locale.getDescriptors(); for (PropertyFileDescriptor descriptor : descriptors) { if (path.equals(descriptor.getLocation())) { return descriptor; } } return null; } private Locale createVariant(String localeString) { return (Locale) PropertiesFactory.eINSTANCE.createFromString(PropertiesPackage.Literals.LOCALE, localeString); } } // ProjectVersionImpl