View Javadoc
1   /*
2    * This file is part of ***  M y C o R e  ***
3    * See http://www.mycore.de/ for details.
4    *
5    * MyCoRe is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * MyCoRe is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with MyCoRe.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package org.mycore.datamodel.classifications2.impl;
20  
21  import java.net.URI;
22  import java.util.Collections;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Locale;
26  import java.util.Optional;
27  import java.util.SortedSet;
28  import java.util.TreeSet;
29  import java.util.stream.Collectors;
30  
31  import org.mycore.common.MCRConstants;
32  import org.mycore.common.MCRSessionMgr;
33  import org.mycore.common.config.MCRConfiguration2;
34  import org.mycore.datamodel.classifications2.MCRCategory;
35  import org.mycore.datamodel.classifications2.MCRCategoryDAOFactory;
36  import org.mycore.datamodel.classifications2.MCRCategoryID;
37  import org.mycore.datamodel.classifications2.MCRLabel;
38  import org.mycore.util.concurrent.MCRReadWriteGuard;
39  
40  /**
41   * @author Thomas Scheffler (yagee)
42   *
43   * @version $Revision$ $Date$
44   * @since 2.0
45   */
46  public abstract class MCRAbstractCategoryImpl implements MCRCategory {
47  
48      protected final MCRReadWriteGuard childGuard = new MCRReadWriteGuard();
49  
50      protected MCRCategory root;
51  
52      protected MCRCategory parent;
53  
54      protected SortedSet<MCRLabel> labels;
55  
56      protected List<MCRCategory> children;
57  
58      private MCRCategoryID id;
59  
60      private URI uri;
61  
62      private String defaultLang;
63  
64      private static HashSet<String> LANGUAGES;
65  
66      static {
67          LANGUAGES = new HashSet<>(MCRConfiguration2.getString("MCR.Metadata.Languages")
68              .map(MCRConfiguration2::splitValue)
69              .map(s -> s.collect(Collectors.toList()))
70              .orElseGet(Collections::emptyList));
71      }
72  
73      public MCRAbstractCategoryImpl() {
74          super();
75          if (defaultLang == null) {
76              defaultLang = MCRConfiguration2.getString("MCR.Metadata.DefaultLang").orElse(MCRConstants.DEFAULT_LANG);
77          }
78          labels = new TreeSet<>();
79      }
80  
81      public List<MCRCategory> getChildren() {
82          return childGuard.lazyLoad(this::childrenNotHere, this::initChildren, () -> children);
83      }
84  
85      private boolean childrenNotHere() {
86          return children == null;
87      }
88  
89      private void initChildren() {
90          setChildrenUnlocked(MCRCategoryDAOFactory.getInstance().getChildren(id));
91      }
92  
93      protected abstract void setChildrenUnlocked(List<MCRCategory> children);
94  
95      public MCRCategoryID getId() {
96          return id;
97      }
98  
99      public void setId(MCRCategoryID id) {
100         this.id = id;
101     }
102 
103     public SortedSet<MCRLabel> getLabels() {
104         return labels;
105     }
106 
107     public MCRCategory getRoot() {
108         if (getId().isRootID()) {
109             return this;
110         }
111         if (root == null && getParent() != null) {
112             root = getParent().getRoot();
113         }
114         return root;
115     }
116 
117     public URI getURI() {
118         return uri;
119     }
120 
121     public void setURI(URI uri) {
122         this.uri = uri;
123     }
124 
125     public boolean hasChildren() {
126         return childGuard
127             .read(() -> Optional.ofNullable(children).map(c -> !c.isEmpty()))
128             .orElse(MCRCategoryDAOFactory.getInstance().hasChildren(id));
129     }
130 
131     public final boolean isCategory() {
132         return !isClassification();
133     }
134 
135     public final boolean isClassification() {
136         return getId().isRootID();
137     }
138 
139     public MCRCategory getParent() {
140         return parent;
141     }
142 
143     public void setParent(MCRCategory parent) {
144         if (this.parent == parent) {
145             return;
146         }
147         detachFromParent();
148         this.parent = parent;
149         if (parent != null) {
150             parent.getChildren().add(this);
151         }
152     }
153 
154     /**
155      *
156      */
157     void detachFromParent() {
158         if (parent != null) {
159             // remove this from current parent
160             parent.getChildren().remove(this);
161             parent = null;
162         }
163     }
164 
165     public Optional<MCRLabel> getCurrentLabel() {
166         if (labels.isEmpty()) {
167             return Optional.empty();
168         }
169 
170         return Optional.of(
171             getLabel(MCRSessionMgr.getCurrentSession().getCurrentLanguage())
172                 .orElseGet(() -> getLabel(defaultLang)
173                     .orElseGet(() -> labels.stream().filter(l -> LANGUAGES.contains(l.getLang())).findFirst()
174                         .orElseGet(() -> labels.stream().filter(l -> !l.getLang().startsWith("x-")).findFirst()
175                             .orElseGet(() -> labels.iterator().next())))));
176     }
177 
178     public Optional<MCRLabel> getLabel(String lang) {
179         String languageTag = Locale.forLanguageTag(lang).toLanguageTag();
180         for (MCRLabel label : labels) {
181             if (label.getLang().equals(languageTag)) {
182                 return Optional.of(label);
183             }
184         }
185         return Optional.empty();
186     }
187 
188     public String toString() {
189         return Optional.ofNullable(id).map(MCRCategoryID::toString).orElse(null);
190     }
191 }