| 1 | /* | |
| 2 | * Copyright (c) 2015 Maxim Yunusov | |
| 3 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 | * you may not use this file except in compliance with the License. | |
| 5 | * You may obtain a copy of the License at | |
| 6 | * | |
| 7 | * http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 | * | |
| 9 | * Unless required by applicable law or agreed to in writing, software | |
| 10 | * distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 | * See the License for the specific language governing permissions and | |
| 13 | * limitations under the License. | |
| 14 | */ | |
| 15 | ||
| 16 | package org.maxur.perfmodel.backend.infrastructure; | |
| 17 | ||
| 18 | import org.iq80.leveldb.WriteBatch; | |
| 19 | import org.jvnet.hk2.annotations.Service; | |
| 20 | import org.maxur.perfmodel.backend.domain.ConflictException; | |
| 21 | import org.maxur.perfmodel.backend.domain.Project; | |
| 22 | import org.maxur.perfmodel.backend.domain.Repository; | |
| 23 | import org.maxur.perfmodel.backend.service.Benchmark; | |
| 24 | import org.maxur.perfmodel.backend.service.DataSource; | |
| 25 | import org.slf4j.Logger; | |
| 26 | ||
| 27 | import javax.inject.Inject; | |
| 28 | import java.io.IOException; | |
| 29 | import java.util.Collection; | |
| 30 | import java.util.Optional; | |
| 31 | ||
| 32 | import static java.lang.String.format; | |
| 33 | import static java.util.Optional.empty; | |
| 34 | import static org.slf4j.LoggerFactory.getLogger; | |
| 35 | ||
| 36 | /** | |
| 37 | * Level Db Implementation of Project Repository. | |
| 38 | * | |
| 39 | * @author myunusov | |
| 40 | * @version 1.0 | |
| 41 | * @since <pre>30.08.2015</pre> | |
| 42 | */ | |
| 43 | @Service | |
| 44 | public class ProjectRepositoryLevelDbImpl implements Repository<Project> { | |
| 45 | ||
| 46 | private static final Logger LOGGER = getLogger(ProjectRepositoryLevelDbImpl.class); | |
| 47 | ||
| 48 | public static final String ROOT_PREFIX = "/"; | |
| 49 | ||
| 50 | @Inject | |
| 51 | private DataSource dataSource; | |
| 52 | ||
| 53 | @Override | |
| 54 | @Benchmark | |
| 55 | public Optional<Project> get(final String key) { | |
| 56 | try { | |
| 57 |
1
1. get : mutated return of Object value for org/maxur/perfmodel/backend/infrastructure/ProjectRepositoryLevelDbImpl::get to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return dataSource.get(key); |
| 58 | } catch (IOException | ClassNotFoundException e) { | |
| 59 |
1
1. get : mutated return of Object value for org/maxur/perfmodel/backend/infrastructure/ProjectRepositoryLevelDbImpl::get to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return throwError(e, "Cannot find project by id '%s'", key); |
| 60 | } | |
| 61 | } | |
| 62 | ||
| 63 | @Override | |
| 64 | @Benchmark | |
| 65 | public Collection<Project> findAll() { | |
| 66 | try { | |
| 67 |
1
1. findAll : mutated return of Object value for org/maxur/perfmodel/backend/infrastructure/ProjectRepositoryLevelDbImpl::findAll to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return dataSource.findAllByPrefix(ROOT_PREFIX); |
| 68 | } catch (IOException | ClassNotFoundException e) { | |
| 69 |
1
1. findAll : mutated return of Object value for org/maxur/perfmodel/backend/infrastructure/ProjectRepositoryLevelDbImpl::findAll to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return throwError(e, "Cannot get all projects"); |
| 70 | } | |
| 71 | } | |
| 72 | ||
| 73 | @Override | |
| 74 | @Benchmark | |
| 75 | public Optional<Project> findByName(final String name) { | |
| 76 | try { | |
| 77 |
1
1. findByName : mutated return of Object value for org/maxur/perfmodel/backend/infrastructure/ProjectRepositoryLevelDbImpl::findByName to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return dataSource.get(path(name)); |
| 78 | } catch (IOException | ClassNotFoundException e) { | |
| 79 |
1
1. findByName : mutated return of Object value for org/maxur/perfmodel/backend/infrastructure/ProjectRepositoryLevelDbImpl::findByName to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return throwError(e, "Cannot find project by name '%s'", name); |
| 80 | } | |
| 81 | } | |
| 82 | ||
| 83 | @Override | |
| 84 | @Benchmark | |
| 85 | public Optional<Project> remove(final String key) { | |
| 86 | try (WriteBatch batch = dataSource.createWriteBatch()) { | |
| 87 | final Optional<Project> result = dataSource.get(key); | |
| 88 |
1
1. remove : negated conditional → NO_COVERAGE |
if (result.isPresent()) { |
| 89 |
1
1. remove : removed call to org/maxur/perfmodel/backend/service/DataSource::delete → NO_COVERAGE |
dataSource.delete(key); |
| 90 |
1
1. remove : removed call to org/maxur/perfmodel/backend/service/DataSource::delete → NO_COVERAGE |
dataSource.delete(path(result.get().getName())); |
| 91 |
1
1. remove : removed call to org/maxur/perfmodel/backend/service/DataSource::commit → NO_COVERAGE |
dataSource.commit(batch); |
| 92 | } | |
| 93 | return result; | |
| 94 | } catch (IOException | ClassNotFoundException e) { | |
| 95 |
1
1. remove : mutated return of Object value for org/maxur/perfmodel/backend/infrastructure/ProjectRepositoryLevelDbImpl::remove to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return throwError(e, "Cannot remove project '%s'", key); |
| 96 | } | |
| 97 | ||
| 98 | } | |
| 99 | ||
| 100 | @Override | |
| 101 | @Benchmark | |
| 102 | public Optional<Project> add(final Project value) throws ConflictException { | |
| 103 | final String id = value.getId(); | |
| 104 | final String newName = value.getName(); | |
| 105 | try (WriteBatch batch = dataSource.createWriteBatch()) { | |
| 106 | final Optional<Project> other = dataSource.get(id); | |
| 107 |
1
1. add : negated conditional → NO_COVERAGE |
if (value.isSame(other)) { |
| 108 | return other; | |
| 109 | } | |
| 110 |
1
1. add : removed call to org/maxur/perfmodel/backend/domain/Project::checkUniqueId → NO_COVERAGE |
value.checkUniqueId(other); |
| 111 |
1
1. add : removed call to org/maxur/perfmodel/backend/domain/Project::checkNamesakes → NO_COVERAGE |
value.checkNamesakes(findByName(newName)); |
| 112 |
1
1. add : removed call to org/maxur/perfmodel/backend/domain/Project::makeVersion → NO_COVERAGE |
value.makeVersion(); |
| 113 |
1
1. add : removed call to org/maxur/perfmodel/backend/service/DataSource::put → NO_COVERAGE |
dataSource.put(id, value); |
| 114 |
1
1. add : removed call to org/maxur/perfmodel/backend/service/DataSource::put → NO_COVERAGE |
dataSource.put(path(newName), value.brief()); |
| 115 |
1
1. add : removed call to org/maxur/perfmodel/backend/service/DataSource::commit → NO_COVERAGE |
dataSource.commit(batch); |
| 116 | return Optional.of(value); | |
| 117 | } catch (IOException | ClassNotFoundException e) { | |
| 118 |
1
1. add : mutated return of Object value for org/maxur/perfmodel/backend/infrastructure/ProjectRepositoryLevelDbImpl::add to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return throwError(e, "Cannot save project '%s'", newName); |
| 119 | } | |
| 120 | } | |
| 121 | ||
| 122 | @Override | |
| 123 | @Benchmark | |
| 124 | // idempotent | |
| 125 | public Optional<Project> amend(final Project value) throws ConflictException { | |
| 126 | final String id = value.getId(); | |
| 127 | final String newName = value.getName(); | |
| 128 |
1
1. amend : removed call to org/maxur/perfmodel/backend/domain/Project::incVersion → NO_COVERAGE |
value.incVersion(); |
| 129 | ||
| 130 | try (WriteBatch batch = dataSource.createWriteBatch()) { | |
| 131 | final Optional<Project> prev = dataSource.get(id); | |
| 132 |
1
1. amend : negated conditional → NO_COVERAGE |
if (!prev.isPresent()) { |
| 133 | return empty(); | |
| 134 | } | |
| 135 |
1
1. amend : negated conditional → NO_COVERAGE |
if (value.isSame(prev)) { |
| 136 | return prev; | |
| 137 | } | |
| 138 |
1
1. amend : removed call to org/maxur/perfmodel/backend/domain/Project::checkConflictWith → NO_COVERAGE |
value.checkConflictWith(prev); |
| 139 |
1
1. amend : negated conditional → NO_COVERAGE |
final boolean mustBeRenamed = !prev.get().getName().equals(newName); |
| 140 |
1
1. amend : negated conditional → NO_COVERAGE |
if (mustBeRenamed) { |
| 141 |
1
1. amend : removed call to org/maxur/perfmodel/backend/domain/Project::checkNamesakes → NO_COVERAGE |
value.checkNamesakes(findByName(newName)); |
| 142 |
1
1. amend : removed call to org/maxur/perfmodel/backend/service/DataSource::delete → NO_COVERAGE |
dataSource.delete(path(prev.get().getName())); |
| 143 | } | |
| 144 |
1
1. amend : removed call to org/maxur/perfmodel/backend/service/DataSource::put → NO_COVERAGE |
dataSource.put(id, value); |
| 145 |
1
1. amend : removed call to org/maxur/perfmodel/backend/service/DataSource::put → NO_COVERAGE |
dataSource.put(path(newName), value.brief()); |
| 146 |
1
1. amend : removed call to org/maxur/perfmodel/backend/service/DataSource::commit → NO_COVERAGE |
dataSource.commit(batch); |
| 147 | return Optional.of(value); | |
| 148 | } catch (IOException | ClassNotFoundException e) { | |
| 149 |
1
1. amend : mutated return of Object value for org/maxur/perfmodel/backend/infrastructure/ProjectRepositoryLevelDbImpl::amend to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return throwError(e, "Cannot save project '%s'", newName); |
| 150 | } | |
| 151 | } | |
| 152 | ||
| 153 | private String path(final String name) { | |
| 154 |
1
1. path : mutated return of Object value for org/maxur/perfmodel/backend/infrastructure/ProjectRepositoryLevelDbImpl::path to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return ROOT_PREFIX + name; |
| 155 | } | |
| 156 | ||
| 157 | private static <T> T throwError(final Exception e, final String message, final String... args) { | |
| 158 | final String msg = format(message, args); | |
| 159 | LOGGER.error(msg, e); | |
| 160 | throw new IllegalStateException(msg, e); | |
| 161 | } | |
| 162 | ||
| 163 | } | |
Mutations | ||
| 57 |
1.1 |
|
| 59 |
1.1 |
|
| 67 |
1.1 |
|
| 69 |
1.1 |
|
| 77 |
1.1 |
|
| 79 |
1.1 |
|
| 88 |
1.1 |
|
| 89 |
1.1 |
|
| 90 |
1.1 |
|
| 91 |
1.1 |
|
| 95 |
1.1 |
|
| 107 |
1.1 |
|
| 110 |
1.1 |
|
| 111 |
1.1 |
|
| 112 |
1.1 |
|
| 113 |
1.1 |
|
| 114 |
1.1 |
|
| 115 |
1.1 |
|
| 118 |
1.1 |
|
| 128 |
1.1 |
|
| 132 |
1.1 |
|
| 135 |
1.1 |
|
| 138 |
1.1 |
|
| 139 |
1.1 |
|
| 140 |
1.1 |
|
| 141 |
1.1 |
|
| 142 |
1.1 |
|
| 144 |
1.1 |
|
| 145 |
1.1 |
|
| 146 |
1.1 |
|
| 149 |
1.1 |
|
| 154 |
1.1 |